.
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # ESP32-WeatherStationRTC
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | 
22 |
23 | 
24 |
25 |
26 |
27 | This project is an ESP32-based desk clock with functionality of monitoring the temperature, atmospheric pressure and humidity in the air. The display is auto dimmed. It is coded using the arduino framework.
28 |
29 | ## Features
30 |
31 | - **Time and date:** Utilizes the DS3231 RTC module for accurate timekeeping and displays the current time and date.
32 | - **Temperature, Humidity, and Pressure Measurement:** Uses the BME280 sensor to measure and display the current temperature, humidity, and pressure.
33 | - **Beep Sound**: Every hour the buzzer beeps.
34 | - **Automatic Brightness Adjustment:** Adjusts the LED matrix display brightness based on the ambient light level detected by the BH1750 sensor.
35 | - **WiFi Time Sync:** In case the RTC loses power, the device attempts to sync the time via an NTP server over WiFi.
36 | - **Button Control:** A button allows cycling through the display modes and turning the display on/off with a long press.
37 | - **Web Server**: A web server for change the clock settings.
38 |
39 | ## Requirements
40 |
41 |
42 |
43 | ### Hardware Requirements
44 |
45 |
46 |
47 | - **ESP32** (other arduino compatible boards are okay, just change the pins)
48 | - **MAX7219** LED matrix module (8 devices needed)
49 | - **DS3231** Real-Time Clock module
50 | - **BME280** sensor module (temperature, humidity, pressure)
51 | - **BH1750** light sensor module
52 | - **Passive Buzzer**
53 | - **(OPTIONAL) PushButton** (the default button is the BOOT button in the ESP32-DevKitC V4 devboard)
54 |
55 |
56 |
57 | ### Software Requirements
58 |
59 |
60 |
61 | - **PlatformIO**
62 | - **Python3**
63 | ## Setup
64 |
65 |
66 |
67 | ### **Software Setup:**
68 |
69 |
70 |
71 | - Install the PlatformIO IDE or PlatformIO CLI (or the VSCode extension, make sure to add ".platformio\penv\Scripts" in your path).
72 | - Connect the board to your computer.
73 | - Change the configuration in ```data/config.json```.
74 | - Build the filesystem and upload it with ```pio run --target uploadfs``` (make sure you have set the pins and addresses correctly in the configuration file, the other settings are changeable via web interface).
75 | - Compile and upload the firmware to your ESP32 board ```pio run --target upload```.
76 |
77 |
78 | ### **Hardware Setup:**
79 |
80 |
81 |
82 | - The reference board is an ESP32-DevKitC V4
83 |
84 |
85 |
86 | | PushButton | ESP32-DevKitC V4 |
87 | | ----------- | ----------- |
88 | | + | 0 |
89 | | - | GND |
90 |
91 |
92 |
93 | **N.B.** The PIN 0 is the one used by the BOOT button on the ESP32-DevKitC V4 devboard so it's not necessary using an external push button.
94 |
95 |
96 |
97 | | Buzzer | ESP32-DevKitC V4 |
98 | | ----------- | ----------- |
99 | | + | 25 |
100 | | - | GND |
101 |
102 | | I2C DEVICES| ESP32-DevKitC V4 |
103 | | ----------- | ----------- |
104 | | VCC | 3V3 |
105 | | GND | GND |
106 | | SCL | 22 |
107 | | SDA | 21 |
108 |
109 |
110 | | MAX7219 (SPI Interface) | ESP32-DevKitC V4 |
111 | | ----------- | ----------- |
112 | | VCC | 5V |
113 | | GND | GND |
114 | | CLK | 18 |
115 | | DIN | 23 |
116 | | CS | 5 |
117 |
118 |
119 |
120 | **N.B.** The two 4 devices displays needs to be connected like this:
121 |
122 |
123 |
124 | # 
125 |
126 |
127 |
128 | ## Settings
129 |
130 | - **WiFi**: you can set your network ssid and password or leave it blank (the clock tries to connect to the first open AP it finds). You can only set the ssid for an open AP.
131 |
132 | - **Supported languages**: english, italian, spanish, german, french.
133 |
134 | - **Timezone**: Timezone.h TimeChangerule format.
135 |
136 | ## First boot
137 | At the first boot the display shows "POWER LOST" and if you push the button it tries to connect to your wifi to sync the RTC with an NTP server.
138 | **So:**
139 | - Set up an AP (mobile hotspot is ok).
140 | - Press the push button on the clock.
141 | - Wait for it to connect to the server.
142 | - Press the button again.
143 |
144 | **IMPORTANT**: this procedure is necessary whenever the DS3231 loses power (i.e. when the battery runs out or one is not inserted and the ESP32 loses power).
145 |
146 | ## Usage
147 |
148 | - The device will automatically display the time and temperature upon startup.
149 | - Press the button to cycle through the different display modes:
150 | - time & temperature (in Celsius)
151 | - date (DDD DD MMM YYYY)
152 | - humidity & pressure (in hPa)
153 | - Hold the button for more than 500ms to turn off the display. Press again to turn it back on.
154 |
155 | ## WebServer
156 | You can reach the web server connecting to
157 | - SSID:```ESP32WeatherStation```
158 | - PASSWORD: ```SuP3r_S3cr3t_P@ssw0rd!```
159 |
160 | at the ```10.10.10.10``` IP address.
161 |
162 |
163 |
164 | ## Home page
165 |
166 | 
167 |
168 |
169 |
170 |
171 |
172 | ## Settings page
173 |
174 | 
175 |
176 |
177 |
178 | ## License
179 |
180 | This project is licensed under the GNU GENERAL PUBLIC LICENSE - see the LICENSE file for details.
181 |
182 | ## Credits
183 | [Leonardo Mirabella](https://github.com/infra-blue)
184 |
--------------------------------------------------------------------------------
/assets/clock.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infra-blue/ESP32-WeatherStationRTC/f16f886171b7d1520c1a2bf1b2ff55aa0ad9808f/assets/clock.gif
--------------------------------------------------------------------------------
/assets/desktop.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infra-blue/ESP32-WeatherStationRTC/f16f886171b7d1520c1a2bf1b2ff55aa0ad9808f/assets/desktop.jpg
--------------------------------------------------------------------------------
/assets/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infra-blue/ESP32-WeatherStationRTC/f16f886171b7d1520c1a2bf1b2ff55aa0ad9808f/assets/home.png
--------------------------------------------------------------------------------
/assets/schematic_display.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infra-blue/ESP32-WeatherStationRTC/f16f886171b7d1520c1a2bf1b2ff55aa0ad9808f/assets/schematic_display.png
--------------------------------------------------------------------------------
/assets/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infra-blue/ESP32-WeatherStationRTC/f16f886171b7d1520c1a2bf1b2ff55aa0ad9808f/assets/settings.png
--------------------------------------------------------------------------------
/data/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "I2C_ADDR": {
3 | "BME_280": 118,
4 | "BH1750": 35,
5 | "DS3231": 104
6 | },
7 |
8 | "MAX7219_PINS": {
9 | "CLK_PIN": 18,
10 | "DATA_PIN": 23,
11 | "CS_PIN": 5
12 | },
13 |
14 | "PINS": {
15 | "BUTTON_PIN": 0,
16 | "BUZZER_PIN": 25
17 | },
18 |
19 | "STD_TIME": {
20 | "abbrev": "CET",
21 | "week": 0,
22 | "dow": 1,
23 | "month": 10,
24 | "hour": 3,
25 | "offset": 60
26 | },
27 |
28 | "DL_TIME": {
29 | "abbrev": "CEST",
30 | "week": 0,
31 | "dow": 1,
32 | "month": 3,
33 | "hour": 2,
34 | "offset": 120
35 | },
36 |
37 | "NTP_SERVER": "pool.ntp.org",
38 |
39 | "LANGUAGE": "en",
40 |
41 | "BUZZ_SOUND": true,
42 |
43 | "FAHRENHEIT": false,
44 |
45 | "WIFI": {
46 | "SSID": "",
47 | "PASSWORD": ""
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/data/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ESP32 Home
7 |
108 |
109 |
110 |
111 | ESP32 WeatherStation Home
112 |
113 |
116 |
119 |
122 |
123 |
124 |
127 |
130 |
131 |
145 |
146 |
--------------------------------------------------------------------------------
/data/settings.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ESP32 Settings
7 |
108 |
109 |
110 | ESP32 WeatherStation Settings
111 |
114 |
115 |
125 |
126 |
134 |
140 |
141 |
155 |
156 |
157 |
244 |
245 |
246 |
263 |
264 |
--------------------------------------------------------------------------------
/include/Macros.h:
--------------------------------------------------------------------------------
1 | #define WIRE_ERR "Check wiring!"
2 |
3 | #define MAX7219_ERR "Could not find MAX7219!"
4 | #define DS3231_ERR "Could not find DS3231 RTC!"
5 | #define BME280_ERR "Could not find BME280 sensor!"
6 | #define BH1750_ERR "Could not find BH1750 sensor!"
7 |
8 | #define RTC_POWER_LOST "RTC lost power. Press the button for trying to set the time."
9 |
10 | #define SPIFFS_ERR "Failed to mount SPIFFS."
11 | #define SPIFFS_SUC "SPIFFS mounted successfully."
12 |
13 | #define MAX7219_DEVICES 8
14 | #define HW_TYPE MD_MAX72XX::FC16_HW
15 |
16 | #define AP_NAME "ESP32WeatherStation"
17 | #define AP_PASSWORD "SuP3r_S3cr3t_P@ssw0rd!"
18 |
19 | #define IP_ADDRESS 10, 10, 10, 10
20 | #define GATEWAY 10, 10, 10, 10
21 | #define SUBNET 255, 255, 255, 0
22 |
--------------------------------------------------------------------------------
/lib/Beep/Beep.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 |
5 | #include "Beep.h"
6 |
7 | void beep_sound() {
8 | int beep[] = {8156, 0, 8156};
9 |
10 | for (int thisNote = 0; thisNote < (sizeof(beep) / sizeof(beep[0])); thisNote++) {
11 | tone(conf.pins.BUZZER_PIN, beep[thisNote], 110);
12 | noTone(conf.pins.BUZZER_PIN);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/lib/Beep/Beep.h:
--------------------------------------------------------------------------------
1 | #ifndef BEEP_H
2 | #define BEEP_H
3 |
4 | extern Config conf;
5 |
6 | void beep_sound();
7 |
8 | #endif
9 |
--------------------------------------------------------------------------------
/lib/Config_Parser/Config_Parser.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "Config_Parser.h"
6 |
7 | void printConfiguration(Config config) {
8 | Serial.printf("Standard TimeChangeRule:\n");
9 | Serial.printf(" Abbreviation: %s\n", config.std.abbrev);
10 | Serial.printf(" Week: %d\n", config.std.week);
11 | Serial.printf(" Day of Week: %d\n", config.std.dow);
12 | Serial.printf(" Month: %d\n", config.std.month);
13 | Serial.printf(" Hour: %d\n", config.std.hour);
14 | Serial.printf(" Offset: %d\n", config.std.offset);
15 |
16 | Serial.printf("Daylight TimeChangeRule:\n");
17 | Serial.printf(" Abbreviation: %s\n", config.dlt.abbrev);
18 | Serial.printf(" Week: %d\n", config.dlt.week);
19 | Serial.printf(" Day of Week: %d\n", config.dlt.dow);
20 | Serial.printf(" Month: %d\n", config.dlt.month);
21 | Serial.printf(" Hour: %d\n", config.dlt.hour);
22 | Serial.printf(" Offset: %d\n", config.dlt.offset);
23 |
24 | Serial.printf("I2C Addresses:\n");
25 | Serial.printf(" BME_280: %d\n", config.i2c.BME_280);
26 | Serial.printf(" BH1750: %d\n", config.i2c.BH1750);
27 | Serial.printf(" DS3231: %d\n", config.i2c.DS3231);
28 |
29 | Serial.printf("MAX7219 Pins:\n");
30 | Serial.printf(" CLK_PIN: %d\n", config.max7219.CLK_PIN);
31 | Serial.printf(" DATA_PIN: %d\n", config.max7219.DATA_PIN);
32 | Serial.printf(" CS_PIN: %d\n", config.max7219.CS_PIN);
33 |
34 | Serial.printf("Other Pins:\n");
35 | Serial.printf(" BUTTON_PIN: %d\n", config.pins.BUTTON_PIN);
36 | Serial.printf(" BUZZER_PIN: %d\n", config.pins.BUZZER_PIN);
37 |
38 | Serial.printf("NTP Server: %s\n", config.ntpServer);
39 | Serial.printf("Language: %s\n", config.language);
40 | Serial.printf("Buzzer Sound: %s\n", config.buzzSound ? "true" : "false");
41 | Serial.printf("Fahrenheit: %s\n", config.fahrenheit ? "true" : "false");
42 |
43 | Serial.printf("WiFi Credentials:\n");
44 | Serial.printf(" SSID: %s\n", config.wifi.SSID);
45 | Serial.printf(" Password: %s\n", config.wifi.PASSWORD);
46 | }
47 |
48 | void loadConfiguration(Config& config) {
49 | File file = SPIFFS.open(PATH_TO_CONF, FILE_READ);
50 | JsonDocument conf;
51 |
52 | DeserializationError error = deserializeJson(conf, file);
53 | if (error)
54 | Serial.println(F("Failed to read file, using default configuration"));
55 |
56 | strlcpy(config.std.abbrev,
57 | conf["STD_TIME"]["abbrev"] | "STD",
58 | sizeof(config.std.abbrev));
59 |
60 | config.std.week = conf["STD_TIME"]["week"] | 1;
61 | config.std.dow = conf["STD_TIME"]["dow"] | 1;
62 | config.std.month = conf["STD_TIME"]["month"] | 1;
63 | config.std.hour = conf["STD_TIME"]["hour"] | 1;
64 | config.std.offset = conf["STD_TIME"]["offset"] | 0;
65 |
66 | strlcpy(config.dlt.abbrev,
67 | conf["DL_TIME"]["abbrev"] | "DLT",
68 | sizeof(config.dlt.abbrev));
69 |
70 | config.dlt.week = conf["DL_TIME"]["week"] | 1;
71 | config.dlt.dow = conf["DL_TIME"]["dow"] | 1;
72 | config.dlt.month = conf["DL_TIME"]["month"] | 1;
73 | config.dlt.hour = conf["DL_TIME"]["hour"] | 1;
74 | config.dlt.offset = conf["DL_TIME"]["offset"] | 0;
75 |
76 | config.i2c.BME_280 = conf["I2C_ADDR"]["BME_280"] | 118;
77 | config.i2c.BH1750 = conf["I2C_ADDR"]["BH1750"] | 35;
78 | config.i2c.DS3231 = conf["I2C_ADDR"]["DS3231"] | 104;
79 |
80 | config.max7219.CLK_PIN = conf["MAX7219_PINS"]["CLK_PIN"] | 18;
81 | config.max7219.DATA_PIN = conf["MAX7219_PINS"]["DATA_PIN"] | 23;
82 | config.max7219.CS_PIN = conf["MAX7219_PINS"]["CS_PIN"] | 5;
83 |
84 | config.pins.BUTTON_PIN = conf["PINS"]["BUTTON_PIN"] | 0;
85 | config.pins.BUZZER_PIN = conf["PINS"]["BUZZER_PIN"] | 14;
86 |
87 | strlcpy(config.ntpServer,
88 | conf["NTP_SERVER"] | "pool.ntp.org",
89 | sizeof(config.ntpServer));
90 |
91 | strlcpy(config.language,
92 | conf["LANGUAGE"] | "en",
93 | sizeof(config.language));
94 |
95 | config.buzzSound = conf["BUZZ_SOUND"] | true;
96 |
97 | config.fahrenheit = conf["FAHRENHEIT"] | false;
98 |
99 | strlcpy(config.wifi.SSID,
100 | conf["WIFI"]["SSID"] | "",
101 | sizeof(config.wifi.SSID));
102 |
103 | strlcpy(config.wifi.PASSWORD,
104 | conf["WIFI"]["PASSWORD"] | "",
105 | sizeof(config.wifi.PASSWORD));
106 |
107 | file.close();
108 | }
109 |
110 | void storeConfiguration(Config config) {
111 | SPIFFS.remove(PATH_TO_CONF);
112 |
113 | File file = SPIFFS.open(PATH_TO_CONF, FILE_WRITE);
114 | if (!file) {
115 | Serial.println(F("Failed to create file"));
116 | return;
117 | }
118 |
119 | JsonDocument conf;
120 |
121 | conf["STD_TIME"]["abbrev"] = config.std.abbrev;
122 | conf["STD_TIME"]["week"] = config.std.week;
123 | conf["STD_TIME"]["dow"] = config.std.dow;
124 | conf["STD_TIME"]["month"] = config.std.month;
125 | conf["STD_TIME"]["hour"] = config.std.hour;
126 | conf["STD_TIME"]["offset"] = config.std.offset;
127 |
128 | conf["DL_TIME"]["abbrev"] = config.dlt.abbrev;
129 | conf["DL_TIME"]["week"] = config.dlt.week;
130 | conf["DL_TIME"]["dow"] = config.dlt.dow;
131 | conf["DL_TIME"]["month"] = config.dlt.month;
132 | conf["DL_TIME"]["hour"] = config.dlt.hour;
133 | conf["DL_TIME"]["offset"] = config.dlt.offset;
134 |
135 | conf["I2C_ADDR"]["BME_280"] = config.i2c.BME_280;
136 | conf["I2C_ADDR"]["BH1750"] = config.i2c.BH1750;
137 | conf["I2C_ADDR"]["DS3231"] = config.i2c.DS3231;
138 |
139 | conf["MAX7219_PINS"]["CLK_PIN"] = config.max7219.CLK_PIN;
140 | conf["MAX7219_PINS"]["DATA_PIN"] = config.max7219.DATA_PIN;
141 | conf["MAX7219_PINS"]["CS_PIN"] = config.max7219.CS_PIN;
142 |
143 | conf["PINS"]["BUTTON_PIN"] = config.pins.BUTTON_PIN;
144 | conf["PINS"]["BUZZER_PIN"] = config.pins.BUZZER_PIN;
145 |
146 | conf["NTP_SERVER"] = config.ntpServer;
147 | conf["LANGUAGE"] = config.language;
148 | conf["BUZZ_SOUND"] = config.buzzSound;
149 | conf["FAHRENHEIT"] = config.fahrenheit;
150 |
151 | conf["WIFI"]["SSID"] = config.wifi.SSID;
152 | conf["WIFI"]["PASSWORD"] = config.wifi.PASSWORD;
153 |
154 | if (serializeJson(conf, file) == 0) {
155 | Serial.println(F("Failed to write to file"));
156 | }
157 |
158 | file.close();
159 | }
160 |
--------------------------------------------------------------------------------
/lib/Config_Parser/Config_Parser.h:
--------------------------------------------------------------------------------
1 | #ifndef CONFIG_PARSER_H
2 | #define CONFIG_PARSER_H
3 |
4 | #define PATH_TO_CONF "/config.json"
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | struct I2CADDR {
12 | uint8_t BME_280;
13 | uint8_t BH1750;
14 | uint8_t DS3231;
15 | };
16 |
17 | struct MAX7219PINS {
18 | uint8_t CLK_PIN;
19 | uint8_t DATA_PIN;
20 | uint8_t CS_PIN;
21 | };
22 |
23 | struct PINS {
24 | uint8_t BUTTON_PIN;
25 | uint8_t BUZZER_PIN;
26 | };
27 |
28 | struct WIFI_CRED {
29 | char SSID[32];
30 | char PASSWORD[32];
31 | };
32 |
33 | struct Config {
34 | TimeChangeRule std;
35 | TimeChangeRule dlt;
36 | I2CADDR i2c;
37 | MAX7219PINS max7219;
38 | PINS pins;
39 | char ntpServer[64];
40 | char language[3];
41 | bool buzzSound;
42 | bool fahrenheit;
43 | WIFI_CRED wifi;
44 | };
45 |
46 | void loadConfiguration(Config& config);
47 | void storeConfiguration(Config config);
48 | void printConfiguration(Config config);
49 |
50 | #endif
--------------------------------------------------------------------------------
/lib/Font_Data/Font_Data.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Font_Data.h"
3 |
4 | MD_MAX72XX::fontType_t small_font[] PROGMEM =
5 | {
6 | 0, // 0
7 | 0, // 1
8 | 0, // 2
9 | 0, // 3
10 | 0, // 4
11 | 0, // 5
12 | 0, // 6
13 | 0, // 7
14 | 0, // 8
15 | 0, // 9
16 | 0, // 10
17 | 0, // 11
18 | 0, // 12
19 | 0, // 13
20 | 0, // 14
21 | 0, // 15
22 | 0, // 16
23 | 0, // 17
24 | 0, // 18
25 | 0, // 19
26 | 0, // 20
27 | 0, // 21
28 | 0, // 22
29 | 0, // 23
30 | 0, // 24
31 | 0, // 25
32 | 0, // 26
33 | 0, // 27
34 | 0, // 28
35 | 0, // 29
36 | 0, // 30
37 | 0, // 31
38 | 1, 0, // 32 - 'Space'
39 | 0, // 33 - '!'
40 | 0, // 34 - '"'
41 | 0, // 35 - '#'
42 | 0, // 36 - '$'
43 | 0, // 37 - '%'
44 | 0, // 38 - '&'
45 | 0, // 39 - '''
46 | 0, // 40 - '('
47 | 0, // 41 - ')'
48 | 0, // 42 - '*'
49 | 0, // 43 - '+'
50 | 0, // 44 '
51 | 0, // 45 - '-'
52 | 1, 64, // 46 - '.'
53 | 0, // 47 - '/'
54 | 3, 62, 34, 62, // 48 - '0'
55 | 3, 36, 62, 32, // 49 - '1'
56 | 3, 58, 42, 46, // 50 - '2'
57 | 3, 42, 42, 62, // 51 - '3'
58 | 3, 14, 8, 62, // 52 - '4'
59 | 3, 46, 42, 58, // 53 - '5'
60 | 3, 62, 42, 58, // 54 - '6'
61 | 3, 6, 2, 62, // 55 - '7'
62 | 3, 62, 42, 62, // 56 - '8'
63 | 3, 46, 42, 62, // 57 - '9'
64 | 1, 20, // 58 - ':'
65 | 0, // 59 - ';'
66 | 0, // 60 - '<'
67 | 0, // 61 - '='
68 | 0, // 62 - '>'
69 | 0, // 63 - '?'
70 | 0, // 64 - '@'
71 | 4, 60, 18, 18, 60, // 65 - 'A'
72 | 4, 62, 42, 42, 20, // 66 - 'B'
73 | 4, 28, 34, 34, 34, // 67 - 'C'
74 | 4, 62, 34, 34, 28, // 68 - 'D'
75 | 4, 62, 42, 42, 42, // 69 - 'E'
76 | 4, 62, 10, 10, 10, // 70 - 'F'
77 | 4, 28, 34, 34, 50, // 71 - 'G'
78 | 4, 62, 8, 8, 62, // 72 - 'H'
79 | 1, 62, // 73 - 'I'
80 | 4, 48, 32, 32, 62, // 74 - 'J'
81 | 4, 62, 8, 20, 34, // 75 - 'K'
82 | 4, 62, 32, 32, 32, // 76 - 'L'
83 | 4, 62, 4, 4, 62, // 77 - 'M'
84 | 4, 62, 4, 8, 62, // 78 - 'N'
85 | 4, 28, 34, 34, 28, // 79 - 'O'
86 | 4, 62, 10, 10, 14, // 80 - 'P'
87 | 4, 62, 34, 18, 46, // 81 - 'Q'
88 | 4, 62, 10, 26, 36, // 82 - 'R'
89 | 4, 36, 42, 42, 18, // 83 - 'S'
90 | 3, 2, 62, 2, // 84 - 'T'
91 | 4, 62, 32, 32, 62, // 85 - 'U'
92 | 4, 30, 48, 48, 30, // 86 - 'V'
93 | 4, 62, 16, 16, 62, // 87 - 'W'
94 | 4, 54, 8, 8, 54, // 88 - 'X'
95 | 3, 6, 56, 6, // 89 - 'Y'
96 | 4, 50, 42, 42, 38, // 90 - 'Z'
97 | 0, // 91 - '['
98 | 0, // 92 - '\'
99 | 0, // 93 - ']'
100 | 0, // 94 - '^'
101 | 0, // 95 - '_'
102 | 0, // 96 - '`'
103 | 4, 60, 18, 18, 60, // 97 - 'a'
104 | 4, 62, 42, 42, 20, // 98 - 'b'
105 | 4, 28, 34, 34, 34, // 99 - 'c'
106 | 4, 62, 34, 34, 28, // 100 - 'd'
107 | 4, 62, 42, 42, 42, // 101 - 'e'
108 | 4, 62, 10, 10, 10, // 102 - 'f'
109 | 4, 28, 34, 34, 50, // 103 - 'g'
110 | 4, 62, 8, 8, 62, // 104 - 'h'
111 | 1, 62, // 105 - 'i'
112 | 4, 48, 32, 32, 62, // 106 - 'j'
113 | 4, 62, 8, 20, 34, // 107 - 'k'
114 | 4, 62, 32, 32, 32, // 108 - 'l'
115 | 4, 62, 4, 4, 62, // 109 - 'm'
116 | 4, 62, 4, 8, 62, // 110 - 'n'
117 | 4, 28, 34, 34, 28, // 111 - 'o'
118 | 4, 62, 10, 10, 14, // 112 - 'p'
119 | 4, 62, 34, 18, 46, // 113 - 'q'
120 | 4, 62, 10, 26, 36, // 114 - 'r'
121 | 4, 36, 42, 42, 18, // 115 - 's'
122 | 3, 2, 62, 2, // 116 - 't'
123 | 4, 62, 32, 32, 62, // 117 - 'u'
124 | 4, 30, 48, 48, 30, // 118 - 'v'
125 | 4, 62, 16, 16, 62, // 119 - 'w'
126 | 4, 54, 8, 8, 54, // 120 - 'x'
127 | 3, 6, 56, 6, // 121 - 'y'
128 | 4, 50, 42, 42, 38, // 122 - 'z'
129 | 0, // 123
130 | 0, // 124
131 | 0, // 125
132 | 0, // 126
133 | 0, // 127
134 | 0, // 128
135 | 0, // 129
136 | 0, // 130
137 | 0, // 131
138 | 0, // 132
139 | 0, // 133
140 | 0, // 134
141 | 0, // 135
142 | 0, // 136
143 | 0, // 137
144 | 0, // 138
145 | 0, // 139
146 | 0, // 140
147 | 0, // 141
148 | 0, // 142
149 | 0, // 143
150 | 0, // 144
151 | 0, // 145
152 | 0, // 146
153 | 0, // 147
154 | 0, // 148
155 | 0, // 149
156 | 0, // 150
157 | 0, // 151
158 | 0, // 152
159 | 0, // 153
160 | 0, // 154
161 | 0, // 155
162 | 0, // 156
163 | 0, // 157
164 | 0, // 158
165 | 0, // 159
166 | 0, // 160
167 | 0, // 161
168 | 0, // 162
169 | 0, // 163
170 | 0, // 164
171 | 0, // 165
172 | 0, // 166
173 | 0, // 167
174 | 0, // 168
175 | 0, // 169
176 | 0, // 170
177 | 0, // 171
178 | 0, // 172
179 | 0, // 173
180 | 0, // 174
181 | 0, // 175
182 | 0, // 176
183 | 0, // 177
184 | 0, // 178
185 | 0, // 179
186 | 0, // 180
187 | 0, // 181
188 | 0, // 182
189 | 0, // 183
190 | 0, // 184
191 | 0, // 185
192 | 0, // 186
193 | 0, // 187
194 | 0, // 188
195 | 0, // 189
196 | 0, // 190
197 | 0, // 191
198 | 0, // 192
199 | 0, // 193
200 | 0, // 194
201 | 0, // 195
202 | 0, // 196
203 | 0, // 197
204 | 0, // 198
205 | 0, // 199
206 | 0, // 200
207 | 0, // 201
208 | 0, // 202
209 | 0, // 203
210 | 0, // 204
211 | 0, // 205
212 | 0, // 206
213 | 0, // 207
214 | 0, // 208
215 | 0, // 209
216 | 0, // 210
217 | 0, // 211
218 | 0, // 212
219 | 0, // 213
220 | 0, // 214
221 | 0, // 215
222 | 0, // 216
223 | 0, // 217
224 | 0, // 218
225 | 0, // 219
226 | 0, // 220
227 | 0, // 221
228 | 0, // 222
229 | 0, // 223
230 | 0, // 224
231 | 0, // 225
232 | 0, // 226
233 | 0, // 227
234 | 0, // 228
235 | 0, // 229
236 | 0, // 230
237 | 0, // 231
238 | 0, // 232
239 | 0, // 233
240 | 0, // 234
241 | 0, // 235
242 | 0, // 236
243 | 0, // 237
244 | 0, // 238
245 | 0, // 239
246 | 0, // 240
247 | 0, // 241
248 | 0, // 242
249 | 0, // 243
250 | 0, // 244
251 | 0, // 245
252 | 0, // 246
253 | 0, // 247
254 | 0, // 248
255 | 0, // 249
256 | 0, // 250
257 | 0, // 251
258 | 0, // 252
259 | 0, // 253
260 | 0, // 254
261 | 0, // 255
262 | };
263 |
264 | MD_MAX72XX::fontType_t pixel_font[] PROGMEM =
265 | {
266 | 0, // 0
267 | 0, // 1
268 | 0, // 2
269 | 0, // 3
270 | 0, // 4
271 | 0, // 5
272 | 0, // 6
273 | 0, // 7
274 | 0, // 8
275 | 0, // 9
276 | 0, // 10
277 | 0, // 11
278 | 0, // 12
279 | 0, // 13
280 | 0, // 14
281 | 0, // 15
282 | 0, // 16
283 | 0, // 17
284 | 0, // 18
285 | 0, // 19
286 | 0, // 20
287 | 0, // 21
288 | 0, // 22
289 | 0, // 23
290 | 0, // 24
291 | 0, // 25
292 | 0, // 26
293 | 0, // 27
294 | 0, // 28
295 | 0, // 29
296 | 0, // 30
297 | 0, // 31
298 | 1, 0, // 32 - 'Space'
299 | 1, 95, // 33 - '!'
300 | 4, 4, 3, 4, 3, // 34 - '"'
301 | 5, 20, 127, 20, 127, 20, // 35 - '#'
302 | 5, 4, 42, 107, 42, 16, // 36 - '$'
303 | 5, 70, 54, 8, 54, 49, // 37 - '%'
304 | 5, 48, 74, 93, 50, 72, // 38 - '&'
305 | 2, 4, 3, // 39 - '''
306 | 3, 28, 34, 65, // 40 - '('
307 | 3, 65, 34, 28, // 41 - ')'
308 | 4, 5, 2, 2, 5, // 42 - '*'
309 | 5, 16, 16, 124, 16, 16, // 43 - '+'
310 | 1, 96, // 44 '
311 | 5, 16, 16, 16, 16, 16, // 45 - '-'
312 | 1, 64, // 46 - '.'
313 | 5, 64, 48, 8, 6, 1, // 47 - '/'
314 | 4, 127, 81, 73, 127, // 48 - '0'
315 | 4, 0, 66, 127, 64, // 49 - '1'
316 | 4, 121, 73, 73, 79, // 50 - '2'
317 | 4, 99, 73, 73, 119, // 51 - '3'
318 | 4, 15, 8, 8, 127, // 52 - '4'
319 | 4, 79, 73, 73, 121, // 53 - '5'
320 | 4, 127, 73, 73, 121, // 54 - '6'
321 | 4, 3, 1, 125, 3, // 55 - '7'
322 | 4, 119, 73, 73, 119, // 56 - '8'
323 | 4, 79, 73, 73, 127, // 57 - '9'
324 | 1, 20, // 58 - ':'
325 | 1, 88, // 59 - ';'
326 | 3, 16, 40, 68, // 60 - '<'
327 | 5, 40, 40, 40, 40, 40, // 61 - '='
328 | 3, 68, 40, 16, // 62 - '>'
329 | 5, 6, 1, 81, 9, 6, // 63 - '?'
330 | 6, 62, 65, 93, 93, 81, 30, // 64 - '@'
331 | 5, 126, 127, 17, 17, 126, // 65 - 'A'
332 | 5, 127, 127, 73, 73, 54, // 66 - 'B'
333 | 5, 62, 127, 65, 65, 34, // 67 - 'C'
334 | 5, 127, 127, 65, 65, 62, // 68 - 'D'
335 | 5, 127, 127, 73, 73, 73, // 69 - 'E'
336 | 5, 127, 127, 9, 9, 9, // 70 - 'F'
337 | 5, 62, 127, 65, 73, 58, // 71 - 'G'
338 | 5, 127, 127, 8, 8, 127, // 72 - 'H'
339 | 2, 127, 127, // 73 - 'I'
340 | 5, 32, 64, 64, 127, 63, // 74 - 'J'
341 | 5, 127, 127, 8, 20, 99, // 75 - 'K'
342 | 5, 127, 127, 64, 64, 64, // 76 - 'L'
343 | 6, 127, 127, 2, 4, 2, 127, // 77 - 'M'
344 | 6, 127, 127, 4, 8, 16, 127, // 78 - 'N'
345 | 5, 62, 127, 65, 65, 62, // 79 - 'O'
346 | 5, 127, 127, 17, 17, 14, // 80 - 'P'
347 | 5, 62, 127, 65, 33, 94, // 81 - 'Q'
348 | 5, 127, 127, 25, 41, 70, // 82 - 'R'
349 | 5, 38, 79, 73, 121, 50, // 83 - 'S'
350 | 6, 1, 1, 127, 127, 1, 1, // 84 - 'T'
351 | 5, 63, 127, 64, 64, 63, // 85 - 'U'
352 | 5, 31, 63, 96, 32, 31, // 86 - 'V'
353 | 6, 63, 63, 96, 48, 96, 63, // 87 - 'W'
354 | 6, 113, 123, 14, 4, 10, 113, // 88 - 'X'
355 | 8, 1, 3, 126, 124, 2, 1, 0, 0, // 89 - 'Y'
356 | 8, 97, 113, 93, 71, 67, 0, 0, 0, // 90 - 'Z'
357 | 3, 127, 65, 65, // 91 - '['
358 | 5, 1, 6, 8, 48, 64, // 92 - '\'
359 | 3, 65, 65, 127, // 93 - ']'
360 | 3, 6, 1, 6, // 94 - '^'
361 | 3, 64, 64, 64, // 95 - '_'
362 | 2, 1, 6, // 96 - '`'
363 | 5, 126, 127, 17, 17, 126, // 97 - 'a'
364 | 5, 127, 127, 73, 73, 54, // 98 - 'b'
365 | 5, 62, 127, 65, 65, 34, // 99 - 'c'
366 | 5, 127, 127, 65, 65, 62, // 100 - 'd'
367 | 5, 127, 127, 73, 73, 73, // 101 - 'e'
368 | 5, 127, 127, 9, 9, 9, // 102 - 'f'
369 | 5, 62, 127, 65, 73, 58, // 103 - 'g'
370 | 5, 127, 127, 8, 8, 127, // 104 - 'h'
371 | 2, 127, 127, // 105 - 'i'
372 | 5, 32, 64, 64, 127, 63, // 106 - 'j'
373 | 5, 127, 127, 8, 20, 99, // 107 - 'k'
374 | 5, 127, 127, 64, 64, 64, // 108 - 'l'
375 | 6, 127, 127, 2, 4, 2, 127, // 109 - 'm'
376 | 6, 127, 127, 4, 8, 16, 127, // 110 - 'n'
377 | 5, 62, 127, 65, 65, 62, // 111 - 'o'
378 | 5, 127, 127, 17, 17, 14, // 112 - 'p'
379 | 5, 62, 127, 65, 33, 94, // 113 - 'q'
380 | 5, 127, 127, 25, 41, 70, // 114 - 'r'
381 | 5, 38, 79, 73, 121, 50, // 115 - 's'
382 | 6, 1, 1, 127, 127, 1, 1, // 116 - 't'
383 | 5, 63, 127, 64, 64, 63, // 117 - 'u'
384 | 5, 31, 63, 96, 32, 31, // 118 - 'v'
385 | 6, 63, 63, 96, 48, 96, 63, // 119 - 'w'
386 | 6, 113, 123, 14, 4, 10, 113, // 120 - 'x'
387 | 8, 1, 3, 126, 124, 2, 1, 0, 0, // 121 - 'y'
388 | 8, 97, 113, 93, 71, 67, 0, 0, 0, // 122 - 'z'
389 | 3, 8, 119, 65, // 123 - '{'
390 | 1, 127, // 124 - '|'
391 | 3, 65, 119, 8, // 125
392 | 6, 16, 8, 8, 16, 16, 8, // 126
393 | 0, // 127
394 | 6, 20, 62, 85, 85, 65, 34, // 128
395 | 0, // 129
396 | 1, 96, // 130
397 | 0, // 131
398 | 0, // 132
399 | 5, 64, 0, 64, 0, 64, // 133
400 | 5, 4, 4, 127, 4, 4, // 134
401 | 0, // 135
402 | 0, // 136
403 | 0, // 137
404 | 0, // 138
405 | 0, // 139
406 | 0, // 140
407 | 0, // 141
408 | 0, // 142
409 | 0, // 143
410 | 0, // 144
411 | 0, // 145
412 | 0, // 146
413 | 0, // 147
414 | 0, // 148
415 | 1, 2, // 149
416 | 3, 16, 16, 16, // 150
417 | 3, 64, 64, 64, // 151
418 | 0, // 152
419 | 7, 1, 7, 1, 0, 7, 2, 7, // 153
420 | 0, // 154
421 | 0, // 155
422 | 0, // 156
423 | 0, // 157
424 | 0, // 158
425 | 0, // 159
426 | 0, // 160
427 | 0, // 161
428 | 0, // 162
429 | 0, // 163
430 | 0, // 164
431 | 0, // 165
432 | 1, 54, // 166
433 | 0, // 167
434 | 0, // 168
435 | 0, // 169
436 | 0, // 170
437 | 5, 16, 40, 84, 40, 68, // 171
438 | 4, 8, 8, 8, 24, // 172
439 | 0, // 173
440 | 0, // 174
441 | 0, // 175
442 | 3, 7, 5, 7, // 176
443 | 5, 72, 72, 92, 72, 72, // 177
444 | 2, 13, 11, // 178
445 | 2, 21, 31, // 179
446 | 0, // 180
447 | 0, // 181
448 | 0, // 182
449 | 0, // 183
450 | 0, // 184
451 | 0, // 185
452 | 0, // 186
453 | 5, 68, 40, 84, 40, 16, // 187
454 | 0, // 188
455 | 0, // 189
456 | 0, // 190
457 | 5, 48, 72, 69, 64, 48, // 191
458 | 0, // 192
459 | 0, // 193
460 | 0, // 194
461 | 0, // 195
462 | 0, // 196
463 | 0, // 197
464 | 7, 124, 18, 17, 127, 73, 73, 65, // 198
465 | 0, // 199
466 | 0, // 200
467 | 0, // 201
468 | 0, // 202
469 | 0, // 203
470 | 0, // 204
471 | 0, // 205
472 | 0, // 206
473 | 0, // 207
474 | 0, // 208
475 | 0, // 209
476 | 0, // 210
477 | 0, // 211
478 | 0, // 212
479 | 0, // 213
480 | 0, // 214
481 | 5, 68, 40, 16, 40, 68, // 215
482 | 0, // 216
483 | 0, // 217
484 | 0, // 218
485 | 0, // 219
486 | 0, // 220
487 | 0, // 221
488 | 0, // 222
489 | 0, // 223
490 | 0, // 224
491 | 0, // 225
492 | 0, // 226
493 | 0, // 227
494 | 0, // 228
495 | 0, // 229
496 | 0, // 230
497 | 0, // 231
498 | 0, // 232
499 | 0, // 233
500 | 0, // 234
501 | 0, // 235
502 | 0, // 236
503 | 0, // 237
504 | 0, // 238
505 | 0, // 239
506 | 0, // 240
507 | 0, // 241
508 | 0, // 242
509 | 0, // 243
510 | 0, // 244
511 | 0, // 245
512 | 0, // 246
513 | 5, 16, 16, 84, 16, 16, // 247
514 | 0, // 248
515 | 0, // 249
516 | 0, // 250
517 | 0, // 251
518 | 0, // 252
519 | 0, // 253
520 | 0, // 254
521 | 0, // 255
522 | };
523 |
--------------------------------------------------------------------------------
/lib/Font_Data/Font_Data.h:
--------------------------------------------------------------------------------
1 | #ifndef FONT_DATA_H
2 | #define FONT_DATA_H
3 |
4 | #include
5 |
6 | extern MD_MAX72XX::fontType_t small_font[] PROGMEM;
7 | extern MD_MAX72XX::fontType_t pixel_font[] PROGMEM;
8 |
9 | #endif
10 |
--------------------------------------------------------------------------------
/lib/Languages/Languages.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "Languages.h"
6 |
7 | std::unordered_map> months = {
8 | {"en", {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}},
9 | {"it", {"Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"}},
10 | {"es", {"Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"}},
11 | {"fr", {"Jan", "Fev", "Mar", "Avr", "Mai", "Jun", "Jul", "Aou", "Sep", "Oct", "Nov", "Dec"}},
12 | {"de", {"Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"}}
13 | };
14 |
15 | std::unordered_map> days = {
16 | {"en", {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}},
17 | {"it", {"Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"}},
18 | {"es", {"Dom", "Lun", "Mar", "Mie", "Jue", "Vie", "Sab"}},
19 | {"fr", {"Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"}},
20 | {"de", {"Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam"}}
21 | };
22 |
--------------------------------------------------------------------------------
/lib/Languages/Languages.h:
--------------------------------------------------------------------------------
1 | #ifndef LANGUAGES_H
2 | #define LANGUAGES_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | extern std::unordered_map> months;
9 | extern std::unordered_map> days;
10 |
11 | #endif
--------------------------------------------------------------------------------
/lib/Screens/Screens.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | #include "Screens.h"
12 |
13 | void print_time_temp() {
14 | char hh_mm[6];
15 | char ss[3];
16 | char temp[10];
17 |
18 | sprintf(hh_mm, "%02d%c%02d", current_time.hour(), ((current_time.second() % 2) ? ':' : ' '), current_time.minute());
19 | sprintf(ss, "%02d", current_time.second());
20 |
21 | if(!conf.fahrenheit)
22 | sprintf(temp, "%3.1f °C", bme.readTemperature());
23 | else
24 | sprintf(temp, "%3.1f °F", (bme.readTemperature() * (9.0 / 5.0)) + 32.0);
25 |
26 | matrix->synchZoneStart();
27 | if(matrix->displayAnimate()) {
28 | matrix->displayZoneText(0, ss, PA_CENTER, 75, 0, PA_PRINT);
29 | matrix->displayZoneText(1, hh_mm, PA_CENTER, 75, 0, PA_PRINT);
30 | matrix->displayZoneText(2, temp, PA_CENTER, 75, 0, PA_PRINT);
31 | }
32 | }
33 |
34 | void print_date() {
35 | char ddd_dd[7];
36 | char mmm_yyyy[9];
37 |
38 | sprintf(ddd_dd, "%s %02d", days[std::string(conf.language)][current_time.dayOfTheWeek()], current_time.day());
39 | sprintf(mmm_yyyy, "%s %d", months[std::string(conf.language)][current_time.month() - 1], current_time.year());
40 |
41 | matrix->synchZoneStart();
42 | if(matrix->displayAnimate()) {
43 | matrix->displayZoneText(3, ddd_dd, PA_CENTER, 75, 0, PA_PRINT);
44 | matrix->displayZoneText(4, mmm_yyyy, PA_CENTER, 75, 0, PA_PRINT);
45 | }
46 | }
47 |
48 | void print_hum_pres() {
49 | char hum[9];
50 | char pres[9];
51 |
52 | if(bme.readHumidity() < 100.0)
53 | sprintf(hum, "H %3.1f%%", bme.readHumidity());
54 | else
55 | sprintf(hum, "H %3.0f%%", bme.readHumidity());
56 |
57 | if((bme.readPressure() / 100.0) > 1000.0)
58 | sprintf(pres, "P%5.1f", bme.readPressure() / 100.0);
59 | else
60 | sprintf(pres, "P %4.1f", bme.readPressure() / 100.0);
61 |
62 | //print humidity and pressure
63 | matrix->synchZoneStart();
64 | if(matrix->displayAnimate()) {
65 | matrix->displayZoneText(5, hum, PA_RIGHT, 75, 0, PA_PRINT);
66 | matrix->displayZoneText(6, pres, PA_LEFT, 75, 0, PA_PRINT);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/Screens/Screens.h:
--------------------------------------------------------------------------------
1 | #ifndef SCREENS_H
2 | #define SCREENS_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 |
14 | #include
15 | #include
16 |
17 | extern MD_Parola* matrix;
18 | extern RTC_DS3231 rtc;
19 | extern Adafruit_BME280 bme;
20 | extern DateTime current_time;
21 |
22 | extern Config conf;
23 |
24 | enum screen{
25 | CLOCK_TEMP,
26 | DATE,
27 | HUMIDITY_PRESSURE
28 | };
29 |
30 | void print_time_temp();
31 | void print_date();
32 | void print_hum_pres();
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/lib/Set_Intensity/Set_Intensity.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "Set_Intensity.h"
7 |
8 | void set_intensity() {
9 | if(light_sensor.measurementReady())
10 | matrix->setIntensity(map(constrain(round(light_sensor.readLightLevel()), 0, 300), 0, 300, 0, 15));
11 | }
12 |
--------------------------------------------------------------------------------
/lib/Set_Intensity/Set_Intensity.h:
--------------------------------------------------------------------------------
1 | #ifndef SET_INTENSITY_H
2 | #define SET_INTENSITY_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | extern BH1750 light_sensor;
9 | extern MD_Parola* matrix;
10 |
11 | void set_intensity();
12 |
13 | #endif
--------------------------------------------------------------------------------
/lib/Set_NTP_Time/Set_NTP_Time.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "Set_NTP_Time.h"
7 |
8 | void wifi_connetion() {
9 | uint8_t n_net = WiFi.scanNetworks();
10 |
11 | if(strcmp(conf.wifi.SSID, "") == 0) {
12 | bool open_ap_found = false;
13 | char SSID[256];
14 |
15 | if (n_net) {
16 | for (uint8_t i = 0; i < n_net; ++i)
17 | if(WiFi.encryptionType(i) == WIFI_AUTH_OPEN) {
18 | strlcpy(SSID, WiFi.SSID(i).c_str(), sizeof(SSID));
19 | open_ap_found = true;
20 | break;
21 | }
22 | }
23 | else
24 | Serial.println("No network found.\n");
25 |
26 | if(open_ap_found) {
27 | WiFi.begin(SSID);
28 | Serial.printf("Connecting to %s ", SSID);
29 | }
30 | else {
31 | Serial.println("No open network found.\n");
32 | return;
33 | }
34 | }
35 | else if((strcmp(conf.wifi.SSID, "") != 0) && (strcmp(conf.wifi.PASSWORD, "") == 0)) {
36 | WiFi.begin(conf.wifi.SSID);
37 | Serial.printf("Connecting to %s ", conf.wifi.SSID);
38 | }
39 | else {
40 | WiFi.begin(conf.wifi.SSID, conf.wifi.PASSWORD);
41 | Serial.printf("Connecting to %s ", conf.wifi.SSID);
42 | }
43 |
44 | while(WiFi.status() != WL_CONNECTED && WiFi.status() != WL_CONNECT_FAILED) {
45 | Serial.print(".");
46 | delay(100);
47 | }
48 |
49 | if(WiFi.status() != WL_CONNECT_FAILED) {
50 | Serial.printf("\nConnected to %s.\n", conf.wifi.SSID);
51 | Serial.println("IP address: ");
52 | Serial.println(WiFi.localIP());
53 | }
54 | else
55 | Serial.printf("\nError connecting to %s.\n", conf.wifi.SSID);
56 | }
57 |
58 | void set_NTP_time() {
59 | WiFiUDP ntpUDP;
60 | NTPClient timeClient(ntpUDP, conf.ntpServer);
61 |
62 | timeClient.begin();
63 | delay(50);
64 | timeClient.update();
65 | delay(500);
66 |
67 | if(timeClient.isTimeSet()) {
68 | rtc.adjust(timeClient.getEpochTime());
69 | Serial.println("RTC adjusted with NTP time.\n");
70 | }
71 | else {
72 | Serial.println("NTP server error. Time not set.\n");
73 | rtc.adjust(DateTime(uint32_t(0)));
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/lib/Set_NTP_Time/Set_NTP_Time.h:
--------------------------------------------------------------------------------
1 | #ifndef SET_NTP_TIME_H
2 | #define SET_NTP_TIME_H
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | extern Config conf;
10 | extern RTC_DS3231 rtc;
11 |
12 | void wifi_connetion();
13 | void set_NTP_time();
14 |
15 | #endif
--------------------------------------------------------------------------------
/lib/Web_Settings/Web_Settings.cpp:
--------------------------------------------------------------------------------
1 | #include "Web_Settings.h"
2 |
3 | String htmlLoader(const char* filename) {
4 | String content = "";
5 | File file = SPIFFS.open(filename, FILE_READ);
6 |
7 | if (!file) {
8 | Serial.printf("Error opening file: %s\n", filename);
9 | return content;
10 | }
11 |
12 | while (file.available())
13 | content += (char)file.read();
14 |
15 | file.close();
16 | return content;
17 | }
18 |
19 | void handleHome() {
20 | String html = HOME_HTML;
21 |
22 | char year[] = "0000";
23 | char month[] = "00";
24 | char day[] = "00";
25 | char hour[] = "00";
26 | char minute[] = "00";
27 | char second[] = "00";
28 |
29 | sprintf(year, "%04d", current_time.year());
30 | sprintf(month, "%02d", current_time.month());
31 | sprintf(day, "%02d", current_time.day());
32 | sprintf(hour, "%02d", current_time.hour());
33 | sprintf(minute, "%02d", current_time.minute());
34 | sprintf(second, "%02d", current_time.second());
35 |
36 | html.replace("{{ TOGGLE_SCREEN }}", String(screen_off ? "Turn On Screen" : "Turn Off Screen"));
37 | html.replace("{{ TEMP }}", conf.fahrenheit ? String(bme.readTemperature() * 1.8 + 32) : String(bme.readTemperature()));
38 | html.replace("{{ TEMPUNIT }}", conf.fahrenheit ? "Fahrenheit" : "Celsius");
39 | html.replace("{{ HUMIDITY }}", String(bme.readHumidity()));
40 | html.replace("{{ PRESSURE }}", String(bme.readPressure() / 100.0));
41 | html.replace("{{ DAY }}", day);
42 | html.replace("{{ MONTH }}", month);
43 | html.replace("{{ YEAR }}", year);
44 | html.replace("{{ HOUR }}", hour);
45 | html.replace("{{ MINUTE }}", minute);
46 | html.replace("{{ SECOND }}", second);
47 |
48 | server.send(200, "text/html", html);
49 | }
50 |
51 | void handleSettings() {
52 | String html = SETTINGS_HTML;
53 |
54 | html.replace("{{ SSID }}", String(conf.wifi.SSID));
55 | html.replace("{{ NTP_SERVER }}", String(conf.ntpServer));
56 |
57 | html.replace("{{ ENGLISH }}", String(!strcmp(conf.language, "en") ? " selected" : ""));
58 | html.replace("{{ ITALIAN }}", String(!strcmp(conf.language, "it") ? " selected" : ""));
59 | html.replace("{{ SPANISH }}", String(!strcmp(conf.language, "es") ? " selected" : ""));
60 | html.replace("{{ GERMAN }}", String(!strcmp(conf.language, "de") ? " selected" : ""));
61 | html.replace("{{ FRENCH }}", String(!strcmp(conf.language, "fr") ? " selected" : ""));
62 |
63 | html.replace("{{ STD_ABBREV }}", String(conf.std.abbrev));
64 |
65 | html.replace("{{ STD_WEEK_0 }}", String(conf.std.week == 0 ? " selected" : ""));
66 | html.replace("{{ STD_WEEK_1 }}", String(conf.std.week == 1 ? " selected" : ""));
67 | html.replace("{{ STD_WEEK_2 }}", String(conf.std.week == 2 ? " selected" : ""));
68 | html.replace("{{ STD_WEEK_3 }}", String(conf.std.week == 3 ? " selected" : ""));
69 | html.replace("{{ STD_WEEK_4 }}", String(conf.std.week == 4 ? " selected" : ""));
70 |
71 | html.replace("{{ STD_DOW_1 }}", String(conf.std.dow == 1 ? " selected" : ""));
72 | html.replace("{{ STD_DOW_2 }}", String(conf.std.dow == 2 ? " selected" : ""));
73 | html.replace("{{ STD_DOW_3 }}", String(conf.std.dow == 3 ? " selected" : ""));
74 | html.replace("{{ STD_DOW_4 }}", String(conf.std.dow == 4 ? " selected" : ""));
75 | html.replace("{{ STD_DOW_5 }}", String(conf.std.dow == 5 ? " selected" : ""));
76 | html.replace("{{ STD_DOW_6 }}", String(conf.std.dow == 6 ? " selected" : ""));
77 | html.replace("{{ STD_DOW_7 }}", String(conf.std.dow == 7 ? " selected" : ""));
78 |
79 | html.replace("{{ STD_MONTH_1 }}", String(conf.std.month == 1 ? " selected" : ""));
80 | html.replace("{{ STD_MONTH_2 }}", String(conf.std.month == 2 ? " selected" : ""));
81 | html.replace("{{ STD_MONTH_3 }}", String(conf.std.month == 3 ? " selected" : ""));
82 | html.replace("{{ STD_MONTH_4 }}", String(conf.std.month == 4 ? " selected" : ""));
83 | html.replace("{{ STD_MONTH_5 }}", String(conf.std.month == 5 ? " selected" : ""));
84 | html.replace("{{ STD_MONTH_6 }}", String(conf.std.month == 6 ? " selected" : ""));
85 | html.replace("{{ STD_MONTH_7 }}", String(conf.std.month == 7 ? " selected" : ""));
86 | html.replace("{{ STD_MONTH_8 }}", String(conf.std.month == 8 ? " selected" : ""));
87 | html.replace("{{ STD_MONTH_9 }}", String(conf.std.month == 9 ? " selected" : ""));
88 | html.replace("{{ STD_MONTH_10 }}", String(conf.std.month == 10 ? " selected" : ""));
89 | html.replace("{{ STD_MONTH_11 }}", String(conf.std.month == 11 ? " selected" : ""));
90 | html.replace("{{ STD_MONTH_12 }}", String(conf.std.month == 12 ? " selected" : ""));
91 |
92 | html.replace("{{ STD_HOUR }}", String(conf.std.hour));
93 | html.replace("{{ STD_OFFSET }}", String(conf.std.offset));
94 |
95 | html.replace("{{ DLT_ABBREV }}", String(conf.dlt.abbrev));
96 |
97 | html.replace("{{ DLT_WEEK_0 }}", String(conf.dlt.week == 0 ? " selected" : ""));
98 | html.replace("{{ DLT_WEEK_1 }}", String(conf.dlt.week == 1 ? " selected" : ""));
99 | html.replace("{{ DLT_WEEK_2 }}", String(conf.dlt.week == 2 ? " selected" : ""));
100 | html.replace("{{ DLT_WEEK_3 }}", String(conf.dlt.week == 3 ? " selected" : ""));
101 | html.replace("{{ DLT_WEEK_4 }}", String(conf.dlt.week == 4 ? " selected" : ""));
102 |
103 | html.replace("{{ DLT_DOW_1 }}", String(conf.dlt.dow == 1 ? " selected" : ""));
104 | html.replace("{{ DLT_DOW_2 }}", String(conf.dlt.dow == 2 ? " selected" : ""));
105 | html.replace("{{ DLT_DOW_3 }}", String(conf.dlt.dow == 3 ? " selected" : ""));
106 | html.replace("{{ DLT_DOW_4 }}", String(conf.dlt.dow == 4 ? " selected" : ""));
107 | html.replace("{{ DLT_DOW_5 }}", String(conf.dlt.dow == 5 ? " selected" : ""));
108 | html.replace("{{ DLT_DOW_6 }}", String(conf.dlt.dow == 6 ? " selected" : ""));
109 | html.replace("{{ DLT_DOW_7 }}", String(conf.dlt.dow == 7 ? " selected" : ""));
110 |
111 | html.replace("{{ DLT_MONTH_1 }}", String(conf.dlt.month == 1 ? " selected" : ""));
112 | html.replace("{{ DLT_MONTH_2 }}", String(conf.dlt.month == 2 ? " selected" : ""));
113 | html.replace("{{ DLT_MONTH_3 }}", String(conf.dlt.month == 3 ? " selected" : ""));
114 | html.replace("{{ DLT_MONTH_4 }}", String(conf.dlt.month == 4 ? " selected" : ""));
115 | html.replace("{{ DLT_MONTH_5 }}", String(conf.dlt.month == 5 ? " selected" : ""));
116 | html.replace("{{ DLT_MONTH_6 }}", String(conf.dlt.month == 6 ? " selected" : ""));
117 | html.replace("{{ DLT_MONTH_7 }}", String(conf.dlt.month == 7 ? " selected" : ""));
118 | html.replace("{{ DLT_MONTH_8 }}", String(conf.dlt.month == 8 ? " selected" : ""));
119 | html.replace("{{ DLT_MONTH_9 }}", String(conf.dlt.month == 9 ? " selected" : ""));
120 | html.replace("{{ DLT_MONTH_10 }}", String(conf.dlt.month == 10 ? " selected" : ""));
121 | html.replace("{{ DLT_MONTH_11 }}", String(conf.dlt.month == 11 ? " selected" : ""));
122 | html.replace("{{ DLT_MONTH_12 }}", String(conf.dlt.month == 12 ? " selected" : ""));
123 |
124 | html.replace("{{ DLT_HOUR }}", String(conf.dlt.hour));
125 | html.replace("{{ DLT_OFFSET }}", String(conf.dlt.offset));
126 |
127 | html.replace("{{ BUZZ_SOUND }}", String(conf.buzzSound ? "checked " : ""));
128 | html.replace("{{ FAHRENHEIT }}", String(conf.fahrenheit ? "checked " : ""));
129 |
130 | server.send(200, "text/html", html);
131 | }
132 |
133 | void handleTimeTempScreen() {
134 | displaySelector = CLOCK_TEMP;
135 | server.sendHeader("Location", "/", true);
136 | server.send(302, "text/plain", "Redirecting to /");
137 | }
138 |
139 | void handleDateScreen() {
140 | displaySelector = DATE;
141 | server.sendHeader("Location", "/", true);
142 | server.send(302, "text/plain", "Redirecting to /");
143 | }
144 |
145 | void handleHumPresScreen() {
146 | displaySelector = HUMIDITY_PRESSURE;
147 | server.sendHeader("Location", "/", true);
148 | server.send(302, "text/plain", "Redirecting to /");
149 | }
150 |
151 | void handleToggleScreen() {
152 | screen_off = !screen_off;
153 |
154 | if (screen_off)
155 | matrix->displayShutdown(true);
156 | else
157 | matrix->displayShutdown(false);
158 |
159 | server.sendHeader("Location", "/", true);
160 | server.send(302, "text/plain", "Redirecting to /");
161 | }
162 |
163 | void handleReboot() {
164 | server.sendHeader("Location", "/", true);
165 | delay(1000);
166 | ESP.restart();
167 | }
168 |
169 | void handleNetworkSubmit() {
170 | if (server.method() == HTTP_POST) {
171 | strncpy(conf.wifi.SSID, server.arg("ssid").c_str(), sizeof(conf.wifi.SSID) - 1);
172 | strncpy(conf.wifi.PASSWORD, server.arg("password").c_str(), sizeof(conf.wifi.PASSWORD) - 1);
173 | storeConfiguration(conf);
174 | server.sendHeader("Location", "/settings", true);
175 | server.send(302, "text/plain", "Redirecting to /settings");
176 | } else {
177 | server.send(405, "text/html", "Method Not Allowed
");
178 | }
179 | }
180 |
181 | void handleNTPSubmit() {
182 | if (server.method() == HTTP_POST) {
183 | strncpy(conf.ntpServer, server.arg("ntpServer").c_str(), sizeof(conf.ntpServer) - 1);
184 | storeConfiguration(conf);
185 | server.sendHeader("Location", "/settings", true);
186 | server.send(302, "text/plain", "Redirecting to /settings");
187 | } else {
188 | server.send(405, "text/html", "Method Not Allowed
");
189 | }
190 | }
191 |
192 | void handleLanguageSubmit() {
193 | if (server.method() == HTTP_POST) {
194 | strncpy(conf.language, server.arg("language").c_str(), sizeof(conf.language) - 1);
195 | storeConfiguration(conf);
196 | server.sendHeader("Location", "/settings", true);
197 | server.send(302, "text/plain", "Redirecting to /settings");
198 | } else {
199 | server.send(405, "text/html", "Method Not Allowed
");
200 | }
201 | }
202 |
203 | void handleTimezoneSubmit() {
204 | if (server.method() == HTTP_POST) {
205 | strncpy(conf.std.abbrev, server.arg("stdAbbrev").c_str(), sizeof(conf.std.abbrev) - 1);
206 | conf.std.abbrev[sizeof(conf.std.abbrev) - 1] = '\0'; // Null-terminate the string
207 | conf.std.week = server.arg("stdWeek").toInt();
208 | conf.std.dow = server.arg("stdDOW").toInt();
209 | conf.std.month = server.arg("stdMonth").toInt();
210 | conf.std.hour = server.arg("stdHour").toInt();
211 | conf.std.offset = server.arg("stdOffset").toInt();
212 | strncpy(conf.dlt.abbrev, server.arg("dltAbbrev").c_str(), sizeof(conf.dlt.abbrev) - 1);
213 | conf.dlt.abbrev[sizeof(conf.dlt.abbrev) - 1] = '\0'; // Null-terminate the string
214 | conf.dlt.week = server.arg("dltWeek").toInt();
215 | conf.dlt.dow = server.arg("dltDOW").toInt();
216 | conf.dlt.month = server.arg("dltMonth").toInt();
217 | conf.dlt.hour = server.arg("dltHour").toInt();
218 | conf.dlt.offset = server.arg("dltOffset").toInt();
219 | storeConfiguration(conf);
220 | server.sendHeader("Location", "/settings", true);
221 | server.send(302, "text/plain", "Redirecting to /settings");
222 | } else {
223 | server.send(405, "text/html", "Method Not Allowed
");
224 | }
225 | }
226 |
227 | void handleAdditionalSubmit() {
228 | if (server.method() == HTTP_POST) {
229 | conf.buzzSound = server.hasArg("buzzSound");
230 | conf.fahrenheit = server.hasArg("fahrenheit");
231 | storeConfiguration(conf);
232 | server.sendHeader("Location", "/settings", true);
233 | server.send(302, "text/plain", "Redirecting to /settings");
234 | } else {
235 | server.send(405, "text/html", "Method Not Allowed
");
236 | }
237 | }
238 |
239 | void handleUpdateTime() {
240 | wifi_connetion();
241 | set_NTP_time();
242 | Serial.println("Disconnecting from WiFi.\n");
243 | WiFi.disconnect();
244 |
245 | if (server.method() == HTTP_POST) {
246 | server.sendHeader("Location", "/settings", true);
247 | server.send(302, "text/plain", "Redirecting to /settings");
248 | }
249 | else {
250 | server.send(405, "text/html", "Method Not Allowed
");
251 | return;
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/lib/Web_Settings/Web_Settings.h:
--------------------------------------------------------------------------------
1 | #ifndef WEB_SETTINGS_H
2 | #define WEB_SETTINGS_H
3 |
4 | #define PATH_TO_HOME "/home.html"
5 | #define PATH_TO_SETTINGS "/settings.html"
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | extern bool screen_off;
22 | extern Config conf;
23 | extern WebServer server;
24 | extern MD_Parola* matrix;
25 | extern Adafruit_BME280 bme;
26 | extern RTC_DS3231 rtc;
27 | extern DateTime current_time;
28 | extern uint8_t displaySelector;
29 |
30 | extern String HOME_HTML;
31 | extern String SETTINGS_HTML;
32 | String htmlLoader(const char* filename);
33 |
34 | void handleHome();
35 | void handleSettings();
36 | void handleNetworkSubmit();
37 | void handleNTPSubmit();
38 | void handleLanguageSubmit();
39 | void handleTimezoneSubmit();
40 | void handleAdditionalSubmit();
41 | void handleTimeTempScreen();
42 | void handleDateScreen();
43 | void handleHumPresScreen();
44 | void handleToggleScreen();
45 | void handleReboot();
46 | void handleUpdateTime();
47 |
48 | #endif
49 |
--------------------------------------------------------------------------------
/partitions.csv:
--------------------------------------------------------------------------------
1 | # Name, Type, SubType, Offset, Size, Flags
2 | nvs, data, nvs, 0x9000, 0x5000,
3 | otadata, data, ota, 0xe000, 0x2000,
4 | app0, app, ota_0, 0x10000, 0x360000,
5 | spiffs, data, spiffs, 0x370000, 0x80000,
6 | coredump, data, coredump,0x3F0000, 0x10000,
7 |
--------------------------------------------------------------------------------
/platformio.ini:
--------------------------------------------------------------------------------
1 | ; PlatformIO Project Configuration File
2 | ;
3 | ; Build options: build flags, source filter
4 | ; Upload options: custom upload port, speed and extra flags
5 | ; Library options: dependencies, extra library storages
6 | ; Advanced options: extra scripting
7 | ;
8 | ; Please visit documentation for the other options and examples
9 | ; https://docs.platformio.org/page/projectconf.html
10 |
11 | [env:esp32dev]
12 | platform = espressif32
13 | board = esp32dev
14 | framework = arduino
15 | monitor_speed = 115200
16 | board_build.filesystem = spiffs
17 | upload_protocol = esptool
18 | board_build.partitions = partitions.csv
19 | build_flags =
20 | -D SPIFFS_GZ
21 | lib_deps =
22 | majicdesigns/MD_MAX72XX@^3.5.1
23 | majicdesigns/MD_Parola@^3.7.3
24 | adafruit/RTClib@^2.1.4
25 | arduino-libraries/NTPClient@^3.2.1
26 | jchristensen/Timezone@^1.2.4
27 | adafruit/Adafruit BME280 Library@^2.2.4
28 | adafruit/Adafruit Unified Sensor@^1.1.14
29 | claws/BH1750@^1.3.0
30 | thomasfredericks/Bounce2@^2.72
31 | bblanchon/ArduinoJson@^7.2.0
32 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #include
22 | #include
23 | #include
24 |
25 | #include
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | Config conf;
37 | WebServer server(80);
38 | String HOME_HTML;
39 | String SETTINGS_HTML;
40 |
41 | MD_Parola* matrix = nullptr;
42 | RTC_DS3231 rtc;
43 | Adafruit_BME280 bme;
44 | BH1750 light_sensor;
45 | Bounce2::Button screen_button = Bounce2::Button();
46 |
47 | DateTime current_time;
48 | Timezone* TMZ = nullptr;
49 |
50 | bool tic = true;
51 | int sound_interval = 0;
52 |
53 | bool screen_off = false;
54 | uint8_t displaySelector = 0;
55 |
56 | int measurement_interval = 0;
57 |
58 | void setup() {
59 | Serial.begin(115200);
60 |
61 | if (!SPIFFS.begin()) {
62 | Serial.printf("%s\n", SPIFFS_ERR);
63 | return;
64 | }
65 | Serial.printf("%s\n", SPIFFS_SUC);
66 |
67 | loadConfiguration(conf);
68 |
69 | WiFi.mode(WIFI_AP_STA);
70 | WiFi.softAP(AP_NAME, AP_PASSWORD);
71 | IPAddress local_IP(IP_ADDRESS);
72 | IPAddress gateway(GATEWAY);
73 | IPAddress subnet(SUBNET);
74 | WiFi.softAPConfig(local_IP, gateway, subnet);
75 |
76 | HOME_HTML = htmlLoader(PATH_TO_HOME);
77 | SETTINGS_HTML = htmlLoader(PATH_TO_SETTINGS);
78 |
79 | server.on("/", handleHome);
80 | server.on("/settings", handleSettings);
81 | server.on("/updateTime", HTTP_POST, handleUpdateTime);
82 | server.on("/toggleScreen", HTTP_POST, handleToggleScreen);
83 | server.on("/reboot", HTTP_POST, handleReboot);
84 | server.on("/timeTempScreen", HTTP_POST, handleTimeTempScreen);
85 | server.on("/dateScreen", HTTP_POST, handleDateScreen);
86 | server.on("/humPresScreen", HTTP_POST, handleHumPresScreen);
87 | server.on("/submitNetwork", HTTP_POST, handleNetworkSubmit);
88 | server.on("/submitNTP", HTTP_POST, handleNTPSubmit);
89 | server.on("/submitLanguage", HTTP_POST, handleLanguageSubmit);
90 | server.on("/submitTimezone", HTTP_POST, handleTimezoneSubmit);
91 | server.on("/submitAdditional", HTTP_POST, handleAdditionalSubmit);
92 | server.begin();
93 |
94 | TMZ = new Timezone(conf.std, conf.dlt);
95 | matrix = new MD_Parola(HW_TYPE, conf.max7219.DATA_PIN, conf.max7219.CLK_PIN, conf.max7219.CS_PIN, MAX7219_DEVICES);
96 |
97 | pinMode(conf.pins.BUZZER_PIN, OUTPUT);
98 | digitalWrite(conf.pins.BUZZER_PIN, LOW);
99 |
100 | screen_button.attach(conf.pins.BUTTON_PIN, INPUT_PULLUP);
101 | screen_button.interval(5);
102 | screen_button.setPressedState(LOW);
103 |
104 | if(!matrix->begin(9)) {
105 | Serial.printf("%s %s\n", MAX7219_ERR, WIRE_ERR);
106 | while(true);
107 | }
108 |
109 | if (!rtc.begin(&Wire)) {
110 | Serial.printf("%s %s\n", DS3231_ERR, WIRE_ERR);
111 | while(true);
112 | }
113 |
114 | if (!bme.begin(conf.i2c.BME_280, &Wire)) {
115 | Serial.printf("%s %s\n", BME280_ERR, WIRE_ERR);
116 | while(true);
117 | }
118 |
119 | if(!light_sensor.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, conf.i2c.BH1750, &Wire)) {
120 | Serial.printf("%s %s\n", BH1750_ERR, WIRE_ERR);
121 | while(true);
122 | }
123 |
124 | if (rtc.lostPower()) {
125 | Serial.printf("%s\n", RTC_POWER_LOST);
126 |
127 | matrix->setZone(7, 4, 7);
128 | matrix->setZone(8, 0, 3);
129 | matrix->setFont(7, small_font);
130 | matrix->setFont(8, small_font);
131 | matrix->setZoneEffect(7, 1, PA_FLIP_UD);
132 | matrix->setZoneEffect(7, 1, PA_FLIP_LR);
133 | matrix->displayZoneText(7, "POWER", PA_CENTER, 75, 10, PA_PRINT);
134 | matrix->displayZoneText(8, "LOST", PA_CENTER, 75, 10, PA_PRINT);
135 | matrix->synchZoneStart();
136 | matrix->displayAnimate();
137 |
138 | while(!screen_button.pressed())
139 | screen_button.update();
140 |
141 | Serial.printf("Button pressed. Trying to sync time with NTP server.\n");
142 |
143 | wifi_connetion();
144 | set_NTP_time();
145 | Serial.println("Disconnecting from WiFi.\n");
146 | WiFi.disconnect();
147 | }
148 |
149 | matrix->setZone(0, 7, 7);
150 | matrix->setZone(1, 4, 6);
151 | matrix->setZone(2, 0, 3);
152 |
153 | matrix->setZoneEffect(0, 1, PA_FLIP_UD);
154 | matrix->setZoneEffect(0, 1, PA_FLIP_LR);
155 | matrix->setZoneEffect(1, 1, PA_FLIP_UD);
156 | matrix->setZoneEffect(1, 1, PA_FLIP_LR);
157 |
158 | matrix->setFont(0, small_font);
159 | matrix->setFont(1, pixel_font);
160 | matrix->setFont(2, pixel_font);
161 |
162 | matrix->setZone(3, 4, 7);
163 | matrix->setZone(4, 0, 3);
164 |
165 | matrix->setZoneEffect(3, 1, PA_FLIP_UD);
166 | matrix->setZoneEffect(3, 1, PA_FLIP_LR);
167 |
168 | matrix->setFont(3, small_font);
169 | matrix->setFont(4, small_font);
170 |
171 | matrix->setZone(5, 4, 7);
172 | matrix->setZone(6, 0, 3);
173 |
174 | matrix->setZoneEffect(5, 1, PA_FLIP_UD);
175 | matrix->setZoneEffect(5, 1, PA_FLIP_LR);
176 |
177 | matrix->setFont(5, pixel_font);
178 | matrix->setFont(6, pixel_font);
179 |
180 | matrix->displayClear();
181 |
182 | bme.setSampling(Adafruit_BME280::MODE_FORCED,
183 | Adafruit_BME280::SAMPLING_X16,
184 | Adafruit_BME280::SAMPLING_X16,
185 | Adafruit_BME280::SAMPLING_X16,
186 | Adafruit_BME280::FILTER_X4,
187 | Adafruit_BME280::STANDBY_MS_1000
188 | );
189 |
190 | printConfiguration(conf);
191 | }
192 |
193 | void loop() {
194 | current_time = TMZ->toLocal((rtc.now()).unixtime());
195 | server.handleClient();
196 |
197 | screen_button.update();
198 | if (screen_button.released())
199 | ++displaySelector %= 3;
200 |
201 | if((millis() - measurement_interval) > 30000)
202 | if(bme.takeForcedMeasurement())
203 | measurement_interval = millis();
204 |
205 | switch(displaySelector) {
206 | case CLOCK_TEMP:
207 | print_time_temp();
208 | break;
209 | case DATE:
210 | print_date();
211 | break;
212 | case HUMIDITY_PRESSURE:
213 | print_hum_pres();
214 | break;
215 | default:
216 | print_time_temp();
217 | break;
218 | }
219 |
220 | if(screen_button.isPressed() && screen_button.currentDuration() > 500) {
221 | matrix->displayShutdown(true);
222 | screen_off = true;
223 | while(!screen_button.released())
224 | screen_button.update();
225 | }
226 |
227 | if(screen_button.pressed() && screen_off) {
228 | matrix->displayShutdown(false);
229 | screen_off = false;
230 | while(!screen_button.released())
231 | screen_button.update();
232 | }
233 |
234 | if(conf.buzzSound){
235 | if(current_time.second() == 0 && current_time.minute() == 0 && tic) {
236 | beep_sound();
237 | tic = false;
238 | sound_interval = millis();
239 | }
240 |
241 | if(!tic && (millis() - sound_interval) > 1000)
242 | tic = true;
243 | }
244 |
245 | set_intensity();
246 | }
247 |
--------------------------------------------------------------------------------