functions
This commit is contained in:
+136
-284
@@ -9,6 +9,8 @@
|
||||
#define SERIAL_BAUD 115200
|
||||
#define MODBUS_BAUD 9600
|
||||
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <hd44780.h>
|
||||
@@ -24,30 +26,34 @@ 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"};
|
||||
// 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.write(aBit);
|
||||
Serial.write(":");
|
||||
// Serial.print(aBit);
|
||||
// Serial.write(":");
|
||||
Serial.write(bitRead(aByte, aBit) ? '1' : '0');
|
||||
Serial.write(" ");
|
||||
// Serial.write(" ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// NA, Pump, Barrel -> Back Left, Back Left -> Barrel, Barrel to Hose, CW to Hose, NA, NA
|
||||
struct Action {
|
||||
struct Action
|
||||
{
|
||||
const char *name;
|
||||
uint8_t stat;
|
||||
uint8_t mask;
|
||||
bool active;
|
||||
};
|
||||
|
||||
enum class ActionId : size_t {
|
||||
enum class ActionId : size_t
|
||||
{
|
||||
CityWaterToHose = 0,
|
||||
BarrelToHose,
|
||||
BackLeftToBarrel,
|
||||
@@ -57,53 +63,101 @@ enum class ActionId : size_t {
|
||||
};
|
||||
|
||||
inline Action g_actions[] = {
|
||||
{ "CityWaterToHose", 0b00001100, 0b00001100, false },
|
||||
{ "BarrelToHose", 0b01000000, 0b01101100, false },
|
||||
{ "BackLeftToBarrel", 0b00010000, 0b00110000, false },
|
||||
{ "BarrelToBackLeft", 0b01101000, 0b01111000, false },
|
||||
{"City -> Hose", 0b00001100, 0b00001100, false},
|
||||
{"Barrel -> Hose", 0b01000000, 0b01101100, false},
|
||||
{"Back Left -> Barrel", 0b00010000, 0b00110000, false},
|
||||
{"Barrel -> Back Left", 0b01101000, 0b01111000, false},
|
||||
{"NotAssigned", 0b00000000, 0b00000000, false},
|
||||
};
|
||||
|
||||
inline Action& getAction(ActionId id) {
|
||||
inline Action &getAction(ActionId id)
|
||||
{
|
||||
return g_actions[static_cast<size_t>(id)];
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t current_stat = 0b00000000;
|
||||
uint8_t current_mask = 0b00000000;
|
||||
|
||||
bool actionCityWaterToHose = false;
|
||||
uint8_t statCityWaterToHose = 0b00001100;
|
||||
uint8_t maskCityWaterToHose = 0b00001100;
|
||||
|
||||
bool actionBarrelToHose = false;
|
||||
uint8_t statBarrelToHose = 0b01000000;
|
||||
uint8_t maskBarrelToHose = 0b01101100;
|
||||
|
||||
bool actionBackLeftToBarrel = false;
|
||||
uint8_t statBackLeftToBarrel = 0b00010000;
|
||||
uint8_t maskBackLeftToBarrel = 0b00110000;
|
||||
|
||||
bool actionBarrelToBackLeft = false;
|
||||
uint8_t statBarrelToBackLeft = 0b01101000;
|
||||
uint8_t maskBarrelToBackLeft = 0b01111000;
|
||||
|
||||
bool actionNotAssigned = false;
|
||||
int g_waterLevelCm = -1;
|
||||
|
||||
enum class ActionId
|
||||
void updateLCDDisplay()
|
||||
{
|
||||
CityWaterToHose,
|
||||
BarrelToHose,
|
||||
BackLeftToBarrel,
|
||||
BarrelToBackLeft,
|
||||
NotAssigned,
|
||||
};
|
||||
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)
|
||||
{
|
||||
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()
|
||||
@@ -119,11 +173,6 @@ void applyRelayStateIfChanged()
|
||||
Serial.print((relayValue >> bit) & 0x01);
|
||||
}
|
||||
Serial.println();
|
||||
// if (relayValue == lastRelayValue)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
Wire.beginTransmission(RELAY_CONTROL_ADDRESS);
|
||||
Wire.write(relayValue);
|
||||
uint8_t error = Wire.endTransmission();
|
||||
@@ -147,198 +196,60 @@ void applyRelayStateIfChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void rebuildCurrentState()
|
||||
void buildTrimmedWaterLevelText(char *outBuffer, size_t outBufferSize)
|
||||
{
|
||||
current_stat = 0;
|
||||
current_mask = 0;
|
||||
|
||||
if (actionCityWaterToHose)
|
||||
{
|
||||
|
||||
current_stat = (current_stat & ~maskCityWaterToHose) | (statCityWaterToHose & maskCityWaterToHose);
|
||||
current_mask |= maskCityWaterToHose;
|
||||
}
|
||||
|
||||
if (actionBarrelToHose)
|
||||
{
|
||||
current_stat = (current_stat & ~maskBarrelToHose) | (statBarrelToHose & maskBarrelToHose);
|
||||
current_mask |= maskBarrelToHose;
|
||||
}
|
||||
|
||||
if (actionBackLeftToBarrel)
|
||||
{
|
||||
current_stat = (current_stat & ~maskBackLeftToBarrel) | (statBackLeftToBarrel & maskBackLeftToBarrel);
|
||||
current_mask |= maskBackLeftToBarrel;
|
||||
}
|
||||
|
||||
if (actionBarrelToBackLeft)
|
||||
{
|
||||
current_stat = (current_stat & ~maskBarrelToBackLeft) | (statBarrelToBackLeft & maskBarrelToBackLeft);
|
||||
current_mask |= maskBarrelToBackLeft;
|
||||
}
|
||||
|
||||
applyRelayStateIfChanged();
|
||||
}
|
||||
|
||||
void formatRightJustifiedWaterLine(char *buffer, size_t bufferSize)
|
||||
{
|
||||
snprintf(buffer, bufferSize, " ");
|
||||
|
||||
if (g_waterLevelCm < 0)
|
||||
if (outBuffer == nullptr || outBufferSize == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char valueText[21];
|
||||
snprintf(valueText, sizeof(valueText), "%d cm", g_waterLevelCm);
|
||||
char temp[24];
|
||||
snprintf(temp, sizeof(temp), "%d cm", g_waterLevelCm);
|
||||
|
||||
size_t valueLength = strlen(valueText);
|
||||
size_t startColumn = valueLength < 20 ? 20 - valueLength : 0;
|
||||
memcpy(buffer + startColumn, valueText, min<size_t>(valueLength, 20));
|
||||
const char *start = temp;
|
||||
while (*start && std::isspace(static_cast<unsigned char>(*start)))
|
||||
{
|
||||
++start;
|
||||
}
|
||||
|
||||
void updateLcdStatesIfChanged()
|
||||
const char *end = temp + strlen(temp);
|
||||
while (end > start && std::isspace(static_cast<unsigned char>(*(end - 1))))
|
||||
{
|
||||
static bool lastActionCityWaterToHose = true;
|
||||
static bool lastActionBarrelToHose = true;
|
||||
static bool lastActionBackLeftToBarrel = true;
|
||||
static bool lastActionBarrelToBackLeft = true;
|
||||
static int lastWaterLevelCm = -2;
|
||||
|
||||
if (lastActionCityWaterToHose == actionCityWaterToHose &&
|
||||
lastActionBarrelToHose == actionBarrelToHose &&
|
||||
lastActionBackLeftToBarrel == actionBackLeftToBarrel &&
|
||||
lastActionBarrelToBackLeft == actionBarrelToBackLeft &&
|
||||
lastWaterLevelCm == g_waterLevelCm)
|
||||
{
|
||||
return;
|
||||
--end;
|
||||
}
|
||||
|
||||
lastActionCityWaterToHose = actionCityWaterToHose;
|
||||
lastActionBarrelToHose = actionBarrelToHose;
|
||||
lastActionBackLeftToBarrel = actionBackLeftToBarrel;
|
||||
lastActionBarrelToBackLeft = actionBarrelToBackLeft;
|
||||
lastWaterLevelCm = g_waterLevelCm;
|
||||
|
||||
lcd.clear();
|
||||
int lcdLine = 0;
|
||||
|
||||
if (actionCityWaterToHose)
|
||||
size_t len = static_cast<size_t>(end - start);
|
||||
if (len >= outBufferSize)
|
||||
{
|
||||
lcd.setCursor(0, lcdLine++);
|
||||
lcd.print("City -> Hose ");
|
||||
len = outBufferSize - 1;
|
||||
}
|
||||
|
||||
if (actionBarrelToHose)
|
||||
{
|
||||
lcd.setCursor(0, lcdLine++);
|
||||
lcd.print("Barrel -> Hose ");
|
||||
memcpy(outBuffer, start, len);
|
||||
outBuffer[len] = '\0';
|
||||
}
|
||||
|
||||
if (actionBackLeftToBarrel)
|
||||
void addWaterLevel()
|
||||
{
|
||||
lcd.setCursor(0, lcdLine++);
|
||||
lcd.print("BackL -> Barrel ");
|
||||
char text[24];
|
||||
buildTrimmedWaterLevelText(text, sizeof(text)); // e.g. "123 cm"
|
||||
|
||||
size_t len = strlen(text);
|
||||
if (len > 20)
|
||||
{
|
||||
len = 20;
|
||||
text[20] = '\0';
|
||||
}
|
||||
|
||||
if (actionBarrelToBackLeft)
|
||||
{
|
||||
lcd.setCursor(0, lcdLine++);
|
||||
lcd.print("Barrel -> BackL ");
|
||||
}
|
||||
const uint8_t row = 3; // last row on 20x4
|
||||
const uint8_t startCol = static_cast<uint8_t>(20 - len); // right-justified
|
||||
|
||||
while (lcdLine < 3)
|
||||
{
|
||||
lcd.setCursor(0, lcdLine++);
|
||||
lcd.print(" ");
|
||||
}
|
||||
// Clear row first so old characters do not remain
|
||||
// lcd.setCursor(0, row);
|
||||
// lcd.print(" "); // 20 spaces
|
||||
|
||||
char waterLine[21];
|
||||
formatRightJustifiedWaterLine(waterLine, sizeof(waterLine));
|
||||
lcd.setCursor(0, 3);
|
||||
lcd.print(waterLine);
|
||||
}
|
||||
|
||||
void applyLatestAction(ActionId latestAction)
|
||||
{
|
||||
switch (latestAction)
|
||||
{
|
||||
case ActionId::CityWaterToHose:
|
||||
actionCityWaterToHose = !actionCityWaterToHose;
|
||||
if (actionCityWaterToHose)
|
||||
{
|
||||
actionBarrelToHose = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ActionId::BarrelToHose:
|
||||
actionBarrelToHose = !actionBarrelToHose;
|
||||
if (actionBarrelToHose)
|
||||
{
|
||||
actionCityWaterToHose = false;
|
||||
actionBarrelToBackLeft = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ActionId::BackLeftToBarrel:
|
||||
actionBackLeftToBarrel = !actionBackLeftToBarrel;
|
||||
if (actionBackLeftToBarrel)
|
||||
{
|
||||
actionBarrelToBackLeft = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ActionId::BarrelToBackLeft:
|
||||
actionBarrelToBackLeft = !actionBarrelToBackLeft;
|
||||
if (actionBarrelToBackLeft)
|
||||
{
|
||||
actionBarrelToHose = false;
|
||||
actionBackLeftToBarrel = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Allowed combinations:
|
||||
// - CityWaterToHose + BackLeftToBarrel
|
||||
// - CityWaterToHose + BarrelToBackLeft
|
||||
// - BarrelToHose + BackLeftToBarrel
|
||||
if (actionCityWaterToHose && actionBarrelToHose)
|
||||
{
|
||||
if (latestAction == ActionId::BarrelToHose)
|
||||
{
|
||||
actionCityWaterToHose = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
actionBarrelToHose = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (actionBackLeftToBarrel && actionBarrelToBackLeft)
|
||||
{
|
||||
if (latestAction == ActionId::BarrelToBackLeft)
|
||||
{
|
||||
actionBackLeftToBarrel = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
actionBarrelToBackLeft = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (actionBarrelToHose && actionBarrelToBackLeft)
|
||||
{
|
||||
if (latestAction == ActionId::BarrelToBackLeft)
|
||||
{
|
||||
actionBarrelToHose = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
actionBarrelToBackLeft = false;
|
||||
}
|
||||
}
|
||||
|
||||
rebuildCurrentState();
|
||||
// Print at exact right-justified cursor position
|
||||
lcd.setCursor(startCol, row);
|
||||
lcd.print(text);
|
||||
}
|
||||
|
||||
void IRAM_ATTR onButtonInterrupt()
|
||||
@@ -411,8 +322,7 @@ void readAndPrintButtons()
|
||||
bool buttonP6Pressed = (portValue & (1 << 6)) == 0;
|
||||
bool buttonP7Pressed = (portValue & (1 << 7)) == 0;
|
||||
|
||||
printBin(portValue);
|
||||
ActionId LastAction;
|
||||
ActionId LastAction = ActionId::Count;
|
||||
|
||||
if (buttonP3Pressed)
|
||||
{
|
||||
@@ -432,7 +342,7 @@ void readAndPrintButtons()
|
||||
}
|
||||
else if (buttonP7Pressed)
|
||||
{
|
||||
LastAction = ActionId::NotAssigned;
|
||||
// LastAction = ActionId::NotAssigned;
|
||||
}
|
||||
|
||||
Serial.printf(
|
||||
@@ -443,72 +353,13 @@ void readAndPrintButtons()
|
||||
buttonP6Pressed,
|
||||
buttonP7Pressed,
|
||||
portValue);
|
||||
|
||||
if (LastAction != ActionId::Count)
|
||||
{
|
||||
updateStateByLastAction(LastAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void readAndPrintButtons()
|
||||
// {
|
||||
// // PCF8574 button wiring:
|
||||
// // - P0 is the shared/common line and must be driven LOW.
|
||||
// // - P3..P7 are button sense lines. Pressed => line pulled LOW (active-low).
|
||||
// Wire.beginTransmission(BUTTONS_CONTROL_ADDRESS);
|
||||
// Wire.write(0b11111110); // P0 LOW, all other pins released HIGH.
|
||||
// Wire.endTransmission();
|
||||
|
||||
// Wire.requestFrom(BUTTONS_CONTROL_ADDRESS, (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;
|
||||
|
||||
// if (buttonP3Pressed && !buttonP4Pressed)
|
||||
// {
|
||||
// applyLatestAction(ActionId::CityWaterToHose);
|
||||
// }
|
||||
|
||||
// if (buttonP4Pressed && !buttonP3Pressed)
|
||||
// {
|
||||
// applyLatestAction(ActionId::BarrelToHose);
|
||||
// }
|
||||
|
||||
// if (buttonP5Pressed)
|
||||
// {
|
||||
// applyLatestAction(ActionId::BackLeftToBarrel);
|
||||
// }
|
||||
|
||||
// if (buttonP6Pressed)
|
||||
// {
|
||||
// applyLatestAction(ActionId::BarrelToBackLeft);
|
||||
// }
|
||||
|
||||
// if (buttonP7Pressed)
|
||||
// {
|
||||
// actionNotAssigned = !actionNotAssigned;
|
||||
// }
|
||||
|
||||
// Serial.printf(
|
||||
// "INT Buttons P3=%d P4=%d P5=%d P6=%d P7=%d (raw=0x%02X)\n",
|
||||
// buttonP3Pressed,
|
||||
// buttonP4Pressed,
|
||||
// buttonP5Pressed,
|
||||
// buttonP6Pressed,
|
||||
// buttonP7Pressed,
|
||||
// portValue);
|
||||
|
||||
// Serial.printf(
|
||||
// "States CityWaterToHose=%d BarrelToHose=%d BackLeftToBarrel=%d BarrelToBackLeft=%d current_stat=0x%02X current_mask=0x%02X\n",
|
||||
// actionCityWaterToHose,
|
||||
// actionBarrelToHose,
|
||||
// actionBackLeftToBarrel,
|
||||
// actionBarrelToBackLeft,
|
||||
// current_stat,
|
||||
// current_mask);
|
||||
// }
|
||||
// }
|
||||
|
||||
void pollSerial2WaterLevel()
|
||||
{
|
||||
@@ -540,6 +391,7 @@ void pollSerial2WaterLevel()
|
||||
{
|
||||
lastPrintedWaterLevelCm = waterLevelCm;
|
||||
g_waterLevelCm = waterLevelCm;
|
||||
addWaterLevel();
|
||||
Serial.printf("Water level: %d cm (%d mm)\n", waterLevelCm, data);
|
||||
}
|
||||
}
|
||||
@@ -577,7 +429,7 @@ void setup()
|
||||
|
||||
int lcdStatus = lcd.begin(20, 4);
|
||||
lcd.clear();
|
||||
updateLcdStatesIfChanged();
|
||||
// updateLcdStatesIfChanged();
|
||||
|
||||
Serial2.begin(MODBUS_BAUD, SERIAL_8N1, RXD_PIN, TXD_PIN);
|
||||
start = millis();
|
||||
@@ -603,6 +455,6 @@ void loop()
|
||||
lastSerial2PollTime = millis();
|
||||
pollSerial2WaterLevel();
|
||||
}
|
||||
updateLcdStatesIfChanged();
|
||||
// updateLcdStatesIfChanged();
|
||||
delay(10);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user