firmware: harden XIAO RS485 telemetry

This commit is contained in:
2026-07-26 18:01:58 -06:00
parent 8c2375d402
commit 35c0721b47
6 changed files with 50 additions and 6 deletions
@@ -1,4 +1,5 @@
#include <ArduinoJson.h>
#include <esp_system.h>
#include "rs485_transport.h"
#include "sensor_node_config.h"
#include "calibration.h"
@@ -6,9 +7,28 @@
namespace {
String commandBuffer;
bool discardCommandUntilNewline = false;
uint32_t bootId = 0;
uint32_t frameSequence = 0;
void drainTransmitEcho(HardwareSerial& serial) {
while (serial.available()) serial.read();
}
void sendJson(HardwareSerial& serial, JsonDocument& doc) {
digitalWrite(RS485_DE_PIN, HIGH); delayMicroseconds(20);
if (doc.overflowed() || measureJson(doc) + 1 > RS485_MAX_FRAME_BYTES) {
#if USB_TELEMETRY_ENABLED
Serial.println("{\"type\":\"rs485_error\",\"error\":\"frame_too_large\"}");
#endif
return;
}
digitalWrite(RS485_DE_PIN, HIGH);
delayMicroseconds(RS485_DRIVER_ENABLE_SETTLE_US);
serializeJson(doc, serial); serial.write('\n'); serial.flush();
// This expansion board can echo TX into RX. At flush completion the
// entire transmitted line has left the UART, so discard that local echo
// before returning the transceiver to receive mode.
drainTransmitEcho(serial);
digitalWrite(RS485_DE_PIN, LOW);
#if USB_TELEMETRY_ENABLED
serializeJson(doc, Serial); Serial.println();
@@ -18,13 +38,17 @@ void sendJson(HardwareSerial& serial, JsonDocument& doc) {
void initRs485(HardwareSerial& serial) {
pinMode(RS485_DE_PIN, OUTPUT); digitalWrite(RS485_DE_PIN, LOW);
serial.setRxBufferSize(RS485_RX_BUFFER_BYTES);
serial.begin(RS485_BAUD, SERIAL_8N1, RS485_RX_PIN, RS485_TX_PIN);
bootId = esp_random();
}
void publishSensorStatus(HardwareSerial& serial, const ImuState& imu, const GpsState& gps) {
StaticJsonDocument<2048> doc;
doc["type"] = "sensor_status"; doc["schema_version"] = SENSOR_NODE_SCHEMA_VERSION;
doc["node_id"] = SENSOR_NODE_NAME; doc["firmware_version"] = SENSOR_NODE_FIRMWARE_VERSION;
doc["boot_id"] = bootId;
doc["frame_sequence"] = frameSequence++;
doc["uptime_ms"] = millis();
JsonObject i = doc.createNestedObject("imu");
i["online"] = imu.online; i["valid"] = imu.valid && millis() - imu.lastUpdateMs <= SENSOR_STALE_MS;