Last active
July 23, 2022 01:32
-
-
Save scottlawsonbc/3308b765e86c74b6f3c577e6f9a4ca4b to your computer and use it in GitHub Desktop.
m5stack watering unit firmware for m5stickc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include <EEPROM.h> | |
#include <M5StickC.h> | |
const int PIN_SENSOR = 33; | |
const int PIN_PUMP = 32; | |
const int PIN_BTNA = 37; | |
const int PIN_BTNB = 39; | |
struct controller { | |
int pinSensor; | |
int pinPump; | |
int pinBtnA; | |
int pinBtnB; | |
int adcWet; // Sensor value when submerged in water. | |
int adcDry; // Sensor value when in dry air. | |
int pumpOn; // Moisture percentage below which pump is turned on. | |
int pumpOff; // Moisture percentage above which pump is turned off. | |
int pumpPwr; // Current pump power state; | |
}; | |
struct controller ctl { | |
PIN_SENSOR, PIN_PUMP, PIN_BTNA, PIN_BTNB, 0, 0, 25, 75 | |
}; | |
int measureADC(controller &c) { | |
const int navg = 2048; | |
float adc = 0; | |
for (int n = 0; n < navg; n++) { | |
adc += analogRead(c.pinSensor); | |
} | |
adc /= navg; | |
return int(adc); | |
} | |
int measureMoisture(controller &c) { | |
if (c.adcWet == 0 || c.adcDry == 0) { | |
return -1; | |
} | |
int adc = measureADC(c); | |
if (adc <= c.adcWet) { | |
return 100; | |
} else if (adc >= c.adcDry) { | |
return 0; | |
} | |
return 100 - (adc - c.adcWet) * 100 / (c.adcDry - c.adcWet); | |
} | |
int isPressedA(controller &c) { | |
int64_t now = millis(); | |
while (!digitalRead(c.pinBtnA)) { | |
} | |
int64_t dt = millis() - now; | |
if (dt > 500) { | |
return 2; | |
} else if (dt > 5) { | |
return 1; | |
} else { | |
return 0; | |
} | |
} | |
int isPressedB(controller &c) { | |
int64_t now = millis(); | |
while (!digitalRead(c.pinBtnB)) { | |
} | |
int64_t dt = millis() - now; | |
if (dt > 500) { | |
return 2; | |
} else if (dt > 5) { | |
return 1; | |
} else { | |
return 0; | |
} | |
} | |
int readIntFromEEPROM(int address) { | |
byte byte1 = EEPROM.read(address); | |
byte byte2 = EEPROM.read(address + 1); | |
return (byte1 << 8) + byte2; | |
} | |
void writeIntIntoEEPROM(int address, int number) { | |
byte byte1 = number >> 8; | |
byte byte2 = number & 0xFF; | |
EEPROM.write(address, byte1); | |
EEPROM.write(address + 1, byte2); | |
} | |
void init(controller &c) { | |
EEPROM.begin(8); | |
M5.begin(); | |
M5.Lcd.setTextSize(1); | |
M5.Lcd.setRotation(1); | |
M5.Lcd.setTextColor(WHITE); | |
M5.Lcd.setCursor(0, 0); | |
M5.Lcd.fillScreen(BLACK); | |
c.adcWet = readIntFromEEPROM(0); | |
c.adcDry = readIntFromEEPROM(2); | |
c.pumpOn = EEPROM.read(4); | |
c.pumpOff = EEPROM.read(5); | |
pinMode(c.pinSensor, INPUT); | |
pinMode(c.pinPump, OUTPUT); | |
digitalWrite(c.pinPump, 0); | |
} | |
void setup() { | |
Serial.begin(115200); | |
init(ctl); | |
} | |
void loop() { | |
int moisturePercent = measureMoisture(ctl); | |
int adcRaw = measureADC(ctl); | |
M5.Lcd.fillScreen(BLACK); | |
M5.Lcd.setCursor(0, 0); | |
M5.Lcd.printf(" adcRaw %d\n" | |
" calDry %d\n" | |
" calWet %d\n" | |
" water%% %d%%\n" | |
" pumpOn <%d%%\n" | |
" pumpOff >%d%%\n" | |
" pumpPwr %s", | |
adcRaw, ctl.adcDry, ctl.adcWet, moisturePercent, ctl.pumpOn, | |
ctl.pumpOff, ctl.pumpPwr == 1 ? "ON" : "OFF"); | |
int pressedA = isPressedA(ctl); | |
int pressedB = isPressedB(ctl); | |
if (pressedA == 1) { // Short press. Change pump threshold. | |
ctl.pumpOn = (ctl.pumpOn + 5) % 95; | |
EEPROM.write(4, ctl.pumpOn); | |
EEPROM.commit(); | |
} else if (pressedA == 2) { // Long press. Calibrate sensor. | |
ctl.adcWet = adcRaw; | |
writeIntIntoEEPROM(0, ctl.adcWet); | |
EEPROM.commit(); | |
} | |
if (pressedB == 1) { // Short press. Change pump threshold. | |
ctl.pumpOff = (ctl.pumpOff + 5) % 100; | |
EEPROM.write(5, ctl.pumpOff); | |
EEPROM.commit(); | |
} else if (pressedB == 2) { // Long press. Calibrate sensor. | |
ctl.adcDry = adcRaw; | |
writeIntIntoEEPROM(2, ctl.adcDry); | |
EEPROM.commit(); | |
} | |
if (moisturePercent != -1 && moisturePercent < ctl.pumpOn) { | |
ctl.pumpPwr = 1; | |
} else if (moisturePercent > ctl.pumpOff) { | |
ctl.pumpPwr = 0; | |
} | |
digitalWrite(ctl.pinPump, ctl.pumpPwr); | |
M5.update(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment