Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e88eee23b | ||
|
|
be6670b982 |
@@ -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
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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_;
|
||||||
|
}
|
||||||
+7
-2
@@ -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_;
|
||||||
|
|||||||
+17
-20
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user