Compare commits

...
2 Commits
8 changed files with 181 additions and 37 deletions
-13
View File
@@ -69,16 +69,3 @@ The physical wiring is already assembled. Current documented wiring is:
## Ground ## Ground
All component ground pins are connected to common `GND`. All component ground pins are connected to common `GND`.
## Assumptions To Verify Later
- The SH1106 module is compatible with the MKR1000 voltage levels
- The AM2302 is powered within its supported operating range
- The button pull-up arrangement matches the intended firmware logic
- Available pins are sufficient for the display, sensor, and both buttons
## Risks To Keep In Mind
- OLED modules may vary by interface and initialization details
- Sensor timing can be sensitive depending on the library used
- Network-based features may require retry logic and fallback screen states
+28
View File
@@ -0,0 +1,28 @@
#ifndef AM2302_SENSOR_H
#define AM2302_SENSOR_H
#include <Arduino.h>
struct Am2302Reading
{
float temperatureC;
float humidityPercent;
bool valid;
};
class Am2302Sensor
{
public:
explicit Am2302Sensor(uint8_t pin);
void begin();
bool update(unsigned long now);
Am2302Reading reading() const;
private:
uint8_t pin_;
unsigned long nextRead_;
Am2302Reading reading_;
};
#endif
+2 -1
View File
@@ -15,6 +15,7 @@ public:
Carousel(Screen *screens, size_t screenCount); Carousel(Screen *screens, size_t screenCount);
void draw(U8G2 &u8g2); void draw(U8G2 &u8g2);
bool consumeDirty(); bool consumeDirty();
void requestRedraw();
void nextScreen(); void nextScreen();
void update(unsigned long now); void update(unsigned long now);
@@ -26,4 +27,4 @@ private:
bool dirty_; bool dirty_;
}; };
#endif #endif
+13
View File
@@ -0,0 +1,13 @@
#ifndef SCREENS_H
#define SCREENS_H
#include <U8g2lib.h>
#include "am2302_sensor.h"
void drawScreen1(U8G2 &u8g2);
void setEnvironmentReading(Am2302Reading reading);
void drawEnvironmentScreen(U8G2 &u8g2);
void drawWeatherIconScreen(U8G2 &u8g2);
#endif
+48
View File
@@ -0,0 +1,48 @@
#include "am2302_sensor.h"
#include <DHT.h>
namespace
{
const unsigned long sensorReadInterval = 30000;
DHT *dht = nullptr;
}
Am2302Sensor::Am2302Sensor(uint8_t pin)
: pin_(pin),
nextRead_(0),
reading_{0.0F, 0.0F, false} {}
void Am2302Sensor::begin()
{
static DHT sensor(pin_, DHT22);
dht = &sensor;
dht->begin();
}
bool Am2302Sensor::update(unsigned long now)
{
if (now < nextRead_) {
return false;
}
nextRead_ = now + sensorReadInterval;
const float humidity = dht->readHumidity();
const float temperature = dht->readTemperature();
if (isnan(humidity) || isnan(temperature)) {
reading_.valid = false;
return true;
}
reading_.temperatureC = temperature;
reading_.humidityPercent = humidity;
reading_.valid = true;
return true;
}
Am2302Reading Am2302Sensor::reading() const
{
return reading_;
}
+8 -3
View File
@@ -5,9 +5,9 @@ const unsigned long pageInterval = 5000;
Carousel::Carousel(Screen *screens, size_t screenCount) Carousel::Carousel(Screen *screens, size_t screenCount)
: screens_(screens), : screens_(screens),
screenCount_(screenCount), screenCount_(screenCount),
dirty_(true),
currentIndex_(0), currentIndex_(0),
nextUpdate_(pageInterval) {} nextUpdate_(pageInterval),
dirty_(true) {}
void Carousel::draw(U8G2 &u8g2) void Carousel::draw(U8G2 &u8g2)
{ {
@@ -22,6 +22,11 @@ bool Carousel::consumeDirty()
return d; return d;
} }
void Carousel::requestRedraw()
{
dirty_ = true;
}
void Carousel::nextScreen() void Carousel::nextScreen()
{ {
currentIndex_ = (currentIndex_ + 1) % screenCount_; currentIndex_ = (currentIndex_ + 1) % screenCount_;
@@ -33,4 +38,4 @@ void Carousel::update(unsigned long now) {
if (now > nextUpdate_) { if (now > nextUpdate_) {
nextScreen(); nextScreen();
} }
} }
+17 -20
View File
@@ -2,33 +2,26 @@
#include <U8g2lib.h> #include <U8g2lib.h>
#include <Wire.h> #include <Wire.h>
#include "am2302_sensor.h"
#include "carousel.h" #include "carousel.h"
#include "screens.h"
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R2, U8X8_PIN_NONE); U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R2, U8X8_PIN_NONE);
int lastButtonState = LOW; int lastButtonNextState = LOW;
uint8_t buttonOne = A3; uint8_t buttonNext = A4;
Am2302Sensor am2302(A3);
int number = 0;
bool dirty = true;
void drawScreen1(U8G2 &u8g2) {
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(0, 20, "Screen 1");
}
void drawScreen2(U8G2 &u8g2) {
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(0, 40, "Screen 2");
}
Screen screens[] = { Screen screens[] = {
{ drawScreen1 }, { drawScreen1 },
{ drawScreen2 } { drawEnvironmentScreen },
{ drawWeatherIconScreen }
}; };
Carousel carousel(screens, sizeof(screens) / sizeof(screens[0])); Carousel carousel(screens, sizeof(screens) / sizeof(screens[0]));
void setup() { void setup() {
pinMode(buttonOne, INPUT); pinMode(buttonNext, INPUT);
am2302.begin();
u8g2.begin(); u8g2.begin();
u8g2.clearBuffer(); u8g2.clearBuffer();
@@ -39,12 +32,16 @@ void loop(){
const unsigned long now = millis(); const unsigned long now = millis();
carousel.update(now); carousel.update(now);
const int currentButtonState = digitalRead(buttonOne); if (am2302.update(now)) {
if (lastButtonState == LOW && currentButtonState == HIGH) { setEnvironmentReading(am2302.reading());
number += 10; carousel.requestRedraw();
}
const int currentButtonState = digitalRead(buttonNext);
if (lastButtonNextState == LOW && currentButtonState == HIGH) {
carousel.nextScreen(); carousel.nextScreen();
} }
lastButtonState = currentButtonState; lastButtonNextState = currentButtonState;
if (carousel.consumeDirty()) { if (carousel.consumeDirty()) {
u8g2.clearBuffer(); u8g2.clearBuffer();
+65
View File
@@ -0,0 +1,65 @@
#include "screens.h"
namespace
{
Am2302Reading environmentReading = {0.0F, 0.0F, false};
void drawSun(U8G2 &u8g2, uint8_t x, uint8_t y)
{
u8g2.drawDisc(x, y, 11);
u8g2.drawLine(x, y - 18, x, y - 14);
u8g2.drawLine(x, y + 14, x, y + 18);
u8g2.drawLine(x - 18, y, x - 14, y);
u8g2.drawLine(x + 14, y, x + 18, y);
u8g2.drawLine(x - 13, y - 13, x - 10, y - 10);
u8g2.drawLine(x + 10, y - 10, x + 13, y - 13);
u8g2.drawLine(x - 13, y + 13, x - 10, y + 10);
u8g2.drawLine(x + 10, y + 10, x + 13, y + 13);
}
void drawCloud(U8G2 &u8g2, uint8_t x, uint8_t y)
{
u8g2.drawDisc(x + 18, y + 14, 12);
u8g2.drawDisc(x + 34, y + 8, 17);
u8g2.drawDisc(x + 52, y + 15, 13);
u8g2.drawBox(x + 17, y + 15, 38, 14);
u8g2.drawRBox(x + 8, y + 18, 58, 15, 7);
}
}
void drawScreen1(U8G2 &u8g2)
{
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(0, 20, "Screen 1");
}
void setEnvironmentReading(Am2302Reading reading)
{
environmentReading = reading;
}
void drawEnvironmentScreen(U8G2 &u8g2)
{
u8g2.setFont(u8g2_font_6x12_tr);
u8g2.drawStr(0, 12, "AM2302");
if (!environmentReading.valid) {
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(0, 40, "No data");
return;
}
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.setCursor(0, 34);
u8g2.print(environmentReading.temperatureC, 1);
u8g2.print(" C");
u8g2.setCursor(0, 60);
u8g2.print(environmentReading.humidityPercent, 0);
u8g2.print(" %");
}
void drawWeatherIconScreen(U8G2 &u8g2)
{
drawSun(u8g2, 78, 22);
drawCloud(u8g2, 29, 24);
}