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.