Complete rewrite of Application

This commit is contained in:
2026-05-04 22:30:50 +02:00
parent 507a874304
commit 1f2a0b253e
9 changed files with 360 additions and 180 deletions

62
Button.cpp Normal file
View File

@@ -0,0 +1,62 @@
#include "Button.h"
Button::Button(uint8_t pin)
: pin(pin),
stableState(HIGH),
lastReading(HIGH),
prevStableState(HIGH),
lastDebounceTime(0),
pressStart(0) {}
void Button::begin() {
pinMode(pin, INPUT_PULLUP);
stableState = digitalRead(pin);
lastReading = stableState;
prevStableState = stableState;
lastDebounceTime = millis();
if (stableState == LOW) {
pressStart = millis();
}
}
void Button::update(unsigned long now) {
prevStableState = stableState;
bool reading = digitalRead(pin);
if (reading != lastReading) {
lastDebounceTime = now;
lastReading = reading;
}
if ((now - lastDebounceTime) > debounceDelay) {
if (stableState != reading) {
stableState = reading;
// Button just became pressed (active LOW)
if (stableState == LOW) {
pressStart = now;
}
}
}
}
bool Button::pressed() {
return (prevStableState == HIGH && stableState == LOW);
}
bool Button::released() {
return (prevStableState == LOW && stableState == HIGH);
}
bool Button::isDown() {
return stableState == LOW;
}
bool Button::held(unsigned long ms) {
if (!isDown()) return false;
return (millis() - pressStart >= ms);
}

31
Button.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef BUTTON_H
#define BUTTON_H
#include <Arduino.h>
class Button {
private:
uint8_t pin;
bool stableState;
bool lastReading;
bool prevStableState;
unsigned long lastDebounceTime;
const unsigned long debounceDelay = 50;
unsigned long pressStart;
public:
Button(uint8_t pin);
void begin();
void update(unsigned long now);
bool pressed();
bool released();
bool isDown();
bool held(unsigned long ms);
};
#endif

34
DisplayManager.cpp Normal file
View File

@@ -0,0 +1,34 @@
#include "DisplayManager.h"
DisplayManager::DisplayManager()
: lcd(0x27, 16, 2), lastUpdate(0) {}
void DisplayManager::begin() {
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Drybox v0.1");
}
bool DisplayManager::ready(unsigned long now) {
if (now - lastUpdate < interval) return false;
lastUpdate = now;
return true;
}
void DisplayManager::showText(String line1, String line2) {
if (line1 == lastLine1 && line2 == lastLine2) {
return;
}
lastLine1 = line1;
lastLine2 = line2;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(line1);
lcd.setCursor(0, 1);
lcd.print(line2);
}

27
DisplayManager.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef DISPLAY_MANAGER_H
#define DISPLAY_MANAGER_H
#include <LiquidCrystal_I2C.h>
#include <Arduino.h>
class DisplayManager {
private:
LiquidCrystal_I2C lcd;
unsigned long lastUpdate;
const unsigned long interval = 1000;
String lastLine1;
String lastLine2;
public:
DisplayManager();
void begin();
bool ready(unsigned long now);
void showText(String line1, String line2);
};
#endif

72
Menu.cpp Normal file
View File

@@ -0,0 +1,72 @@
#include "Menu.h"
Menu::Menu() {
type = MENU_MAIN;
index = 0;
}
int Menu::getSize(MenuType type) {
switch (type) {
case MENU_MAIN: return MAIN_SIZE;
case MENU_SETUP: return SETUP_SIZE;
}
return 0;
}
const char* Menu::getItem(MenuType type, int index) {
switch (type) {
case MENU_MAIN:
switch (index) {
case 0: return "Start";
case 1: return "Setup";
case 2: return "Version";
}
break;
case MENU_SETUP:
switch (index) {
case 0: return "Temperature";
case 1: return "Humidity";
case 2: return "Back";
}
break;
}
return "";
}
void Menu::next() {
index = (index + 1) % getSize(type);
}
void Menu::prev() {
index--;
if (index < 0) index = getSize(type) - 1;
}
void Menu::enter() {
if (type == MENU_MAIN) {
if (index == 1) type = MENU_SETUP;
}
index = 0;
}
void Menu::back() {
if (type != MENU_MAIN) {
type = MENU_MAIN;
index = 0;
}
}
const char* Menu::getCurrent() {
return getItem(type, index);
}
const char* Menu::getNext() {
int nextIndex = (index + 1) % getSize(type);
return getItem(type, nextIndex);
}
MenuType Menu::getType() {
return type;
}

37
Menu.h Normal file
View File

@@ -0,0 +1,37 @@
#ifndef MENU_H
#define MENU_H
#include <Arduino.h>
enum MenuType {
MENU_MAIN,
MENU_SETUP,
};
class Menu {
private:
MenuType type;
int index;
static const int MAIN_SIZE = 3;
static const int SETUP_SIZE = 3;
const char* getItem(MenuType type, int index);
int getSize(MenuType type);
public:
Menu();
void next();
void prev();
void enter();
void back();
const char* getCurrent();
const char* getNext();
MenuType getType();
};
#endif

26
SensorManager.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include "SensorManager.h"
SensorManager::SensorManager(uint8_t pin)
: sensor(pin), temperature(NAN), humidity(NAN), lastRead(0) {}
void SensorManager::begin() {
sensor.begin();
}
void SensorManager::update(unsigned long now) {
if (now - lastRead < interval) return;
lastRead = now;
if (sensor.read() == AM2302::AM2302_READ_OK) {
humidity = sensor.get_Humidity();
temperature = sensor.get_Temperature();
}
}
float SensorManager::getTemp() const {
return temperature;
}
float SensorManager::getHumidity() const {
return humidity;
}

25
SensorManager.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef SENSOR_MANAGER_H
#define SENSOR_MANAGER_H
#include <AM2302-Sensor.h>
class SensorManager {
private:
AM2302::AM2302_Sensor sensor;
float temperature;
float humidity;
unsigned long lastRead;
const unsigned long interval = 2000;
public:
SensorManager(uint8_t pin);
void begin();
void update(unsigned long now);
float getTemp() const;
float getHumidity() const;
};
#endif

View File

@@ -1,192 +1,58 @@
#include <AM2302-Sensor.h>
#include <LiquidCrystal_I2C.h>
#include "DisplayManager.h"
#include "SensorManager.h"
#include "Button.h"
#include "Menu.h"
LiquidCrystal_I2C lcd(0x27, 16, 2);
DisplayManager display;
SensorManager sensor(7);
constexpr unsigned int SENSOR_PIN {7U};
AM2302::AM2302_Sensor am2302{SENSOR_PIN};
Button downButton(8);
Button upButton(9);
Button okButton(10);
Button backButton(11);
const int potPin = A1;
const int buttonPin = 8;
Menu menu;
// ---------------- STATE MACHINE ----------------
enum State {
SET_MAX_TEMP,
SET_HUMIDITY,
CONFIRM,
VIEW
};
State state = SET_MAX_TEMP;
// ---------------- SENSOR VALUES ----------------
float temperature = NAN;
float humidity = NAN;
// ---------------- SETTINGS ----------------
float maxTemperature = 30.0;
float targetHumidity = 50.0;
// ---------------- CONFIRM ----------------
bool confirmYes = false;
// ---------------- TIMING ----------------
unsigned long lastLcdUpdate = 0;
unsigned long lastSensorRead = 0;
const unsigned long lcdInterval = 500;
const unsigned long sensorInterval = 2000;
// ---------------- BUTTON ----------------
bool lastButtonState = HIGH;
// ---------------- SENSOR ----------------
void readSensor(unsigned long now) {
if (now - lastSensorRead >= sensorInterval) {
lastSensorRead = now;
if (am2302.read() == AM2302::AM2302_READ_OK) {
humidity = am2302.get_Humidity();
temperature = am2302.get_Temperature();
}
}
}
// ---------------- BUTTON HANDLER ----------------
void handleButton() {
static bool lastReading = HIGH;
static unsigned long lastDebounce = 0;
const unsigned long debounceDelay = 50;
bool reading = digitalRead(buttonPin);
if (lastReading == HIGH && reading == LOW) {
// CONFIRM LOGIC
if (state == CONFIRM) {
if (confirmYes) {
state = VIEW; // accept settings
} else {
state = SET_MAX_TEMP; // restart setup
}
}
else {
// NORMAL FLOW
if (state == SET_MAX_TEMP) {
state = SET_HUMIDITY;
}
else if (state == SET_HUMIDITY) {
state = CONFIRM;
}
else if (state == VIEW) {
state = SET_MAX_TEMP;
}
}
}
lastReading = reading;
}
// ---------------- LCD ----------------
void updateLCD(unsigned long now) {
if (now - lastLcdUpdate < lcdInterval) return;
lastLcdUpdate = now;
lcd.clear();
int potValue = analogRead(potPin);
// ---------------- SET MAX TEMP ----------------
if (state == SET_MAX_TEMP) {
maxTemperature = map(potValue, 0, 1023, 20, 60);
lcd.setCursor(0, 0);
lcd.print("Set Max Temp:");
lcd.setCursor(0, 1);
lcd.print(maxTemperature);
lcd.print(" C");
return;
}
// ---------------- SET HUMIDITY ----------------
if (state == SET_HUMIDITY) {
targetHumidity = map(potValue, 0, 1023, 0, 80);
lcd.setCursor(0, 0);
lcd.print("Set Humidity:");
lcd.setCursor(0, 1);
lcd.print(targetHumidity);
lcd.print("%");
return;
}
// ---------------- CONFIRM ----------------
if (state == CONFIRM) {
confirmYes = (potValue < 512);
lcd.setCursor(0, 0);
lcd.print("Confirm Settings");
lcd.setCursor(0, 1);
if (confirmYes) {
lcd.print("> YES NO");
} else {
lcd.print(" YES > NO");
}
return;
}
// ---------------- VIEW MODE ----------------
lcd.setCursor(0, 0);
lcd.print("AH:");
lcd.print(humidity);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("AT:");
lcd.print(temperature);
lcd.print("C");
// show target humidity
// show target
lcd.setCursor(10, 1);
lcd.print("TH:");
lcd.print(targetHumidity);
// show target
lcd.setCursor(10, 0);
lcd.print("TT:");
lcd.print(maxTemperature);
}
// ---------------- SETUP ----------------
void setup() {
lcd.init();
lcd.backlight();
display.begin();
sensor.begin();
am2302.begin();
pinMode(buttonPin, INPUT_PULLUP);
lcd.setCursor(0, 0);
lcd.print("System Start");
upButton.begin();
downButton.begin();
okButton.begin();
backButton.begin();
}
// ---------------- LOOP ----------------
void loop() {
unsigned long now = millis();
handleButton();
readSensor(now);
updateLCD(now);
upButton.update(now);
downButton.update(now);
okButton.update(now);
backButton.update(now);
sensor.update(now);
if (upButton.pressed()) {
menu.prev();
}
if (downButton.pressed()) {
menu.next();
}
if (okButton.pressed()) {
menu.enter();
}
if(backButton.pressed()) {
menu.back();
}
if (display.ready(now)) {
display.showText(
String("> ") + menu.getCurrent(),
String(" ") + menu.getNext()
);
}
}