Corrupted communications between atmega2560 and ESP8266

How much data are you sending ??

Yes that can be done. The normal way is to execute read() repeatedly and discard the contents, until it is empty, but if you look into hardwareSerial.cpp, you will find that

int HardwareSerial::available(void)
{
  return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE;
}

if you add a function that assigns

_rx_buffer_tail = _rx_buffer_head;

that will also clear it, much faster.

You've answered that, and yes.
from hardwareSerial.h

#if  (SERIAL_RX_BUFFER_SIZE>256)
typedef uint16_t rx_buffer_index_t;
#else
typedef uint8_t rx_buffer_index_t;
#endif

But all of these issues are caused by either the program being in an interrupt for too long, (at 115200bps that would be more than 85uS or so) and not responding to the UART's RX interrupt on time, or because you don't read the buffer before it is full. At 115200, eh let's do the math. 8N1 = 10 bits (1 start, 8 data, 1 stop) so 11520 Bps = approx 11.520 Bytes / ms, which comes down to 87us per byte * however big the buffer is.

You just have to keep in mind that if you use external libraries, they may do things that conflict with your priorities.

Thanks again, unfortunately it's quite late in my time zone, so I'll be back tomorrow. But I had a very interesting question, will an external interrupt on Serial fix my problem? if so, how can this be implemented.

Thanks a lot

After a short search I came to the NeoSerial library, with which I read messages using the RX interrupt. Strange but the problem is still there.

Also, after reading the EasyButton documentation for a while, I realized that I was using polling, not interruptions.

Now my code looks like this:

bool handleRXChar(uint8_t inByte) {
  static char *message = new char[MAX_MESSAGE_LENGTH];
  static uint8_t message_pos = 0;

  if (inByte != ';' && (message_pos < MAX_MESSAGE_LENGTH - 1)) {
    message[message_pos] = inByte;
    message_pos++;
  } else {
    message[message_pos] = '\0';
    strcpy(buffer, message);
    NeoSerial.println(buffer);
    __processMessage();
    delete[] message;
    message_pos = 0;
  }

  return false;
}

Here is the ESP8266 code that sends messages:

void startup() {
    delay(500);
    Serial.begin(BAUD);
    delay(500);

    Serial.println("powerOn;");

    wifiManager.autoConnect("Ara Ara", "IseeIsee"); Serial.println(";");
    Serial.println("connectedWF;");

    setDateTime();
    Serial.println("setupDate;");
    
    client.onMessage(callback);
}

(*This is not the whole code, but all messages in the code are sent in this way. And they are all corrupted)

Here is an example of corrupted messages:

powrOn


connectdWF

connectedWF
se

How can I check it?

Just to tell you that the use of dynamic variables is discouraged on a small MCU to prevent heap fragmentation.

Actually it looks like the RX interrupt is not always executed on time.

Eh yeah, but it does that polling at a regular interval and not by calling a function from the main loop. So i suspect it is using a timer interrupt to call a function. When that function is called by a timer, it is an ISR, which disables all other interrupts while it is within that.

So, just to verify. If you do a simple Serial Passthrough (no other code anywhere !) do you lose bytes ?
If so then the issue is in code you have included

Well i always simply look at the code. Either on Github or i open the .h & .cpp files using notepad++, so i can see what resources are used and how the library is structured. Usually things are not to complex, though sometimes i am left scratching my head as well. Rarely does it not provide me with answers.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.