Serial Communication between two teensy 4.1

ajc225

Active member
Hi
I'm new to Serial communication. I've been trying to send encoder and current information between two teensys using Serial 6 and 7. I test the code using one teensy and it worked at any speed. However when I use two teensys the packets of information that I send start to shift at frequencies higher than 100Hz. I've been using USB serial to monitor what is being sent. I have no idea why the info shifts at higher frequencies. I've attached the code. It is the same between two the two teensys, I just switch the channels used in my send and receive functions. View attachment read_test2.ino
 
Code:
#define CH2 Serial7
#define CH1 Serial6

/* Data Type to be sent received */
struct dataType {
    float vPos, hPos, vCurrent, hCurrent;
};

dataType a, i;   // Variables to hold the data for Send/Receive

//placeholder for information getting sent
float ivpos = 0.10, ihpos = 0.20, ivcurrent = 0.0, ihcurrent = 0.0;
float avpos = 0.50, ahpos = 0.70, avcurrent = 0.29, ahcurrent = 0.35;


void setup() {

    // Initialize serial interface
    Serial.begin(9600);
    CH2.begin(115200);
    CH1.begin(115200);

    // Wait until the serial interfaces are active
    while (!Serial && millis()<5000);  // Wait for Serial (USB) to become active
//    while (!CH2);
//    while (!CH1);
    Serial.println("Serial ports active");

    //  InterfaceTime.begin(ReceivePacket, 5000);
    //  AvatarTime.begin(SendPacket, 5000);

}



void loop() {
   delay( 1000 ) ;   // Don't want to swamp the other Teensy

// Put data into variable a for sending.
    a.vPos = avpos;
    a.hPos = ahpos;
    a.vCurrent = avcurrent;
    a.hCurrent = ahcurrent;

/*  SendPacket */
    CH2.write((uint8_t*) &a, sizeof(a));    //Send the data

    if (CH1.available() >= sizeof(i)) {       // Wait for complete data received
/*        ReceivePacket */
        CH1.readBytes((uint8_t*) &i, sizeof(i));   // Get the data from Serial Buffer
        delay(10);
        Serial.print(i.vPos);
        Serial.print(" , ");
        Serial.print(i.hPos);
        Serial.print(" , ");
        Serial.print(i.vCurrent);
        Serial.print(" , ");
        Serial.print(i.hCurrent);
        Serial.println("    <--- Read packet.");
        Serial.println();
    }
  }
You could give the code above a try. It does compile, though I must admit that I have not tried it.
 
This might be the problem:
Code:
  sprintf ( outgoingBytes , "s,%2.4f,%2.4f,%2.4f,%2.4f,e" , var1 , var2 , var3 , var4 ) ;
The format specifiers aren't right. %2.4f means that the whole field is two characters long and there are four digits after the decimal point.
If the integer part can be over 100, then the specifiers would each have to be at least %8.4f. If the integer can be in the thousands, it would have to be %9.4f.
Either way, you'll have to make the character array larger:
Code:
  char outgoingBytes[50] ;
and the same in the receiving end:
Code:
  char incomingBytes[50] ;

Pete
 
I think you need to wait until all the characters have been received:

Code:
void ReceivePacket () {

  char incomingBytes[35] ;

  // Check if data is available
  if ( CH1.available() ) {              [COLOR="#FF0000"]Will be true even if less than 35 characters received.  Perhaps CH1.available >= 35 would test if this is the issue
                                              but really you should be checking the s, start characters and ,e end characters of the string for valid data.[/COLOR]

    // Read bytes into char array
    for ( unsigned int i = 0 ; i < sizeof ( incomingBytes ) ; i++ ) {
      incomingBytes[i] = CH1.read() ;                                         [COLOR="#FF0000"] returns -1 if character not available[/COLOR]
      if ( DEBUG ) Serial.print ( incomingBytes[i] ) ;
    }


Also you have a data buffer overrun on writing the string as sprintf terminates the string with a zero.


edit: I now see the BriComp post also shows the need to wait for the complete string to be received.
 
Thanks for the code and help! I added some usb serial prints so I can see both what I'm sending and reading. I also am trying to have the data send super fast (around 10kHz) so I got rid of the delays, but for some reason one of the teensy still reads the packet incorrectly. This is the biggest problem I seem to be running into where, either one or both teensy seem to read the packets all shifted. Sometimes I'm able to unplug and replug the teensys at the same time and it fixes it but not all the time. So I'm worried that when I add in the other processes to the code, the messages will send all scrambled.

This is with the new code.

Teensy 1.jpgteensy 2.jpg


and when I try editing my original code it seemed to make no difference and this is what happens.
original teensy 1.jpgoriginal teensy 2.jpg
 
Last edited:
This is the new code that you suggested. I just added in some prints to the usb and got rid of delays.

View attachment Teensy_1.inoView attachment Teensy_2.ino

My original code is the same because the two edits didn't really make a difference.

Code:
#define CH2 Serial7
#define CH1 Serial6

/* Data Type to be sent received */
struct dataType {
  float vPos, hPos, vCurrent, hCurrent;
};


dataType a, i;   // Variables to hold the data for Send/Receive

//placeholder for information getting sent
float ivpos = 0.10, ihpos = 0.20, ivcurrent = 0.0, ihcurrent = 0.0;
float avpos = 0.50, ahpos = 0.70, avcurrent = 0.29, ahcurrent = 0.35;


void setup() {

  // Initialize serial interface
  Serial.begin(9600);
  CH2.begin(115200);
  CH1.begin(115200);

  // Wait until the serial interfaces are active
  while (!Serial && millis() < 5000); // Wait for Serial (USB) to become active
  //    while (!CH2);
  //    while (!CH1);
  Serial.println("Serial ports active");

  //  InterfaceTime.begin(ReceivePacket, 5000);
  //  AvatarTime.begin(SendPacket, 5000);

}



void loop() {
//  delay( 10 ) ;   // Don't want to swamp the other Teensy

  // Put data into variable a for sending.
  i.vPos = ivpos;
  i.hPos = ihpos;
  i.vCurrent = ivcurrent;
  i.hCurrent = ihcurrent;

  /*  SendPacket */
  CH1.write((uint8_t*) &i, sizeof(i));    //Send the data
  Serial.print(i.vPos);
  Serial.print(" , ");
  Serial.print(i.hPos);
  Serial.print(" , ");
  Serial.print(i.vCurrent);
  Serial.print(" , ");
  Serial.print(i.hCurrent);
  Serial.println("    <--- Send packet through CH1.");
  Serial.println();

  if (CH2.available() >= sizeof(a)) {       // Wait for complete data received
    /*        ReceivePacket */
    CH2.readBytes((uint8_t*) &a, sizeof(a));   // Get the data from Serial Buffer
//    delay(10);
    Serial.print(a.vPos);
    Serial.print(" , ");
    Serial.print(a.hPos);
    Serial.print(" , ");
    Serial.print(a.vCurrent);
    Serial.print(" , ");
    Serial.print(a.hCurrent);
    Serial.println("    <--- Read packet in CH2.");
    Serial.println();
  }
}


Code:
#define CH2 Serial7
#define CH1 Serial6

/* Data Type to be sent received */
struct dataType {
  float vPos, hPos, vCurrent, hCurrent;
};



dataType a, i;   // Variables to hold the data for Send/Receive

//placeholder for information getting sent
float ivpos = 0.10, ihpos = 0.20, ivcurrent = 0.0, ihcurrent = 0.0;
float avpos = 0.50, ahpos = 0.70, avcurrent = 0.29, ahcurrent = 0.35;


void setup() {

  // Initialize serial interface
  Serial.begin(9600);
  CH2.begin(115200);
  CH1.begin(115200);

  // Wait until the serial interfaces are active
  while (!Serial && millis() < 5000); // Wait for Serial (USB) to become active
  //    while (!CH2);
  //    while (!CH1);
  Serial.println("Serial ports active");

  //  InterfaceTime.begin(ReceivePacket, 5000);
  //  AvatarTime.begin(SendPacket, 5000);

}



void loop() {
  //   delay( 10 ) ;   // Don't want to swamp the other Teensy

  // Put data into variable a for sending.
  a.vPos = avpos;
  a.hPos = ahpos;
  a.vCurrent = avcurrent;
  a.hCurrent = ahcurrent;

  /*  SendPacket */
  CH2.write((uint8_t*) &a, sizeof(a));    //Send the data
  Serial.print(a.vPos);
  Serial.print(" , ");
  Serial.print(a.hPos);
  Serial.print(" , ");
  Serial.print(a.vCurrent);
  Serial.print(" , ");
  Serial.print(a.hCurrent);
  Serial.println("    <--- Send packet through CH2.");
  Serial.println();

  if (CH1.available() >= sizeof(i)) {       // Wait for complete data received
    /*        ReceivePacket */
    CH1.readBytes((uint8_t*) &i, sizeof(i));   // Get the data from Serial Buffer
//    delay(10);
    Serial.print(i.vPos);
    Serial.print(" , ");
    Serial.print(i.hPos);
    Serial.print(" , ");
    Serial.print(i.vCurrent);
    Serial.print(" , ");
    Serial.print(i.hCurrent);
    Serial.println("    <--- Read packet in CH1.");
    Serial.println();
  }
}
 
Last edited by a moderator:
I believe you should try EasyTransfer. In Arduino, click File > Examples > EasyTransfer_TX_Example and also File > Examples > EasyTransfer_RX_Example.

Edit those examples to use Serial6 or Serial7 as needed. They are written with just "Serial" so they can work on boards like Arduino Uno which don't have extra serial ports. Obviously on Teensy you would use Serial1 to Serial8, since "Serial" talks to your PC by USB.
 
Been Playing around with this on and off all day.
Finally found my STUPID mistake and working fine now.
Works at 230400 baud.
Boy does it FLY!
Code:
/************************
     Send and Receive Code
************************/

#define RxD Serial7
#define TxD Serial6

#define baud 230400 //115200

#pragma pack(push,1)

/* Data Type to be sent received */
struct dataType {
    uint32_t dataIdx;
    float vPos, hPos, vCurrent, hCurrent;
};

dataType tx, rx;   // Variables to hold the data for Send/Receive
#pragma pack(pop)

//placeholder for information getting sent
float ivpos = 0.10, ihpos = 0.20, ivcurrent = 0.0, ihcurrent = 0.0;
float avpos = 0.50, ahpos = 0.70, avcurrent = 0.29, ahcurrent = 0.35;

void ClearSerialBuffers() {
    TxD.flush();
    RxD.clear();
    delay(1000);
    TxD.flush();
    RxD.clear();
}

void setup() {

    // Initialize serial interface
    Serial.begin(9600);
    RxD.begin(baud);
    TxD.begin(baud);

    pinMode(LED_BUILTIN, OUTPUT);
    // Wait until the serial interfaces are active
    while (!Serial && millis() < 5000);  // Wait for Serial (USB) to become active
    Serial.println("Serial ports active:");
    Serial.println("     Sending on Serial6 Tx, Receiving on Serial 7 Rx");

    tx.dataIdx = 0;
    ClearSerialBuffers();
    delay(1000);    // Just to allow synch time between T4.1s
}

elapsedMillis timeout;
#define waitTime 5000

void loop() {

    tx.vPos = avpos;
    tx.hPos = ahpos;
    tx.vCurrent = avcurrent;
    tx.hCurrent = ahcurrent;
    tx.dataIdx++;

    /*  SendPacket */
    digitalWriteFast(LED_BUILTIN, HIGH);
    TxD.write((uint8_t*)&tx, sizeof(tx));    //Send the data
    TxD.flush();

    digitalWriteFast(LED_BUILTIN, LOW);

    Serial.print("Sent packet ---->  ");
    Serial.print(tx.dataIdx);
    Serial.print(" , ");
    Serial.print(tx.vPos);
    Serial.print(" , ");
    Serial.print(tx.hPos);
    Serial.print(" , ");
    Serial.print(tx.vCurrent);
    Serial.print(" , ");
    Serial.print(tx.hCurrent);
    Serial.println();

    timeout = 0;

    while ((RxD.available() < sizeof(rx)) && (timeout <= waitTime)) {}       // Wait for complete data received
    /*        ReceivePacket */
    if (timeout >= waitTime) {
        Serial.println("Timeout waiting for Rx Data");
        ClearSerialBuffers();
    }
    else {
        rx.dataIdx = 0;
        rx.hCurrent = 0;
        rx.hPos = 0;
        rx.vCurrent = 0;
        rx.vPos = 0;

        RxD.readBytes((uint8_t*)&rx, sizeof(rx));   // Get the data from Serial Buffer
        Serial.print("Read packet ---->  ");
        Serial.print(rx.dataIdx);
        Serial.print(" , ");
        Serial.print(rx.vPos);
        Serial.print(" , ");
        Serial.print(rx.hPos);
        Serial.print(" , ");
        Serial.print(rx.vCurrent);
        Serial.print(" , ");
        Serial.print(rx.hCurrent);
        Serial.println();

        if (rx.dataIdx != tx.dataIdx) {
            Serial.println("Lost Packet");
            ClearSerialBuffers();
        }

    }
}
Code:
/*****************************
  Receive and Echo Back Code
******************************/

#define RxD Serial7
#define TxD Serial6
#pragma pack(push,1)

/* Data Type to be sent received */
struct dataType {
    uint32_t dataIdx;
    float vPos, hPos, vCurrent, hCurrent;
};

dataType rx;   // Variables to hold the data for Send/Receive
#pragma pack(pop)

#define baud 230400  //115200

void ClearSerialBuffers() {
    TxD.flush();
    RxD.clear();
    delay(1000);
    TxD.flush();
    RxD.clear();
}

void setup() {

    // Initialize serial interface
    Serial.begin(9600);
    RxD.begin(baud);
    TxD.begin(baud);

    pinMode(LED_BUILTIN, OUTPUT);
    // Wait until the serial interfaces are active
    while (!Serial && millis() < 5000);  // Wait for Serial (USB) to become active
    Serial.println("Serial ports active:");
    Serial.println("     Receiving on Serial7 Rx, Sending on Serial 6 Tx");

    ClearSerialBuffers();

}
void loop() {

    if (RxD.available() >= sizeof(rx)){
 
    /*        ReceivePacket */
        digitalWriteFast(LED_BUILTIN, HIGH);
        rx.dataIdx = 0;
        rx.hCurrent = 0;
        rx.hPos = 0;
        rx.vCurrent = 0;
        rx.vPos = 0;
        RxD.readBytes((uint8_t*)&rx, sizeof(rx));   // Get the data from Serial Buffer
        /*  SendPacket */
        TxD.write((uint8_t*)&rx, sizeof(rx));    //Send the data
        TxD.flush();
        digitalWriteFast(LED_BUILTIN, LOW);

    }
}
 
Back
Top