bump
This commit is contained in:
+291
-255
@@ -1,4 +1,3 @@
|
||||
|
||||
#define RXD_PIN 5
|
||||
#define TXD_PIN 6
|
||||
#define CONTROL_PIN 4
|
||||
@@ -17,33 +16,23 @@
|
||||
#include <hd44780ioClass/hd44780_I2Cexp.h>
|
||||
|
||||
constexpr uint8_t LCD_I2C_ADDRESS = 0x27;
|
||||
hd44780_I2Cexp lcd(LCD_I2C_ADDRESS, 20, 4);
|
||||
constexpr uint8_t LCD_COLS = 20;
|
||||
constexpr uint8_t LCD_ROWS = 4;
|
||||
constexpr uint8_t WATER_ROW = LCD_ROWS - 1;
|
||||
|
||||
hd44780_I2Cexp lcd(LCD_I2C_ADDRESS, LCD_COLS, LCD_ROWS);
|
||||
|
||||
constexpr uint8_t RELAY_CONTROL_ADDRESS = 0x21;
|
||||
constexpr uint8_t BUTTONS_CONTROL_ADDRESS = 0x20;
|
||||
|
||||
constexpr unsigned long COMMAND_INTERVAL_MS = 1000;
|
||||
constexpr uint16_t MODBUS_RESPONSE_TIMEOUT_MS = 200;
|
||||
|
||||
uint8_t modbusReadCmd[] = {0x01, 0x03, 0x00, 0x04, 0x00, 0x01};
|
||||
unsigned long lastCommandTime = 0;
|
||||
const unsigned long COMMAND_INTERVAL = 1000;
|
||||
|
||||
volatile bool g_buttonInterruptFired = false;
|
||||
int g_waterLevelCm = -1;
|
||||
void addWaterLevel();
|
||||
|
||||
// String *descr[] = {"NA", "Pump", "Barrel -> Back Left", "Back Left -> Barrel", "Barrel to Hose", "CW to Hose", "NA", "NA"};
|
||||
|
||||
void printBin(byte aByte)
|
||||
{
|
||||
for (int8_t aBit = 7; aBit >= 0; aBit--)
|
||||
{
|
||||
// Serial.print(aBit);
|
||||
// Serial.write(":");
|
||||
Serial.write(bitRead(aByte, aBit) ? '1' : '0');
|
||||
// Serial.write(" ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// NA, Pump, Barrel -> Back Left, Back Left -> Barrel, Barrel to Hose, CW to Hose, NA, NA
|
||||
struct Action
|
||||
{
|
||||
const char *name;
|
||||
@@ -70,130 +59,36 @@ inline Action g_actions[] = {
|
||||
{"NotAssigned", 0b00000000, 0b00000000, false},
|
||||
};
|
||||
|
||||
uint8_t current_stat = 0b00000000;
|
||||
uint8_t current_mask = 0b00000000;
|
||||
|
||||
// Forward declarations
|
||||
void updateLCDDisplay();
|
||||
void addWaterLevel();
|
||||
void applyRelayStateIfChanged();
|
||||
void generateMasksByActive();
|
||||
void updateStateByLastAction(ActionId lastAction);
|
||||
void readAndPrintButtons();
|
||||
void pollSerial2WaterLevel();
|
||||
uint16_t calculateCRC16(const uint8_t *data, uint8_t length);
|
||||
void sendCommand(const uint8_t *cmd, size_t len);
|
||||
void sendModbusCommand();
|
||||
void scanI2CDevices();
|
||||
void buildTrimmedWaterLevelText(char *outBuffer, size_t outBufferSize);
|
||||
void buildRightJustifiedWaterRow(char *rowBuffer, size_t rowBufferSize);
|
||||
|
||||
inline Action &getAction(ActionId id)
|
||||
{
|
||||
return g_actions[static_cast<size_t>(id)];
|
||||
}
|
||||
|
||||
uint8_t current_stat = 0b00000000;
|
||||
uint8_t current_mask = 0b00000000;
|
||||
|
||||
void updateLCDDisplay()
|
||||
void printBin(byte aByte)
|
||||
{
|
||||
lcd.clear();
|
||||
uint8_t c_row = 0;
|
||||
for (size_t i = 0; i < static_cast<size_t>(ActionId::Count); ++i)
|
||||
for (int8_t aBit = 7; aBit >= 0; --aBit)
|
||||
{
|
||||
if (g_actions[i].active)
|
||||
{
|
||||
lcd.setCursor(0, c_row);
|
||||
lcd.print(g_actions[i].name);
|
||||
c_row++;
|
||||
}
|
||||
}
|
||||
addWaterLevel();
|
||||
}
|
||||
|
||||
void generateMasksByActive()
|
||||
{
|
||||
current_stat = 0b00000000;
|
||||
current_mask = 0b00000000;
|
||||
for (size_t i = 0; i < static_cast<size_t>(ActionId::Count); ++i)
|
||||
{
|
||||
Action &c_action = g_actions[i];
|
||||
if (c_action.active)
|
||||
{
|
||||
current_mask = current_mask | c_action.mask;
|
||||
current_stat = (current_stat & ~c_action.mask) | (c_action.stat & c_action.mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateStateByLastAction(ActionId LastAction)
|
||||
{
|
||||
Action &c_action = getAction(LastAction);
|
||||
|
||||
if (c_action.active)
|
||||
{
|
||||
c_action.active = false;
|
||||
generateMasksByActive();
|
||||
updateLCDDisplay();
|
||||
return;
|
||||
}
|
||||
uint8_t change_stat = c_action.stat;
|
||||
uint8_t change_mask = c_action.mask;
|
||||
|
||||
uint8_t old_stat = current_stat;
|
||||
uint8_t old_mask = current_mask;
|
||||
|
||||
uint8_t potential_new_stat = (current_stat & ~change_mask) | (change_stat & change_mask);
|
||||
|
||||
uint8_t potential_old_change = (potential_new_stat ^ old_stat) & old_mask;
|
||||
|
||||
if (potential_old_change > 0)
|
||||
{
|
||||
Serial.print(c_action.name);
|
||||
Serial.print(" collides with existing. Setting new mask to this one");
|
||||
Serial.println();
|
||||
|
||||
current_stat = change_stat;
|
||||
current_mask = change_mask;
|
||||
for (size_t i = 0; i < static_cast<size_t>(ActionId::Count); ++i)
|
||||
{
|
||||
g_actions[i].active = false;
|
||||
}
|
||||
c_action.active = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(c_action.name);
|
||||
Serial.print(" has no collisions with existing. Setting updated mask");
|
||||
Serial.println();
|
||||
current_stat = potential_new_stat;
|
||||
current_mask = old_mask | change_mask;
|
||||
c_action.active = true;
|
||||
}
|
||||
Serial.print("Stat: ");
|
||||
printBin(current_stat);
|
||||
Serial.print("Mask: ");
|
||||
printBin(current_mask);
|
||||
updateLCDDisplay();
|
||||
}
|
||||
|
||||
void applyRelayStateIfChanged()
|
||||
{
|
||||
static uint8_t lastRelayValue = 0xFF;
|
||||
// Serial.println(current_stat, BIN);
|
||||
// Serial.println(current_mask, BIN);
|
||||
// uint8_t relayValue = static_cast<uint8_t>(~((current_stat & current_mask) | static_cast<uint8_t>(~current_mask)));
|
||||
|
||||
uint8_t relayValue = ~current_stat;
|
||||
for (int8_t bit = 7; bit >= 0; --bit)
|
||||
{
|
||||
Serial.print((relayValue >> bit) & 0x01);
|
||||
Serial.write(bitRead(aByte, aBit) ? '1' : '0');
|
||||
}
|
||||
Serial.println();
|
||||
Wire.beginTransmission(RELAY_CONTROL_ADDRESS);
|
||||
Wire.write(relayValue);
|
||||
uint8_t error = Wire.endTransmission();
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
lastRelayValue = relayValue;
|
||||
Serial.printf(
|
||||
"Relay state updated: value=0x%02X stat=0x%02X mask=0x%02X\n",
|
||||
relayValue,
|
||||
current_stat,
|
||||
current_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf(
|
||||
"Relay write failed: addr=0x%02X error=%u value=0x%02X\n",
|
||||
RELAY_CONTROL_ADDRESS,
|
||||
error,
|
||||
relayValue);
|
||||
}
|
||||
}
|
||||
|
||||
void buildTrimmedWaterLevelText(char *outBuffer, size_t outBufferSize)
|
||||
@@ -228,28 +123,157 @@ void buildTrimmedWaterLevelText(char *outBuffer, size_t outBufferSize)
|
||||
outBuffer[len] = '\0';
|
||||
}
|
||||
|
||||
void addWaterLevel()
|
||||
void buildRightJustifiedWaterRow(char *rowBuffer, size_t rowBufferSize)
|
||||
{
|
||||
char text[24];
|
||||
buildTrimmedWaterLevelText(text, sizeof(text)); // e.g. "123 cm"
|
||||
|
||||
size_t len = strlen(text);
|
||||
if (len > 20)
|
||||
if (rowBuffer == nullptr || rowBufferSize < (LCD_COLS + 1))
|
||||
{
|
||||
len = 20;
|
||||
text[20] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t row = 3; // last row on 20x4
|
||||
const uint8_t startCol = static_cast<uint8_t>(20 - len); // right-justified
|
||||
memset(rowBuffer, ' ', LCD_COLS);
|
||||
rowBuffer[LCD_COLS] = '\0';
|
||||
|
||||
// Clear row first so old characters do not remain
|
||||
// lcd.setCursor(0, row);
|
||||
// lcd.print(" "); // 20 spaces
|
||||
char text[24];
|
||||
buildTrimmedWaterLevelText(text, sizeof(text));
|
||||
|
||||
// Print at exact right-justified cursor position
|
||||
lcd.setCursor(startCol, row);
|
||||
lcd.print(text);
|
||||
size_t len = strlen(text);
|
||||
if (len > LCD_COLS)
|
||||
{
|
||||
len = LCD_COLS;
|
||||
}
|
||||
|
||||
const size_t startCol = LCD_COLS - len;
|
||||
memcpy(rowBuffer + startCol, text, len);
|
||||
}
|
||||
|
||||
void addWaterLevel()
|
||||
{
|
||||
char row[LCD_COLS + 1];
|
||||
buildRightJustifiedWaterRow(row, sizeof(row));
|
||||
lcd.setCursor(0, WATER_ROW);
|
||||
lcd.print(row);
|
||||
}
|
||||
|
||||
void updateLCDDisplay()
|
||||
{
|
||||
lcd.clear();
|
||||
|
||||
uint8_t c_row = 0;
|
||||
for (size_t i = 0; i < static_cast<size_t>(ActionId::Count); ++i)
|
||||
{
|
||||
if (g_actions[i].active)
|
||||
{
|
||||
if (c_row >= WATER_ROW) // keep last row for water level
|
||||
{
|
||||
break;
|
||||
}
|
||||
lcd.setCursor(0, c_row);
|
||||
lcd.print(g_actions[i].name);
|
||||
++c_row;
|
||||
}
|
||||
}
|
||||
|
||||
addWaterLevel();
|
||||
}
|
||||
|
||||
void generateMasksByActive()
|
||||
{
|
||||
current_stat = 0;
|
||||
current_mask = 0;
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(ActionId::Count); ++i)
|
||||
{
|
||||
Action &c_action = g_actions[i];
|
||||
if (c_action.active)
|
||||
{
|
||||
current_mask |= c_action.mask;
|
||||
current_stat = (current_stat & ~c_action.mask) | (c_action.stat & c_action.mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateStateByLastAction(ActionId lastAction)
|
||||
{
|
||||
Action &c_action = getAction(lastAction);
|
||||
|
||||
if (c_action.active)
|
||||
{
|
||||
c_action.active = false;
|
||||
generateMasksByActive();
|
||||
applyRelayStateIfChanged();
|
||||
updateLCDDisplay();
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t change_stat = c_action.stat;
|
||||
const uint8_t change_mask = c_action.mask;
|
||||
|
||||
const uint8_t old_stat = current_stat;
|
||||
const uint8_t old_mask = current_mask;
|
||||
|
||||
const uint8_t potential_new_stat = (current_stat & ~change_mask) | (change_stat & change_mask);
|
||||
const uint8_t potential_old_change = (potential_new_stat ^ old_stat) & old_mask;
|
||||
|
||||
if (potential_old_change != 0)
|
||||
{
|
||||
Serial.print(c_action.name);
|
||||
Serial.println(" collides with existing. Setting only this action.");
|
||||
|
||||
current_stat = change_stat;
|
||||
current_mask = change_mask;
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(ActionId::Count); ++i)
|
||||
{
|
||||
g_actions[i].active = false;
|
||||
}
|
||||
c_action.active = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(c_action.name);
|
||||
Serial.println(" has no collisions. Merging action.");
|
||||
|
||||
current_stat = potential_new_stat;
|
||||
current_mask = old_mask | change_mask;
|
||||
c_action.active = true;
|
||||
}
|
||||
|
||||
Serial.print("Stat: ");
|
||||
printBin(current_stat);
|
||||
Serial.print("Mask: ");
|
||||
printBin(current_mask);
|
||||
|
||||
applyRelayStateIfChanged();
|
||||
updateLCDDisplay();
|
||||
}
|
||||
|
||||
void applyRelayStateIfChanged()
|
||||
{
|
||||
static uint8_t lastRelayValue = 0xFF;
|
||||
const uint8_t relayValue = static_cast<uint8_t>(~current_stat);
|
||||
|
||||
if (relayValue == lastRelayValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Wire.beginTransmission(RELAY_CONTROL_ADDRESS);
|
||||
Wire.write(relayValue);
|
||||
uint8_t error = Wire.endTransmission();
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
lastRelayValue = relayValue;
|
||||
Serial.printf(
|
||||
"Relay state updated: value=0x%02X stat=0x%02X mask=0x%02X\n",
|
||||
relayValue, current_stat, current_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf(
|
||||
"Relay write failed: addr=0x%02X error=%u value=0x%02X\n",
|
||||
RELAY_CONTROL_ADDRESS, error, relayValue);
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR onButtonInterrupt()
|
||||
@@ -257,155 +281,174 @@ void IRAM_ATTR onButtonInterrupt()
|
||||
g_buttonInterruptFired = true;
|
||||
}
|
||||
|
||||
uint16_t calculateCRC16(uint8_t *data, uint8_t length)
|
||||
uint16_t calculateCRC16(const uint8_t *data, uint8_t length)
|
||||
{
|
||||
uint16_t crc = 0xFFFF;
|
||||
for (int i = 0; i < length; i++)
|
||||
for (uint8_t i = 0; i < length; ++i)
|
||||
{
|
||||
crc ^= data[i];
|
||||
for (int j = 0; j < 8; j++)
|
||||
for (uint8_t j = 0; j < 8; ++j)
|
||||
{
|
||||
crc = (crc & 0x0001) ? (crc >> 1) ^ 0xA001 : crc >> 1;
|
||||
crc = (crc & 0x0001) ? (crc >> 1) ^ 0xA001 : (crc >> 1);
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
void sendCommand(uint8_t *cmd, size_t len)
|
||||
void sendCommand(const uint8_t *cmd, size_t len)
|
||||
{
|
||||
uint16_t crc = calculateCRC16(cmd, len);
|
||||
uint8_t crcL = crc & 0xFF;
|
||||
uint8_t crcH = (crc >> 8) & 0xFF;
|
||||
uint16_t crc = calculateCRC16(cmd, static_cast<uint8_t>(len));
|
||||
uint8_t crcL = static_cast<uint8_t>(crc & 0xFF);
|
||||
uint8_t crcH = static_cast<uint8_t>((crc >> 8) & 0xFF);
|
||||
|
||||
Serial2.write(cmd, len);
|
||||
Serial2.write(crcL);
|
||||
Serial2.write(crcH);
|
||||
}
|
||||
|
||||
void sendModbusCommand() { sendCommand(modbusReadCmd, sizeof(modbusReadCmd)); }
|
||||
void sendModbusCommand()
|
||||
{
|
||||
sendCommand(modbusReadCmd, sizeof(modbusReadCmd));
|
||||
}
|
||||
|
||||
void scanI2CDevices()
|
||||
{
|
||||
uint8_t found = 0;
|
||||
for (uint8_t address = 1; address < 127; address++)
|
||||
for (uint8_t address = 1; address < 127; ++address)
|
||||
{
|
||||
Wire.beginTransmission(address);
|
||||
uint8_t error = Wire.endTransmission();
|
||||
if (error == 0)
|
||||
{
|
||||
Serial.printf("I2C device found at 0x%02X\n", address);
|
||||
found++;
|
||||
++found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool i2cAddressResponds(uint8_t address)
|
||||
{
|
||||
Wire.beginTransmission(address);
|
||||
return (Wire.endTransmission() == 0);
|
||||
if (found == 0)
|
||||
{
|
||||
Serial.println("No I2C devices found.");
|
||||
}
|
||||
}
|
||||
|
||||
void readAndPrintButtons()
|
||||
{
|
||||
|
||||
Wire.beginTransmission(BUTTONS_CONTROL_ADDRESS);
|
||||
Wire.write(0b11111110); // P0 LOW, all other pins released HIGH.
|
||||
Wire.write(0b11111110); // P0 LOW, others HIGH
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(BUTTONS_CONTROL_ADDRESS, (uint8_t)1);
|
||||
if (Wire.available())
|
||||
Wire.requestFrom(BUTTONS_CONTROL_ADDRESS, static_cast<uint8_t>(1));
|
||||
if (!Wire.available())
|
||||
{
|
||||
uint8_t portValue = Wire.read();
|
||||
bool buttonP3Pressed = (portValue & (1 << 3)) == 0;
|
||||
bool buttonP4Pressed = (portValue & (1 << 4)) == 0;
|
||||
bool buttonP5Pressed = (portValue & (1 << 5)) == 0;
|
||||
bool buttonP6Pressed = (portValue & (1 << 6)) == 0;
|
||||
bool buttonP7Pressed = (portValue & (1 << 7)) == 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ActionId LastAction = ActionId::Count;
|
||||
uint8_t portValue = Wire.read();
|
||||
bool buttonP3Pressed = (portValue & (1 << 3)) == 0;
|
||||
bool buttonP4Pressed = (portValue & (1 << 4)) == 0;
|
||||
bool buttonP5Pressed = (portValue & (1 << 5)) == 0;
|
||||
bool buttonP6Pressed = (portValue & (1 << 6)) == 0;
|
||||
bool buttonP7Pressed = (portValue & (1 << 7)) == 0;
|
||||
|
||||
if (buttonP3Pressed)
|
||||
{
|
||||
LastAction = ActionId::CityWaterToHose;
|
||||
}
|
||||
else if (buttonP4Pressed)
|
||||
{
|
||||
LastAction = ActionId::BarrelToHose;
|
||||
}
|
||||
else if (buttonP5Pressed)
|
||||
{
|
||||
LastAction = ActionId::BackLeftToBarrel;
|
||||
}
|
||||
else if (buttonP6Pressed)
|
||||
{
|
||||
LastAction = ActionId::BarrelToBackLeft;
|
||||
}
|
||||
else if (buttonP7Pressed)
|
||||
{
|
||||
// LastAction = ActionId::NotAssigned;
|
||||
}
|
||||
ActionId lastAction = ActionId::Count;
|
||||
|
||||
Serial.printf(
|
||||
"INT Buttons P3=%d P4=%d P5=%d P6=%d P7=%d (raw=0x%02X)\n",
|
||||
buttonP3Pressed,
|
||||
buttonP4Pressed,
|
||||
buttonP5Pressed,
|
||||
buttonP6Pressed,
|
||||
buttonP7Pressed,
|
||||
portValue);
|
||||
if (buttonP3Pressed)
|
||||
{
|
||||
lastAction = ActionId::CityWaterToHose;
|
||||
}
|
||||
else if (buttonP4Pressed)
|
||||
{
|
||||
lastAction = ActionId::BarrelToHose;
|
||||
}
|
||||
else if (buttonP5Pressed)
|
||||
{
|
||||
lastAction = ActionId::BackLeftToBarrel;
|
||||
}
|
||||
else if (buttonP6Pressed)
|
||||
{
|
||||
lastAction = ActionId::BarrelToBackLeft;
|
||||
}
|
||||
else if (buttonP7Pressed)
|
||||
{
|
||||
// reserved
|
||||
}
|
||||
|
||||
if (LastAction != ActionId::Count)
|
||||
{
|
||||
updateStateByLastAction(LastAction);
|
||||
}
|
||||
Serial.printf(
|
||||
"INT Buttons P3=%d P4=%d P5=%d P6=%d P7=%d (raw=0x%02X)\n",
|
||||
buttonP3Pressed, buttonP4Pressed, buttonP5Pressed, buttonP6Pressed, buttonP7Pressed, portValue);
|
||||
|
||||
if (lastAction != ActionId::Count)
|
||||
{
|
||||
updateStateByLastAction(lastAction);
|
||||
}
|
||||
}
|
||||
|
||||
void pollSerial2WaterLevel()
|
||||
{
|
||||
static uint8_t responseBuffer[256];
|
||||
static int responseIndex = 0;
|
||||
static uint8_t responseBuffer[7];
|
||||
static uint8_t responseIndex = 0;
|
||||
static int lastPrintedWaterLevelCm = -1;
|
||||
static unsigned long lastByteTimeMs = 0;
|
||||
static unsigned long lastCommandTimeMs = 0;
|
||||
|
||||
sendModbusCommand();
|
||||
unsigned long now = millis();
|
||||
|
||||
// Periodic request
|
||||
if ((now - lastCommandTimeMs) >= COMMAND_INTERVAL_MS)
|
||||
{
|
||||
lastCommandTimeMs = now;
|
||||
sendModbusCommand();
|
||||
}
|
||||
|
||||
// Reset partial frame on timeout
|
||||
if (responseIndex > 0 && (now - lastByteTimeMs) > MODBUS_RESPONSE_TIMEOUT_MS)
|
||||
{
|
||||
responseIndex = 0;
|
||||
}
|
||||
|
||||
while (Serial2.available())
|
||||
{
|
||||
responseBuffer[responseIndex++] = Serial2.read();
|
||||
if (responseIndex >= 256)
|
||||
{
|
||||
responseIndex = 0;
|
||||
}
|
||||
}
|
||||
uint8_t b = static_cast<uint8_t>(Serial2.read());
|
||||
lastByteTimeMs = millis();
|
||||
|
||||
if (responseIndex == 7)
|
||||
{
|
||||
uint16_t data = ((uint16_t)responseBuffer[3] << 8) | responseBuffer[4];
|
||||
uint16_t receivedCRC = ((uint16_t)responseBuffer[6] << 8) | responseBuffer[5];
|
||||
uint16_t calculatedCRC = calculateCRC16(responseBuffer, 5);
|
||||
|
||||
if (receivedCRC == calculatedCRC)
|
||||
if (responseIndex < sizeof(responseBuffer))
|
||||
{
|
||||
int waterLevelCm = data / 10;
|
||||
if (waterLevelCm != lastPrintedWaterLevelCm)
|
||||
{
|
||||
lastPrintedWaterLevelCm = waterLevelCm;
|
||||
g_waterLevelCm = waterLevelCm;
|
||||
addWaterLevel();
|
||||
Serial.printf("Water level: %d cm (%d mm)\n", waterLevelCm, data);
|
||||
}
|
||||
responseBuffer[responseIndex++] = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("CRC mismatch: received=0x%04X calculated=0x%04X\n", receivedCRC, calculatedCRC);
|
||||
responseIndex = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
responseIndex = 0;
|
||||
}
|
||||
else if (responseIndex != 0)
|
||||
{
|
||||
Serial.printf("Unexpected response length: %d (expected 7)\n", responseIndex);
|
||||
responseIndex = 0;
|
||||
if (responseIndex == 7)
|
||||
{
|
||||
uint16_t receivedCRC = static_cast<uint16_t>(responseBuffer[5]) |
|
||||
(static_cast<uint16_t>(responseBuffer[6]) << 8);
|
||||
uint16_t calculatedCRC = calculateCRC16(responseBuffer, 5);
|
||||
|
||||
if (responseBuffer[0] == 0x01 &&
|
||||
responseBuffer[1] == 0x03 &&
|
||||
responseBuffer[2] == 0x02 &&
|
||||
receivedCRC == calculatedCRC)
|
||||
{
|
||||
uint16_t dataMm = (static_cast<uint16_t>(responseBuffer[3]) << 8) | responseBuffer[4];
|
||||
int waterLevelCm = static_cast<int>(dataMm / 10);
|
||||
|
||||
if (waterLevelCm != lastPrintedWaterLevelCm)
|
||||
{
|
||||
lastPrintedWaterLevelCm = waterLevelCm;
|
||||
g_waterLevelCm = waterLevelCm;
|
||||
addWaterLevel();
|
||||
Serial.printf("Water level: %d cm (%u mm)\n", waterLevelCm, dataMm);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Invalid Modbus frame or CRC mismatch.");
|
||||
}
|
||||
|
||||
responseIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,9 +470,8 @@ void setup()
|
||||
|
||||
scanI2CDevices();
|
||||
|
||||
int lcdStatus = lcd.begin(20, 4);
|
||||
lcd.clear();
|
||||
// updateLcdStatesIfChanged();
|
||||
lcd.begin(LCD_COLS, LCD_ROWS);
|
||||
updateLCDDisplay();
|
||||
|
||||
Serial2.begin(MODBUS_BAUD, SERIAL_8N1, RXD_PIN, TXD_PIN);
|
||||
start = millis();
|
||||
@@ -437,24 +479,18 @@ void setup()
|
||||
{
|
||||
delay(10);
|
||||
}
|
||||
|
||||
applyRelayStateIfChanged();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// NA, Pump, Barrel -> Back Left, Back Left -> Barrel, Barrel to Hose, CW to Hose, NA, NA
|
||||
static unsigned long lastSerial2PollTime = 0;
|
||||
|
||||
if (g_buttonInterruptFired)
|
||||
{
|
||||
g_buttonInterruptFired = false;
|
||||
readAndPrintButtons();
|
||||
}
|
||||
|
||||
if (millis() - lastSerial2PollTime >= COMMAND_INTERVAL)
|
||||
{
|
||||
lastSerial2PollTime = millis();
|
||||
pollSerial2WaterLevel();
|
||||
}
|
||||
// updateLcdStatesIfChanged();
|
||||
pollSerial2WaterLevel();
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user