Argon Serial/UART LOSS

I have an issue with missed Serial data. I don´t know how to solve it. I am only sending/receiving very small packages which are under 10 Bytes each, so I believe it can´t be an overflow issue.

If Serial data is available I am running a while loop until there is no data for 1 second and then publish the data via MQTT.

I double checked with my logic analyzer and there are two messages about 5 seconds apart, but only the first one is recognized and send. The behaviour definitely happens repeatedly

Here is the critical code part:

void loop()
{
    static unsigned long    tReconnect      = 0;
    int                     iLast           = 0;
    char                    received[100]   = {};
    
    if (client.isConnected())
        client.loop();
    else if(millis() - tReconnect > 30000)
    {
        client.connect("Siro-Gateway");
        if (client.isConnected())
        {
            client.publish("MQTT/SiroGateway/online","1");
            client.subscribe("MQTT/SiroGateway/set/#");
        }
        tReconnect = millis();
    }
    
    if(iLast = Receive(received))
    {
        client.publish("MQTT/SiroGateway/received", received);
        
        for(int i = 0; i <= iLast; i++) {
            received[i] = 0;
        }
        
        iLast = 0;
    }
}

int Receive(char received[])
{
    int             byteCount   = 0;
    int             i           = 0;
    int             iLast       = 0;
    unsigned long   tLast       = 0;
    
    
    while(Serial1.available() || ((micros() - tLast) < 1000))
    {
        if(Serial1.available())
        {
            byteCount = Serial1.available();
            
            for(i = iLast; i < byteCount + iLast; i++) {
                received[i] = Serial1.read();
            }
            
            iLast = i;
            tLast = micros();
        }
        
        if((micros() - tLast) > 1000)
            return iLast;
    }
    
    return 0;
}

Make sure you are running the latest device OS release as there are some fixes with regards to Serial1.available()

Actually with (micros() - tLast) < 1000 you are only reading for 1 millisecond (=1000µs).

1 Like

Thanks for your help! I actually just looked over and didn´t see that it was micros instead of millis. But actually I changed it before I got your reply and it now works fine, although I did the opposite and made the reading interval even shorter. Here is the current code:

while(Serial1.available() || ((micros() - tLast) < 150))
    {
        if(Serial1.available())
        {
            byteCount = Serial1.available();
            
            for(i = iLast; i < byteCount + iLast; i++)
                received[i] = Serial1.read();
            
            iLast = i;
            tLast = micros();
        }
    }
    
    return iLast;

It´s now running 1.2.1. I believe before it was 1.1.1 but I am not sure.

But actually it is not quite correct to say I am only reading for 1ms or now 0.15ms, because all communication that happens in between the readings gets into the buffer, unless there is an overflow, which in my rare communication is really unlikely. I only implemented it this way, so it will not send an message before it is complete.

Please let me know is there is anything wrong with my understanding of how this works. Also how long is incoming serial communication stored in the buffer? I believe in Arduino this can be set with setTimeout().

And again my communication is based on short (~10 Byte) Messages, that are send seperated by at least a few ms but normaly a few 100ms or minutes apart. I want them to be captured and send via MQTT one Message at a time. If it happens occassionally that two messages are send as one that is no problem, I can parse that externally, but missing is not an option.

If this is what you’re after, you may want to consider using
Serial1.readBytes(received, 10)
This will wait for 10 bytes to read with a timeout set via Serial1.setTimeout().