Complete rewrite of Application
This commit is contained in:
62
Button.cpp
Normal file
62
Button.cpp
Normal 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
31
Button.h
Normal 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
34
DisplayManager.cpp
Normal 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("Humidity controll");
|
||||||
|
}
|
||||||
|
|
||||||
|
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
27
DisplayManager.h
Normal 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
72
Menu.cpp
Normal 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
37
Menu.h
Normal 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
26
SensorManager.cpp
Normal 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
25
SensorManager.h
Normal 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
|
||||||
226
drybox.ino
226
drybox.ino
@@ -1,192 +1,58 @@
|
|||||||
#include <AM2302-Sensor.h>
|
#include "DisplayManager.h"
|
||||||
#include <LiquidCrystal_I2C.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};
|
Button downButton(8);
|
||||||
AM2302::AM2302_Sensor am2302{SENSOR_PIN};
|
Button upButton(9);
|
||||||
|
Button okButton(10);
|
||||||
|
Button backButton(11);
|
||||||
|
|
||||||
const int potPin = A1;
|
Menu menu;
|
||||||
const int buttonPin = 8;
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------- 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() {
|
void setup() {
|
||||||
lcd.init();
|
display.begin();
|
||||||
lcd.backlight();
|
sensor.begin();
|
||||||
|
|
||||||
am2302.begin();
|
upButton.begin();
|
||||||
|
downButton.begin();
|
||||||
pinMode(buttonPin, INPUT_PULLUP);
|
okButton.begin();
|
||||||
|
backButton.begin();
|
||||||
lcd.setCursor(0, 0);
|
|
||||||
lcd.print("System Start");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------- LOOP ----------------
|
|
||||||
void loop() {
|
void loop() {
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
|
|
||||||
handleButton();
|
upButton.update(now);
|
||||||
readSensor(now);
|
downButton.update(now);
|
||||||
updateLCD(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()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user