Unreliable serial communication with a C# app

Hi ! I'm having some kind of memory bug or race condition and I can't get to the root of it. The computer is sending instructions to the arduino which reads them and sends back what was asked for. Instructions are 1 byte. I'm communicating from a C# program this way :

packetParser.Send<Out.TriggerDeviceCountPacket>();
var count = packetParser.Parse<In.DeviceCountPacket>().DeviceCount;

The implementation is a layer of abstraction over the SerialPort object in C#, it has been verified that the packets are being sent (and successfully received on the arduino side) thanks to a serial traffic watcher.

On the Arduino side :

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_PIN 3
#define MEASUREMENT_PRECISION 10 // takes 190 ms MAX to convert temp value in the sensor
#define POST_MEASUREMENT_REQUEST_DELAY 200
#define MAX_SENSOR_COUNT 4

OneWire oneWireBus(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWireBus);

DeviceAddress sensorAddresses[MAX_SENSOR_COUNT];

byte deviceCount = 0;

// send buffer
byte serialBuffer[16];
int bufferIndex = 0;

void serialBufferAppendByte(byte b) {
  serialBuffer[bufferIndex] = b; 
  bufferIndex++;
}
void serialBufferAppendBytes(byte b[], int len) {
  // TODO : replace with memcopy
  for (int i = 0; i < len; i++) {
    serialBufferAppendByte(b[i]);
  }
}
void serialBufferFlush() {
  if (bufferIndex == 0) { return; }
  Serial.write(serialBuffer, bufferIndex);
  Serial.flush();
  bufferIndex = 0;
}

void setup() {
  // init serial
  Serial.begin(9600);

  // init sensors
  sensors.begin();
  sensors.setResolution(MEASUREMENT_PRECISION);

   // wait for serial
  while (!Serial) { ; }
}

union {
  float f;
  byte bytes[sizeof(float)];
} RawFloat;

byte readInstructionBuffer;

void loop() {
  
  if (Serial.available() > 0) {

    readInstructionBuffer = Serial.read();

    switch (readInstructionBuffer) {
      case 0xA1: // device count packet
        deviceCount = sensors.getDeviceCount();

        // send device count
        serialBufferAppendByte(0x1);
        serialBufferAppendByte(deviceCount);
        serialBufferFlush();
        break;

      case 0xA2: // device addresses packets
        // send addresses
        for (byte i = 0; i < deviceCount; i++) {
          bool r = sensors.getAddress(sensorAddresses[i], i);
          if (r) {
            serialBufferAppendByte(0x2);
            serialBufferAppendBytes(sensorAddresses[i], sizeof(DeviceAddress));
            serialBufferFlush();
          }
        }
        break;

      case 0xA3: // device temperatures
        // request temps for all connected sensors
        sensors.requestTemperatures();

        // wait for sensor to convert data
        delay(POST_MEASUREMENT_REQUEST_DELAY);

        // send sensor data
        for (byte i = 0; i < deviceCount; i++) {
          float temp = sensors.getTempC(sensorAddresses[i]); // get temp as float
          RawFloat.f = temp;
          
          serialBufferAppendByte(0x3);
          serialBufferAppendByte(i);
          serialBufferAppendBytes(RawFloat.bytes, sizeof(float));
          serialBufferFlush();
        }
        break;

        default:
          break;
    }
  }
}

On startup, the C# program asks for device count and device addresses, so it sends 0xA1, waits for an answer, then sends 0xA2 and waits for an answer.

When I reset the adruino and start the program everything works fine. But when I restart the program without restarting the arduino : the arduino receives the "request" (the 'trigger' byte) but does not answer.
I think this has to do with my 'serialBuffer' code, but I really can't find the bug.

Note that sometimes it works two time in a row but then proceeds to never work again until I reset the arduino.
On the serial analyzer it looks something like this, the read is left pending forever, or until the readtimeout is expired on the C# side.

when you open the Serial port in your C# code, your arduino likely reboots. if your C# code does not wait for the arduino to boot and sends commands right away then they will be lost

you could modify your set up to let your C# program that the Arduino is ready by sending a custom byte

const byte arduinoIsReady  = 0x42;

void setup() {
  // init serial
  Serial.begin(9600);
   // wait for serial
  while (!Serial) { ; }

  // init sensors
  sensors.begin();
  sensors.setResolution(MEASUREMENT_PRECISION);

  Serial.write(arduinoIsReady); // tell the PC we are ready to receive commands
}

on the C# side, you would wait until you get the 0x42 signal to know you can proceed

Thank you ! this resolved the issue :blush:

I think I had kind of excluded the possibility that it was a race condition because the Serial monitor application I was using showed that the packet was succesfully delivered and I assumed that it meant the arduino had it in it's buffer, but I assumed wrong !
Thank you again, have a great day.

cool - have fun !