Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,43 @@ https://api.openweathermap.org/data/2.5/forecast?q=Boeblingen,de&units=metric&&a

The query string could contain cnt=N param to limit output list, but cnt=2 would mean get +3 and +6 hour forcast for today, looks there is no 'one-item-per-day' filter in the api.

#### ArduinJson
We use ArduinJson to parse the response as a stream directly after submitting the api request. Some ArduinoJson filtering is applied to further reduce the returned data.

##### ArduinJson Filter (example)
More info here: https://arduinojson.org/v6/example/filter/

Assistant:

https://arduinojson.org/v6/assistant/#

```
{
"city": true,
"list": [
{
"dt": true,
"weather": [
{
"icon": true,
"id": true
}
],
"wind": {
"speed": true
},
"main": {
"temp": true,
"temp_min": true,
"temp_max": true,
"pressure": true,
"grnd_level": true,
"humidity": true
}
}
]
}
```

## Issues
* the "middle" row of the clock digigts is somehow "mirrowed" at the top row, so it is slightly visible but not very bight.
Expand Down
47 changes: 42 additions & 5 deletions code/include/common.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#ifndef COMMON_H
#define COMMON_H

#include <array>

#include "config.h"
#include "rgb_display.h"
#include "light_sensor.h"
#include "temp_pressure_sensor.h"

#include <WiFi.h>
#include <PubSubClient.h>
Expand Down Expand Up @@ -31,9 +34,10 @@ extern HTTPClient http;
extern unsigned long lastStatusSend;

//Time of last sensor events
extern unsigned long lastSensorRead;
extern unsigned long lastLightRead;
extern unsigned long lastI2cSensorRead;
extern unsigned long lastLedBlink;
extern unsigned long lastMqttSensorRead;
extern unsigned long lastMqttSensorShow;

//Log message persistence
//Is a log message currently displayed?
Expand All @@ -53,8 +57,9 @@ extern MatrixPanel_I2S_DMA *dma_display;
extern struct tm timeinfo;

//Flags to trigger display section updates
// fixme: differentiate between external (mqtt) and internal (i2c) sensors
extern bool clockStartingUp;
extern bool newSensorData;
extern bool newMqttSensorData;
extern bool sensorDead;

//The actual sensor data
Expand All @@ -67,7 +72,10 @@ struct forecast_info {
long time;
int condition;
float temp;
float temp_min;
float temp_max;
int pressure;
int grnd_level;
int humidity;
float wind;
};
Expand All @@ -77,8 +85,8 @@ struct city_info {
long sunset;
struct forecast_info forecasts[5];
};
//extern struct forecast_info forecasts[5];
extern struct city_info my_weather;

extern struct city_info myWeather;

//Just a heartbeat for the watchdog...
extern bool heartBeat;
Expand All @@ -90,6 +98,35 @@ extern BH1750 lightSensor;
extern Adafruit_TSL2591 lightSensor;
#endif

// map sensors in the array to some name or Id !?
enum SensorId {
CO2_HOME1 = 0, // at my desk

};

enum SensorType {
TEMPERATURE = 0, /* degree celcius */
HUMIDITY, /* (rel) percentage */
PRESSURE, /* barometric pressure in Pa. */
LIGHT, /* light level in lux */
CO2 /* co2 level ppm */
};

struct MqttSensor
{
SensorType type;
unsigned long lastRead; // millis() timestamp
bool newData; // mqtt data received
bool isDead; // no new data within SENSOR_DEAD_INTERVAL_SEC

union {
int val_i;
float val_f;
};
};
typedef std::array<MqttSensor, NUM_MQTT_SENSORS> MqttSensors;

extern MqttSensors mySensors;

// utility functions
String epoch2String(unsigned long);
Expand Down
18 changes: 15 additions & 3 deletions code/include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@
#define MQTT_HOSTNAME "esp32-morphclock"
#define MQTT_CLIENT_ID MQTT_HOSTNAME
#define MQTT_REPORT_INTERVAL_MILLIS 30000
#define MQTT_SENSOR_DISPLAY_INTERVALL_SEC 10

// MQTT Topics
#define MQTT_TEMPERATURE_SENSOR_TOPIC MQTT_CLIENT_ID "/sensor/temperature"
#define MQTT_HUMIDITY_SENSOR_TOPIC MQTT_CLIENT_ID "/sensor/humidity"
#define MQTT_CO2_SENSOR_TOPIC MQTT_CLIENT_ID "/co2_ampel1/co2ppm"
//#define MQTT_CO2_SENSOR_TOPIC MQTT_CLIENT_ID "/co2_ampel1/co2ppm"
#define MQTT_CO2_SENSOR_TOPIC "co2_ampel_7448/co2ppm"
#define MQTT_STATUS_TOPIC MQTT_CLIENT_ID "/state"
#define MQTT_GENERAL_CMD_TOPIC MQTT_CLIENT_ID "/cmd"
#define MQTT_UPDATE_CMD_TOPIC MQTT_CLIENT_ID "/cmd/update"
//#define MQTT_VERSION_CMD_TOPIC MQTT_CLIENT_ID "/cmd/version"
#define MQTT_SEND_MESSAGE_TOPIC MQTT_CLIENT_ID "/message/send"
#define MQTT_BUZZER_CONFIG_TOPIC MQTT_CLIENT_ID "/buzzer/config"
#define MQTT_CONFIG_BUZZER_TOPIC MQTT_CLIENT_ID "/config/buzzer"
#define MQTT_CONFIG_BRIGHTNESS_TOPIC MQTT_CLIENT_ID "/config/brightness"

// How often we refresh the time from the NTP server
#define NTP_REFRESH_INTERVAL_SEC 3600
Expand All @@ -31,6 +34,12 @@
// DST delta to apply
#define TIMEZONE_DST_SEC 0 //3600 FIXME does DST work?! doesnt look like

// configure NTP
// https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
#define MY_NTP_SERVER "de.pool.ntp.org"
#define MY_TZ "CET-1CEST,M3.5.0,M10.5.0/3"


// How long are informational messages kept on screen
#define LOG_MESSAGE_PERSISTENCE_MSEC 30000

Expand Down Expand Up @@ -82,7 +91,7 @@
#define LIGHT_DATA_COLOR ((0x00 & 0xF8) << 8) | ((0xFF & 0xFC) << 3) | (0x00 >> 3)
//Maximum lux value that will be accepted as valid (sometimes the sensor will return erroneous values)
#define LIGHT_THRESHOLD 54612.5
#define LIGHT_READ_INTERVAL_SEC 3
#define I2C_READ_INTERVAL_SEC 5

// Log messages at the bottom
#define LOG_MESSAGE_COLOR ((0xFF & 0xF8) << 8) | ((0x00 & 0xFC) << 3) | (0x00 >> 3)
Expand All @@ -97,5 +106,8 @@
// (limited by API throttling)
#define WEATHER_REFRESH_INTERVAL_SEC 900

// number of mqtt sensor readings
#define NUM_MQTT_SENSORS 3


#endif
18 changes: 18 additions & 0 deletions code/include/config_64x64.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@
#define SENSOR_DATA_WIDTH ((PANEL_WIDTH / 2) - 2)
#define SENSOR_DATA_HEIGHT 16

// todo: change to SENSOR_1_DATA x/y, SENSOR_2_DATA x/y, and SENSOR_3_DATA x/y
#define SENSOR_1_DATA_X 0
#define SENSOR_1_DATA_Y 0
#define SENSOR_1_DATA_WIDTH ((PANEL_WIDTH / 2) - 2)
#define SENSOR_1_DATA_HEIGHT 8

#define SENSOR_2_DATA_X 0
#define SENSOR_2_DATA_Y 8
#define SENSOR_2_DATA_WIDTH ((PANEL_WIDTH / 2) - 2)
#define SENSOR_2_DATA_HEIGHT 8

#define SENSOR_3_DATA_X 0
#define SENSOR_3_DATA_Y 16
#define SENSOR_3_DATA_WIDTH ((PANEL_WIDTH / 2) - 2)
#define SENSOR_3_DATA_HEIGHT 8



// ... FIXME: adjust to 64x64 if we want to use it (merged from bogdan)
// Weather - today, and 5-day forecast
#define WEATHER_TODAY_X 56
Expand Down
1 change: 1 addition & 0 deletions code/include/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
void displayUpdater(); // Ticker callback
//void sensorUpdater(); // Ticker callback
void lightUpdate();
void i2cSensorUpdate();

#endif
4 changes: 4 additions & 0 deletions code/include/rgb_display.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#ifndef RGB_DISPLAY_H
#define RGB_DISPLAY_H


#include "config.h"
//#include "common.h"
//struct MqttSensor;
//typedef std::array<MqttSensor, NUM_MQTT_SENSORS> MqttSensors;

/* Custom board
#define R1_PIN 25
Expand Down
14 changes: 14 additions & 0 deletions code/include/temp_pressure_sensor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef TEMP_PRESSURE_SENSOR_H
#define TEMP_PRESSURE_SENSOR_H

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>


void configureTempSensor();
float getTempData();
float getPressureData();

#endif

2 changes: 1 addition & 1 deletion code/include/version.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#ifndef _PROG_VERSION_H__
#define _PROG_VERSION_H__

const char* PROG_VERSION = "0.1.1";
const char* PROG_VERSION = "0.1.4";

#endif
1 change: 1 addition & 0 deletions code/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ build_flags =
-DMATRIX_HEIGHT=64
-DMATRIX_WIDTH=64
-DLIGHT_SENSOR_BH1750=1
-DTEMP_SENSOR_BMP280=1
; -DLIGHT_SENSOR_TSL2591=1
3 changes: 2 additions & 1 deletion code/src/clock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ void displayClock() {
int hh = timeinfo.tm_hour;
int mm = timeinfo.tm_min;
int ss = timeinfo.tm_sec;
Serial.printf("%d:%d:%d\n", hh, mm, ss);
delay(500);

if (clockStartingUp) { // If we didn't have a previous time. Just draw it without morphing.
Expand Down Expand Up @@ -89,5 +90,5 @@ void displayDate() {

// fixme: for some reason the minute update clear the col 0 of the sensor data (temp),
// this call fixes the symptom ... but I don't know why we have that problem in the first place
displayWeatherData(my_weather);
displayWeatherData(myWeather);
}
16 changes: 10 additions & 6 deletions code/src/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ unsigned long lastStatusSend = 0;

//Time of last client.loop()
unsigned long lastLoop = 0;
//Time of last weather sensor data receive
unsigned long lastSensorRead = 0;
//Time of last light sensor read
unsigned long lastLightRead = 0;

unsigned long lastI2cSensorRead = 0;
//Time of last mqtt (weather) sensor data receive
unsigned long lastMqttSensorRead = 0;
// Time of last mqtt sensor data display update
unsigned long lastMqttSensorShow = 0;

// NTP
const int8_t timeZone = 2;
Expand All @@ -39,7 +40,7 @@ MatrixPanel_I2S_DMA *dma_display = nullptr;

// Flags to trigger display updates
bool clockStartingUp = true;
bool newSensorData = false;
bool newMqttSensorData = false;
bool sensorDead = true;

//Heartbeat marker
Expand All @@ -59,7 +60,10 @@ int sensorCo2Mqtt;

// 5-day forecast ids/icons (https://openweathermap.org/weather-conditions)
//struct forecast_info forecasts[5];
struct city_info my_weather;
struct city_info myWeather;

// NUM_MQTT_SENSORS sensors
MqttSensors mySensors;

String epoch2String(unsigned long t) {
char buf[32];
Expand Down
22 changes: 11 additions & 11 deletions code/src/digit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,8 @@ void Digit::Morph0() {
// ZERO
for (int i = 0; i <= segWidth; i++)
{
if (_value==1) { // If 1 to 0, slide B to F and E to C
// slide B to F
if (_value==1) { // If 1 to 0, slide B to F and E to C
// slide B to F
drawLine(segWidth - i, segHeight * 2+1 , segWidth - i, segHeight + 2, _color);
if (i > 0) drawLine(segWidth - i + 1, segHeight * 2+1, segWidth - i + 1, segHeight + 2, black);

Expand All @@ -222,36 +222,36 @@ void Digit::Morph0() {
if (i<segWidth) drawPixel(segWidth - i, segHeight * 2 + 2 , _color); // Draw A
if (i<segWidth) drawPixel(segWidth - i, 0, _color); // Draw D
}

if (_value==2) { // If 2 to 0, slide B to F and Flow G to C
// slide B to F
// slide B to F
drawLine(segWidth - i, segHeight * 2+1 , segWidth - i, segHeight + 2, _color);
if (i > 0) drawLine(segWidth - i + 1, segHeight * 2+1, segWidth - i + 1, segHeight + 2, black);

drawPixel(1+i, segHeight + 1, black); // Erase G left to right
if (i<segWidth) drawPixel(segWidth + 1, segHeight + 1- i, _color);// Draw C
}

if (_value==3) { // B to F, C to E
// slide B to F
// slide B to F
drawLine(segWidth - i, segHeight * 2+1 , segWidth - i, segHeight + 2, _color);
if (i > 0) drawLine(segWidth - i + 1, segHeight * 2+1, segWidth - i + 1, segHeight + 2, black);

// Move C to E
drawLine(segWidth - i, 1, segWidth - i, segHeight, _color);
if (i > 0) drawLine(segWidth - i + 1, 1, segWidth - i + 1, segHeight, black);

// Erase G from right to left
drawPixel(segWidth - i, segHeight + 1, black); // G
}

if (_value==5) { // If 5 to 0, we also need to slide F to B
if (i<segWidth) {
if (i>0) drawLine(1 + i, segHeight * 2 + 1, 1 + i, segHeight + 2, black);
drawLine(2 + i, segHeight * 2 + 1, 2 + i, segHeight + 2, _color);
if (i>0) drawLine(1 + i, segHeight * 2 + 1, 1 + i, segHeight + 2, black);
drawLine(2 + i, segHeight * 2 + 1, 2 + i, segHeight + 2, _color);
}
}

if (_value==5 || _value==9) { // If 9 or 5 to 0, Flow G into E
if (i<segWidth) drawPixel(segWidth - i, segHeight + 1, black);
if (i<segWidth) drawPixel(0, segHeight - i, _color);
Expand Down
Loading