Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 32

Thread: Teensy LC and 3.1 slow usb serial reads

  1. #1
    Junior Member
    Join Date
    Feb 2020
    Posts
    16

    Teensy LC and 3.1 slow usb serial reads

    Hi, this is my first post, I've been searching all day for an answer to what must be a very simple problem without success so here goes.

    I have an open-source arduino project that needs more power so I'm migrating to a Teensy LC.
    It involves reading usb serial at 38400 baud from a GPS (five sentences, with around 150 characters in each sentence)
    I can do this on the Nano with hardly any overhead so I'm free to read I2C devices and drive a stepper motor at 50 Hz.
    When I transfer the code to the Teensy I loose the last two NMEA sentences.
    To investigate the problem I threw out all my code and used the code below to run tests:
    (its from a well known arduino reference)

    const byte numChars = 200;
    char receivedChars[numChars]; // an array to store the received data

    boolean newData = false;

    void setup() {
    Serial.begin(38400);
    Serial.println("<Arduino is ready>");
    }

    void loop() {

    recvWithEndMarker();
    showNewData();
    }

    void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;

    while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

    if (rc != endMarker) {
    receivedChars[ndx] = rc;
    ndx++;
    if (ndx >= numChars) {
    ndx = numChars - 1;
    }
    }
    else {
    receivedChars[ndx] = '\0'; // terminate the string
    ndx = 0;
    newData = true;
    }
    }
    }
    long time1;

    void showNewData() {
    if (newData == true) {
    Serial.println(millis() - time1);
    time1 = millis();
    Serial.print("This just in ... ");
    Serial.println(receivedChars);
    newData = false;
    }
    }

    In my application (Cotswold Vario sailplane vertical speed indicator) the Teensy or Nano communicates with an LK8000 open-source Flight navigation system which is able to display the serial output.

    When this runs on my LC or 3.1s I see times of around 150 milli-sec to read 150 characters and I loose the last two sentences (same as my code).
    When I load the same code on a Nano I see times around 15 milli-sec and I see all five sentences at 1 Hz (GPS outputs 5 sentences each second).
    I thought this question must've come up a lot but have searched this forum and the web in vain.
    I've picked this up from the PJRC site:

    On a Teensy, the entire packet, up to 64 bytes, becomes available all at once. Sketches that do other work while receiving data might depend on slow reception behavior, where successive calls to Serial.available() are very unlikely to return true. On a Teensy receiving large amounts of data, it may be necessary to add a variable to count the number of bytes processed and limit the delay before other important work must be done.

    Could this be the problem?

  2. #2
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    Well, I'm still stuck. can't believe that I'm the first person to try to read NMEA strings with a teensy. So the question must be so trivial that its not worth answering. I've tried using the work arounds on the PJRC site to avoid receive serial blocking by using the DateTime library to synch with a pc, but the library link loads a library that gives compile errors. I don't have a pc connected to the teensy so this was done in desperation to try to learn if this could really be the problem.
    My usbotg host is a Kobo reader running LK8000, it has a serial terminal included
    I would really appreciate help from someone who is able to read 200 characters at 38400 over usb in less than 200 milli-sec!

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,288
    Do you have copies of the expected incoming data?

    Can you reproduce the problem using only the Arduino Serial Monitor on a PC or Mac, where you send "send" button in the serial monitor to transmit the data.

  4. #4
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,163
    Quote Originally Posted by andydasmith View Post
    Hi, this is my first post, I've been searching all day for an answer to what must be a very simple problem without success so here goes.
    Copy and paste does never help.
    The program was so full of bugs - I tried to fix them but, sorry, it was faster to write a new one.
    Code:
    const int numChars = 200;
    char receivedChars[numChars + 1]; // an array to store the received data
    long t;
    int ndx = 0;
    const char endMarker = '\n';
    
    void setup() {
      //Serial.begin(38400); //<- pointless, not needed
      while (!Serial); // wait for PC to init usb-connection
      Serial.println("<Arduino is ready>");
    }
    
    void loop() {
      char rc;
      if (Serial.available()) {
        if (ndx == 0) t = micros();
        rc = Serial.read();
        if (rc == endMarker) {
          t = micros() - t;
          Serial.print("Received this:");
          Serial.println(receivedChars);
          Serial.print("in ");
          Serial.print(t);
          Serial.println(" microseconds.");
          ndx = 0;
        }
        else if (ndx < numChars) {
          receivedChars[ndx] = rc;
          receivedChars[ndx + 1] = 0;
          ndx++;
        }
      }
    }
    I don't say mine is bug-free - but, at least, it works
    And yes, the teensys are much faster than a 8bit arduino. I had to use microseconds, because it needs less than 1 millisecond on a T3.2
    Try to practice a little more with simpler programs, and take time to find and fix the problems in your version before you claim that Teensys are slow next time.

    Don't forget to set the Arduino Monitor to send NL (Newline)

    Edit: The previous version stored the newline in the array - i think you don't want that. i've put the new version here.
    Last edited by Frank B; 02-07-2020 at 06:57 PM. Reason: NL reminder

  5. #5
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,163
    Quote Originally Posted by andydasmith View Post
    at 38400 over usb
    Usb on teensy is always the highest possible speed. You can write Serial.begin(3); and it is still faster than 38400.

  6. #6
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    Hi, thanks for the suggestions. I've tried the code and it shows much faster read times but still has the same problem of dropping complete NMEA sentences.
    I'm reading 4 sentences of about 65 characters. With the teensy 3.1 or LC I always miss the 3rd sentence. This happens with my original code, the code I included in my post and the code kindly suggested by Frank B.
    My first thought was that it must be the serial buffer overflowing in the teensy and there would be a simple fix (64 bytes obviously can't hold my 5 GPS messages). Lots of searching on the internet and in this forum didn't turn anything up on changing the size of the buffer so I asked this question. Subsequent searches have come up with a possible modification of the Wire library for I2c communication (https://forum.pjrc.com/threads/45379...ase-Teensy-3-2) but I don't think this is relevant in my case.
    I'm trying to read 4 sentences with around 65 characters separated by returns (/n) over the usb port transmitted once per second. The code works perfectly on the arduino Nano so I'm trying to find how to configure the teensy so it can do the same job. If I can make it work I can take advantage of the additional capability the teensy offers.
    I'm sure I can't be the first person to read GPS data over teensy usb.

    $GPRMC,135833.00,A,5128.66840,N,00235.80440,W,0.95 0,,090220,,,A*66
    $GPGGA,135833.00,5128.66840,N,00235.80440,W,1,05,2 .51,52.0,M,48.6,M,,*71
    $GPGSA,A,3,17,24,19,10,32,,,,,,,,3.93,2.51,3.02*04
    $PFLAU,0,1,2,1,0,0,2,0,2147483647*68
    $GPRMC,135834.00,A,5128.66856,N,00235.80437,W,0.33 9,,090220,,,A*63
    $GPGGA,135834.00,5128.66856,N,00235.80437,W,1,05,2 .51,52.4,M,48.6,M,,*75
    $GPGSA,A,3,17,24,19,10,32,,,,,,,,3.93,2.51,3.02*04

    3rd sentence $GPGSA is always missing

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,288
    Asking again, can you try just sending a copy of the 5 GPS messages to Teensy using the Arduino Serial Monitor?

    The idea is to figure out whether this problem really is something wrong with the code on Teensy, which does the same wrong thing regardless of whether the USB host is your computer or that LK8000 product.

    If it works with a PC but not with LK8000, then pouring a lot of effort into buffer sizes and other work on Teensy probably isn't worthwhile. Then the question is what's different between the two hosts, if both send the same data but different things happen when Teensy runs the same code.

  8. #8
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    Sorry Paul, I was adding this while you sent your reply. Thanks for your help

  9. #9
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,163
    Can you show the code you are using?

    It can't be just echoing the input. Or, what does the LK8000 do with the echoed characters?

  10. #10
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    The messages here are the 4 when the system is at its basic mode
    $GPRMC,135833.00,A,5128.66840,N,00235.80440,W,0.95 0,,090220,,,A*66
    $GPGGA,135833.00,5128.66840,N,00235.80440,W,1,05,2 .51,52.0,M,48.6,M,,*71
    $GPGSA,A,3,17,24,19,10,32,,,,,,,,3.93,2.51,3.02*04
    $PFLAU,0,1,2,1,0,0,2,0,2147483647*68
    $GPRMC,135834.00,A,5128.66856,N,00235.80437,W,0.33 9,,090220,,,A*63
    $GPGGA,135834.00,5128.66856,N,00235.80437,W,1,05,2 .51,52.4,M,48.6,M,,*75
    $GPGSA,A,3,17,24,19,10,32,,,,,,,,3.93,2.51,3.02*04

    An additional 2 messages are added as the device detects additional targets, again the nano has no problem dealing with these

  11. #11
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    LK8000 receives the NMEA stream and has the capability to pass it through for use by connected usb devices
    LK8000 runs on a Kobo linux as host.
    I have the teensy and the GPS source connected to two terminal of an MTT usb hub

  12. #12
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,163
    II wrote your GPS data to a textfile, opened a Serial Terminal Program (I used Coolterm) and sent the file to the teensy.
    The output is as expected:
    Code:
    <Arduino is ready>
    Received this:$GPRMC,135833.00,A,5128.66840,N,00235.80440,W,0.95 0,,090220,,,A*66
    in 244 microseconds.
    Received this:$GPGGA,135833.00,5128.66840,N,00235.80440,W,1,05,2 .51,52.0,M,48.6,M,,*71
    in 266 microseconds.
    Received this:$GPGSA,A,3,17,24,19,10,32,,,,,,,,3.93,2.51,3.02*04
    in 182 microseconds.
    Received this:$PFLAU,0,1,2,1,0,0,2,0,2147483647*68
    in 128 microseconds.
    Received this:$GPRMC,135834.00,A,5128.66856,N,00235.80437,W,0.33 9,,090220,,,A*63
    in 235 microseconds.
    Received this:$GPGGA,135834.00,5128.66856,N,00235.80437,W,1,05,2 .51,52.4,M,48.6,M,,*75
    in 260 microseconds.
    Received this:$GPGSA,A,3,17,24,19,10,32,,,,,,,,3.93,2.51,3.02*04
    in 182 microseconds.
    Nothing is missing. So - either your device is not sending what you think - or it has problems displaying the the text (maybe the device is too slow?) - or you modified the sketch.
    Again, it would be useful to know *why* you send the gps back? (I suspect you don't and use an *unknown* other Sketch)

  13. #13
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    I've isolated the problem by replacing my teensy code with that suggested by Frank B above. All three code approaches I've tried behave the same way, third sentence is dropped

  14. #14
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,163
    Quote Originally Posted by andydasmith View Post
    the nano has no problem dealing with these
    Maybe the receiving device is too slow to handle the Teensy incomming messages.
    You could try to add delays.

  15. #15
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,163
    Please do a test: Increase the buffer in my code to 300 - what happens?

  16. #16
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    Thanks, I can try compiling a pc version of LK8000 and running that as host in place of the Kobo. I'll let you know how I get on

  17. #17
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    Hi Frank, I did try
    const int numChars = 2000;
    but there was no change

  18. #18
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,163
    next test: add a delay :
    Code:
    const int numChars = 200;
    char receivedChars[numChars + 1]; // an array to store the received data
    long t;
    int ndx = 0;
    const char endMarker = '\n';
    
    void setup() {
      //Serial.begin(38400); //<- pointless, not needed
      while (!Serial); // wait for PC to init usb-connection
      Serial.println("<Arduino is ready>");
    }
    
    void loop() {
      char rc;
      if (Serial.available()) {
        if (ndx == 0) t = micros();
        rc = Serial.read();
        if (rc == endMarker) {
          t = micros() - t;
          Serial.print("Received this:");
          Serial.println(receivedChars);
          Serial.print("in ");
          Serial.print(t);
          Serial.println(" microseconds.");
          ndx = 0;
          delay(100);
        }
        else if (ndx < numChars) {
          receivedChars[ndx] = rc;
          receivedChars[ndx + 1] = 0;
          ndx++;
        }
      }
    }
    What happens?

    (edit: you can verify my result if you just use a terminal program which can send a textfile - you'll see, everything works)

  19. #19
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    Just tried
    const int numChars = 300;
    no luck

  20. #20
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,163
    That 300 was just to check if the lineending is really "\n" ;-) the output would be a little different, then
    Try the delay. I suspect your kobo is too slow. maybe try delay(200) and delay(50) too.
    The Teensys can send so fast, that sometimes a PC with Windows has problems to display all..
    Last edited by Frank B; 02-09-2020 at 02:57 PM.

  21. #21
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    Tried the delay, no luck

  22. #22
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,163
    ..i've run out of ideas, if the delay does not help.
    maybe a bug on the kobo or your software. As you've seen above (Terminal-Software) it's not a Teensy problem.

  23. #23
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,163
    Screenshot:
    Click image for larger version. 

Name:	2020-02-09 16_00_39-Start.png 
Views:	6 
Size:	38.9 KB 
ID:	19005
    Nothing is missing.
    The data was send with the "send file" function - so, as fast as possible.

  24. #24
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,085
    Sorry, I am unsure from all of the descriptions on where the problem is? Is it the Teensy is not receiving the data or the data output from the Teensy is not seen on the other end?
    Also it might help to know which version of Arduino, which version of Teensyduino...

    If it were me, I would probably try a few more things. Again from everything I have seen I think it should already work like Frank has it...

    But a few things I would try slightly different to see if you get any more hints...
    Code:
    const int numChars = 200;
    char receivedChars[numChars + 1]; // an array to store the received data
    long t;
    int ndx = 0;
    int line_number = 0;
    const char endMarker = '\n';
    
    void setup() {
      //Serial.begin(38400); //<- pointless, not needed
      while (!Serial); // wait for PC to init usb-connection
      Serial.println("<Arduino is ready>");
    }
    
    void loop() {
      char rc;
      if (Serial.available()) {
        if (ndx == 0) t = micros();
        rc = Serial.read();
        if (rc == endMarker) {
          t = micros() - t;
          line_number++;
          Serial.print(line_number, DEC);
          Serial.print(" Received this:");
          Serial.println(receivedChars);
          Serial.print("in ");
          Serial.print(t);
          Serial.println(" microseconds.");
          ndx = 0;
          //delay(100);
          Serial.flush();  // See if forcing one line out helps? 
        }
        else if (ndx < numChars) {
          receivedChars[ndx] = rc;
          receivedChars[ndx + 1] = 0;
          ndx++;
        }
      }
    }
    The main changes is that keep a running line number so if you see output line 2 followed by line 4, you know the teensy tried to output line 3 earlier...

    Also added Serial.flush(), as to force out each line without a delay...

    Again I don't imagine that this would make much of a difference, but that is some of the next steps I would take.

  25. #25
    Junior Member
    Join Date
    Feb 2020
    Posts
    16
    Tried the delay, no luck

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •