Teensy 3.X Hardware Serial Elapsed Time Problem

Status
Not open for further replies.

EVL

Member
Having timing problems with Teensy 3.2 hardware serial and XBEE radios. The remote control unit with an XBEE device transmits a 17 character string representing longitudinal and lateral commands, and the Teensy paired with it's own XBEE receives and parses the string. Example:

Code:
 $  3827  1813  #

The remote control shoots that message when the Teensy 3.2 sends a trigger character ("%").

The problem is timing. If each loop is programmed to pause for 5,000 microseconds, the Teensy does not receive the string. In contrast, all works perfectly fine with 10,000 microseconds. However, when I check how long it takes to receive and parse the 17 character message with the micros() function, it only takes ~90 microseconds, far less than the extra 5,000 microsecond pause needed to make it work. Does micros() count hardware serial events? Is there a lag associated with the Serial commands?

The problem persists with a Teensy 3.5. Here's the complete Teensy receiver code:

Code:
#define   HWSERIAL      Serial4
#define   NSERIAL       12        // No. of chances to receive message
#define   NPHRASE       17        // Length of message
#define   NAVAIL        17        // Wait until NAVAIL bytes in buffer
#define   NXBEE_RETRY   5

char      phrase[NPHRASE];  // Controller message string
int       xbee_dropout=0;
int       adc_raw_long;     // Controller value - longitudinal
int       adc_raw_lat;      // Controller value - lateral


void serial_comm()
{

    boolean  xbee_available=0;    
    char     serial3char=' ';
    int      ii, signx, hitc;


    // SEND HANDSHAKE - TRIGGER REMOTE CONTROL
    //----------------------------------------------
    HWSERIAL.print('%');
    delayMicroseconds(50);

 
    //  GIVE SERIAL BUFFER A CHANCE TO RECEIVE MESSAGE
    //-------------------------------------------------
    ii=0;
    while (ii<NSERIAL && xbee_available==0)
    {
        ii++;          
        if (HWSERIAL.available() >= NAVAIL )  xbee_available = 1;                    
    }

       
    //  PARSE MESSAGE
    //----------------------
    if (xbee_available)
    {   
        xbee_dropout = 0;
             
        for (ii=0; ii<NPHRASE; ii++)   phrase[ii]=' ';   // Initialize phrase variable
        
        ii   =  0;
        hitc = -1;   
        while (hitc<NPHRASE  &&  serial3char != '#')
        {
            ii++;
            serial3char = HWSERIAL.read();

            if (serial3char == '$')  hitc = 0;
            if (serial3char == '#')  hitc = -1;

            if ( hitc >=0 )
            {
                phrase[hitc] = serial3char;
                hitc++;
            }            
        }        

        sscanf(phrase+1, "%d %d", &adc_raw_long, &adc_raw_lat);   // Read controller string
    }
    else
    {
        xbee_dropout++;
    }


    // AFTER SO MANY DROPOUTS, RESET CONTROLLER VARIABLES
    //-------------------------------------------------------
    if (xbee_dropout > NXBEE_RETRY ) 
    { 
        adc_raw_long = 0;
        adc_raw_lat  = 0;
    }
    
}


void setup() 
{
    long  time0, time1, dt;

    Serial.begin(115200); 
    HWSERIAL.begin(115200);

    delayMicroseconds(4000000);
 
    for (int ii=0; ii<12000; ii++)
    {
        time0 = micros();

        serial_comm();

        Serial.print(adc_raw_long);
        Serial.print(" ");
        Serial.print(adc_raw_lat);
        Serial.print(" ");
        
        time1 = micros();
        dt    = time1 - time0;
        
        Serial.println(dt);

      //delayMicroseconds(5000);    // Doesn't work.
        delayMicroseconds(10000);   // Works correctly
    }

    Serial.println("Program Done.");
}


void loop()
{

}

The command sender is an Arduino Due board with the same XBEE model. BAUD rate for all boards and all XBEE devices is set at 115,200.
 
Transmitting 17 characters at 115200 takes around 1500 ms ( 9ms/bit*10 bits/char (with start and stop)*17 ), from the sender to the transmitting XBEE, then at least that long time over the radios, and also from the receiving XBee to your Teensy. Then add the time to send the single trigger character the other way plus the time to prepare the data message. So a time larger than 5000 is not unrealistic.

The 90 ms you measure for serial_comm() is the time to grab the incoming results already in the receiver buffer in response to your previous trigger character.
 
Last edited:
Transmitting 17 characters at 115200 takes around 1500 ms ( 9ms/bit*10 bits/char (with start and stop)*17 ), from the sender to the transmitting XBEE...
The 90 ms you measure for serial_comm() is the time to grab the incoming results already in the receiver buffer in response to your previous trigger character.

I think you meant 1500 microseconds, but yes, your explanation makes sense. The micros() function cannot count events associated with the wireless communication, which occur independently from the Teensy 3.X. By the time the Teensy is ready to receive & parse the message, either the message is there or not.

The 1500 microsec transmit time is not as bad as I thought because it's an independent event, and my Teensy will be doing other control system operations during that time which will take longer.

My production program uses an IntervalTimer object that samples every 10,000 microsec, so that'll accommodate independent operations. Just have to make sure the transmittal time is always less than the control system operation time.
 
Status
Not open for further replies.
Back
Top