pserial with 3 parsed variables numbers

Store Forums Video Experimenter Bugs/Problems pserial with 3 parsed variables numbers

This topic contains 7 replies, has 2 voices, and was last updated by  Michael 2 months ago.

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #11007

    pedroe
    Participant

    Hi,

    I have the video experimenter shield, and Im trying to communicate via pserial between 2 arduinos. To explain my issued, lets consider that the arduino master prints “1000,12,24.70” in the serial. Then the slave arduino which has the video experimenter shield has to read that info (“1000,12,24.70”) and then parse, so that the 1000, 12 and 24.70 becomes 3 diferente variables, 1 long 1 integer and 1 float.

    Since my knowledge is very limited, Im not able to convert the char strings into numbers. At the moment, with all my internet search I was able to find some pieces of code that is working until the point of correct parsing, has follows:

    TV.println(strings[0]); overlays 1000
    TV.println(strings[1]); overlays 12
    TV.println(strings[2]); overlays 24.70

    But now I would like to assign:

    long int dist to strings[0]
    int var to strings[1], and
    float rad to strings[2]

    which I would ask for some help since Im not able to code a solution that works.

    My slave arduino has the following code:

    #include <TVout.h>
    #include <pollserial.h>
    #include <fontALL.h>
    
    TVout TV;
    pollserial pserial;
    
    char *strings[10];
    char *ptr = NULL;
    
    void setup()
    {
       TV.begin(PAL,184,72);
      TV.select_font(font6x8);
      initOverlay();
      TV.println("Serial Terminal");
      TV.println("-- Version 0.1 --");
      TV.set_hbi_hook(pserial.begin(4800));
    }
    
    void initOverlay() {
      TCCR1A = 0;
      // Enable timer1.  ICES0 is set to 0 for falling edge detection on input capture pin.
      TCCR1B = _BV(CS10);
    
      // Enable input capture interrupt
      TIMSK1 |= _BV(ICIE1);
    
      // Enable external interrupt INT0 on pin 2 with falling edge.
      EIMSK = _BV(INT0);
      EICRA = _BV(ISC01);
    }
    
    // Required to reset the scan line when the vertical sync occurs
    ISR(INT0_vect) {
      display.scanLine = 0;
    }
    
    void loop()
    {
      //Reads serial
       if (pserial.available()) {
    
     static char input[25];
     static uint8_t i;
     char c = pserial.read ();
    
     if ( c != '\r' && i < 24 ) // assuming "Carriage Return" is chosen in the Serial monitor as the line ending character
       input[i++] = c;
       
     else
     {
       input[i] = '\0';
       i = 0;
        
    
         //Parsing the input
         byte index = 0;
        ptr = strtok(input, ",");  // takes a list of delimiters
        while(ptr != NULL)
        {
            strings[index] = ptr;
            index++;
            ptr = strtok(NULL, ",");  // takes a list of delimiters
        }
    
        TV.println(strings[0]);
        TV.println(strings[1]);
        TV.println(strings[2]);
        
    
        
       }//if
    
     }//pserial available
    }//loop

    The master arduino has the following code:

    int long A=1000;
    int B=12;
    float C=24.7;
    
    void setup() {
      Serial.begin(4800);
      
    
    }
    
    void loop() {
    
      
      Serial.print(A);
      Serial.print(",");
      Serial.print(B);
      Serial.print(",");
      Serial.println(C);
      delay(2000);
    
    }
    • This topic was modified 2 months ago by  pedroe.
    • This topic was modified 2 months ago by  pedroe.
    #11042

    Michael
    Keymaster

    The Arduino String object has methods to create integer and float types.
    First create a String object from char array:

    String longString = String(strings[0]);
    String intString = String(strings[1]);
    String floatString = String(strings[2]);

    Then use methods on String object to get primitive data types.

    long int dist = longString.toInt(); // returns long
    int var = (int)intString.toInt(); // returns long, so cast to int
    float rad = floatString.toFloat();

    That should work.

    • This reply was modified 2 months ago by  Michael.
    #11044

    pedroe
    Participant

    Michael I really appreciate your input! Thank you!

    If i apply your suggestion using Serial instead of pserial and removing the TVout and the overlay, it outputs for the Serial monitor the correct values, parsed and in numbers:

    char *strings[10];
    char *ptr = NULL;
    
            
    
    void setup()
    {
    Serial.begin(4800);
    }
    
    void loop()
    {
      //Reads serial
       if (Serial.available()) {
    
     static char input[25];
     static uint8_t i;
     char c = Serial.read ();
    
     if ( c != '\r' && i < 24 ) // assuming "Carriage Return" is chosen in the Serial monitor as the line ending character
       input[i++] = c;
       
     else
     {
       input[i] = '\0';
       i = 0;
        
    
         //Parsing the input
         byte index = 0;
        ptr = strtok(input, ",");  // takes a list of delimiters
        while(ptr != NULL)
        {
            strings[index] = ptr;
           
            index++;
            ptr = strtok(NULL, ",");  // takes a list of delimiters
            
           // t0=atoi(strings[0]);
          
           // t1=atoi(strings[1]);
          
           // t2=atoi(strings[2]);
          
        }
    
      String longString = String(strings[0]);
      String intString = String(strings[1]);
      String floatString = String(strings[2]);
        
        
    
      long int dist = longString.toInt(); // returns long
      int var = (int)intString.toInt(); // returns long, so cast to int
      float rad = floatString.toFloat();
    
       Serial.println(dist+1);
       Serial.println( var+1);
       Serial.println( rad+1);
     
    
           
       }//if
     
     }//pserial available
    
    }//loop  

    But using pserial and the tvout library with overlay it doesnt work. The overlayd output is:
    0
    0
    0.00

    #include <TVout.h>
    #include <pollserial.h>
    #include <fontALL.h>
    
    TVout TV;
    pollserial pserial;
    
    char *strings[10];
    char *ptr = NULL;
    
            
    
    void setup()
    {
      TV.begin(PAL,184,72);
      TV.select_font(font6x8);
      initOverlay();
      TV.println("Serial Terminal");
      TV.println("-- Version 0.1 --");
      TV.set_hbi_hook(pserial.begin(4800));
    }
    
    void initOverlay() {
      TCCR1A = 0;
      // Enable timer1.  ICES0 is set to 0 for falling edge detection on input capture pin.
      TCCR1B = _BV(CS10);
    
      // Enable input capture interrupt
      TIMSK1 |= _BV(ICIE1);
    
      // Enable external interrupt INT0 on pin 2 with falling edge.
      EIMSK = _BV(INT0);
      EICRA = _BV(ISC01);
    }
    
    // Required to reset the scan line when the vertical sync occurs
    ISR(INT0_vect) {
      display.scanLine = 0;
    }
    
    void loop()
    {
      //Reads serial
       if (pserial.available()) {
    
     static char input[25];
     static uint8_t i;
     char c = pserial.read ();
    
     if ( c != '\r' && i < 24 ) // assuming "Carriage Return" is chosen in the Serial monitor as the line ending character
       input[i++] = c;
       
     else
     {
       input[i] = '\0';
       i = 0;
        
    
         //Parsing the input
         byte index = 0;
        ptr = strtok(input, ",");  // takes a list of delimiters
        while(ptr != NULL)
        {
            strings[index] = ptr;
           
            index++;
            ptr = strtok(NULL, ",");  // takes a list of delimiters
            
           // t0=atoi(strings[0]);
          
           // t1=atoi(strings[1]);
          
           // t2=atoi(strings[2]);
          
        }
    
      String longString = String(strings[0]);
      String intString = String(strings[1]);
      String floatString = String(strings[2]);
        
        
    
      long int dist = longString.toInt(); // returns long
      int var = (int)intString.toInt(); // returns long, so cast to int
      float rad = floatString.toFloat();
    
       TV.print(0,20, dist);
       TV.print(0,30, var);
       TV.print(0,40, rad);
    
           
       }//if
     
     }//pserial available
    
    }//loop
    • This reply was modified 2 months ago by  pedroe.
    #11046

    Michael
    Keymaster

    Hmm. Are the strings in the array still correct? That is, do strings[0] etc. contain the right values still?
    You might be running out of memory for the String objects. Try reducing your resolution and remove these lines:

    TV.println("Serial Terminal");
    TV.println("-- Version 0.1 --");

    These string literals in the println() statements take up memory. Your video buffer is using 1656 bytes ((184/8) * 72). Try 128×72 and see if it works.

    #11047

    pedroe
    Participant

    Michael,

    Reducing to 128×72 WORKED!!! Thank you very much!
    You have no idea how many hours i spent trying to solve this problem! Ready for the next one 🙂

    #11048

    Michael
    Keymaster

    With a lot of experience, I have learned that when the behavior of an Arduino program doesn’t make sense, the problem is almost always a lack of memory!

    #11051

    pedroe
    Participant

    Michael,

    One more question;
    The above solution worked fine, but i notice that frequently the pserial communication skips some characters/numbers.
    For example, if the master arduino sends 245 through serial, the slave with the shield might only overlay 24 skipping a 5. In the next loop the value is corrected, but after a few seconds it happens again. Per my understanding is a communication problem, and the variable in the slave side actually only gets the value 24 instead of 245.

    Do you have any idea about this? Memory again? Sorry to bother.

    #11054

    Michael
    Keymaster

    This problem is due to the polling nature of the serial communication. It’s probably not going to be perfectly reliable. I haven’t seen this myself, though. Maybe try a lower speed?

Viewing 8 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic.