T3: Can't get serialEvent3 to work

Status
Not open for further replies.

el_supremo

Well-known member
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);
}
 
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);

}
//----------------------------------------------------------------------------------------
:cool:
 
Last edited:
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
 
Ah, the serialEvent example doesn't seem to work either. Perhaps Paul hasn't got around to that yet?

Pete
 
// 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:
I had a closer look through the code and, if I read it correctly, serialEvent isn't implemented in Teensy3 yet.

Pete
 
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.
 
Was about to create new forum post, be here are same issue, serialEvent doesn't fire.
Looking forward to see this code implemented.
 
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 ?
 
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.
 
@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;
}
}
}
 
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.
 
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.....
 
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.
 
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:D
 
Last edited:
Status
Not open for further replies.
Back
Top