Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 17 of 17

Thread: T3: Can't get serialEvent3 to work

  1. #1
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,108

    T3: Can't get serialEvent3 to work

    I've set up my Adafruit GPS on Serial3 and have TinyGPS parsing the NMEA sentences when I use Serial3.available() in loop().
    I tried changing the code so that it used serialEvent3 to read the chars from the GPS but the serialEvent3 function is never executed.
    In the code below the BASIC_TEST shows that the GPS is sending data.
    If serialEvent3 executes it should light LED13 and print the chars to Serial but nothing happens.

    How do I get that to work?

    Pete

    Code:
    // tiny_gps_event
    // Use serial event to read Serial3 and pass the characters
    // to the TinyGPS code. When it indicates a decoded NMEA sentence
    // print some info.
    
    #include "TinyGPS.h"
    TinyGPS gps;
    
    int string_complete = false;
    
    void setup(void)
    {
      Serial.begin(115200);
      while(!Serial);
      Serial3.begin(9600);
      pinMode(13,OUTPUT);
      
    }
    void loop()
    {
      int c;
      long lat, lon;
      int year;
      byte month, day, hour, minute, second, hundredths;
    
      unsigned long fix_age, time, date, speed, course;
    
      char ostring[128];
    
    //#define BASIC_TEST
    #ifdef BASIC_TEST
    // See if there's anything at all coming from the GPS
      while(Serial3.available()) {
       Serial.write(Serial3.read());
      }
    return; 
    #endif
      // Just give up if we haven't got a complete string yet
      if(!string_complete)return;
    
      // Now decode and print the info
    //  string_complete = false;
      gps.crack_datetime(&year, &month, &day,
          &hour, &minute, &second, &hundredths, &fix_age);
      sprintf(ostring,"%04d/%02d/%02d %02d:%02d:%02d.%02d",
                      year,month,day,hour,minute,second,hundredths);
      Serial.print(ostring);
      // retrieves +/- lat/long in 100000ths of a degree
      gps.get_position(&lat, &lon, &fix_age);
      sprintf(ostring," %d %d (%d)",lat,lon,fix_age);  
      Serial.println(ostring);
    }
    
    
    /*
      SerialEvent3 occurs whenever a new data comes in the
     hardware serial RX.  This routine is run between each
     time loop() runs, so using delay inside loop can delay
     response.  Multiple bytes of data may be available.
     */
    
    void serialEvent3() {
      char c;
    
      while (Serial3.available()) {
        digitalWrite(13,1);
        // get the new byte:
        c = (char)Serial3.read();
    // debug
    Serial.write(c); 
        if(gps.encode(c)) {
          string_complete = true;
        }
        return;
      }
    //  digitalWrite(13,0);
    }

  2. #2
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    Code:
    #include <TinyGPS.h>                      // Uses serial port 3 hardware UART for NEMA decode.
    
    // globals variables
    byte GPS_Hour; // GPS GMT <---<<<<<
    byte GPS_Minute;
    byte GPS_Second;
    byte GPS_DOW;     // Sun = 7 
    byte GPS_Hdrds; // not used?
    byte GPS_Day;
    byte GPS_Month;
    int  GPS_Year;
    long GPS_Unix_Local;
    long GPS_Unix_GMT;
    long GPS_DIFF;
    
    
    // Instanciate ....
    TinyGPS gps;
    
    
    void setup(){
     Serial3.begin(9600); // Adafruit Ultimate GPS
    }
    
    
    void loop(){
    // call poll GPS - uncomment the print statements
    poll_GPS(); 
    }
    
    void poll_GPS(void){
      // from simple test TinyGPS <---------------<<<<<<<<<<<<<<<<
      bool newData = false;
      unsigned long chars;
      unsigned short sentences, failed;
      unsigned long t = 0;
    
      // For one second we parse GPS data and report some key values
      for (unsigned long start = millis(); millis() - start < 1000;) //<-------<<<<< Min of 1 sec poll needed !!!!
      {
    
        while (Serial1.available())
        {
          char c = Serial3.read();
          //Serial3.write(c); // uncomment this line if you want to see the GPS data flowing
          if (gps.encode(c)) // Did a new valid sentence come in?
            newData = true;
    
        }
      }
    
      if (newData)
      {
        float flat, flon;
        int gps_yr;
        unsigned long age;
        byte gps_mon, gps_day, gps_hour, gps_minute, gps_second, gps_hundredths;
        unsigned long gps_fix_age;  
    
    
        gps.f_get_position(&flat, &flon, &age);
        gps.crack_datetime(&gps_yr, &gps_mon, &gps_day, &gps_hour, &gps_minute, &gps_second, &gps_hundredths, &gps_fix_age);
    
    
        GPS_LAT = flat;
        GPS_LONG = flon;
    
        GPS_Hour = gps_hour; // GMT
        GPS_Minute = gps_minute;
        GPS_Second = gps_second;
        GPS_Hdrds = gps_hundredths;
    
        GPS_Month = gps_mon;
        GPS_Day = gps_day;    
        GPS_Year = gps_yr;
    
        // compute unix time GMT
        //hh = GPS_Hour; 
        //mm = GPS_Minute; 
        //ss = GPS_Second; 
    
        //d = GPS_Day; 
        //m = GPS_Month; 
        //yOff = GPS_Year;
    
        //GPS_DOW = dayOfWeek();
    
        //t = unixtime();
        //GPS_Unix_GMT = t;
        //Serial.print("GPS Unix GMT = ");
        //Serial.println(GPS_Unix_GMT, DEC);
    
        //Calculate_TZ_DST();
    
        //if (TZ == -4){
          //GPS_Unix_Local = GPS_Unix_GMT - 14400; 
        //}    
        //if (TZ == -5){
          GPS_Unix_Local = GPS_Unix_GMT - 18000;
       // } 
        //Serial.print("GPS Unix GMT Local = ");   
        //Serial.println(GPS_Unix_Local, DEC);
    
    
    
        //Serial.print("Day of Week Sun-->7 DOW = ");
        //Serial.println(GPS_DOW, DEC);
    
    
        //Serial.print("LAT=");
        //Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
        //Serial.print(" LON=");
        //Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
        //Serial.print(" SAT=");
        //Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
        //Serial.print(" PREC=");
        //Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
        //Serial.println(" ");
        //Serial.print("GPS Date= ");
        //Serial.print(gps_mon == TinyGPS::GPS_INVALID_DATE ? 0 : gps_mon);
        //Serial.print("/");
        //Serial.print(gps_day == TinyGPS::GPS_INVALID_DATE ? 0 : gps_day);
        //Serial.print("/");
        //Serial.print(gps_yr == TinyGPS::GPS_INVALID_DATE ? 0 : gps_yr);
        //Serial.print("GPS Time= ");
        //Serial.print(gps_hour == TinyGPS::GPS_INVALID_TIME  ? 0 : gps_hour);
        //Serial.print(":");
        //Serial.print(gps_minute == TinyGPS::GPS_INVALID_TIME  ? 0 : gps_minute);
        //Serial.print(":");
        //Serial.print(gps_second == TinyGPS::GPS_INVALID_TIME  ? 0 : gps_second);
      }
    
      //gps.stats(&chars, &sentences, &failed);
      //Serial.print(" CHARS=");
      //Serial.print(chars);
      //Serial.print(" SENTENCES=");
      //Serial.print(sentences);
      //Serial.print(" CSUM ERR=");
      //Serial.println(failed);
    
    }
    //----------------------------------------------------------------------------------------
    Last edited by t3andy; 01-23-2013 at 02:10 AM.

  3. #3
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,108
    Yeah, as I mentioned, my code works when I just poll Serial3.available in the loop() (or called from there as in your code).

    But, in theory, serialEvent3() should be called (like an interrupt routine/callback) whenever data is received at the Serial3 port and then in there I can read whatever has been received. This would allow a program to do the NMEA reading and parsing in the background.

    Hmmm. I haven't actually tried plain old serialEvent() to see if that works.

    Pete

  4. #4
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,108
    Ah, the serialEvent example doesn't seem to work either. Perhaps Paul hasn't got around to that yet?

    Pete

  5. #5
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    // For one second we parse GPS data and report some key values
    for (unsigned long start = millis(); millis() - start < 1000 //<-------<<<<< Min of 1 sec poll needed !!!!
    {
    I found polling anything less than 1 second gives unstable values?
    My function is "blocking" and until 1 second of polling is up nothing else can be done.

    The other alternatives is to have an interrupt driven routine to work just like the Adafruit GPS library created for the Arduino but they used AVR timers and interrupts which the T3 does not have. The interrupts on the T3 are not fully complete due to the fact that on the K20 there are a lot of them. (work in progress by P S)

    Another alternative is to go to a RTOS and have it do the dirty work of background polling.
    Its a shame to wait 1 second for a NEMA poll to finish on the Teensy 3.

    BTW ... @el_supremo if you come up with a faster solution please do post your code!
    Last edited by t3andy; 01-23-2013 at 03:21 AM.

  6. #6
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,108
    I had a closer look through the code and, if I read it correctly, serialEvent isn't implemented in Teensy3 yet.

    Pete

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,174
    Opps.... yup, I didn't implement serialEvent.

    I've just added it to my TO-DO list, which doesn't mean I'll get it done soon, but at least I won't forget.

  8. #8
    Junior Member
    Join Date
    Feb 2013
    Posts
    12
    Was about to create new forum post, be here are same issue, serialEvent doesn't fire.
    Looking forward to see this code implemented.

  9. #9
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    Opps.... yup, I didn't implement serialEvent.
    I've just added it to my TO-DO list, which doesn't mean I'll get it done soon, but at least I won't forget.
    @Paul ... Is serialeventx() working ?

  10. #10
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,174
    No. I haven't implemented any of the serialevent stuff. It's on my todo list....

  11. #11
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    01-24-2013
    You must have one long todo list with priority interrupts

  12. #12
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,174
    Yes indeed, my todo list is VERY long. Some stuff has been on there for many years (like the unsigned windows driver problem). Truth is, answering questions and day-to-day business, especially the more technical stuff Robin & Erin can't do, generally trumps development.

    Then my development time gets split between filling in features (eg, all the stuff to soon be released as 1.17), developing new stuff (like the audio library), fixing/porting libraries, and sometimes even a little work towards new products. On extremely rare occasions, I even work a little on the website.

    In terms of priorities, so far it seems like relatively few people really use the serial event stuff. It's also very simple to work around with a just a couple lines of code at the beginning of loop(). Both those factors keep it a lower priority than many other things.

  13. #13
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    @Paul

    In terms of priorities, so far it seems like relatively few people really use the serial event stuff. It's also very simple to work around with a just a couple lines of code at the beginning of loop().
    OK, patch this with your "couple lines of code" without the serialEvent function

    // Application using serialEvent for serial GPS Nema (background) processing and serial callbacks like in SimpleHMI

    String inputString = ""; // a string to hold incoming data
    boolean stringComplete = false; // whether the string is complete

    void setup() {
    // initialize serial:
    Serial.begin(9600);
    // reserve 200 bytes for the inputString:
    inputString.reserve(200);
    }

    void loop() {
    // print the string when a newline arrives:
    if (stringComplete) {
    Serial.println(inputString);
    // clear the string:
    inputString = "";
    stringComplete = false;
    }
    }

    /*
    SerialEvent occurs whenever a new data comes in the
    hardware serial RX. This routine is run between each
    time loop() runs, so using delay inside loop can delay
    response. Multiple bytes of data may be available.
    */
    void serialEvent() { //<---------------<<<<<<<<<<
    while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
    stringComplete = true;
    }
    }
    }

  14. #14
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    I rate serial.event as high... for things like talking to Xbees and so on via libraries. Polling loop is hard to do within a library.

  15. #15
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,174
    I have a plan for serialEvent that will be much better than Arduino's simple check after loop() runs, and will also avoid interrupt context. But it's a lot more than just 2 simple lines.....

  16. #16
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    Right... as in an RTOS which would not want to poll...
    serial.event is supposed to be an ISR based thing. Signals that the receive buffer is not empty or transmit buffer is empty, etc. Function of course needs to do something very simple and return.

  17. #17
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    I have a plan for serialEvent that will be much better than Arduino's simple check after loop() runs, and will also avoid interrupt context. But it's a lot more than just 2 simple lines.....
    Anything is better than nothing ... go for it.


    You must have one long todo list with priority interrupts
    Now we know, your priority interrupt was Teensy 3.1
    Last edited by t3andy; 12-13-2013 at 08:43 PM.

Posting Permissions

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