Problems with Serial1.read(). UART communication with ESP32-S3

AlecF

New member
Hi all.
I work on a project which requires UART communication between a Teensy 4.1 and an ESP32-S3. To be flexible and have some kind of delimiters, i choose 170 as START_BYTE and 255 (must be two times in a row) as END_BYTE. In between those delimiters i send the message in the following format: "Code, Value_byte1, Value_byte2". Code is used, to tell the receiving device, to which variable the value should be assigned. The communication should later be happening both ways, but right know, im stuck with the read function on the teensy. Maybe, someone has an idea:
The Teensy code is as follows. Each byte is stored in a vector, to later handle the values and put together the individual bytes to an int16_t. Sadly, in between the delimiters, i dont receive the correct values. The ESP sends the correct data (at least according to the messages printet in the serial monitor).

void ESPcom::refreshMsg()
{
//Check if something is there to read
if (Serial1.available() > 0)
{
while (true)
{
m_received_byte = Serial1.read();
Serial.printf("Read Byte %d: \n", m_received_byte);

/* Serial.printf("Received Byte: %d Value as Serial.write: ", m_received_byte);
Serial.write(m_received_byte);
Serial.printf("\n");*/

if (m_received_byte == START_BYTE && m_read == false)
{
m_read = true;
Serial.printf("Read START_BYTE: %d\n", m_received_byte);
}

//If the read Byte is not 0xFF
else if (m_read && m_received_byte != END_BYTE)
{
m_Messages_received.push_back(m_received_byte);
Serial.printf("Read msg: %d\n", m_received_byte);
}

else if (m_read && m_end_byte_1 == false && m_received_byte == END_BYTE)
{
m_end_byte_1 = true;
}

//Set m_end_byte_1 to false again because this was just a "full" byte. Push it back,
else if (m_read && m_end_byte_1 == true && m_received_byte != END_BYTE)
{
m_Messages_received.push_back(0xFF);
m_ammount_read_bytes++;
Serial.printf("Read msg (m_end_byte1): %d\n", 0xFF);
m_Messages_received.push_back(m_received_byte);
m_ammount_read_bytes++;
Serial.printf("Read msg (m_end_byte1 false): %d\n", m_received_byte);

m_end_byte_1 = false;
}

//If two END_BYTE in a row, set m_read to false
else if (m_read && m_end_byte_1 == true && m_received_byte == END_BYTE)
{
Serial.printf("Read 2x END_BYTE: %d\n", m_received_byte);
m_read = false;
m_end_byte_1 = false;
break;
}
else
{
break;
}
}
}

}

void TeensyCom::write()
{
uart_write_bytes(UART_NUM_1, &m_start_byte, sizeof(m_start_byte));
printf("Message: %d\n", m_start_byte);
uint8_t msg = 0;

for(int i = 0; i < MsgToSend.size() ; i++)
{
msg = MsgToSend.at(i);
uart_write_bytes(UART_NUM_1, &msg, sizeof(msg));
printf("Message: %d\n", MsgToSend.at(i));
}
//Send two (!) END_BYTE so that the teensy can differentiate between normal msg and end byte
uart_write_bytes(UART_NUM_1, &m_end_byte, sizeof(m_end_byte));
printf("Message: %d\n", m_end_byte);
uart_write_bytes(UART_NUM_1, &m_end_byte, sizeof(m_end_byte));
printf("Message: %d\n", m_end_byte);

MsgToSend.clear();
}
The picture shows, what is send to test the function. START_BYTE (170), code(19), value_byte1(0), value_byte2(100), code(24), value_byte1(1), value_byte2(244), END_BYTE, END_BYTE. Between the delimiters 19, 0, 100, 24 1, 244 is send. The int16_t values are in this case 100 and 500. But the teensy only receives 34, 100, 20 and 244 between the delimiters. Interestingly, the delimiters are read correct.
If someone has an idea why there is this difference, i would very much appreciate the help, i've been trying to find a solution since hours.

Thank you very much
 

Attachments

  • problem_teeny_esp_com.png
    problem_teeny_esp_com.png
    2.3 KB · Views: 20
Thank you very much for your response. I'm quit sure, this all matches. But i'm gonna look again...would be kinda anoying if it would be just that. They're both on the same ground, this should not be the problem.
 
What baud rate? How are they connected? Wires? How long.

How long are the messages, and how long between the time you look for them?
That is Serial1 by default has a software queue of 64 bytes. If you receive more than this before you read the data, data will be lost.

It messages may be longer than this, you might extend the read buffer?
Code:
// Increase the amount of buffer memory between reception of bytes by the
    // serial hardware and the available() and read() functions. This is useful
    // when your program must spend lengthy times performing other work, like
    // writing to a SD card, before it can return to reading the incoming serial
    // data.  The buffer array must be a global or static variable.
    void addMemoryForRead(void *buffer, size_t length);
 
i've been trying to find a solution since hours.

If you're stuck, maybe put some of them time into turning the code samples from msg #1 into self-contained programs anyone can copy into Arduino IDE and upload to a Teensy to reproduce the problem. Perhaps for the transmit side, just write a very simple program which sends an array of bytes, so it could be run on Teensy as well as ESP32.

If you post 2 simple self-contained programs that can both run on Teensy, I'll probably copy them into Arduino IDE and upload to a couple boards here, and then connect my oscilloscope to view the actual communication. But I can't do this with code fragments, especially when they depend on a lot of stuff we can't see like m_Messages_received or MsgToSend. If you instead turn this code into 2 simpler program which anyone can copy into Arduino IDE and upload, I and many others here can probably help much more.
 
This is an ESP32C3 program that I use to receive ESPNo2 data from a partner ESP and send to a T4.1 over UART.
Perhaps it might help you.

Code:
/*

ESP32C3: Receive data via ESP Now from other ESP32C3s and Send to T4.1 via UART.

    SoftwareId: S.0004.0003.001
    SoftwareId: S.0004.0003.001a - Altered to handle the availability of Serial better when offline to PC. No functional difference.
*/
#define softwareId "S.0004.0003.001a"

#include <esp_now.h>
#include <WiFi.h>

#define useHardwareSerial
#define ledPin 8
#define ledPinOn LOW

#ifdef useHardwareSerial

#include <HardwareSerial.h>
HardwareSerial TeensySerial(0);
#else
#define TeensySerial Serial1
#endif

const uint32_t identifier = 57767959;

typedef struct msgType {
    uint32_t ident = identifier;
    uint8_t  id;
    uint16_t temp;
    uint16_t humidity;
} msgType;

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
    uint8_t Id;
    float temp;
    float humidity;
} struct_message;

msgType sendMsg;

// Create a struct_message called myData
struct_message myData;

bool serialUp;

void send(const msgType* msg)
{
    TeensySerial.write((const char*)msg, sizeof(msgType));  // 2 bytes.
}

bool receive(msgType* msg)
{
    return (Serial1.readBytes((char*)msg, sizeof(msgType)) == sizeof(msgType));
}
// callback function that will be executed when data is received
void OnDataRecv(const uint8_t* mac, const uint8_t* incomingData, int len) {


    digitalWrite(ledPin, LOW);
    memcpy(&myData, incomingData, sizeof(myData));
    if (serialUp) {
        Serial.print("Id: "); Serial.print(myData.Id);
        Serial.print("     Temp: "); Serial.print(myData.temp); Serial.print(" degC");
        Serial.print("     Humidity: "); Serial.print(myData.humidity); Serial.println(" %RH");
    }
    sendMsg.id = myData.Id;

    sendMsg.temp = (uint16_t)((myData.temp * 100.0) + 0.5); //(uint8_t)(t / 100 );

    sendMsg.humidity = (uint16_t)((myData.humidity * 100.0) + 0.5); //(uint8_t)( t / 100 );

    send(&sendMsg);

    digitalWrite(ledPin, HIGH);
}

void setup() {
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW);
    delay(4000);
    digitalWrite(ledPin, HIGH);
    // Initialize Serial Monitor
    Serial.begin(115200);
    TeensySerial.begin(115200, SERIAL_8N1, 20, 21);
    TeensySerial.println();
    TeensySerial.print("Hello from ESP32. SoftwareId: ");    TeensySerial.println(softwareId);
    while (!Serial && millis()<3000){}
    serialUp = Serial;

    if (serialUp) { Serial.print("SoftwareId: ");    Serial.println(softwareId); }

    // Set device as a Wi-Fi Station
    WiFi.mode(WIFI_STA);

    // Init ESP-NOW
    if (esp_now_init() != ESP_OK) {
        if (serialUp) Serial.println("Error initializing ESP-NOW");
        return;
    }

    // Once ESPNow is successfully Init, we will register for recv CB to
    // get recv packer info
    esp_now_register_recv_cb(OnDataRecv);
}

void loop() {

}
 
Hi all
First, thank you very much to all of you for your very appreciated help. I did what was suggested (sadly, i didnt even think about that before) and made a quick and dirty version for the teensy, basically just serial1.read and print it to the usb serial.
The data arrives correct and is read correct by the teensy, somewhere in my function is a mistake. I just didn't even think about trying it again with a simpler method (a little bit of tunnel vision was going on there).
Thank you all again for your responses and the time you put in them! I highly appreciate that and gonna post the solution in hope, if someone is going to have a similar problem, it can help.
Have a nice evening

edit: spelling mistake
 
Well, it was Serial.beginn(), for some reason completely unclear to me i added SERIAL_8N2. There would have been no way to solve the problem just by looking at the code part i uploaded. I beg your pardon, you had to invest time in such a "simple" mistake without even the complete/right code segment uploaded.
 
Back
Top