Skip to content

Instantly share code, notes, and snippets.

@scottlawsonbc
Last active July 23, 2022 01:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scottlawsonbc/3308b765e86c74b6f3c577e6f9a4ca4b to your computer and use it in GitHub Desktop.
Save scottlawsonbc/3308b765e86c74b6f3c577e6f9a4ca4b to your computer and use it in GitHub Desktop.
m5stack watering unit firmware for m5stickc
#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