Announcement

Collapse
No announcement yet.

uLCD-32PTU Man in the middle serial.

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • uLCD-32PTU Man in the middle serial.

    I have an application to monitor unencrypted string serial data being transmitted at 115200, between a pc and a device, string format is "XXXXXXXX \n" (string terminated with \n).
    The PC will send a serial string command and the device will echo back acknowledgement or possibly some form of short string data.

    I want to display these strings on the screen , sort of "man in the middle",

    pseudocode:

    Com0 = PC, Com1 = Device,

    While(Com0 == Com0.serialAvailable || Com1 ==Com1.serialAvailable){

    a = ReadString Com0 ; DisplayString(a,BlueColour);WriteString Com1(a)
    b = ReadString Com1 ; DisplayString(b,GreenColour);WriteString Com0(a)

    wend.

    The uLCD-32PTU board has two coms so my questions:

    1. Is the picaso processor fast enough to read the incoming data from both PC and the device and echo from COM0 to COM1 and vice versa?
    (fwiw i tried this with arduino uno and it failed miserably because i was trying to software serial, worked ok on my 2560 though with two hardware ports.

    2. Is it possible to power the screen via one of the two usb connectors?

    (Goal here is to remove that big ass 2560 from the build if possible.)

    Many thanks!
    CB
    Last edited by CeeBee; 21st January 2019, 02:59 PM.

  • #2
    so far this works using pins 28/30 for COM1,

    Q1: presumably if i power to vin and GND from the usb, then jump rx/tx over to the COM0 rx tx pins then I could go both ways?
    [self resolved, yes the board powers and works with power from USB to vin/gnd and transmits/receives on tx1/rx at pins 28/30 connected)

    Q2:If there a simpler way to read a char[13] terminated string than below? Many thanks.

    #platform "uLCD-32PTU"
    #inherit "4DGL_16bitColours.fnc"
    var buffer[100];
    var CodeBuffer[80];
    var CharCount,i;
    var getchar;

    func main()
    CharCount := 0;
    txt_Width(1); txt_Height(1);
    gfx_ScreenMode(LANDSCAPE);
    com_SetBaud(COM1,11520);
    com_SetBaud(COM0,11520);
    com_Init(buffer, 50, 0);
    redraw();

    while(1)
    getchar := serin1();
    if (getchar >0 && getchar !=13)
    CodeBuffer[CharCount] := getchar;
    CharCount++;
    endif

    if (getchar==13)
    for(i:=0;i<=CharCount;i++)
    to(TEXT);putch(CodeBuffer[i]);
    to(COM1);putch(CodeBuffer[i]);
    to(COM0);putch(CodeBuffer[i]);
    next
    to(COM1);putch(13);to(TEXT);
    CharCount := 0;
    redraw();
    endif
    wend
    endfunc

    func redraw()
    pause(2000);
    gfx_Cls();
    gfx_MoveTo(0,0);
    txt_FGcolour(WHITE);
    print("Next line read is:");
    txt_FGcolour(YELLOW);
    gfx_MoveTo(0,12);
    endfunc
    Attached Files
    Last edited by CeeBee; 21st January 2019, 06:34 PM.

    Comment


    • #3
      Hi,

      As far as I understood you want the display to monitor the data sent by pc to device and by device to pc.
      If so, try the code below. Read the comments to be guided.
      Code:
      var recvBytesCom0[8]; // COM0 buffer - can hold  8*2 char
      var recvBytesCom1[8]; // COM1 buffer - can hold  8*2 char
      
      func main()
      
          gfx_ScreenMode(LANDSCAPE);
      
          com_SetBaud(COM0,11520);
          com_SetBaud(COM1,11520);
          com_Init(recvBytesCom0, 2*8, 'x');  // accepts data if start char  x
          com1_Init(recvBytesCom1, 2*8, 'x');  // accepts data if start char  x
      
      
          txt_FGcolour(WHITE);
          print("Read serial in COM0:");
          txt_MoveCursor(2,0);
          print("Read serail in COM1:");
          txt_FGcolour(RED);
      
          repeat
      
              if(com_Count() && com_Full())       // store bytes in recvBytes until full
                  txt_MoveCursor(1,0);
                  putstr(recvBytesCom0);
      
                  to(COM1);putstr(recvBytesCom0);      // send received packet to COM1
                  com_Init(recvBytesCom0, 2*8, 'x');  //  reinitialize COM0
              endif
      
              if(com1_Count() && com_Full())      // store bytes in recvBytes until full
                  txt_MoveCursor(3,0);
                  putstr(recvBytesCom1);
      
                  to(COM0);putstr(recvBytesCom1);      // send received packet to COM0
                  com1_Init(recvBytesCom1, 2*8, 'x');  //  reinitialize COM1
              endif
      
          forever
      
      endfunc
      Hope this will help.

      Best regards,
      Vince_4D

      Comment


      • #4
        Thanks Vince,

        I am at this point, code may not actually run, as im not at a pc with my device so cannot test, but this is the logic. I will never know what the first character is as I am not generating the first character, it can vary between being white space, '/','G','P','M', 'S' and probably a few others.. in those hordes I am looking for only a few as defined below, how would I go about that?

        But i want to also extract the float/double number (0000.000) after a certain gcode prefix, and even possible make a decision based on that number anbd a user input to inject a line to the device before the next line of code gets sent (not time critical)

        As an example I am wanting to store the double value of X, Y, Z , F and E in DRO's where the '/n' terminated line I read was

        G0 X123.456 Y345.678 Z 678.876 F1200.00 E15.500

        So in my code

        double XP := 123.456 >> post to DRO
        etc etc.

        Code:
        #platform "uLCD-32PTU"
        #inherit "4DGL_16bitColours.fnc"
        var buffer[100];
        var codeBuffer[80];
        var charCount,i,ii;
        var getChar, echoChar;
        var XP,YP,ZP,FP,EP;
        
        func main()
        
        gfx_ScreenMode(LANDSCAPE);
        com_SetBaud(COM0,11520);
        com_SetBaud(COM1,11520);
        com_Init(buffer, 50, 0);
        
        while(true)
            getChar := serin1();     //read from PC
            serout(getChar);         //pass to device
            echoChar = serin();     //read ACK from device
            serout1(echoChar);        //pass to PC
                
            if (getChar >0 && getChar !=13)
                codeBuffer[charCount] := getChar;
                charCount++;
            endif
            
            if (getChar==13)            
                for(i:=0;i<=charCount;i++)
                    if(codeBuffer[i] == "X")XP := ExtractCode(i,codeBuffer);            
                    if(codeBuffer[i] == "Y")YP := ExtractCode(i,codeBuffer);
                    if(codeBuffer[i] == "Z")ZP := ExtractCode(i,codeBuffer);
                    if(codeBuffer[i] == "F")FP := ExtractCode(i,codeBuffer);
                    if(codeBuffer[i] == "E")EP := ExtractCode(i,codeBuffer);            
                next        
                charCount := 0;
                redraw();
            endif    
        wend
        endfunc
        
        func ExtractCode(var i, var CBuf)
            var P;
            var PB;
            var ii := i+1;
                while(CBuf[i+ii] != ' ')
                    PB[i]=codeBuffer[i+ii];
                    ii++;
                wend
            flt_VAL(P,PB);
            return P;
        endfunc
        
        func redraw()
            pause(20); //replace with led dro's.
            gfx_Cls();
            gfx_MoveTo(0,0);
            print("X:",[STR]XP);
            gfx_MoveTo(0,12);
            print("Y:",[STR]YP);
            gfx_MoveTo(0,24);
            print("Z:",[STR]ZP);
            gfx_MoveTo(0,36);
            print("F:",[STR]FP);
            gfx_MoveTo(0,48);
            print("E:",[STR]EP);
        endfunc
        Last edited by CeeBee; 22nd January 2019, 02:15 PM.

        Comment


        • #5
          Hi,

          I will never know what the first character is as I am not generating the first character, it can vary between being white space, '/','G','P','M', 'S' and probably a few others..
          You should utilize the string pointers to achieve this routine, not by array locations. Note that in 4DGL, buffer accommodates 2 char per location.
          Please refer to the attached code to be guided.

          Also, knowing the concept of string pointers will also allow you to parse data between characters, in your case X, Y, Z , F and E.
          If you find any problem in its implementation, feel free to ask.

          Hope this will help and best regards,















          Attached Files
          Vince_4D

          Comment


          • #6
            Hi Vince,

            Thank you for your reply.

            Opening your project and changing only the board type to uLCD-32PTU, i get nothing showing onscreen in COM1, I get nothing echoed back from com1 to com0, if i send via com0 i get something onscreen but nothing echoed to com1

            Using my rather clunky code in my original post i get bidirectional on com0 and com1.

            Screen captures of duplex com0/com1 from my original sketch, and capture from the sketch you supplied, i tried to draw in the result

            Attached Files

            Comment


            • #7
              Hi,

              The charCom1 := serin1(); line was somehow omitted in the program. Also, the code sent was just for reference to show how string pointers are implemented. You could always optimize the code (such as implementing timing routine) in your application. But I'll try to implement the routine as a whole and will get back to you once done.

              Best regards,
              Vince_4D

              Comment


              • #8
                Originally posted by Vince_4D View Post
                But I'll try to implement the routine as a whole and will get back to you once done.

                Best regards,
                Just read that last bit, thanks a million, still not working but i found another code bug if it speeds you up.

                one of these had a zero in it still, copy-pasta i guess, I caught that but nothing more so far.

                ptrBuff1 := str_Ptr(recvBytesCom1);
                ptrBuff1Min := ptrBuff1;


                Comment


                • #9
                  joy at last, had to unplug and replug the usb port today, suddenly its going. strange. but. at least working!

                  Vince the flt_VAL function is not available on my board, I cannot find examples on the forum using search that can suggest a replacement methodology?

                  I found this which kinda does what atof does for c, but I cannot make it work with 4dg as I cannot understand its for loop section.
                  https://stackoverflow.com/questions/...hout-atof-in-c

                  I need to parse the string EX:

                  G1 X105.123 Y234.56 Z-0.56 F1200.50 E15

                  stripping out the G1,
                  then returning the value:
                  105.123 into a variable X
                  234.56 into a variable Y etc etc

                  so that I can display them on a DRO and secondly perform math on them,.

                  Attached Files
                  Last edited by CeeBee; 23rd January 2019, 07:34 PM.

                  Comment


                  • #10
                    Hi,

                    Sorry for the delayed response and thank you for pointing out the error.

                    Attached is a sample code that can parse the packet data coming from a serial COM. Kindly read the comments in the code to be guided.
                    If you found any problem, feel free to notify me.
                    With regards to utilizing the parsed values, may I know the specific computation you would want to implement so that I could try it on my end?

                    Best regards,
                    Attached Files
                    Vince_4D

                    Comment


                    • #11
                      Hi VInce,

                      No worries, you have an actual job to do i presume, and taking time to help with this appreciated.

                      The concept is to inject a standalone interpreter between the controller and the device (could be cnc mill, 3d printer, dlp printer etc, they are all just variants of gcode anyhow)

                      A: Act as a live DRO at the printer with more information than is present on typical machine based displays
                      B: read the values being passed for all axis' so that if offsets are detected (by operator eye) the user has an option to add or subtract values to the running code to fix them
                      (example the machine started loosing stpes over a deep cut, operator saw it happen, and adds 0.1mm to every X move, keeps and eye on it, still looks a tad out, adds another 0.1mm and so on, for each axis.

                      Very simple math, but it would require floats/doubles parse from the string to determinet he value being given to the printer, intercet, add a given value, parse back to string, then pass the fixed code onto the device.



                      Comment


                      • #12
                        just an update, got this reading and writing both ways successfully, after a snag with the printer being ftdi, i located the pins on the other side of its usb-ttl convertor and had success.

                        its a setback because it means the board cannot be plug and play without the enduser having to do some sort of tomfoolery at their motherboard level, this owrked on the 2560 because i could use the printers usb to its usb and the issue didnt occur, .but. in terms of figuring out if the 32ptu had enough processing power to pull it off without an arduino, yes, it does, seemless communication, neither device on either end of the ptu was affected at all, no measure loss in communication speed over 2000 instructions measured.

                        I will see how involved it is to set a usb-ttl somewhere between the board and the printer inline, they are not expensive.

                        the math is probably not required as i will use a interupt between lines of code to do a G91; G1(XYZ) +-(#.###);G90; to set the offsets instead of the addition to each line of code, less processing issues either side, however, id still like to be able to use the 32ptu's nice guages and DRO graphics to display the values, but I cannot pass a string to them, if the manual Convert.ToDouble(string) is too complex and chews too many cycles I may have to just live with a text interface.

                        Comment


                        • #13
                          Hi,

                          Glad to hear your project development.

                          To sum up the given information, you would want to set up a communication between a PC and a device with a Picaso display module as the middle interface. In this setup, the display module will show the PC’s transmitted data (parsed) as well as get inputs from the user to adjust/command the device.

                          With this, I highly suggest that you let the PC do the complex tasks since it has significantly more processing power than the Picaso display module. So instead of doing the computation in the module when an input is received, the module will just have to send data to the PC and let the PC interpret the data. I think this method is ideal the given setup if there is no other constraint.

                          With regards to updating a gauge from float/decimal values, what I'm thinking is you need to convert the string into an integer in order for the gauge to more or less represent the value. Note that the number of gauge frames is directly proportional to the memory it consumes.
                          For the basic implementation, refer to the attached code.
                          Hope this helps.


                          Best regards,
                          Attached Files
                          Vince_4D

                          Comment


                          • #14
                            thanks, ill need doubles/decimal as the motion being controlled sub 1 unit, down to 0.01. The dro will be the red/green LED one which I see has a decimal point option, not tested it yet but presumably it will accept a double or a float truncated to however many digits past eh decimal you set it.

                            In terms of sending back to the pc, no can do, "pc" in this case may be an rpi, an actual pc, embedded controller etc. I have no control over what might be plugged in, other than knowing it will send a serial stream of gcode OUT.. some more complex control system have what I am trying to build, already in their software, but in most cases its a terrible interface, and the controller is remote, imagine trying to adapt an 0.05mm increment/decrement, from another room, then running to the machine to see what the result was.

                            Some printers with newer firmware can control the Z to some extent locally, but again, its a clunky 5 button interface that requires jumping through a myriad of menus to access.

                            SO: Im jumping between the two, once the code is good, i have a few up/down buttons, a slection of preset offsets (0.01, 0.02, 0.05, 0.1 etc), a selectable Axis to apply the offset to, and a then inject the code G91; G1(XYZ) +-(#.###);G90; (instructs machine to move in relative motion, add the offset to its current axis, then return motion to absolute, and neither the controller nor device know it happened, a line of code simply appeared and was acted on by the hardware.

                            I tested this and it caused a com issue, then i relaised that if the controller didnt know it sent it, one ACK to many came back, so i suppressed the first ack after the send, and return duplex to both.

                            Works surprisingly well.

                            Comment

                            Working...
                            X