#include <Arduino.h>
#include <Wire.h>
#include <U8g2lib.h>
#include "accessories.h"
#include "bitmaps.h"
#define RELAY_PIN 1
#define SOIL_PIN A0
// real with pot
// #define SOIL_MAX 4095
// #define SOIL_MIN 0
#define BTN 2
// for wokwi
#define SOIL_MAX 3619
#define SOIL_MIN 1680
#define PUMP RELAY_PIN
#define DEBUG
// initialization for the 128x64px OLED display
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
String lastPumpActivationTime;
void setup() {
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(PUMP, LOW);
pinMode(BTN, INPUT_PULLUP);
//set the resolution to 16 bits (0-4095)
analogReadResolution(12);
// Start serial for debugging only
#ifdef DEBUG
Serial.begin(115200);
#endif
// Initialize I2C devices
Wire.begin();
u8g2.begin();
drawStartup();
if (!initializeSensors()) {
drawError();
errorHandler();
}
}
void loop() {
// Read moisture from analog sensor
int16_t soilReading = analogRead(SOIL_PIN);
int8_t moisture = map(soilReading, SOIL_MAX, SOIL_MIN, 0, 100);
bool isPumping = watering(moisture);
int8_t temperature = getTemperature();
drawDisplay(moisture, isPumping, temperature);
}
bool watering(int8_t moisture) {
static bool previousPumpingState = LOW; // Track the previous state of the pump
bool currentPumpingState = previousPumpingState;
if (moisture > 75) {
currentPumpingState = LOW;
} else if (moisture < 20) {
currentPumpingState = HIGH;
}
if (currentPumpingState != previousPumpingState) {
digitalWrite(PUMP, currentPumpingState);
previousPumpingState = currentPumpingState;
if (currentPumpingState == HIGH) {
lastPumpActivationTime = getTime(); // Update the last activation time
}
return currentPumpingState; // Return only when the state has changed
}
return previousPumpingState; // Otherwise, return the previous state
}
void drawDisplay(uint8_t moisture, bool isPumping, int8_t temperature) {
u8g2.clearBuffer();
drawFlower(moisture);
drawMoisture(moisture);
drawThermometer();
drawTemperature(temperature);
drawTime();
drawTap(isPumping);
drawPumpStatus(isPumping);
drawBg();
u8g2.sendBuffer();
}
void drawFlower(int8_t moisture) {
u8g2.drawXBMP(16, 0, 32, 64, bitmaps_flowers[constrain(map(moisture, 0, 100, 0, 10), 0, 10)]);
}
void drawMoisture(int8_t moisture) {
char buffer[10];
int8_t str_width;
u8g2.setFont(u8g2_font_7x14_tf);
sprintf(buffer, "%d", constrain(moisture, 0, 100));
str_width = u8g2.getStrWidth(buffer);
u8g2.drawStr(32 - str_width/2, 12, buffer);
}
void drawThermometer() {
u8g2.drawXBMP(68, 5, 11, 23, epd_bitmap__thermometer);
}
void drawTemperature(int8_t temperature) {
static const /*unsigned*/ char DEGREE_CELSIUS[] = {0xB0, 0x43, 0x00};
char buffer[4];
int8_t str_width;
sprintf(buffer, "%d", temperature);
str_width = u8g2.getStrWidth(buffer);
// air temperature (text)
u8g2.setFont(u8g2_font_NokiaSmallBold_tf);
u8g2.drawStr(80, 14, "Air Temp");
// draw temperature
u8g2.setFont(u8g2_font_9x6LED_tf);
u8g2.drawStr(84, 26, buffer);
u8g2.drawStr(84 + str_width+2, 26, DEGREE_CELSIUS);
}
void drawTime() {
u8g2.setFont(u8g2_font_5x7_tf);
u8g2.drawStr(96, 58, lastPumpActivationTime.c_str());
}
void drawTap(byte isPumping) {
u8g2.drawXBMP(67, 35, 20, 18, epd_bitmap__tap);
if (isPumping) // draw water drop
u8g2.drawXBMP(80, 54, 4, 6, epd_bitmap__drop);
else { // draw X
u8g2.drawLine(80, 55-1, 84, 59-1);
u8g2.drawLine(80, 59-1, 84, 55-1);
}
}
void drawPumpStatus(byte isPumping) {
u8g2.setFont(u8g2_font_9x6LED_tf);
(isPumping) ? u8g2.drawStr(98+3, 47, "ON") : u8g2.drawStr(98, 47, "OFF");
}
void drawBg() {
u8g2.drawRFrame(65, 33, 62, 30, 3); // top_border: temp
u8g2.drawRFrame(65, 1, 62, 30, 3); // bottom_border: status
u8g2.drawRFrame(92, 50, 32, 10, 3); // time_border: clock
}
void drawStartup() {
for (int8_t i = 0; i <= 10; i++) {
u8g2.clearBuffer();
u8g2.drawXBMP(48, -5, 32, 64, bitmaps_flowers[i]);
u8g2.drawRFrame(1, 1, 126, 62, 12);
u8g2.sendBuffer();
delay(50);
}
u8g2.clear();
}
void errorHandler() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.println(F("System initialization failed!"));
while (1) {
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
}
}
void drawError() {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_NokiaSmallBold_tf);
u8g2.drawStr(15, 26, "System initialization");
u8g2.drawStr(50, 36, "failed!");
u8g2.setFont(u8g2_font_5x7_tf);
u8g2.drawStr(19, 60, "Check the sensors.");
u8g2.sendBuffer();
}
Loading
esp32-c3-devkitm-1
esp32-c3-devkitm-1