Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read glbytes v2 #64

Merged
merged 2 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions sensor/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ build_flags =
-D RSC3
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1

[env:pico32]
platform = espressif32
board = pico32
116 changes: 78 additions & 38 deletions sensor/src/sensor.ino
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <WiFi.h>
#include <WiFiAP.h>
#include <esp_task_wdt.h>
#include <driver/uart.h>
#else
#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>
Expand Down Expand Up @@ -60,6 +61,7 @@ int delayTime = DELAY_TIME_DEFAULT;

#ifdef RSC3
#define tub Serial1
#define tubUART UART_NUM_1
#define RX_PIN 3
#define TX_PIN 10
#define RTS_PIN 5 // RS485 direction control, RequestToSend TX or RX, required for MAX485 board.
Expand All @@ -70,6 +72,7 @@ Adafruit_NeoPixel pixels(1, 4, NEO_GRB + NEO_KHZ800);

#elif ESP32
#define tub Serial2
#define tubUART UART_NUM_2
#define RX_PIN 19
#define TX_PIN 23
#define RTS_PIN 22 // RS485 direction control, RequestToSend TX or RX, required for MAX485 board.
Expand Down Expand Up @@ -143,6 +146,23 @@ String state = "unknown";

ArduinoQueue<String> sendBuffer(10); // TODO: might be better bigger for large temp changes. Would need testing

void clearRXbuffer(void) {
// clear the rx buffer
#if defined(ESP32) || defined(RSC3)
uart_flush(tubUART);
#else
// not tested but according to the code flush clears the buffer
// https://github.com/plerup/espsoftwareserial/blob/main/src/SoftwareSerial.cpp#L434
tub.flush();
#endif
}

// Triggered when pin5 falling - ie our panel is selected
// clears serial receive buffer
void IRAM_ATTR panelSelect() {
clearRXbuffer();
}

void sendCommand(String command, int count) {
Serial.printf("Sending %s - %u times\n", command.c_str(), count);
for (int i = 0; i < count; i++) {
Expand Down Expand Up @@ -335,6 +355,9 @@ void setup() {
TX_PIN); // added here to see if line about was where the hang was
tub.updateBaudRate(115200);
#endif
// enable interrupt for pin5 falling level change so we can clear the rx buffer
// everytime our panel is selected
attachInterrupt(digitalPinToInterrupt(PIN_5_PIN), panelSelect, FALLING);

init_wifi(ssid, passphrase, "hottub-sensor");
webota.init(8080, "/update");
Expand Down Expand Up @@ -460,23 +483,54 @@ uint32_t lastUptime = 0;
String timeString = "";
int msgLength = 0;
boolean panelDetected = false;

void handleBytes(size_t len, uint8_t buf[]);
const unsigned long readBytesTimeout = 2500; // Timeout in microseconds (2.5 ms)

/*
* waitforGLBytes checks the first byte in the serial buffer
* since we've cleared the serial buffer when pin5 went low
* there will only be data meant for our panel in the buffer.
* Depending on the message type, wait for the expected number
* of bytes to be available with a timeout of 2ms
* returns number of bytes to read
*/
int waitforGLBytes() {
int msgLength = 0;
setPixel(STATUS_OK);
// define message length from starting Byte
switch (tub.peek()) {
case 0xFA:
msgLength = 23;
break;
case 0xAE:
msgLength = 16;
break;
default:
Serial.print("Unknown message start Byte: ");
int peekedByte = tub.peek();
Serial.println(peekedByte, HEX);
return 0;
}
// we'll wait here for up to 2.5ms until the expected number of bytes are available
unsigned long startTime = micros();
while (tub.available() < msgLength) {
if (micros() - startTime >= readBytesTimeout) {
Serial.printf("Timeout: %u bytes not available in 2.5ms\n", msgLength);
return 0;
}
}
return msgLength;
}

void loop() {
bool panelSelect = digitalRead(PIN_5_PIN); // LOW when we are meant to read data
if (tub.available() > 0) {
setPixel(STATUS_OK);
size_t len = tub.available();
// Serial.printf("bytes avail = %u\n", len);
uint8_t buf[len]; // TODO: swap to fixed buffer to help prevent fragmentation of memory
tub.read(buf, len);
if (panelSelect == LOW) { // Only read data meant for us
handleBytes(len, buf);
} else {
// Serial.print("H");
result = "";
msgLength = 0;
// is data available and we are selected
if ((tub.available() > 0) && (panelSelect == LOW)) {
int msgLength = waitforGLBytes();
// only do something if we've got a message
if (msgLength > 0) {
uint8_t buf[msgLength];
tub.read(buf, msgLength);
handleMessage(msgLength, buf);
}
}
else {
Expand Down Expand Up @@ -529,36 +583,20 @@ void loop() {
#endif
}

void handleBytes(size_t len, uint8_t buf[]) {
void handleMessage(size_t len, uint8_t buf[]) {
// Serial.print("message = ");
// Serial.println(result);
// check if we need to send command first
if (buf[0] == 0xFA) {
sendCommand();
}
result = "";
for (int i = 0; i < len; i++) {
if (buf[i] < 0x10) {
result += '0';
}
result += String(buf[i], HEX);
}
if (msgLength == 0 && result.length() == 2) {
String messageType = result.substring(0, 2);
if (messageType == "fa") {
msgLength = 46;
} else if (messageType == "ae") {
msgLength = 32;
} else {
Serial.print("Unknown message length for ");
Serial.println(messageType);
}
} else if (result.length() == msgLength) {
if (result.length() == 46) {
sendCommand(); // send reply *before* we parse the FA string as we don't want to delay the reply by
// say sending MQTT updates
}
handleMessage();
}
}

void handleMessage() {
// Serial.print("message = ");
// Serial.println(result);

if (result.substring(0, 4) == "fa14") {
// Serial.println("FA 14");
// telnetSend(result);
Expand Down Expand Up @@ -817,6 +855,8 @@ void sendCommand() {
Serial.printf("message sent : %u\n", delayTime);
// delayTime += 10;
}
//clear the RX buffer since it will have the FB command we just sent
clearRXbuffer();
// else {
// Serial.println("ERROR: Pin5 went high before command could be sent after flush");
// }
Expand Down