├── ESP8266 └── ESP8266_LED_Matrix_Bar_Weather_Station │ ├── Config.h │ ├── DHT.h │ ├── DHT12.cpp │ ├── DHT12.h │ ├── DHT12Driver.h │ ├── DS18B20.h │ ├── ESP8266_LED_Matrix_Bar_Weather_Station.ino │ ├── LEDMatrix_ClockWeather.h │ ├── LEDStrip.h │ ├── LEDStripDriver.cpp │ ├── LEDStripDriver.h │ ├── MQTT.h │ ├── NTPClient.cpp │ ├── NTPClient.h │ ├── WS2812B_NeoPixel.h │ ├── Web_Server.h │ ├── WiFi_Manager.h │ ├── WiFi_Setup.h │ ├── fonts.h │ └── max7219.h ├── README.md └── images ├── Alarm_clock_digital_time_4732015_128.png ├── Alarm_clock_digital_time_4732015_256.png ├── Alarm_clock_digital_time_4732015_512.png ├── LEDMatrixBarWeatherStation-V2_01.png ├── LEDMatrixBarWeatherStation-V2_02.png ├── LEDMatrixBarWeatherStation-V2_03.png ├── LEDMatrixBarWeatherStation-V2_24.png ├── LEDMatrixBarWeatherStation-V3_01.png ├── LEDMatrixBarWeatherStation-V3_02.png ├── LEDMatrixBarWeatherStation-V3_03.png ├── LEDMatrixBarWeatherStation-V3_24.png ├── LEDMatrixBarWeatherStation_V1_01.jpg ├── LED_Matrix_Bar_Weather_Station_v104_Schematic_1of2.png ├── LED_Matrix_Bar_Weather_Station_v104_Schematic_2of2.png ├── cloudy_weather_icon_128px.png ├── cloudy_weather_icon_256px.png ├── cloudy_weather_icon_512px.png ├── display_128px.png ├── display_256px.png ├── display_512px.png ├── electronic_clock_0000_811469_128.png ├── electronic_clock_0000_811469_256.png ├── electronic_clock_0000_811469_512.png ├── electronic_clock_1200_811483_128.png ├── electronic_clock_1200_811483_256.png ├── electronic_clock_1200_811483_512.png ├── favicon.ico ├── favicon_display.ico ├── favicon_electronic_clock_random_time_stopwatch.ico ├── favicon_electronic_clock_time.ico ├── favicon_if_home.ico ├── favicon_if_home_40798.ico ├── favicon_time_management_clock.ico ├── google_home_5710541_128.png ├── google_home_5710541_256.png ├── google_home_5710541_512.png ├── screencapture-ledmatrixbarweatherstation-mobile-2021-06-25-20_04_00.png ├── screencapture-ledmatrixbarweatherstation-pc-2021-06-25-20_23_22.png ├── time_management_clock_128px.png ├── time_management_clock_256px.png ├── time_management_clock_512px.png ├── weather_2_2682849_128.png ├── weather_2_2682849_256.png └── weather_2_2682849_512.png /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/Config.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4b (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * Configuration 9 | * ========================================================================= 10 | */ 11 | 12 | #ifndef CONFIG_H 13 | #define CONFIG_H 14 | 15 | //#define USE_UART // debug mode 16 | 17 | // DEV Board =============================================================== 18 | //#define DEV_BOARD_ESP01 // ESP-01 19 | #define DEV_BOARD_WeMos_D1_mini // WeMos D1 mini or ESP-12E 20 | //#define DEV_BOARD_Witty // Witty Cloud Board 21 | //#define DEV_BOARD_WiFi_RELAY_MODULE // WiFi Relay Module 22 | 23 | // LED Matrix ============================================================== 24 | #define USE_LEDMATRIX_CLOCKWEATHER // Do not... 25 | //#define USE_LED_MATRIX_DISABLE // Does not use LED Matrix 26 | 27 | // Sensors ================================================================= 28 | #ifndef USE_UART 29 | //#define USE_DS18B20 // Use DS18B20 OneWire temperature sensor 30 | //#define USE_DS18B20_A // Use another DS18B20 OneWire temperature sensor 31 | #endif 32 | #define USE_DHT // Use DHT11, DHT22, DHT21 OneWire temperature and humidity sensor (or DHT11) 33 | #ifdef USE_DHT 34 | #define DHTTYPE DHT11 // DHT11, DHT22(AM2302), DHT21(AM2301) 35 | #endif 36 | //#define USE_DHT12 // Use DHT12 I2C temperature and humidity sensor 37 | 38 | // RGB LED ================================================================= 39 | #define USE_RGB_LED_NEOPIXEL // Use RGB LED WS2812B 40 | //#define USE_RGB_LED_DIRECT // USE RGB LED Strip Direct Control - Witty Cloud 41 | //#define USE_RGB_LED_STRIP_DRIVER // USE RGB LED Strip Driver Module Shield https://github.com/MrKrabat/LED-Strip-Driver-Module 42 | 43 | // Control ================================================================= 44 | #define USE_LIGHT // Use LED Light 45 | #define USE_RELAY // Use Relay 46 | 47 | // Clock =================================================================== 48 | #define USE_TIMER // Use Timer 49 | 50 | // Weather Forcast ========================================================= 51 | // CHANGE YOUR CONFIG HERE: Weather Host http://api.openweathermap.org 52 | // ========================================================================= 53 | #define WEATHER_KEY " " // API Key 54 | #define WEATHER_LANG "&lang=en" // "&lang=en" English 55 | #define CITY_ID " " // 1842030 Gunpo, KR - City ID Number http://openweathermap.org/find 56 | // read OpenWeather api description for more info 57 | 58 | // Network ================================================================= 59 | #define USE_WEB_SERVER // Use Web Server 60 | //#define USE_MQTT // Use Adafruit IO MQTT 61 | #ifdef USE_MQTT 62 | /************************* Adafruit.io Setup **************************/ 63 | #define AIO_SERVER "io.adafruit.com" 64 | #define AIO_SERVERPORT 1883 // use 1883 for SSL 65 | #define AIO_USERNAME " " // Replace it with your username 66 | #define AIO_KEY " " // Replace with your Project Auth Key 67 | /************************* Adafruit.io ********************************/ 68 | #endif 69 | 70 | // ========================================================================= 71 | // ######################################################################### 72 | // ========================================================================= 73 | // Important: The settings below are good to understand and change the code. 74 | // ========================================================================= 75 | // ######################################################################### 76 | // ========================================================================= 77 | 78 | #define PROJECT_NAME "LED Matrix Bar Weather Station" // Project Name 79 | #define PROJECT_VERSION "v1.0.4b" // Project Version 80 | 81 | #define USE_OTA // Use OTA 82 | #define OTA_MODE 1 83 | 84 | // UART ==================================================================== 85 | #define SERIAL_SPEED 115200 86 | 87 | // WiFi ==================================================================== 88 | #define AP_PASSWORD "0123456789" // local AP password 89 | #ifdef USE_LED_MATRIX_DISABLE 90 | #define mDNS_NAME "HomeIoTLight-XXXXXX" // mDNS Name: Change only the first 12 characters and keep "-XXXXXX" 91 | #else 92 | #define mDNS_NAME "LEDMatrixBar-XXXXXX" // mDNS Name: Change only the first 12 characters and keep "-XXXXXX" 93 | #endif 94 | 95 | // WebApp ================================================================== 96 | #define WEB_TITLE "LED Matrix Bar" // "LED Matrix Bar", "Workspace Lights", "Livingroom Lights", "Main Room Lights","RGB LED Lights" // Web Title Name 97 | #define WEB_SUBTITLE "Weather Station" // Web Sub-Title Name 98 | #define WEB_PAGE_REFRESH 180 // web page refresh time: 180 = 3 min, 300 = 5 min, 600 = 10 min 99 | #ifdef USE_LED_MATRIX_DISABLE 100 | #define ICON_LINK "https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/master/images/google_home_5710541_512.png" 101 | #define FAVICON_LINK "https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/master/images/favicon.ico" 102 | #else 103 | #define ICON_LINK "https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/master/images/electronic_clock_1200_811483_512.png" 104 | #define FAVICON_LINK "https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/master/images/favicon_if_home.ico" 105 | #endif 106 | #define WEB_INTERNALTEMPTITLE "Internal" // Intenal Temperature Sensor Web Title Name 107 | 108 | // Pin Assignment ========================================================== 109 | // LED Matrix for NodeMCU 1.0 (ESP-12E Module) 110 | // ========================================================================= 111 | #ifdef USE_RGB_LED_DIRECT 112 | #define RGB_LED_RED_PIN 15 // D8 (GPIO15) RED 113 | #define RGB_LED_GREEN_PIN 12 // D6 (GPIO12) GREEN 114 | #define RGB_LED_BLUE_PIN 13 // D7 (GPIO13) BLUE 115 | #define DIN_PIN 10 // Null 116 | #define CS_PIN 10 // Null 117 | #define CLK_PIN 10 // Null 118 | #endif 119 | #ifndef USE_RGB_LED_DIRECT 120 | #define DIN_PIN 13 // D7 (GPIO13) DIN 121 | #define CS_PIN 15 // D8 (GPIO15) CS 122 | #define CLK_PIN 14 // D5 (GPIO14) CLK 123 | #endif 124 | // Data wire 125 | #ifdef USE_DS18B20 126 | #define ONE_WIRE_BUS 1//1 // TXD (GPIO01) DS18B20 127 | #endif 128 | #define DHTPIN 2//2 // D4 (GPIO02) 129 | // Battery Power Monitor 130 | #define BATTERY_PIN 17 // A0 (ADC) Wemos: 3.2V max. 131 | // RGBW LED or Buzzer or Relay or Switch (Alarm On/Off, Lamp, Scroll) 132 | #define RED_PIN 16 // D0 (GPIO16) Alarm On/Off Switch 133 | #ifdef USE_RGB_LED_STRIP_DRIVER 134 | #define GREEN_PIN 12 // D6 (GPIO12) Lamp Push Button 135 | #endif 136 | #ifndef USE_RGB_LED_STRIP_DRIVER 137 | #define GREEN_PIN 0 // D3 (GPIO00) Lamp Push Button 138 | #endif 139 | #ifdef USE_RGB_LED_DIRECT 140 | #define BLUE_PIN 14 // D5 (GPIO14) Manual Scroll Push Button 141 | #endif 142 | #ifndef USE_RGB_LED_DIRECT 143 | #define BLUE_PIN 12 // D6 (GPIO12) Manual Scroll Push Button 144 | #endif 145 | #define WHITE_PIN 3 // RXD (GPIO03) Buzzer or Relay or GPIO Output 146 | #ifndef USE_DHT12 147 | #if defined(DEV_BOARD_WeMos_D1_mini) || defined(DEV_BOARD_ESP01) 148 | #define USE_RELAY_PIN 5 // SCL (GPIO05) Relay - WeMos D1 mini 149 | #define USE_RGB_LED_PIN 4 // SDA (GPIO04) WS2812B RGB LED - WeMos D1 mini 150 | #endif 151 | #ifdef DEV_BOARD_Witty 152 | #define USE_LIGHT_PIN 5 // SCL (GPIO05) Light - Witty Cloud 153 | #define USE_RELAY_PIN 4 // SDA (GPIO04) Relay - Witty Cloud 154 | #define USE_RGB_LED_PIN 3 // RXD (GPIO03) WS2812B RGB LED 155 | #endif 156 | #ifdef DEV_BOARD_WiFi_RELAY_MODULE 157 | #define USE_INPUT_PIN 5 // SCL (GPIO05) Input - WiFi Relay Module 158 | #define USE_RELAY_PIN 4 // SDA (GPIO04) Relay - WiFi Relay Module 159 | #define USE_RGB_LED_PIN 3 // RXD (GPIO03) WS2812B RGB LED 160 | #endif 161 | #endif 162 | #ifdef USE_DHT12 163 | #ifdef DEV_BOARD_Witty 164 | #define USE_LIGHT_PIN 3 // RXD (GPIO03) Light - Witty Cloud 165 | #endif 166 | #define USE_RGB_LED_PIN 3 // RXD (GPIO03) WS2812B RGB LED 167 | #define USE_RELAY_PIN 3 // RXD (GPIO03) Relay 168 | #ifndef USE_RGB_LED_PIN 169 | #define USE_LED_PIN 3 // RXD (GPIO03) LED Light 170 | #endif 171 | #endif 172 | // RGB LED 173 | #define NUMPIXELS 64 //1 //16 //64 //256 174 | // LEDStripDriver(DIN, CIN); DIN = GPIO02, CIN = GPIO00 in this example 175 | #ifdef USE_RGB_LED_STRIP_DRIVER 176 | #define LEDSTRIPDRIVER_CIN 0 //13 //5 // SCL (GPIO05) CIN - ESP-01 177 | #define LEDSTRIPDRIVER_DIN 2 //12 //4 // SDA (GPIO04) DIN - ESP-01 178 | #endif 179 | 180 | // LED Matrix Bar Configulation ============================================ 181 | // Default status ========================================================== 182 | // ========================================================================= 183 | #if defined(USE_RGB_LED_DIRECT) || defined(DEV_BOARD_ESP01) 184 | #elif defined(USE_LED_MATRIX_DISABLE) 185 | #else 186 | #define USE_LED_MATRIX // LED Matrix Enable 187 | #endif 188 | #define NUM_MAX 6 // Number of MAX7219's connected 189 | #define MAX_DIGITS 16 190 | #define SET_INTENSITY 1 // Initial led matrix intensity, 0-15 191 | #define CLOCK 1 192 | #define DATE_SCROLL 0 193 | #define WEATHER_SCROLL 0 194 | #define INDOOR 1 195 | #define OUTDOOR 0 196 | #define INDOOR_SCROLL 0 197 | #define OUTDOOR_SCROLL 0 198 | #define WAIT_SCROLL 50 // Waiting after executing web command 199 | #define WEATHER_SCROLL_INTERVAL 30000 // default: 15000 clock for 15s, then scrolls for about 30s, 60000 = 1m 200 | #define STRING_SHIFT_DELAY 35 // Scroll Speed 201 | 202 | // Clock =================================================================== 203 | #define SHOW_ANIM_CLOCK_SW 0 204 | #define UTC_OFFSET 9 // UTC+9, Coordinated Universal Time(UTC) 205 | #define AM_PM 12 // AM-PM Mode, 24: 24-hour clock, 12: 12-hour clock 206 | #define ALARM_STATE 0 // Alarm state setting, 0: alarm off, 1: alarm on 207 | #define ALARM_H_SET 6 // Hours unit setting 208 | #define ALARM_M_SET 30 // Minute unit setting 209 | #define ALARM_MESSAGE "Appointment Time!" // Alarm scroll message 210 | #define OnTIME_MESSAGE "Break Time!" // Alarm On-Time scroll message 211 | #define TIMER_STATE 0 // Timer state setting, 0: Timer off, 1: Timer on 212 | #define TIMER_H_START 6 // Start hours unit setting 213 | #define TIMER_M_START 30 // Start minute unit setting 214 | #define TIMER_H_STOP 12 // Stop hours unit setting 215 | #define TIMER_M_STOP 30 // Stop minute unit setting 216 | #define TIMER_START_MESSAGE "Timer Start" // Timer start scroll message 217 | #define TIMER_STOP_MESSAGE "Timer Stop" // Timer stop scroll message 218 | 219 | // ========================================================================= 220 | #define UPDATE_TIME_COUNT 20 // default: 10 // every 10 scrolls, ~450s = 7.5m 221 | // 40 scrolls, ~1,800s = 30m (about) 222 | // 80 scrolls, ~3,600s = 60m (about) 223 | // 1920 scrolls, ~86,400s = 24h 224 | #endif 225 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/DHT.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * DHT11 temperature and humidity sensor 9 | * DHT22(AM2302) temperature and humidity sensor 10 | * DHT21(AM2301) temperature and humidity sensor 11 | * ========================================================================= 12 | */ 13 | 14 | #ifndef DHT22_H 15 | #define DHT22_H 16 | 17 | #include 18 | 19 | DHT dht(DHTPIN, DHTTYPE); 20 | 21 | int dhtGet = 0; 22 | float dhtHumidity; 23 | float dhtCTemp; 24 | float dhtFTemp; 25 | 26 | void DHT_setup() { 27 | dht.begin(); 28 | } 29 | 30 | void DHT_action() { 31 | // DHT22 Temperature & Humidity Sensor 32 | // Wait a few seconds between measurements. 33 | delay(2000); 34 | // Reading temperature or humidity takes about 250 milliseconds! 35 | // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) 36 | dhtHumidity = dht.readHumidity(); 37 | // Read temperature as Celsius (the default) 38 | dhtCTemp = dht.readTemperature(); 39 | // Read temperature as Fahrenheit (isFahrenheit = true) 40 | dhtFTemp = dht.readTemperature(true); 41 | 42 | // Check if any reads failed and exit early (to try again). 43 | if (isnan(dhtHumidity) || isnan(dhtCTemp) || isnan(dhtFTemp)) { 44 | #ifdef USE_UART 45 | Serial.println("Failed to read from DHT sensor!"); 46 | Serial.println(); 47 | #endif 48 | dhtGet = 1; 49 | return; 50 | } else { 51 | dhtGet = 0; 52 | 53 | // Compute heat index in Fahrenheit (the default) 54 | float hif = dht.computeHeatIndex(dhtFTemp, dhtHumidity); 55 | // Compute heat index in Celsius (isFahreheit = false) 56 | float hic = dht.computeHeatIndex(dhtCTemp, dhtHumidity, false); 57 | 58 | #ifdef USE_UART 59 | Serial.println("DHT Temperature & Humidity Sensor (D4 - 2)"); 60 | Serial.print("Temperature in Celsius : "); 61 | Serial.print(dhtCTemp, 1); 62 | Serial.println(" 'C "); 63 | Serial.print("Temperature in Fahrenheit : "); 64 | Serial.print(dhtFTemp, 1); 65 | Serial.println(" 'F\t"); 66 | Serial.print("Relative Humidity: "); 67 | Serial.print(dhtHumidity, 1); 68 | Serial.println(" %\t"); 69 | Serial.print("Heat index: "); 70 | Serial.print(hic); 71 | Serial.print(" 'C "); 72 | Serial.print(hif); 73 | Serial.println(" 'F"); 74 | Serial.println(); 75 | #endif 76 | } 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/DHT12.cpp: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * DHT12 temperature and humidity sensor library 9 | * MIT license 10 | * written by Renzo Mischianti 11 | * ========================================================================= 12 | */ 13 | 14 | #include "DHT12Driver.h" 15 | #include "Wire.h" 16 | 17 | // Default is i2c on default pin with default DHT12 adress 18 | DHT12::DHT12(void) { 19 | 20 | } 21 | 22 | DHT12::DHT12(uint8_t addressOrPin, bool oneWire) { 23 | _isOneWire = oneWire; 24 | if (oneWire) { 25 | _pin = addressOrPin; 26 | #ifdef __AVR 27 | _bit = digitalPinToBitMask(_pin); 28 | _port = digitalPinToPort(_pin); 29 | #endif 30 | _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for 31 | // reading pulses from DHT sensor. 32 | // Note that count is now ignored as the DHT reading algorithm adjusts itself 33 | // basd on the speed of the processor. 34 | 35 | DEBUG_PRINTLN("PIN MODE"); 36 | } else { 37 | _address = addressOrPin; 38 | DEBUG_PRINTLN("I2C MODE"); 39 | } 40 | } 41 | 42 | // Is not good idea use other pin for i2c as standard on Arduino you can get lag. 43 | // The lag happens when you choose "different pins", because you are then using a 44 | // slow software emulation of the I2C hardware. The built in I2C hardware has fixed pin assignments. 45 | #ifndef __AVR 46 | DHT12::DHT12(uint8_t sda, uint8_t scl) { 47 | _isOneWire = false; 48 | _sda = sda; 49 | _scl = scl; 50 | } 51 | 52 | DHT12::DHT12(uint8_t sda, uint8_t scl, uint8_t address) { 53 | _isOneWire = false; 54 | _sda = sda; 55 | _scl = scl; 56 | _address = address; 57 | } 58 | #endif 59 | 60 | void DHT12::begin() { 61 | _lastreadtime = -(MIN_ELAPSED_TIME + 1); 62 | if (_isOneWire) { 63 | // set up the pins! 64 | pinMode(_pin, INPUT_PULLUP); 65 | // Using this value makes sure that millis() - lastreadtime will be 66 | // >= MIN_INTERVAL right away. Note that this assignment wraps around, 67 | // but so will the subtraction. 68 | DEBUG_PRINT("Max clock cycles: "); 69 | DEBUG_PRINTLN(_maxcycles, DEC); 70 | } else { 71 | #ifndef __AVR 72 | Wire.begin(_sda, _scl); 73 | #else 74 | // Default pin for AVR some problem on software emulation 75 | // #define SCL_PIN _scl 76 | // #define SDA_PIN _sda 77 | Wire.begin(); 78 | #endif 79 | DEBUG_PRINT("I2C Inizialization: sda, scl: "); 80 | DEBUG_PRINT(_sda); 81 | DEBUG_PRINT(","); 82 | DEBUG_PRINTLN(_scl); 83 | } 84 | } 85 | 86 | DHT12::ReadStatus DHT12::readStatus(bool force) { 87 | // Check if sensor was read less than two seconds ago and return early 88 | // to use last reading. 89 | uint32_t currenttime = millis(); 90 | if (!force && ((currenttime - _lastreadtime) < MIN_ELAPSED_TIME)) { 91 | return _lastresult; // return last correct measurement 92 | } 93 | _lastreadtime = currenttime; 94 | 95 | if (_isOneWire) { 96 | // Reset 40 bits of received data to zero. 97 | data[0] = data[1] = data[2] = data[3] = data[4] = 0; 98 | 99 | // Send start signal. See DHT datasheet for full signal diagram: 100 | // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf 101 | 102 | // Go into high impedence state to let pull-up raise data line level and 103 | // start the reading process. 104 | digitalWrite(_pin, HIGH); 105 | delay(250); 106 | 107 | // First set data line low for 20 milliseconds. 108 | pinMode(_pin, OUTPUT); 109 | digitalWrite(_pin, LOW); 110 | delay(20); 111 | 112 | uint32_t cycles[80]; 113 | { 114 | // Turn off interrupts temporarily because the next sections are timing critical 115 | // and we don't want any interruptions. 116 | // InterruptLock lock; //################################### 117 | 118 | // End the start signal by setting data line high for 40 microseconds. 119 | digitalWrite(_pin, HIGH); 120 | delayMicroseconds(40); 121 | 122 | // Now start reading the data line to get the value from the DHT sensor. 123 | pinMode(_pin, INPUT_PULLUP); 124 | delayMicroseconds(10); // Delay a bit to let sensor pull data line low. 125 | 126 | // First expect a low signal for ~80 microseconds followed by a high signal 127 | // for ~80 microseconds again. 128 | if (expectPulse(LOW) == 0) { 129 | DEBUG_PRINTLN(F("Timeout waiting for start signal low pulse.")); 130 | _lastresult = ERROR_TIMEOUT_LOW; 131 | return _lastresult; 132 | } 133 | if (expectPulse(HIGH) == 0) { 134 | DEBUG_PRINTLN(F("Timeout waiting for start signal high pulse.")); 135 | _lastresult = ERROR_TIMEOUT_HIGH; 136 | return _lastresult; 137 | } 138 | 139 | // Now read the 40 bits sent by the sensor. Each bit is sent as a 50 140 | // microsecond low pulse followed by a variable length high pulse. If the 141 | // high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds 142 | // then it's a 1. We measure the cycle count of the initial 50us low pulse 143 | // and use that to compare to the cycle count of the high pulse to determine 144 | // if the bit is a 0 (high state cycle count < low state cycle count), or a 145 | // 1 (high state cycle count > low state cycle count). Note that for speed all 146 | // the pulses are read into a array and then examined in a later step. 147 | for (int i = 0; i < 80; i += 2) { 148 | cycles[i] = expectPulse(LOW); 149 | cycles[i + 1] = expectPulse(HIGH); 150 | } 151 | 152 | // Inspect pulses and determine which ones are 0 (high state cycle count < low 153 | // state cycle count), or 1 (high state cycle count > low state cycle count). 154 | for (int i=0; i<40; ++i) { 155 | uint32_t lowCycles = cycles[2*i]; 156 | uint32_t highCycles = cycles[2*i+1]; 157 | if ((lowCycles == 0) || (highCycles == 0)) { 158 | DEBUG_PRINTLN(F("Timeout waiting for pulse.")); 159 | _lastresult = ERROR_TIMEOUT; 160 | return _lastresult; 161 | } 162 | data[i/8] <<= 1; 163 | // Now compare the low and high cycle times to see if the bit is a 0 or 1. 164 | if (highCycles > lowCycles) { 165 | // High cycles are greater than 50us low cycle count, must be a 1. 166 | data[i/8] |= 1; 167 | } 168 | // Else high cycles are less than (or equal to, a weird case) the 50us low 169 | // cycle count so this must be a zero. Nothing needs to be changed in the 170 | // stored data. 171 | } 172 | 173 | DEBUG_PRINTLN(F("Received:")); 174 | DEBUG_PRINT(data[0], HEX); DEBUG_PRINT(F(", ")); 175 | DEBUG_PRINT(data[1], HEX); DEBUG_PRINT(F(", ")); 176 | DEBUG_PRINT(data[2], HEX); DEBUG_PRINT(F(", ")); 177 | DEBUG_PRINT(data[3], HEX); DEBUG_PRINT(F(", ")); 178 | DEBUG_PRINT(data[4], HEX); DEBUG_PRINT(F(" =? ")); 179 | DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0xFF, HEX); 180 | 181 | DHT12::ReadStatus cks = DHT12::_checksum(); 182 | if (cks != OK) { 183 | DEBUG_PRINTLN("CHECKSUM ERROR!"); 184 | _lastresult = cks; 185 | return cks; 186 | } 187 | 188 | _lastresult = OK; 189 | return OK; 190 | } 191 | // return DHT12::_readSensor(DHTLIB_DHT_WAKEUP, DHTLIB_DHT_LEADING_ZEROS); 192 | // return DHT12::_readSensor(DHTLIB_DHT11_WAKEUP, DHTLIB_DHT11_LEADING_ZEROS); 193 | 194 | } else { 195 | DEBUG_PRINT("I2C START READING.."); 196 | Wire.beginTransmission(_address); 197 | Wire.write(0); 198 | if (Wire.endTransmission() != 0) { 199 | DEBUG_PRINTLN("CONNECTION ERROR!"); 200 | _lastresult = ERROR_CONNECT; 201 | return _lastresult; 202 | } 203 | Wire.requestFrom(_address, (uint8_t) 5); 204 | for (uint8_t i = 0; i < 5; ++i) { 205 | data[i] = Wire.read(); 206 | DEBUG_PRINTLN(data[i]); 207 | } 208 | 209 | delay(1); 210 | if (Wire.available() != 0) { 211 | DEBUG_PRINTLN("TIMEOUT ERROR!"); 212 | _lastresult = ERROR_TIMEOUT; 213 | return _lastresult; 214 | } 215 | 216 | DHT12::ReadStatus cks = DHT12::_checksum(); 217 | if (cks != OK) { 218 | DEBUG_PRINTLN("CHECKSUM ERROR!"); 219 | _lastresult = cks; 220 | return cks; 221 | } 222 | 223 | DEBUG_PRINTLN("...READING OK"); 224 | _lastresult = OK; 225 | return _lastresult; 226 | } 227 | } 228 | 229 | bool DHT12::read(bool force) { 230 | ReadStatus chk = DHT12::readStatus(force); 231 | DEBUG_PRINT(F("\nRead sensor: ")); 232 | DEBUG_PRINT((chk != DHT12::OK)); 233 | switch (chk) { 234 | case DHT12::OK: 235 | DEBUG_PRINTLN(F("OK")); 236 | break; 237 | case DHT12::ERROR_CHECKSUM: 238 | DEBUG_PRINTLN(F("Checksum error")) 239 | ; 240 | break; 241 | case DHT12::ERROR_TIMEOUT: 242 | DEBUG_PRINTLN(F("Timeout error")) 243 | ; 244 | break; 245 | case DHT12::ERROR_TIMEOUT_HIGH: 246 | DEBUG_PRINTLN(F("Timeout error high")) 247 | ; 248 | break; 249 | case DHT12::ERROR_TIMEOUT_LOW: 250 | DEBUG_PRINTLN(F("Timeout error low")) 251 | ; 252 | break; 253 | case DHT12::ERROR_CONNECT: 254 | DEBUG_PRINTLN(F("Connect error")) 255 | ; 256 | break; 257 | case DHT12::ERROR_ACK_L: 258 | DEBUG_PRINTLN(F("AckL error")) 259 | ; 260 | break; 261 | case DHT12::ERROR_ACK_H: 262 | DEBUG_PRINTLN(F("AckH error")) 263 | ; 264 | break; 265 | case DHT12::ERROR_UNKNOWN: 266 | DEBUG_PRINTLN(F("Unknown error DETECTED")) 267 | ; 268 | break; 269 | case DHT12::NONE: 270 | DEBUG_PRINTLN(F("No result")) 271 | ; 272 | break; 273 | default: 274 | DEBUG_PRINTLN(F("Unknown error")) 275 | ; 276 | break; 277 | } 278 | return (chk == DHT12::OK); 279 | } 280 | 281 | float DHT12::convertCtoF(float c) { 282 | return c * 1.8 + 32; 283 | } 284 | 285 | float DHT12::convertFtoC(float f) { 286 | return (f - 32) * 0.55555; 287 | } 288 | 289 | // boolean isFahrenheit: True == Fahrenheit; False == Celsius 290 | float DHT12::computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit) { 291 | // Using both Rothfusz and Steadman's equations 292 | // http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml 293 | float hi; 294 | 295 | if (!isFahrenheit) 296 | temperature = convertCtoF(temperature); 297 | 298 | hi = 0.5 299 | * (temperature + 61.0 + ((temperature - 68.0) * 1.2) 300 | + (percentHumidity * 0.094)); 301 | 302 | if (hi > 79) { 303 | hi = -42.379 + 2.04901523 * temperature + 10.14333127 * percentHumidity 304 | + -0.22475541 * temperature * percentHumidity 305 | + -0.00683783 * pow(temperature, 2) 306 | + -0.05481717 * pow(percentHumidity, 2) 307 | + 0.00122874 * pow(temperature, 2) * percentHumidity 308 | + 0.00085282 * temperature * pow(percentHumidity, 2) 309 | + -0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2); 310 | 311 | if ((percentHumidity < 13) && (temperature >= 80.0) 312 | && (temperature <= 112.0)) 313 | hi -= ((13.0 - percentHumidity) * 0.25) 314 | * sqrt((17.0 - abs(temperature - 95.0)) * 0.05882); 315 | 316 | else if ((percentHumidity > 85.0) && (temperature >= 80.0) 317 | && (temperature <= 87.0)) 318 | hi += ((percentHumidity - 85.0) * 0.1) 319 | * ((87.0 - temperature) * 0.2); 320 | } 321 | 322 | return isFahrenheit ? hi : convertFtoC(hi); 323 | } 324 | 325 | float DHT12::readHumidity(bool force) { 326 | DEBUG_PRINTLN("----------------------------"); 327 | float humidity = NAN; 328 | 329 | if (_isOneWire) { 330 | if (DHT12::read(force)) { 331 | DEBUG_PRINT(data[0]); 332 | humidity = data[0]; 333 | } 334 | } else { 335 | if (DHT12::read(force)) { 336 | humidity = (data[0] + (float) data[1] / 10); 337 | } 338 | } 339 | return humidity; 340 | } 341 | 342 | // boolean S == Scale. True == Fahrenheit; False == Celsius 343 | float DHT12::readTemperature(bool scale, bool force) { 344 | float temperature = NAN; 345 | if (_isOneWire) { 346 | if (DHT12::read(force)) { 347 | temperature = data[2]; 348 | if (scale) { 349 | temperature = convertCtoF(temperature); 350 | } 351 | } 352 | } else { 353 | 354 | bool r = DHT12::read(force); 355 | DEBUG_PRINT("READ ---> "); 356 | DEBUG_PRINTLN(r); 357 | if (r) { 358 | DEBUG_PRINT("BIT 0 -> "); 359 | DEBUG_PRINTLN(data[0], BIN); 360 | DEBUG_PRINT("BIT 1 -> "); 361 | DEBUG_PRINTLN(data[1], BIN); 362 | DEBUG_PRINT("BIT 2 -> "); 363 | DEBUG_PRINTLN(data[2], BIN); 364 | DEBUG_PRINT("BIT 3 -> "); 365 | DEBUG_PRINTLN(data[3], BIN); 366 | DEBUG_PRINT("BIT 4 -> "); 367 | DEBUG_PRINTLN(data[4], BIN); 368 | DEBUG_PRINT("BIT 5 -> "); 369 | DEBUG_PRINTLN(data[5], BIN); 370 | 371 | byte scaleValue = data[3] & B01111111; 372 | byte signValue = data[3] & B10000000; 373 | 374 | temperature = (data[2] + (float) scaleValue / 10);// ((data[2] & 0x7F)*256 + data[3]); 375 | if (signValue) // negative temperature 376 | temperature = -temperature; 377 | 378 | if (scale) { 379 | temperature = convertCtoF(temperature); 380 | } 381 | } 382 | } 383 | return temperature; 384 | 385 | } 386 | 387 | #include 388 | // dewPoint function NOAA 389 | // reference (1) : http://wahiduddin.net/calc/density_algorithms.htm 390 | // reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm 391 | // 392 | // boolean S == Scale. True == Fahrenheit; False == Celsius 393 | float DHT12::dewPoint(float temperature, float humidity, bool isFahrenheit) { 394 | // sloppy but good approximation for 0 ... +70 °C with max. deviation less than 0.25 °C 395 | 396 | float temp; 397 | 398 | if(!isFahrenheit){ 399 | temp = temperature; 400 | } else { 401 | temp = convertFtoC(temperature); 402 | } 403 | 404 | float humi = humidity; 405 | float ans = (temp - (14.55 + 0.114 * temp) * (1 - (0.01 * humi)) - pow(((2.5 + 0.007 * temp) * (1 - (0.01 * humi))),3) - (15.9 + 0.117 * temp) * pow((1 - (0.01 * humi)), 14)); 406 | 407 | if(!isFahrenheit){ 408 | return ans; // returns dew Point in Celsius 409 | } 410 | 411 | return convertCtoF(ans); // returns dew Point in Fahrenheit 412 | } 413 | 414 | //////// PRIVATE 415 | DHT12::ReadStatus DHT12::_checksum() { 416 | uint8_t sum = data[0] + data[1] + data[2] + data[3]; 417 | if (data[4] != sum) 418 | return ERROR_CHECKSUM; 419 | return OK; 420 | } 421 | 422 | // Expect the signal line to be at the specified level for a period of time and 423 | // return a count of loop cycles spent at that level (this cycle count can be 424 | // used to compare the relative time of two pulses). If more than a millisecond 425 | // ellapses without the level changing then the call fails with a 0 response. 426 | // This is adapted from Arduino's pulseInLong function (which is only available 427 | // in the very latest IDE versions): 428 | // https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c 429 | uint32_t DHT12::expectPulse(bool level) { 430 | uint32_t count = 0; 431 | // On AVR platforms use direct GPIO port access as it's much faster and better 432 | // for catching pulses that are 10's of microseconds in length: 433 | #ifdef __AVR 434 | uint8_t portState = level ? _bit : 0; 435 | while ((*portInputRegister(_port) & _bit) == portState) { 436 | if (count++ >= _maxcycles) { 437 | return 0; // Exceeded timeout, fail. 438 | } 439 | } 440 | // Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266 441 | // right now, perhaps bugs in direct port access functions?). 442 | #else 443 | while (digitalRead(_pin) == level) { 444 | if (count++ >= _maxcycles) { 445 | return 0; // Exceeded timeout, fail. 446 | } 447 | } 448 | #endif 449 | 450 | return count; 451 | } 452 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/DHT12.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * DHT12 temperature and humidity sensor 9 | * ========================================================================= 10 | */ 11 | 12 | #ifndef DHT12_H 13 | #define DHT12_H 14 | 15 | #include "DHT12Driver.h" 16 | 17 | // Set dht12 i2c comunication on default Wire pin 18 | DHT12 dht12; 19 | int timeSinceLastRead = 0; 20 | int dht12get = 0; 21 | 22 | void DHT12_setup() { 23 | dht12.begin(); 24 | } 25 | 26 | void DHT12_action() { 27 | // Report every 2 seconds. 28 | if(timeSinceLastRead > 2000) { 29 | // Read temperature as Celsius (the default) 30 | float t12 = dht12.readTemperature(); 31 | // Read temperature as Fahrenheit (isFahrenheit = true) 32 | float f12 = dht12.readTemperature(true); 33 | // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) 34 | float h12 = dht12.readHumidity(); 35 | bool dht12Read = true; 36 | // Check if any reads failed and exit early (to try again). 37 | if (isnan(h12) || isnan(t12) || isnan(f12)) { 38 | Serial.println("Failed to read from DHT12 sensor!"); 39 | dht12Read = false; 40 | dht12get = 1; 41 | } 42 | dht12get = 0; 43 | timeSinceLastRead = 0; 44 | } 45 | timeSinceLastRead += 100; 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/DHT12Driver.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * DHT12 temperature and humidity sensor library 9 | * MIT license 10 | * written by Renzo Mischianti 11 | * ========================================================================= 12 | */ 13 | 14 | #ifndef DHT12_DRIVER_H 15 | #define DHT12_DRIVER_H 16 | 17 | #if ARDUINO >= 100 18 | #include "Arduino.h" 19 | #else 20 | #include "WProgram.h" 21 | #endif 22 | #include "Wire.h" 23 | 24 | #define DEFAULT_DHT12_ADDRESS 0x5C; 25 | #define DEFAULT_SDA SDA; 26 | #define DEFAULT_SCL SCL; 27 | 28 | #define MIN_ELAPSED_TIME 2000 29 | 30 | // Uncomment to enable printing out nice debug messages. 31 | //#define DHT_DEBUG 32 | 33 | // Define where debug output will be printed. 34 | #define DEBUG_PRINTER Serial 35 | 36 | // Setup debug printing macros. 37 | #ifdef DHT_DEBUG 38 | #define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); } 39 | #define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); } 40 | #else 41 | #define DEBUG_PRINT(...) {} 42 | #define DEBUG_PRINTLN(...) {} 43 | #endif 44 | 45 | #ifndef __AVR 46 | #define DHTLIB_TIMEOUT 10000 // should be approx. clock/40000 47 | #else 48 | #ifndef F_CPU 49 | #define DHTLIB_TIMEOUT 1000 // should be approx. clock/40000 50 | #else 51 | #define DHTLIB_TIMEOUT (F_CPU/40000) 52 | #endif 53 | #endif 54 | 55 | class DHT12 { 56 | public: 57 | /**Status of the read*/ 58 | enum ReadStatus { 59 | OK, /**All ok*/ 60 | ERROR_CHECKSUM, /**Error on checksum*/ 61 | ERROR_TIMEOUT, /**Timeout error*/ 62 | ERROR_TIMEOUT_LOW, /**Timeout on wait after low pulse*/ 63 | ERROR_TIMEOUT_HIGH,/**Timeout on wait after high pulse*/ 64 | ERROR_CONNECT, /**Connection error (Wire)*/ 65 | ERROR_ACK_L,/**Acknowledge Low */ 66 | ERROR_ACK_H,/**Acknowledge High */ 67 | ERROR_UNKNOWN, /**Error unknown */ 68 | NONE 69 | }; 70 | 71 | /** 72 | * Standard constructor, default wire connection on default SDA SCL pin 73 | */ 74 | DHT12(void); 75 | /** 76 | * Constructor 77 | * @param addressORPin If oneWire == true this is pin number if oneWire false this is address of i2c 78 | * @param oneWire select if is oneWire of i2c 79 | */ 80 | DHT12(uint8_t addressORPin, bool oneWire = false); 81 | #ifndef __AVR 82 | /** 83 | * Additional parameter non tested for Arduino, Arduino very slow on software i2c 84 | */ 85 | DHT12(uint8_t sda, uint8_t scl); 86 | DHT12(uint8_t sda, uint8_t scl, uint8_t address); 87 | #endif 88 | /** 89 | * Start handshake 90 | */ 91 | void begin(void); 92 | /** 93 | * Read temperature 94 | * @param scale Select false --> Celsius true --> Fahrenheit 95 | * @param force 96 | * @return 97 | */ 98 | float readTemperature(bool scale = false, bool force = false); 99 | /** 100 | * Convert Celsius to Fahrenheit 101 | * @param 102 | * @return 103 | */ 104 | float convertCtoF(float); 105 | /** 106 | * Convert Fahrenheit to Celsius 107 | * @param 108 | * @return 109 | */ 110 | float convertFtoC(float); 111 | /** 112 | * The heat index (HI) or humiture is an index that combines air temperature and relative humidity, in shaded areas, as an attempt to determine the human-perceived equivalent temperature, as how hot it would feel if the humidity were some other value in the shade. The result is also known as the "felt air temperature" or "apparent temperature". 113 | * @param temperature 114 | * @param percentHumidity 115 | * @param isFahrenheit specify scale of temperature 116 | * @return 117 | */ 118 | float computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit = true); 119 | /** 120 | * Read humidity percentage 121 | * @param force Force to request new data (if 2secs is not passed from previous request) 122 | * @return 123 | */ 124 | float readHumidity(bool force = false); 125 | /** 126 | * Dew point the atmospheric temperature (varying according to pressure and humidity) below which water droplets begin to condense and dew can form. 127 | * @param temperature 128 | * @param humidity 129 | * @param isFahrenheit specify scale of temperature 130 | * @return 131 | */ 132 | float dewPoint(float temperature, float humidity, bool isFahrenheit = true); 133 | /** 134 | * Read and return status of the read 135 | * @param force 136 | * @return 137 | */ 138 | ReadStatus readStatus(bool force = false);bool read(bool force = false); 139 | 140 | private: 141 | bool _isOneWire = false; 142 | 143 | uint8_t data[5]; 144 | uint8_t _address = DEFAULT_DHT12_ADDRESS; 145 | uint8_t _sda = DEFAULT_SDA; 146 | uint8_t _scl = DEFAULT_SCL; 147 | 148 | uint32_t _lastreadtime = 0; 149 | ReadStatus _lastresult = NONE; 150 | 151 | uint8_t _pin = 3; 152 | #ifdef __AVR 153 | // Use direct GPIO access on an 8-bit AVR so keep track of the port and bitmask 154 | // for the digital pin connected to the DHT. Other platforms will use digitalRead. 155 | uint8_t _bit = 0, _port = 0; 156 | #endif 157 | uint32_t _maxcycles = 0; 158 | 159 | ReadStatus _checksum(void); 160 | uint32_t expectPulse(bool level); 161 | ReadStatus _readSensor(uint8_t wakeupDelay, uint8_t leadingZeroBits); 162 | }; 163 | 164 | /* 165 | //################################################################## 166 | class InterruptLock { 167 | public: 168 | InterruptLock() { 169 | noInterrupts(); 170 | } 171 | ~InterruptLock() { 172 | interrupts(); 173 | } 174 | }; 175 | //################################################################## 176 | */ 177 | #endif 178 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/DS18B20.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * DS18B20 temperature sensor 9 | * ========================================================================= 10 | */ 11 | 12 | #ifndef DS18B20_H 13 | #define DS18B20_H 14 | 15 | #include 16 | #include 17 | 18 | // Setup a oneWire instance to communicate with any OneWire devices 19 | OneWire ourWire(ONE_WIRE_BUS); 20 | // Pass our oneWire reference to Dallas Temperature. 21 | DallasTemperature sensors(&ourWire); 22 | 23 | // arrays to hold device addresses 24 | DeviceAddress insideThermometer, outsideThermometer; 25 | 26 | int ds18b20get = 0; 27 | 28 | void DS18B20_setup() { 29 | pinMode(ONE_WIRE_BUS, INPUT); 30 | sensors.begin(); 31 | 32 | // search for devices on the bus and assign based on an index. 33 | if (!sensors.getAddress(insideThermometer, 0)) { 34 | #ifdef USE_UART 35 | Serial.println("Unable to find address for Device 0"); 36 | #endif 37 | ds18b20get = 1; 38 | return; 39 | } 40 | if (!sensors.getAddress(outsideThermometer, 1)) { 41 | #ifdef USE_UART 42 | Serial.println("Unable to find address for Device 1"); 43 | #endif 44 | //ds18b20get = 2; 45 | return; 46 | } 47 | } 48 | 49 | void DS18B20_action() { 50 | sensors.requestTemperatures(); // Send the command to get temperatures 51 | if (ds18b20get == 0) { 52 | #ifdef USE_UART 53 | Serial.println("DS18B20 Temperature Sensor (TX - 1)"); 54 | Serial.print("Temperature: "); 55 | Serial.print(sensors.getTempCByIndex(0)); 56 | Serial.print(" 'C, "); 57 | Serial.print(sensors.getTempFByIndex(0)); 58 | Serial.println(" 'F"); 59 | Serial.println(); 60 | #endif 61 | } else if(ds18b20get == 1) { 62 | #ifdef USE_UART 63 | Serial.println("Unable to find address for Device X"); 64 | Serial.println("Failed to read from DS18B20 sensor!"); 65 | Serial.println(); 66 | #endif 67 | ds18b20get = 1; 68 | return; 69 | } 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/ESP8266_LED_Matrix_Bar_Weather_Station.ino: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4b (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * -> Change WebApp scroll control (2021/01/11) 9 | * -> Added timer setting (2020/10/13) 10 | * -> Added alarm message setting function: 11 | * .................Set scroll message to alarm message (2020/09/13) 12 | * -> Added alarm setting (2020/09/10) 13 | * -> AM-PM Mode, 24-hour clock, 12-hour clock (2020/09/09) 14 | * -> Google clock replaced with NTP clock (2020/09/07) 15 | * -> Resolved a problem that initialized when receiving Google clock 16 | * -> Added web page refresh time (2020/09/06) 17 | * -> Added RGB LED (2020/09/05) 18 | * -> Error: ets jan 8 2013,rst cause:2, boot mode:(3,6) (2020/09/05) 19 | * -> Added MQTT - Adafruit IO MQTT + IFTTT + Google Assistant (2020/07/30) 20 | * -> Update Count 7.5m to 60m (2020/07/22) 21 | * -> Added CHAR_SHIFT_DELAY - Config (2020/07/22) 22 | * -> Change DHT12 Library (2018/03/12) 23 | * ========================================================================= 24 | * Parts List: 25 | * - 6 x MAX7219 8x8 Matrix LED 26 | * - 1 x WeMos D1 mini 27 | * - 1 x Interface shield 28 | * Additional Parts: 29 | * - 1 x DS18B20 temperature sensor (Option) 30 | * - 1 x DHT22 temperature and humidity sensor (Option) 31 | * - 1 x DHT12 temperature and humidity sensor (Option) 32 | * - N x WS2812B RGB LED (Option) 33 | * - 1 x Alarm On/Off button switch 34 | * - 1 x Lamp Push button switch 35 | * - 1 x Scroll Push button switch 36 | * - 1 x Power On/Off switch 37 | * - 1 x Buzzer 38 | * ------------------------------------------------------------------------- 39 | * Fuctions: 40 | * - OTA 41 | * - mDNS 42 | * - WiFi Manager 43 | * - Web Server (WebUI) 44 | * - LED Matrix Clock 45 | * - Open Weather Map Weather Forecast 46 | * - Indoor and Outdoor temperature and Humidity sensor monitor 47 | * - Scrolling message 48 | * - Scroll Push Switch 49 | * - Lamp Push Switch 50 | * - Alarm time setting (WebUI) 51 | * - Alarm On/Off and Switch 52 | * - Google Assistant: Adafruit IO MQTT + IFTTT 53 | * ========================================================================= 54 | */ 55 | 56 | #include // this needs to be first, or it all crashes and burns... 57 | 58 | #include 59 | #include "Config.h" 60 | #include "WiFi_Setup.h" 61 | // Shields: ================================================================ 62 | #ifdef USE_DS18B20 63 | #include "DS18B20.h" 64 | #endif 65 | #ifdef USE_DHT 66 | #include "DHT.h" 67 | #endif 68 | #ifdef USE_DHT12 69 | #include "DHT12.h" 70 | #endif 71 | #ifdef USE_RGB_LED_NEOPIXEL 72 | #include "WS2812B_NeoPixel.h" 73 | #endif 74 | #ifdef USE_RGB_LED_STRIP_DRIVER 75 | #include "LEDStrip.h" 76 | #endif 77 | // ========================================================================= 78 | #ifdef USE_LEDMATRIX_CLOCKWEATHER 79 | #include "LEDMatrix_ClockWeather.h" 80 | #endif 81 | #ifdef USE_WEB_SERVER 82 | #include "Web_Server.h" 83 | #endif 84 | #ifdef USE_MQTT 85 | #include "MQTT.h" 86 | #endif 87 | 88 | int ScrollingMessage = 0; 89 | int weatherScrollInterval = WEATHER_SCROLL_INTERVAL; 90 | 91 | int freq[] = {1047, 1175, 1319, 1397, 1568, 1760, 1976, 2093}; 92 | String note[] = {"C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7"}; 93 | 94 | int alarm_action = 1; 95 | String alarm_message = ""; 96 | String onTimeMessage = OnTIME_MESSAGE; 97 | int timer_action_start = 1; 98 | int timer_action_stop = 1; 99 | String timerStartMessage = TIMER_START_MESSAGE; 100 | String timerStopMessage = TIMER_STOP_MESSAGE; 101 | 102 | void setup() { // ######################################################### 103 | // put your setup code here, to run once: 104 | Serial.begin(SERIAL_SPEED); 105 | Serial.println("LED Matrix Bar Weather Station"); 106 | Serial.println(); 107 | delay(10); 108 | #ifdef USE_DHT 109 | pinMode(DHTPIN, INPUT); // TXD --> DHT11, DHT22 110 | #endif 111 | #ifdef USE_DS18B20 112 | pinMode(ONE_WIRE_BUS, INPUT); // DS18B20 113 | #endif 114 | pinMode(RED_PIN, OUTPUT); // Alarm ON/OFF SW (Red) 115 | pinMode(GREEN_PIN, OUTPUT); // Lamp Push Button SW (Green) 116 | pinMode(BLUE_PIN, OUTPUT); // Weather Scroll Push Button SW (Blue) 117 | pinMode(WHITE_PIN, OUTPUT); // RXD --> Buzzer & LED 118 | digitalWrite(RED_PIN, LOW); 119 | digitalWrite(GREEN_PIN, LOW); 120 | digitalWrite(BLUE_PIN, LOW); 121 | digitalWrite(WHITE_PIN, LOW); 122 | #ifndef USE_DHT 123 | #ifndef USE_RGB_LED_STRIP_DRIVER 124 | pinMode(DHTPIN, OUTPUT); // D4 (GPIO02) 125 | digitalWrite(DHTPIN, HIGH); // Build-in blue LED disable 126 | #endif 127 | #endif 128 | #ifdef USE_RGB_LED_DIRECT 129 | pinMode(RGB_LED_RED_PIN, OUTPUT); 130 | pinMode(RGB_LED_GREEN_PIN, OUTPUT); 131 | pinMode(RGB_LED_BLUE_PIN, OUTPUT); 132 | digitalWrite(RGB_LED_RED_PIN, LOW); 133 | digitalWrite(RGB_LED_GREEN_PIN, LOW); 134 | digitalWrite(RGB_LED_BLUE_PIN, LOW); 135 | #endif 136 | #if defined(DEV_BOARD_WeMos_D1_mini) || defined(DEV_BOARD_ESP01) 137 | pinMode(USE_RELAY_PIN, OUTPUT); // Relay 138 | digitalWrite(USE_RELAY_PIN, LOW); 139 | #endif 140 | #ifdef DEV_BOARD_Witty 141 | pinMode(USE_LIGHT_PIN, OUTPUT); // Light 142 | pinMode(USE_RELAY_PIN, OUTPUT); // Relay 143 | digitalWrite(USE_LIGHT_PIN, LOW); 144 | digitalWrite(USE_RELAY_PIN, LOW); 145 | #endif 146 | #ifdef DEV_BOARD_WiFi_RELAY_MODULE 147 | pinMode(USE_INPUT_PIN, OUTPUT); // Input to Output 148 | pinMode(USE_RELAY_PIN, OUTPUT); // Relay 149 | digitalWrite(USE_INPUT_PIN, LOW); 150 | digitalWrite(USE_RELAY_PIN, LOW); 151 | #endif 152 | 153 | WiFi_setup(); 154 | 155 | // Shields ================================================================= 156 | #ifdef USE_DS18B20 157 | DS18B20_setup(); 158 | #endif 159 | #ifdef USE_DHT 160 | DHT_setup(); 161 | #endif 162 | #ifdef USE_DHT12 163 | DHT12_setup(); 164 | #endif 165 | #ifdef USE_RGB_LED_NEOPIXEL 166 | NeoPixel_setup(); 167 | #endif 168 | #ifdef USE_RGB_LED_STRIP_DRIVER 169 | led.setColor(); 170 | #endif 171 | // ========================================================================= 172 | #ifdef USE_LEDMATRIX_CLOCKWEATHER 173 | LEDMatrix_ClockWeather_setup(); 174 | #endif 175 | #ifdef USE_WEB_SERVER 176 | Webserver_setup(); 177 | #endif 178 | #ifdef USE_MQTT 179 | MQTT_setup(); 180 | #endif 181 | } 182 | 183 | void loop() { // ########################################################## 184 | ESP.wdtFeed(); // feeds the dog // Error: ets jan 8 2013,rst cause:2, boot mode:(3,6) 185 | #ifdef USE_OTA 186 | if (OTAmode == 1) { 187 | OTA_action(); 188 | } 189 | #endif 190 | #ifdef USE_WEB_SERVER 191 | Webserver_action(); 192 | #endif 193 | #ifdef USE_LEDMATRIX_CLOCKWEATHER 194 | LEDMatrix_action(); 195 | if(millis() - clkTime > weatherScrollInterval && !del && dots) { // clock for 15s, then scrolls for about 30s 196 | #ifdef USE_LED_MATRIX 197 | if (dateScroll == 1) { 198 | LEDMatrix_Date_action(); 199 | } 200 | #ifdef USE_DHT 201 | if (indoorScroll == 1) { 202 | LEDMatrix_DHT_action(); 203 | } 204 | #endif 205 | #ifdef USE_DHT12 206 | if (outdoorScroll == 1) { 207 | LEDMatrix_DHT12_action(); 208 | } 209 | #endif 210 | if (weatherScroll == 1) { 211 | LEDMatrix_Weather_action(); 212 | } 213 | #endif 214 | updCnt--; 215 | clkTime = millis(); 216 | } 217 | #endif 218 | if (Clock == 1) { 219 | LEDMatrix_Clock_action(); 220 | } 221 | // Alarm On/Off Switch 222 | if (digitalRead(RED_PIN)) { 223 | if (printMsg == "") { 224 | alarm_message = ALARM_MESSAGE; 225 | } else { 226 | alarm_message = printMsg; 227 | } 228 | if (m == alarm_m_set && alarm_action == 1) { 229 | // On-time Alarm 230 | if (onTimeAlarm == 1 && m == alarm_m_set && alarm_state == 1) { 231 | for (int i = 0; i < 8; i++) { 232 | digitalWrite(WHITE_PIN, HIGH); 233 | #ifdef USE_RGB_LED_DIRECT 234 | digitalWrite(RGB_LED_RED_PIN, HIGH); digitalWrite(RGB_LED_GREEN_PIN, HIGH); digitalWrite(RGB_LED_BLUE_PIN, HIGH); 235 | #endif 236 | delay(500); 237 | digitalWrite(WHITE_PIN, LOW); 238 | #ifdef USE_RGB_LED_DIRECT 239 | digitalWrite(RGB_LED_RED_PIN, LOW); digitalWrite(RGB_LED_GREEN_PIN, LOW); digitalWrite(RGB_LED_BLUE_PIN, LOW); 240 | #endif 241 | delay(500); 242 | } 243 | #ifdef USE_RGB_LED_STRIP_DRIVER 244 | ledStripColorWipe(); 245 | #endif 246 | #ifdef USE_LED_MATRIX 247 | printStringWithShift(" ", stringShiftDelay); 248 | printStringWithShift(onTimeMessage.c_str(), stringShiftDelay); 249 | delay(1000); 250 | printStringWithShift(" ", stringShiftDelay); 251 | delay(waitScroll); 252 | #endif 253 | // 12-hour clock Alarm 254 | } else if (am_pm == 12 && ampm == alarm_ampm_select && h == alarm_h_set && m == alarm_m_set && alarm_state == 1) { 255 | for (int i = 0; i < 8; i++) { 256 | digitalWrite(WHITE_PIN, HIGH); 257 | #ifdef USE_RGB_LED_DIRECT 258 | digitalWrite(RGB_LED_RED_PIN, HIGH); digitalWrite(RGB_LED_GREEN_PIN, HIGH); digitalWrite(RGB_LED_BLUE_PIN, HIGH); 259 | #endif 260 | delay(500); 261 | digitalWrite(WHITE_PIN, LOW); 262 | #ifdef USE_RGB_LED_DIRECT 263 | digitalWrite(RGB_LED_RED_PIN, LOW); digitalWrite(RGB_LED_GREEN_PIN, LOW); digitalWrite(RGB_LED_BLUE_PIN, LOW); 264 | #endif 265 | delay(500); 266 | } 267 | #ifdef USE_RGB_LED_STRIP_DRIVER 268 | ledStripColorWipe(); 269 | #endif 270 | #ifdef USE_LED_MATRIX 271 | printStringWithShift(" ", stringShiftDelay); 272 | printStringWithShift(alarm_message.c_str(), stringShiftDelay); 273 | delay(1000); 274 | printStringWithShift(" ", stringShiftDelay); 275 | delay(waitScroll); 276 | #endif 277 | // 24-hour clock Alarm 278 | } else if (am_pm == 24 && h == alarm_h_set && m == alarm_m_set && alarm_state == 1) { 279 | for (int i = 0; i < 8; i++) { 280 | digitalWrite(WHITE_PIN, HIGH); 281 | #ifdef USE_RGB_LED_DIRECT 282 | digitalWrite(RGB_LED_RED_PIN, HIGH); digitalWrite(RGB_LED_GREEN_PIN, HIGH); digitalWrite(RGB_LED_BLUE_PIN, HIGH); 283 | #endif 284 | delay(200); 285 | digitalWrite(WHITE_PIN, LOW); 286 | #ifdef USE_RGB_LED_DIRECT 287 | digitalWrite(RGB_LED_RED_PIN, LOW); digitalWrite(RGB_LED_GREEN_PIN, LOW); digitalWrite(RGB_LED_BLUE_PIN, LOW); 288 | #endif 289 | delay(200); 290 | } 291 | #ifdef USE_RGB_LED_STRIP_DRIVER 292 | ledStripColorWipe(); 293 | #endif 294 | #ifdef USE_LED_MATRIX 295 | printStringWithShift(" ", stringShiftDelay); 296 | printStringWithShift(alarm_message.c_str(), stringShiftDelay); 297 | delay(1000); 298 | printStringWithShift(" ", stringShiftDelay); 299 | delay(waitScroll); 300 | #endif 301 | } 302 | alarm_action = 0; 303 | } else if (m == alarm_m_set + 1) { 304 | alarm_action = 1; 305 | } 306 | } 307 | // Lamp Push Button Switch 308 | if (digitalRead(GREEN_PIN)) { 309 | #ifdef USE_RELAY 310 | digitalWrite(USE_RELAY_PIN, HIGH); 311 | #endif 312 | } 313 | if (!digitalRead(GREEN_PIN)) { 314 | #ifdef USE_RELAY 315 | digitalWrite(USE_RELAY_PIN, LOW); 316 | #endif 317 | } 318 | #ifdef USE_LED_MATRIX 319 | // Weather Scroll Push Button Switch 320 | if (digitalRead(BLUE_PIN)) { 321 | if (dateScroll == 0) { 322 | LEDMatrix_Date_action(); 323 | } 324 | #ifdef USE_DHT 325 | if (indoorScroll == 0) { 326 | LEDMatrix_DHT_action(); 327 | } 328 | #endif 329 | #ifdef USE_DHT12 330 | if (outdoorScroll == 0) { 331 | LEDMatrix_DHT12_action(); 332 | } 333 | #endif 334 | if (weatherScroll == 0) { 335 | LEDMatrix_Weather_action(); 336 | } 337 | } 338 | #endif 339 | #ifdef DEV_BOARD_Witty 340 | if (light05on_state == 1) { 341 | digitalWrite(USE_LIGHT_PIN, HIGH); 342 | } 343 | if (light05on_state == 0) { 344 | digitalWrite(USE_LIGHT_PIN, LOW); 345 | } 346 | } 347 | if (digitalRead(USE_RELAY_PIN)) { 348 | digitalWrite(RGB_LED_RED_PIN, HIGH); digitalWrite(RGB_LED_GREEN_PIN, HIGH); digitalWrite(RGB_LED_BLUE_PIN, HIGH); 349 | } 350 | if (!digitalRead(USE_RELAY_PIN)) { 351 | digitalWrite(RGB_LED_RED_PIN, LOW); digitalWrite(RGB_LED_GREEN_PIN, LOW); digitalWrite(RGB_LED_BLUE_PIN, LOW); 352 | } 353 | #endif 354 | #ifdef DEV_BOARD_WiFi_RELAY_MODULE 355 | if (light05on_state == 1) { 356 | digitalWrite(USE_INPUT_PIN, HIGH); 357 | } 358 | if (light05on_state == 0) { 359 | digitalWrite(USE_INPUT_PIN, LOW); 360 | } 361 | #endif 362 | #ifdef USE_TIMER 363 | // Timer start 364 | if (m == timer_m_start && timer_action_start == 1) { 365 | // 12-hour clock 366 | if (am_pm == 12 && ampm == timer_start_ampm_select && h == timer_h_start && m == timer_m_start && timer_state == 1) { 367 | #ifdef DEV_BOARD_Witty 368 | digitalWrite(USE_LIGHT_PIN, HIGH); 369 | light05on_state = 1; 370 | #endif 371 | digitalWrite(GREEN_PIN, HIGH); 372 | #ifdef USE_RGB_LED_DIRECT 373 | digitalWrite(RGB_LED_RED_PIN, HIGH); digitalWrite(RGB_LED_GREEN_PIN, HIGH); digitalWrite(RGB_LED_BLUE_PIN, HIGH); 374 | #endif 375 | #ifdef USE_RGB_LED_STRIP_DRIVER 376 | ledStripColorWipe(); 377 | led.setColor(255, 255, 255); 378 | #endif 379 | #ifdef USE_LED_MATRIX 380 | printStringWithShift(" ", stringShiftDelay); 381 | printStringWithShift(timerStartMessage.c_str(), stringShiftDelay); 382 | delay(1000); 383 | printStringWithShift(" ", stringShiftDelay); 384 | delay(waitScroll); 385 | #endif 386 | timer_action_start = 0; 387 | timer_action_stop = 1; 388 | // 24-hour clock 389 | } else if (am_pm == 24 && h == timer_h_start && m == timer_m_start && timer_state == 1) { 390 | #ifdef DEV_BOARD_Witty 391 | digitalWrite(USE_LIGHT_PIN, HIGH); 392 | light05on_state = 1; 393 | #endif 394 | digitalWrite(GREEN_PIN, HIGH); 395 | #ifdef USE_RGB_LED_DIRECT 396 | digitalWrite(RGB_LED_RED_PIN, HIGH); digitalWrite(RGB_LED_GREEN_PIN, HIGH); digitalWrite(RGB_LED_BLUE_PIN, HIGH); 397 | #endif 398 | #ifdef USE_RGB_LED_STRIP_DRIVER 399 | ledStripColorWipe(); 400 | led.setColor(255, 255, 255); 401 | #endif 402 | #ifdef USE_LED_MATRIX 403 | printStringWithShift(" ", stringShiftDelay); 404 | printStringWithShift(timerStartMessage.c_str(), stringShiftDelay); 405 | delay(1000); 406 | printStringWithShift(" ", stringShiftDelay); 407 | delay(waitScroll); 408 | #endif 409 | timer_action_start = 0; 410 | timer_action_stop = 1; 411 | } 412 | } 413 | // Timer stop 414 | if (m == timer_m_stop && timer_action_stop == 1) { 415 | // 12-hour clock 416 | if (am_pm == 12 && ampm == timer_stop_ampm_select && h == timer_h_stop && m == timer_m_stop && timer_state == 1) { 417 | #ifdef DEV_BOARD_Witty 418 | digitalWrite(USE_LIGHT_PIN, LOW); 419 | light05on_state = 0; 420 | #endif 421 | digitalWrite(GREEN_PIN, LOW); 422 | #ifdef USE_RGB_LED_DIRECT 423 | digitalWrite(RGB_LED_RED_PIN, LOW); digitalWrite(RGB_LED_GREEN_PIN, LOW); digitalWrite(RGB_LED_BLUE_PIN, LOW); 424 | #endif 425 | #ifdef USE_RGB_LED_STRIP_DRIVER 426 | led.setColor(); 427 | #endif 428 | #ifdef USE_LED_MATRIX 429 | printStringWithShift(" ", stringShiftDelay); 430 | printStringWithShift(timerStopMessage.c_str(), stringShiftDelay); 431 | delay(1000); 432 | printStringWithShift(" ", stringShiftDelay); 433 | delay(waitScroll); 434 | #endif 435 | timer_action_stop = 0; 436 | timer_action_start = 1; 437 | // 24-hour clock 438 | } else if (am_pm == 24 && h == timer_h_stop && m == timer_m_stop && timer_state == 1) { 439 | #ifdef DEV_BOARD_Witty 440 | digitalWrite(USE_LIGHT_PIN, LOW); 441 | light05on_state = 0; 442 | #endif 443 | digitalWrite(GREEN_PIN, LOW); 444 | #ifdef USE_RGB_LED_DIRECT 445 | digitalWrite(RGB_LED_RED_PIN, LOW); digitalWrite(RGB_LED_GREEN_PIN, LOW); digitalWrite(RGB_LED_BLUE_PIN, LOW); 446 | #endif 447 | #ifdef USE_RGB_LED_STRIP_DRIVER 448 | led.setColor(); 449 | #endif 450 | #ifdef USE_LED_MATRIX 451 | printStringWithShift(" ", stringShiftDelay); 452 | printStringWithShift(timerStopMessage.c_str(), stringShiftDelay); 453 | delay(1000); 454 | printStringWithShift(" ", stringShiftDelay); 455 | delay(waitScroll); 456 | #endif 457 | timer_action_stop = 0; 458 | timer_action_start = 1; 459 | } 460 | } 461 | #endif 462 | #ifdef USE_MQTT 463 | MQTT_action(); 464 | #endif 465 | } 466 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/LEDMatrix_ClockWeather.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * LED Matrix Bar Interface 9 | * ========================================================================= 10 | */ 11 | 12 | #ifndef LEDMATRIX_CLOCKWEATHER_H 13 | #define LEDMATRIX_CLOCKWEATHER_H 14 | 15 | #include 16 | #include "NTPClient.h" 17 | 18 | WiFiClient client; 19 | 20 | const char *projectName = PROJECT_NAME; 21 | const char *projectVersion = PROJECT_VERSION; 22 | 23 | int stringShiftDelay = STRING_SHIFT_DELAY; 24 | int updateTimeCount = UPDATE_TIME_COUNT; 25 | 26 | String weatherMain = ""; 27 | String weatherDescription = ""; 28 | String weatherLocation = ""; 29 | String country; 30 | int humidity; 31 | int pressure; 32 | float temp; 33 | float tempMin, tempMax; 34 | int clouds; 35 | float windSpeed; 36 | 37 | String date; 38 | String weatherString; 39 | 40 | #include "MAX7219.h" 41 | #include "Fonts.h" 42 | 43 | // ======================================================================= 44 | String weatherKey = WEATHER_KEY; 45 | String weatherLang = WEATHER_LANG; 46 | String cityID = CITY_ID; 47 | // read OpenWeather api description for more info 48 | // ======================================================================= 49 | 50 | // ======================================================================= 51 | int setIntensity = SET_INTENSITY; 52 | byte dig[MAX_DIGITS] = {0}; 53 | byte digold[MAX_DIGITS] = {0}; 54 | byte digtrans[MAX_DIGITS] = {0}; 55 | int updCnt = 0; 56 | int dots = 0; 57 | long dotTime = 0; 58 | long clkTime = 0; 59 | int dx = 0; 60 | int dy = 0; 61 | byte del = 0; 62 | int h,m,s; 63 | // ======================================================================= 64 | int am_pm = AM_PM; 65 | float utcOffset = UTC_OFFSET; 66 | long localEpoc = 0; 67 | long localMillisAtUpdate = 0; 68 | // ======================================================================= 69 | int showAnimClockSW = SHOW_ANIM_CLOCK_SW; 70 | // ======================================================================= 71 | int showChar(char ch, const uint8_t *data) { 72 | int len = pgm_read_byte(data); 73 | int i, w = pgm_read_byte(data + 1 + ch * len); 74 | for (i = 0; i < w; i++) 75 | scr[NUM_MAX*8 + i] = pgm_read_byte(data + 1 + ch * len + 1 + i); 76 | scr[NUM_MAX*8 + i] = 0; 77 | return w; 78 | } 79 | 80 | // ======================================================================= 81 | int dualChar = 0; 82 | 83 | unsigned char convertPolish(unsigned char _c) { 84 | unsigned char c = _c; 85 | if(c == 196 || c == 197 || c == 195) { 86 | dualChar = c; 87 | return 0; 88 | } 89 | if(dualChar) { 90 | switch(_c) { 91 | case 133: c = 1+'~'; break; // 'ą' 92 | case 135: c = 2+'~'; break; // 'ć' 93 | case 153: c = 3+'~'; break; // 'ę' 94 | case 130: c = 4+'~'; break; // 'ł' 95 | case 132: c = dualChar==197 ? 5+'~' : 10+'~'; break; // 'ń' and 'Ą' 96 | case 179: c = 6+'~'; break; // 'ó' 97 | case 155: c = 7+'~'; break; // 'ś' 98 | case 186: c = 8+'~'; break; // 'ź' 99 | case 188: c = 9+'~'; break; // 'ż' 100 | //case 132: c = 10+'~'; break; // 'Ą' 101 | case 134: c = 11+'~'; break; // 'Ć' 102 | case 152: c = 12+'~'; break; // 'Ę' 103 | case 129: c = 13+'~'; break; // 'Ł' 104 | case 131: c = 14+'~'; break; // 'Ń' 105 | case 147: c = 15+'~'; break; // 'Ó' 106 | case 154: c = 16+'~'; break; // 'Ś' 107 | case 185: c = 17+'~'; break; // 'Ź' 108 | case 187: c = 18+'~'; break; // 'Ż' 109 | default: break; 110 | } 111 | dualChar = 0; 112 | return c; 113 | } 114 | switch(_c) { 115 | case 185: c = 1+'~'; break; 116 | case 230: c = 2+'~'; break; 117 | case 234: c = 3+'~'; break; 118 | case 179: c = 4+'~'; break; 119 | case 241: c = 5+'~'; break; 120 | case 243: c = 6+'~'; break; 121 | case 156: c = 7+'~'; break; 122 | case 159: c = 8+'~'; break; 123 | case 191: c = 9+'~'; break; 124 | case 165: c = 10+'~'; break; 125 | case 198: c = 11+'~'; break; 126 | case 202: c = 12+'~'; break; 127 | case 163: c = 13+'~'; break; 128 | case 209: c = 14+'~'; break; 129 | case 211: c = 15+'~'; break; 130 | case 140: c = 16+'~'; break; 131 | case 143: c = 17+'~'; break; 132 | case 175: c = 18+'~'; break; 133 | default: break; 134 | } 135 | return c; 136 | } 137 | 138 | // ======================================================================= 139 | void showDigit(char ch, int col, const uint8_t *data) { 140 | if(dy < -8 | dy > 8) return; 141 | int len = pgm_read_byte(data); 142 | int w = pgm_read_byte(data + 1 + ch * len); 143 | col += dx; 144 | for (int i = 0; i < w; i++) 145 | if(col + i >= 0 && col + i < 8 * NUM_MAX) { 146 | byte v = pgm_read_byte(data + 1 + ch * len + 1 + i); 147 | if(!dy) scr[col + i] = v; else scr[col + i] |= dy > 0 ? v >> dy : v << -dy; 148 | } 149 | } 150 | 151 | // ======================================================================= 152 | void setCol(int col, byte v) { 153 | if(dy < -8 | dy > 8) return; 154 | col += dx; 155 | if(col >= 0 && col < 8 * NUM_MAX) 156 | if(!dy) scr[col] = v; else scr[col] |= dy > 0 ? v >> dy : v << -dy; 157 | } 158 | 159 | // ======================================================================= 160 | void showSimpleClock() { 161 | dx = dy = 0; 162 | clr(); 163 | showDigit(h/10, 0, dig6x8); 164 | showDigit(h%10, 8, dig6x8); 165 | showDigit(m/10, 17, dig6x8); 166 | showDigit(m%10, 25, dig6x8); 167 | showDigit(s/10, 34, dig6x8); 168 | showDigit(s%10, 42, dig6x8); 169 | setCol(15,dots ? B00100100 : 0); 170 | setCol(32,dots ? B00100100 : 0); 171 | /* Number of MAX7219's connected 172 | showDigit(h/10, 8, dig6x8); 173 | showDigit(h%10, 16, dig6x8); 174 | showDigit(m/10, 25, dig6x8); 175 | showDigit(m%10, 33, dig6x8); 176 | showDigit(s/10, 42, dig6x8); 177 | showDigit(s%10, 50, dig6x8); 178 | setCol(23,dots ? B00100100 : 0); 179 | setCol(40,dots ? B00100100 : 0); 180 | */ 181 | refreshAll(); 182 | } 183 | 184 | // ======================================================================= 185 | void showAnimClock() { 186 | byte digPos[6] = {0,8,17,25,34,42}; 187 | int digHt = 12; 188 | int num = 6; 189 | int i; 190 | if(del == 0) { 191 | del = digHt; 192 | for(i = 0; i < num; i++) digold[i] = dig[i]; 193 | dig[0] = h/10 ? h/10 : 10; 194 | dig[1] = h%10; 195 | dig[2] = m/10; 196 | dig[3] = m%10; 197 | dig[4] = s/10; 198 | dig[5] = s%10; 199 | for(i = 0; i < num; i++) digtrans[i] = (dig[i] == digold[i]) ? 0 : digHt; 200 | } else 201 | del--; 202 | 203 | clr(); 204 | for(i = 0; i < num; i++) { 205 | if(digtrans[i] == 0) { 206 | dy = 0; 207 | showDigit(dig[i], digPos[i], dig6x8); 208 | } else { 209 | dy = digHt-digtrans[i]; 210 | showDigit(digold[i], digPos[i], dig6x8); 211 | dy = -digtrans[i]; 212 | showDigit(dig[i], digPos[i], dig6x8); 213 | digtrans[i]--; 214 | } 215 | } 216 | dy = 0; 217 | setCol(15,dots ? B00100100 : 0); 218 | setCol(32,dots ? B00100100 : 0); 219 | refreshAll(); 220 | delay(30); 221 | } 222 | 223 | // ======================================================================= 224 | void printCharWithShift(unsigned char c, int shiftDelay) { 225 | c = convertPolish(c); 226 | if (c < ' ' || c > '~' + 25) return; 227 | c -= 32; 228 | int w = showChar(c, font); 229 | for (int i = 0; i < w + 1; i++) { 230 | delay(shiftDelay); 231 | scrollLeft(); 232 | refreshAll(); 233 | } 234 | } 235 | 236 | // ======================================================================= 237 | void printStringWithShift(const char* s, int shiftDelay) { 238 | while (*s) { 239 | printCharWithShift(*s, shiftDelay); 240 | s++; 241 | } 242 | } 243 | 244 | // ======================================================================= 245 | const char *ntpHost = "pool.ntp.org"; 246 | // ======================================================================= 247 | // Define NTP Client to get time 248 | WiFiUDP ntpUDP; 249 | NTPClient timeClient(ntpUDP, ntpHost); 250 | //Week Days 251 | String weekDays[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 252 | //Month names 253 | String months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; 254 | String ampm; 255 | 256 | void ntpTime_start() { 257 | timeClient.begin(); 258 | // Set offset time in seconds to adjust for your timezone, for example: 259 | // GMT +1 = 3600, GMT +9 = 32400, GMT -1 = -3600, GMT 0 = 0 260 | timeClient.setTimeOffset(3600 * utcOffset); // 261 | } 262 | 263 | void ntpTime() { 264 | timeClient.update(); 265 | 266 | int day = timeClient.getDay(); 267 | String date_time; 268 | date_time = timeClient.getFormattedDate(); 269 | int index_date = date_time.indexOf("T"); 270 | date = " " + date_time.substring(0, index_date) + " " + weekDays[day] + " "; 271 | 272 | h = timeClient.getHours(); 273 | m = timeClient.getMinutes(); 274 | s = timeClient.getSeconds(); 275 | if (am_pm == 12) { 276 | if (h > 12) { 277 | h = h - 12; 278 | ampm = "PM"; 279 | } else { 280 | ampm = "AM"; 281 | } 282 | } else { 283 | ampm = ""; 284 | } 285 | localMillisAtUpdate = millis(); 286 | localEpoc = (h * 60 * 60 + m * 60 + s); 287 | } 288 | 289 | // ======================================================================= 290 | const char *weatherHost = "api.openweathermap.org"; 291 | // ======================================================================= 292 | void getWeatherData() { 293 | #ifdef USE_UART 294 | Serial.print("connecting to "); Serial.println(weatherHost); 295 | #endif 296 | if (client.connect(weatherHost, 80)) { 297 | client.println(String("GET /data/2.5/weather?id=") + 298 | cityID + "&units=metric&appid=" + 299 | weatherKey + weatherLang + "\r\n" + 300 | "Host: " + weatherHost + "\r\n" + 301 | "User-Agent: ArduinoWiFi/1.1\r\n" + 302 | "Connection: close\r\n\r\n"); 303 | } else { 304 | #ifdef USE_UART 305 | Serial.println("connection failed"); 306 | #endif 307 | return; 308 | } 309 | int repeatCounter = 0; 310 | while (!client.available() && repeatCounter < 10) { 311 | delay(500); 312 | #ifdef USE_UART 313 | Serial.println("w."); 314 | #endif 315 | repeatCounter++; 316 | } 317 | String line; 318 | while (client.connected() && client.available()) { 319 | char c = client.read(); 320 | if (c == '[' || c == ']') c = ' '; 321 | line += c; 322 | } 323 | client.stop(); 324 | 325 | DynamicJsonBuffer jsonBuf; 326 | JsonObject &root = jsonBuf.parseObject(line); 327 | if (!root.success()) 328 | { 329 | #ifdef USE_UART 330 | Serial.println("parseObject() failed"); 331 | #endif 332 | return; 333 | } 334 | //weatherMain = root["weather"]["main"].as(); 335 | weatherDescription = root["weather"]["description"].as(); 336 | weatherDescription.toLowerCase(); 337 | //weatherLocation = root["name"].as(); 338 | country = root["sys"]["country"].as(); 339 | temp = root["main"]["temp"]; 340 | humidity = root["main"]["humidity"]; 341 | pressure = root["main"]["pressure"]; 342 | tempMin = root["main"]["temp_min"]; 343 | tempMax = root["main"]["temp_max"]; 344 | windSpeed = root["wind"]["speed"]; 345 | clouds = root["clouds"]["all"]; 346 | String deg = String(char('~'+25)); 347 | weatherString = " Temp: " + String(temp,1) + deg + "C (" + String(tempMin,1) + deg + "-" + String(tempMax,1) + deg + ") "; 348 | weatherString += weatherDescription; 349 | weatherString += " Humidity: " + String(humidity) + "% "; 350 | weatherString += " Pressure: " + String(pressure) + "hPa "; 351 | weatherString += " Clouds: " + String(clouds) + "% "; 352 | weatherString += " Wind: " + String(windSpeed,1) + "m/s "; 353 | } 354 | 355 | // ======================================================================= 356 | void updateTime() 357 | { 358 | long curEpoch = localEpoc + ((millis() - localMillisAtUpdate) / 1000); 359 | //long epoch = round(curEpoch + 3600 * utcOffset + 86400L) % 86400L; // gClock 360 | long epoch = round(curEpoch + 86400L) % 86400L; // NTP 361 | h = ((epoch % 86400L) / 3600) % 24; // 24-hour clock, 12-hour clock 362 | m = (epoch % 3600) / 60; 363 | s = epoch % 60; 364 | } 365 | // ======================================================================= 366 | 367 | void LEDMatrix_ClockWeather_setup() { 368 | initMAX7219(); 369 | sendCmdAll(CMD_SHUTDOWN, 1); 370 | sendCmdAll(CMD_INTENSITY, setIntensity); 371 | #ifdef USE_UART 372 | Serial.print("Connecting WiFi "); 373 | #endif 374 | #ifdef USE_LED_MATRIX 375 | printStringWithShift(projectName, 15); 376 | delay(1000); 377 | printStringWithShift(" ", 15); 378 | printStringWithShift(projectVersion, 15); 379 | delay(1000); 380 | printStringWithShift(" ", 15); 381 | delay(1000); 382 | printStringWithShift("Connecting ", 20); 383 | char result[16]; 384 | sprintf(result, "%3d.%3d.%1d.%3d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]); 385 | printStringWithShift(result, 25); 386 | #endif 387 | ntpTime_start(); 388 | } 389 | 390 | #ifdef USE_DHT 391 | void LEDMatrix_DHT_action() { 392 | DHT_action(); 393 | char dhtCTemp[10] = ""; 394 | char dhtHumidity[10] = ""; 395 | dtostrf(dht.readTemperature(), 3, 1, dhtCTemp); 396 | dtostrf(dht.readHumidity(), 3, 1, dhtHumidity); 397 | String deg = String(char('~'+25)); 398 | if(dhtGet == 0) { 399 | #ifdef USE_LED_MATRIX 400 | printStringWithShift(" ", stringShiftDelay); 401 | printStringWithShift("INDOOR", stringShiftDelay); 402 | printStringWithShift(" ", stringShiftDelay); 403 | printStringWithShift("Temp: ", stringShiftDelay); 404 | printStringWithShift(dhtCTemp, stringShiftDelay); 405 | printStringWithShift(deg.c_str(), stringShiftDelay); 406 | printStringWithShift("C", stringShiftDelay); 407 | printStringWithShift(" ", stringShiftDelay); 408 | printStringWithShift("Humidity: ", stringShiftDelay); 409 | printStringWithShift(dhtHumidity, stringShiftDelay); 410 | printStringWithShift("% ", stringShiftDelay); 411 | printStringWithShift(" ", stringShiftDelay); 412 | #endif 413 | } 414 | } 415 | #endif 416 | #ifdef USE_DHT12 417 | void LEDMatrix_DHT12_action() { 418 | DHT12_action(); 419 | char dht12cTemp[10] = ""; 420 | char dht12Humidity[10] = ""; 421 | dtostrf(dht12.readTemperature(), 3, 1, dht12cTemp); 422 | dtostrf(dht12.readHumidity(), 3, 1, dht12Humidity); 423 | String deg = String(char('~'+25)); 424 | if(dht12get == 0) { 425 | #ifdef USE_LED_MATRIX 426 | printStringWithShift(" ", stringShiftDelay); 427 | printStringWithShift("OUTDOOR", stringShiftDelay); 428 | printStringWithShift(" ", stringShiftDelay); 429 | printStringWithShift("Temp: ", stringShiftDelay); 430 | printStringWithShift(dht12cTemp, stringShiftDelay); 431 | printStringWithShift(deg.c_str(), stringShiftDelay); 432 | printStringWithShift("C", stringShiftDelay); 433 | printStringWithShift(" ", stringShiftDelay); 434 | printStringWithShift("Humidity: ", stringShiftDelay); 435 | printStringWithShift(dht12Humidity, stringShiftDelay); 436 | printStringWithShift("% ", stringShiftDelay); 437 | printStringWithShift(" ", stringShiftDelay); 438 | #endif 439 | } 440 | } 441 | #endif 442 | 443 | void LEDMatrix_Date_action() { 444 | printStringWithShift(date.c_str(), stringShiftDelay); 445 | } 446 | 447 | void LEDMatrix_Weather_action() { 448 | printStringWithShift(weatherString.c_str(), stringShiftDelay); 449 | } 450 | 451 | void LEDMatrix_Clock_action() { 452 | if(millis() - dotTime > 500) { 453 | dotTime = millis(); 454 | dots = !dots; 455 | } 456 | updateTime(); 457 | if (showAnimClockSW == 0) { 458 | showSimpleClock(); 459 | } else { 460 | showAnimClock(); 461 | } 462 | } 463 | 464 | void LEDMatrix_action() { 465 | if(updCnt <= 0) { 466 | updCnt = updateTimeCount; // default: 10, every 10 scrolls, ~450s = 7.5m // 80 scrolls, ~3600s = 60m 467 | #ifdef USE_UART 468 | Serial.println("Getting data ..."); 469 | #endif 470 | #ifdef USE_LED_MATRIX 471 | printStringWithShift(" Getting data", 15); 472 | #endif 473 | ntpTime(); 474 | getWeatherData(); 475 | #ifdef USE_UART 476 | Serial.println("Data loaded"); 477 | #endif 478 | clkTime = millis(); 479 | } 480 | } 481 | 482 | #endif 483 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/LEDStrip.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4a (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * RGB LED Driver 9 | * MIT license 10 | * written by Renzo Mischianti 11 | * ========================================================================= 12 | */ 13 | 14 | #ifndef LED_STRIP_DRIVER_H 15 | #define LED_STRIP_DRIVER_H 16 | 17 | #include "LEDStripDriver.h" 18 | 19 | LEDStripDriver led = LEDStripDriver(LEDSTRIPDRIVER_DIN, LEDSTRIPDRIVER_CIN); 20 | 21 | void ledStripColorWipe() { 22 | for (uint16_t color = 0; color < 256; color++) { 23 | led.setColor(color, 0, 0); 24 | delay(10); 25 | } 26 | for (uint16_t color = 0; color < 256; color++) { 27 | led.setColor( 0, color, 0); 28 | delay(10); 29 | } 30 | for (uint16_t color = 0; color < 256; color++) { 31 | led.setColor( 0, 0, color); 32 | delay(10); 33 | } 34 | for (uint16_t color = 0; color < 256; color++) { 35 | led.setColor(color, color, color); 36 | delay(10); 37 | } 38 | led.setColor(); 39 | } 40 | 41 | void ledStrip_action() { 42 | // put your main code here, to run repeatedly: 43 | led.setColor(255, 0, 0); // RGB 44 | delay(1000); 45 | led.setColor("#00FF00"); // Hex String 46 | delay(1000); 47 | led.setColor(0x0000FF); // Hex 48 | delay(1000); 49 | led.setColor(); // turn off 50 | delay(1000); 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/LEDStripDriver.cpp: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4a (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * RGB LED Driver library 9 | * MIT license 10 | * written by Renzo Mischianti 11 | * ========================================================================= 12 | */ 13 | 14 | #include 15 | 16 | #include "LEDStripDriver.h" 17 | 18 | /**************************************************************************/ 19 | /*! 20 | @brief class constructor 21 | @param din the data pin to use 22 | @param cin the clock pin to use 23 | */ 24 | /**************************************************************************/ 25 | LEDStripDriver::LEDStripDriver(uint8_t din, uint8_t cin) : _din(din), _cin(cin), _delay(20) { 26 | pinMode(din, OUTPUT); 27 | pinMode(cin, OUTPUT); 28 | } 29 | 30 | /**************************************************************************/ 31 | /*! 32 | @brief class constructor 33 | @param din the data pin to use 34 | @param cin the clock pin to use 35 | @param delay the clock delay in microseconds 36 | */ 37 | /**************************************************************************/ 38 | LEDStripDriver::LEDStripDriver(uint8_t din, uint8_t cin, uint16_t delay) : _din(din), _cin(cin), _delay(delay) { 39 | pinMode(din, OUTPUT); 40 | pinMode(cin, OUTPUT); 41 | } 42 | 43 | /**************************************************************************/ 44 | /*! 45 | @brief set color from r,g,b parameter 46 | @param red amount of red color [0-255] 47 | @param green amount of green color [0-255] 48 | @param blue amount of blue color [0-255] 49 | */ 50 | /**************************************************************************/ 51 | void LEDStripDriver::setColor(uint8_t red, uint8_t green, uint8_t blue) { 52 | uint32_t dx = 0; 53 | dx |= (uint32_t)0x03 << 30; 54 | dx |= (uint32_t)getColorCode(blue) << 28; 55 | dx |= (uint32_t)getColorCode(green) << 26; 56 | dx |= (uint32_t)getColorCode(red) << 24; 57 | 58 | dx |= (uint32_t)blue << 16; 59 | dx |= (uint32_t)green << 8; 60 | dx |= red; 61 | 62 | senddata(dx); 63 | } 64 | 65 | /**************************************************************************/ 66 | /*! 67 | @brief set color from hex parameter 68 | @param hex hex number [0x000000-0xFFFFFF] 69 | */ 70 | /**************************************************************************/ 71 | void LEDStripDriver::setColor(uint32_t hex) { 72 | uint8_t red = (hex >> 16) & 0xFF; 73 | uint8_t green = (hex >> 8) & 0xFF; 74 | uint8_t blue = (hex) & 0xFF; 75 | setColor(red, green, blue); 76 | } 77 | 78 | /**************************************************************************/ 79 | /*! 80 | @brief set color from hex string 81 | @param str string of hex color, e.g. "#00FF00" 82 | */ 83 | /**************************************************************************/ 84 | void LEDStripDriver::setColor(String str) { 85 | uint32_t hex = (uint32_t)strtol(&str[1], NULL, 16); 86 | setColor(hex); 87 | } 88 | 89 | /**************************************************************************/ 90 | /*! 91 | @brief set color to off 92 | */ 93 | /**************************************************************************/ 94 | void LEDStripDriver::setColor() { 95 | setColor(0, 0, 0); 96 | } 97 | 98 | /**************************************************************************/ 99 | /*! 100 | @brief send data over data pin 101 | @param dx data to transmitt 102 | */ 103 | /**************************************************************************/ 104 | void LEDStripDriver::senddata(uint32_t dx) { 105 | sendzero(); 106 | for (uint8_t i = 0; i < 32; i++) { 107 | if ((dx & 0x80000000) != 0) { 108 | digitalWrite(_din, HIGH); 109 | } else { 110 | digitalWrite(_din, LOW); 111 | } 112 | dx <<= 1; 113 | sendclock(); 114 | } 115 | sendzero(); 116 | } 117 | 118 | /**************************************************************************/ 119 | /*! 120 | @brief send a sequence of zeros 121 | */ 122 | /**************************************************************************/ 123 | void LEDStripDriver::sendzero() { 124 | for (uint8_t i = 0; i < 32; i++) { 125 | digitalWrite(_din, LOW); 126 | sendclock(); 127 | } 128 | } 129 | 130 | /**************************************************************************/ 131 | /*! 132 | @brief send one clock impulse 133 | */ 134 | /**************************************************************************/ 135 | void LEDStripDriver::sendclock() { 136 | digitalWrite(_cin, LOW); 137 | delayMicroseconds(_delay); 138 | digitalWrite(_cin, HIGH); 139 | delayMicroseconds(_delay); 140 | } 141 | 142 | /**************************************************************************/ 143 | /*! 144 | @brief convert color to code 145 | */ 146 | /**************************************************************************/ 147 | uint8_t LEDStripDriver::getColorCode(uint8_t color) { 148 | uint8_t tmp = 0; 149 | if ((color & 0x80) == 0) { 150 | tmp |= 0x02; 151 | } 152 | if ((color & 0x40) == 0) { 153 | tmp |= 0x01; 154 | } 155 | return tmp; 156 | } 157 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/LEDStripDriver.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4a (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * RGB LED Driver library 9 | * MIT license 10 | * written by Renzo Mischianti 11 | * ========================================================================= 12 | */ 13 | 14 | #ifndef __LEDStripDriver_H__ 15 | #define __LEDStripDriver_H__ 16 | 17 | #include 18 | 19 | class LEDStripDriver { 20 | public: 21 | // constructors 22 | LEDStripDriver(uint8_t din, uint8_t cin); 23 | LEDStripDriver(uint8_t din, uint8_t cin, uint16_t delay); 24 | 25 | // color manipulation 26 | void setColor(uint8_t red, uint8_t green, uint8_t blue); 27 | void setColor(uint32_t hex); 28 | void setColor(String str); 29 | void setColor(); 30 | 31 | private: 32 | uint8_t _din, _cin; 33 | uint16_t _delay; 34 | 35 | // private methods 36 | uint8_t getColorCode(uint8_t color); 37 | void senddata(uint32_t dx); 38 | void sendzero(); 39 | void sendclock(); 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/MQTT.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * MQTT 9 | * ========================================================================= 10 | */ 11 | 12 | #ifndef MQTT_H 13 | #define MQTT_H 14 | 15 | #include "Adafruit_MQTT.h" 16 | #include "Adafruit_MQTT_Client.h" 17 | 18 | /************************* Adafruit.io Setup *********************************/ 19 | //#define AIO_SERVER "io.adafruit.com" 20 | //#define AIO_SERVERPORT 1883 // use 1883 for SSL 21 | //#define AIO_USERNAME " " // Replace it with your username 22 | //#define AIO_KEY " " // Replace with your Project Auth Key 23 | /************************* Adafruit.io ***************************************/ 24 | // WiFi Client 25 | //WiFiClient client; 26 | // Setup the MQTT client class by passing in the WiFi client and MQTT server and login details. 27 | Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY); 28 | /****************************** Feeds ****************************************/ 29 | // Setup a feed called 'onoff' for subscribing to changes. 30 | Adafruit_MQTT_Subscribe weatherForcast = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/Forcast"); // FeedName 31 | Adafruit_MQTT_Subscribe indoorForcast = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/Indoor"); // FeedName 32 | Adafruit_MQTT_Subscribe outdoorForcast = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/Outdoor"); // FeedName 33 | 34 | int weatherForcast_State; 35 | int indoorForcast_State; 36 | int outdoorForcast_State; 37 | 38 | void MQTT_connect(); 39 | 40 | /************************* Adafruit.io ***************************************/ 41 | void MQTT_connect() { 42 | int8_t ret; 43 | 44 | // Stop if already connected. 45 | if (mqtt.connected()) { 46 | return; 47 | } 48 | Serial.print("Connecting to MQTT... "); 49 | uint8_t retries = 3; 50 | 51 | while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected 52 | Serial.println(mqtt.connectErrorString(ret)); 53 | Serial.println("Retrying MQTT connection in 5 seconds..."); 54 | mqtt.disconnect(); 55 | //delay(5000); // wait 5 seconds 56 | retries--; 57 | if (retries == 0) { 58 | // basically die and wait for WDT to reset me 59 | while (1); 60 | } 61 | } 62 | Serial.println("MQTT Connected!"); 63 | } 64 | 65 | void MQTT_setup() { 66 | /************************* Adafruit.io ***************************************/ 67 | // Setup MQTT subscription for onoff feed. 68 | mqtt.subscribe(&weatherForcast); 69 | mqtt.subscribe(&indoorForcast); 70 | mqtt.subscribe(&outdoorForcast); 71 | } 72 | 73 | void MQTT_action() { 74 | /************************* Adafruit.io ***************************************/ 75 | MQTT_connect(); 76 | /************************* Adafruit.io ***************************************/ 77 | Adafruit_MQTT_Subscribe *subscription; 78 | while ((subscription = mqtt.readSubscription(100))) { // 5000 79 | if (subscription == &weatherForcast) { 80 | Serial.print(F("Got: ")); 81 | Serial.println((char *)weatherForcast.lastread); 82 | int weatherForcast_State = atoi((char *)weatherForcast.lastread); 83 | //digitalWrite(12, (weatherForcast_State)); 84 | LEDMatrix_Date_action(); 85 | LEDMatrix_Weather_action(); 86 | } 87 | if (subscription == &indoorForcast) { 88 | Serial.print(F("Got: ")); 89 | Serial.println((char *)indoorForcast.lastread); 90 | int indoorForcast_State = atoi((char *)indoorForcast.lastread); 91 | //digitalWrite(12, indoorForcast_State); 92 | LEDMatrix_DHT22_action(); 93 | } 94 | if (subscription == &outdoorForcast) { 95 | Serial.print(F("Got: ")); 96 | Serial.println((char *)outdoorForcast.lastread); 97 | int outdoorForcast_State = atoi((char *)outdoorForcast.lastread); 98 | //digitalWrite(12, outdoorForcast_State); 99 | LEDMatrix_DHT12_action(); 100 | } 101 | } 102 | } 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/NTPClient.cpp: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * The MIT License (MIT) 9 | * Copyright (c) 2015 by Fabrice Weinberg 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * The above copyright notice and this permission notice shall be included in all 18 | * copies or substantial portions of the Software. 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | * SOFTWARE. 26 | * ========================================================================= 27 | */ 28 | 29 | #include "NTPClient.h" 30 | 31 | NTPClient::NTPClient(UDP& udp) { 32 | this->_udp = &udp; 33 | } 34 | 35 | NTPClient::NTPClient(UDP& udp, int timeOffset) { 36 | this->_udp = &udp; 37 | this->_timeOffset = timeOffset; 38 | } 39 | 40 | NTPClient::NTPClient(UDP& udp, const char* poolServerName) { 41 | this->_udp = &udp; 42 | this->_poolServerName = poolServerName; 43 | } 44 | 45 | NTPClient::NTPClient(UDP& udp, const char* poolServerName, int timeOffset) { 46 | this->_udp = &udp; 47 | this->_timeOffset = timeOffset; 48 | this->_poolServerName = poolServerName; 49 | } 50 | 51 | NTPClient::NTPClient(UDP& udp, const char* poolServerName, int timeOffset, unsigned long updateInterval) { 52 | this->_udp = &udp; 53 | this->_timeOffset = timeOffset; 54 | this->_poolServerName = poolServerName; 55 | this->_updateInterval = updateInterval; 56 | } 57 | 58 | void NTPClient::begin() { 59 | this->begin(NTP_DEFAULT_LOCAL_PORT); 60 | } 61 | 62 | void NTPClient::begin(int port) { 63 | this->_port = port; 64 | 65 | this->_udp->begin(this->_port); 66 | 67 | this->_udpSetup = true; 68 | } 69 | 70 | bool NTPClient::isValid(byte * ntpPacket) 71 | { 72 | //Perform a few validity checks on the packet 73 | if((ntpPacket[0] & 0b11000000) == 0b11000000) //Check for LI=UNSYNC 74 | return false; 75 | 76 | if((ntpPacket[0] & 0b00111000) >> 3 < 0b100) //Check for Version >= 4 77 | return false; 78 | 79 | if((ntpPacket[0] & 0b00000111) != 0b100) //Check for Mode == Server 80 | return false; 81 | 82 | if((ntpPacket[1] < 1) || (ntpPacket[1] > 15)) //Check for valid Stratum 83 | return false; 84 | 85 | if( ntpPacket[16] == 0 && ntpPacket[17] == 0 && 86 | ntpPacket[18] == 0 && ntpPacket[19] == 0 && 87 | ntpPacket[20] == 0 && ntpPacket[21] == 0 && 88 | ntpPacket[22] == 0 && ntpPacket[22] == 0) //Check for ReferenceTimestamp != 0 89 | return false; 90 | 91 | return true; 92 | } 93 | 94 | bool NTPClient::forceUpdate() { 95 | #ifdef DEBUG_NTPClient 96 | Serial.println("Update from NTP Server"); 97 | #endif 98 | // flush any existing packets 99 | while(this->_udp->parsePacket() != 0) 100 | this->_udp->flush(); 101 | this->sendNTPPacket(); 102 | 103 | // Wait till data is there or timeout... 104 | byte timeout = 0; 105 | int cb = 0; 106 | do { 107 | delay ( 10 ); 108 | cb = this->_udp->parsePacket(); 109 | 110 | if(cb > 0) 111 | { 112 | this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE); 113 | if(!this->isValid(this->_packetBuffer)) 114 | cb = 0; 115 | } 116 | 117 | if (timeout > 100) return false; // timeout after 1000 ms 118 | timeout++; 119 | } while (cb == 0); 120 | 121 | this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time 122 | 123 | unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]); 124 | unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]); 125 | // combine the four bytes (two words) into a long integer 126 | // this is NTP time (seconds since Jan 1 1900): 127 | unsigned long secsSince1900 = highWord << 16 | lowWord; 128 | 129 | this->_currentEpoc = secsSince1900 - SEVENZYYEARS; 130 | 131 | return true; 132 | } 133 | 134 | bool NTPClient::update() { 135 | if ((millis() - this->_lastUpdate >= this->_updateInterval) // Update after _updateInterval 136 | || this->_lastUpdate == 0) { // Update if there was no update yet. 137 | if (!this->_udpSetup) this->begin(); // setup the UDP client if needed 138 | return this->forceUpdate(); 139 | } 140 | return true; 141 | } 142 | 143 | unsigned long NTPClient::getEpochTime() { 144 | return this->_timeOffset + // User offset 145 | this->_currentEpoc + // Epoc returned by the NTP server 146 | ((millis() - this->_lastUpdate) / 1000); // Time since last update 147 | } 148 | 149 | int NTPClient::getDay() { 150 | return (((this->getEpochTime() / 86400L) + 4 ) % 7); //0 is Sunday 151 | } 152 | int NTPClient::getHours() { 153 | return ((this->getEpochTime() % 86400L) / 3600); 154 | } 155 | int NTPClient::getMinutes() { 156 | return ((this->getEpochTime() % 3600) / 60); 157 | } 158 | int NTPClient::getSeconds() { 159 | return (this->getEpochTime() % 60); 160 | } 161 | 162 | String NTPClient::getFormattedTime(unsigned long secs) { 163 | unsigned long rawTime = secs ? secs : this->getEpochTime(); 164 | unsigned long hours = (rawTime % 86400L) / 3600; 165 | String hoursStr = hours < 10 ? "0" + String(hours) : String(hours); 166 | 167 | unsigned long minutes = (rawTime % 3600) / 60; 168 | String minuteStr = minutes < 10 ? "0" + String(minutes) : String(minutes); 169 | 170 | unsigned long seconds = rawTime % 60; 171 | String secondStr = seconds < 10 ? "0" + String(seconds) : String(seconds); 172 | 173 | return hoursStr + ":" + minuteStr + ":" + secondStr; 174 | } 175 | 176 | // Based on https://github.com/PaulStoffregen/Time/blob/master/Time.cpp 177 | // currently assumes UTC timezone, instead of using this->_timeOffset 178 | String NTPClient::getFormattedDate(unsigned long secs) { 179 | unsigned long rawTime = (secs ? secs : this->getEpochTime()) / 86400L; // in days 180 | unsigned long days = 0, year = 1970; 181 | uint8_t month; 182 | static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; 183 | 184 | while((days += (LEAP_YEAR(year) ? 366 : 365)) <= rawTime) 185 | year++; 186 | rawTime -= days - (LEAP_YEAR(year) ? 366 : 365); // now it is days in this year, starting at 0 187 | days=0; 188 | for (month=0; month<12; month++) { 189 | uint8_t monthLength; 190 | if (month==1) { // february 191 | monthLength = LEAP_YEAR(year) ? 29 : 28; 192 | } else { 193 | monthLength = monthDays[month]; 194 | } 195 | if (rawTime < monthLength) break; 196 | rawTime -= monthLength; 197 | } 198 | String monthStr = ++month < 10 ? "0" + String(month) : String(month); // jan is month 1 199 | String dayStr = ++rawTime < 10 ? "0" + String(rawTime) : String(rawTime); // day of month 200 | return String(year) + "-" + monthStr + "-" + dayStr + "T" + this->getFormattedTime(secs ? secs : 0) + "Z"; 201 | } 202 | 203 | void NTPClient::end() { 204 | this->_udp->stop(); 205 | 206 | this->_udpSetup = false; 207 | } 208 | 209 | void NTPClient::setTimeOffset(int timeOffset) { 210 | this->_timeOffset = timeOffset; 211 | } 212 | 213 | void NTPClient::setUpdateInterval(unsigned long updateInterval) { 214 | this->_updateInterval = updateInterval; 215 | } 216 | 217 | void NTPClient::sendNTPPacket() { 218 | // set all bytes in the buffer to 0 219 | memset(this->_packetBuffer, 0, NTP_PACKET_SIZE); 220 | // Initialize values needed to form NTP request 221 | // (see URL above for details on the packets) 222 | this->_packetBuffer[0] = 0b11100011; // LI, Version, Mode 223 | this->_packetBuffer[1] = 0; // Stratum, or type of clock 224 | this->_packetBuffer[2] = 6; // Polling Interval 225 | this->_packetBuffer[3] = 0xEC; // Peer Clock Precision 226 | // 8 bytes of zero for Root Delay & Root Dispersion 227 | this->_packetBuffer[12] = 0x49; 228 | this->_packetBuffer[13] = 0x4E; 229 | this->_packetBuffer[14] = 0x49; 230 | this->_packetBuffer[15] = 0x52; 231 | 232 | // all NTP fields have been given values, now 233 | // you can send a packet requesting a timestamp: 234 | this->_udp->beginPacket(this->_poolServerName, 123); //NTP requests are to port 123 235 | this->_udp->write(this->_packetBuffer, NTP_PACKET_SIZE); 236 | this->_udp->endPacket(); 237 | } 238 | 239 | void NTPClient::setEpochTime(unsigned long secs) { 240 | this->_currentEpoc = secs; 241 | } 242 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/NTPClient.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * NTP Client 9 | * ========================================================================= 10 | */ 11 | 12 | #ifndef NTP_H 13 | #define NTP_H 14 | 15 | #pragma once 16 | 17 | #include "Arduino.h" 18 | 19 | #include 20 | 21 | #define SEVENZYYEARS 2208988800UL 22 | #define NTP_PACKET_SIZE 48 23 | #define NTP_DEFAULT_LOCAL_PORT 1337 24 | #define LEAP_YEAR(Y) ( (Y>0) && !(Y%4) && ( (Y%100) || !(Y%400) ) ) 25 | 26 | 27 | class NTPClient { 28 | private: 29 | UDP* _udp; 30 | bool _udpSetup = false; 31 | 32 | const char* _poolServerName = "pool.ntp.org"; // Default time server 33 | int _port = NTP_DEFAULT_LOCAL_PORT; 34 | int _timeOffset = 0; 35 | 36 | unsigned long _updateInterval = 60000; // In ms 37 | 38 | unsigned long _currentEpoc = 0; // In s 39 | unsigned long _lastUpdate = 0; // In ms 40 | 41 | byte _packetBuffer[NTP_PACKET_SIZE]; 42 | 43 | void sendNTPPacket(); 44 | bool isValid(byte * ntpPacket); 45 | 46 | public: 47 | NTPClient(UDP& udp); 48 | NTPClient(UDP& udp, int timeOffset); 49 | NTPClient(UDP& udp, const char* poolServerName); 50 | NTPClient(UDP& udp, const char* poolServerName, int timeOffset); 51 | NTPClient(UDP& udp, const char* poolServerName, int timeOffset, unsigned long updateInterval); 52 | 53 | /** 54 | * Starts the underlying UDP client with the default local port 55 | */ 56 | void begin(); 57 | 58 | /** 59 | * Starts the underlying UDP client with the specified local port 60 | */ 61 | void begin(int port); 62 | 63 | /** 64 | * This should be called in the main loop of your application. By default an update from the NTP Server is only 65 | * made every 60 seconds. This can be configured in the NTPClient constructor. 66 | * 67 | * @return true on success, false on failure 68 | */ 69 | bool update(); 70 | 71 | /** 72 | * This will force the update from the NTP Server. 73 | * 74 | * @return true on success, false on failure 75 | */ 76 | bool forceUpdate(); 77 | 78 | int getDay(); 79 | int getHours(); 80 | int getMinutes(); 81 | int getSeconds(); 82 | 83 | /** 84 | * Changes the time offset. Useful for changing timezones dynamically 85 | */ 86 | void setTimeOffset(int timeOffset); 87 | 88 | /** 89 | * Set the update interval to another frequency. E.g. useful when the 90 | * timeOffset should not be set in the constructor 91 | */ 92 | void setUpdateInterval(unsigned long updateInterval); 93 | 94 | /** 95 | * @return secs argument (or 0 for current time) formatted like `hh:mm:ss` 96 | */ 97 | String getFormattedTime(unsigned long secs = 0); 98 | 99 | /** 100 | * @return time in seconds since Jan. 1, 1970 101 | */ 102 | unsigned long getEpochTime(); 103 | 104 | /** 105 | * @return secs argument (or 0 for current date) formatted to ISO 8601 106 | * like `2004-02-12T15:19:21+00:00` 107 | */ 108 | String getFormattedDate(unsigned long secs = 0); 109 | 110 | /** 111 | * Stops the underlying UDP client 112 | */ 113 | void end(); 114 | 115 | /** 116 | * Replace the NTP-fetched time with seconds since Jan. 1, 1970 117 | */ 118 | void setEpochTime(unsigned long secs); 119 | }; 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/WS2812B_NeoPixel.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * WS2812B RGB LED 9 | * ========================================================================= 10 | */ 11 | 12 | #ifndef WS2812B_NEOPIXEL_H 13 | #define WS2812B_NEOPIXEL_H 14 | 15 | #include 16 | 17 | // Which pin on the Arduino is connected to the NeoPixels? 18 | // On a Trinket or Gemma we suggest changing this to 1 19 | //#define RGB_LED_PIN 4 // D2 (GPIO04) 20 | // How many NeoPixels are attached to the Arduino? 21 | //#define NUMPIXELS 1 //16 // 64 // 16 22 | // Parameter 1 = number of pixels in strip 23 | // Parameter 2 = Arduino pin number (most are valid) 24 | // Parameter 3 = pixel type flags, add together as needed: 25 | // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) 26 | // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) 27 | // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) 28 | // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) 29 | // NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products) 30 | Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, USE_RGB_LED_PIN, NEO_GRB + NEO_KHZ800); 31 | int delayval = 200; // delay for half a second 32 | 33 | // WS2812B RGB LED strip 34 | // Input a value 0 to 255 to get a color value. 35 | // The colours are a transition r - g - b - back to r. 36 | uint32_t Wheel(byte WheelPos) { 37 | WheelPos = 255 - WheelPos; 38 | if(WheelPos < 85) { 39 | return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); 40 | } 41 | if(WheelPos < 170) { 42 | WheelPos -= 85; 43 | return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); 44 | } 45 | WheelPos -= 170; 46 | return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); 47 | } 48 | 49 | // Fill the dots one after the other with a color 50 | void colorWipe(uint32_t c, uint8_t wait) { 51 | for(uint16_t i = 0; i < strip.numPixels(); i++) { 52 | strip.setPixelColor(i, c); 53 | strip.show(); 54 | delay(wait); 55 | } 56 | } 57 | 58 | void rainbow(uint8_t wait) { 59 | uint16_t i, j; 60 | 61 | for(j = 0; j < 256; j++) { 62 | for(i = 0; i < strip.numPixels(); i++) { 63 | strip.setPixelColor(i, Wheel((i + j) & 255)); 64 | } 65 | strip.show(); 66 | delay(wait); 67 | } 68 | } 69 | 70 | // Slightly different, this makes the rainbow equally distributed throughout 71 | void rainbowCycle(uint8_t wait) { 72 | uint16_t i, j; 73 | 74 | for(j = 0; j < 256*5; j++) { // 5 cycles of all colors on wheel 75 | for(i = 0; i < strip.numPixels(); i++) { 76 | strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); 77 | } 78 | strip.show(); 79 | delay(wait); 80 | } 81 | } 82 | 83 | // Theatre-style crawling lights. 84 | void theaterChase(uint32_t c, uint8_t wait) { 85 | for (int j = 0; j < 10; j++) { // do 10 cycles of chasing 86 | for (int q = 0; q < 3; q++) { 87 | for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) { 88 | strip.setPixelColor(i + q, c); // turn every third pixel on 89 | } 90 | strip.show(); 91 | delay(wait); 92 | for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) { 93 | strip.setPixelColor(i + q, 0); // turn every third pixel off 94 | } 95 | } 96 | } 97 | } 98 | 99 | // Theatre-style crawling lights with rainbow effect 100 | void theaterChaseRainbow(uint8_t wait) { 101 | for (int j = 0; j < 256; j++) { // cycle all 256 colors in the wheel 102 | for (int q = 0; q < 3; q++) { 103 | for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) { 104 | strip.setPixelColor(i + q, Wheel((i + j) % 255)); // turn every third pixel on 105 | } 106 | strip.show(); 107 | delay(wait); 108 | for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) { 109 | strip.setPixelColor(i + q, 0); // turn every third pixel off 110 | } 111 | } 112 | } 113 | } 114 | 115 | void NeoPixel_setup() { 116 | strip.begin(); 117 | strip.show(); // Initialize all pixels to 'off' 118 | } 119 | 120 | void NeoPixel_action() { 121 | // WS2812B RGB LED 122 | // Some example procedures showing how to display to the pixels: 123 | #ifdef USE_UART 124 | Serial.println("WS2812B RGB LED Strip (D2 - 4)"); 125 | #endif 126 | colorWipe(strip.Color(255, 0, 0), 50); // Red 127 | colorWipe(strip.Color( 0, 255, 0), 50); // Green 128 | colorWipe(strip.Color( 0, 0, 255), 50); // Blue 129 | colorWipe(strip.Color(255, 255, 255), 50); // White 130 | colorWipe(strip.Color( 0, 0, 0), 50); // Black 131 | //colorWipe(strip.Color( 0, 0, 0, 255), 50); // White RGBW 132 | // Send a theater pixel chase in... 133 | theaterChase(strip.Color(127, 127, 127), 50); // White 134 | theaterChase(strip.Color(127, 0, 0), 50); // Red 135 | theaterChase(strip.Color( 0, 127, 0), 50); // Green 136 | theaterChase(strip.Color( 0, 0, 127), 50); // Blue 137 | 138 | rainbow(20); 139 | rainbowCycle(20); 140 | theaterChaseRainbow(50); 141 | } 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/WiFi_Manager.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * WiFi Manager 9 | * ========================================================================= 10 | */ 11 | 12 | #ifndef WIFI_MANAGER_H 13 | #define WIFI_MANAGER_H 14 | 15 | #include 16 | #include 17 | #include // https://github.com/tzapu/WiFiManager 18 | 19 | uint8_t MAC_array[6]; // MAC address of Wifi module 20 | char MAC_char[18]; 21 | char *APname; 22 | char *mDNS_Name = mDNS_NAME; 23 | 24 | void WiFiManager_setup() { 25 | // Local intialization. Once its business is done, there is no need to keep it around 26 | WiFiManager wifiManager; 27 | // exit after config instead of connecting 28 | wifiManager.setBreakAfterConfig(true); 29 | // reset settings - for testing 30 | //wifiManager.resetSettings(); 31 | // tries to connect to last known settings 32 | // if it does not connect it starts an access point with the specified name 33 | // here "AutoConnectAP" with password "password" 34 | // and goes into a blocking loop awaiting configuration 35 | 36 | // Generate host name. SSID=LEDMatrixBar-XXXXXX, PASS=0123456789 37 | #ifdef USE_UART 38 | Serial.println("\nStarting WIFI in SOFTAP mode"); 39 | #endif 40 | APname = mDNS_Name; 41 | WiFi.macAddress(MAC_array); 42 | for (int i = 0; i < sizeof(MAC_array); ++i){ 43 | sprintf(MAC_char, "%s%02x:", MAC_char, MAC_array[i]); 44 | } 45 | APname[13] = MAC_char[9]; 46 | APname[14] = MAC_char[10]; 47 | APname[15] = MAC_char[12]; 48 | APname[16] = MAC_char[13]; 49 | APname[17] = MAC_char[15]; 50 | APname[18] = MAC_char[16]; 51 | #ifdef USE_UART 52 | Serial.println(""); 53 | Serial.print("MAC:"); 54 | Serial.println(MAC_char); 55 | Serial.print("SSID:"); 56 | Serial.println(APname); 57 | #endif 58 | const char *ssid = APname; 59 | const char *password = AP_PASSWORD; 60 | #ifdef USE_UART 61 | Serial.print("SSID: "); 62 | Serial.println(ssid); 63 | Serial.print("Password: "); 64 | Serial.println(password); 65 | IPAddress myIP = WiFi.softAPIP(); 66 | Serial.print("AP IP address: "); 67 | Serial.println(myIP); 68 | #endif 69 | 70 | if (!wifiManager.autoConnect(ssid, password)) { 71 | #ifdef USE_UART 72 | Serial.println("failed to connect, we should reset as see if it connects"); 73 | #endif 74 | delay(3000); 75 | ESP.reset(); 76 | delay(5000); 77 | } 78 | //if you get here you have connected to the WiFi 79 | #ifdef USE_UART 80 | Serial.println("connected...yeey :)"); 81 | 82 | Serial.print("Local IP: "); 83 | Serial.println(WiFi.localIP()); 84 | #endif 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/WiFi_Setup.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * WiFi setup 9 | * ========================================================================= 10 | */ 11 | 12 | #ifndef WIFI_SETUP_H 13 | #define WIFI_SETUP_H 14 | 15 | #include 16 | #include 17 | #include 18 | #include "WiFi_Manager.h" 19 | 20 | MDNSResponder mdns; 21 | 22 | void WiFi_setup() { 23 | WiFiManager_setup(); 24 | 25 | #ifdef USE_OTA 26 | // Port defaults to 8266 27 | //ArduinoOTA.setPort(8266); 28 | // Hostname defaults to esp8266-[ChipID] 29 | //ArduinoOTA.setHostname("myesp8266"); 30 | // No authentication by default 31 | //ArduinoOTA.setPassword((const char *)"123"); 32 | #ifdef USE_UART 33 | ArduinoOTA.onStart([]() { 34 | Serial.println("Start"); 35 | }); 36 | ArduinoOTA.onEnd([]() { 37 | Serial.println("End"); 38 | }); 39 | ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { 40 | Serial.printf("Progress: %u%%\n", (progress / (total / 100))); 41 | }); 42 | ArduinoOTA.onError([](ota_error_t error) { 43 | Serial.printf("Error[%u]: ", error); 44 | if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); 45 | else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); 46 | else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); 47 | else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); 48 | else if (error == OTA_END_ERROR) Serial.println("End Failed"); 49 | }); 50 | #endif 51 | ArduinoOTA.begin(); 52 | #ifdef USE_UART 53 | Serial.println("OTA Ready!"); 54 | Serial.print("IP address: "); 55 | Serial.println(WiFi.localIP()); 56 | #endif 57 | #endif 58 | 59 | // Set up mDNS responder: ################################################## 60 | // - first argument is the domain name, in this example 61 | // the fully-qualified domain name is "homeiot.local" 62 | // - second argument is the IP address to advertise 63 | // we send our IP address on the WiFi network 64 | // - dmain name "homeiotlrl: Home IoT Living Room Lamp" 65 | // first two character is location - lr: Living Room, mr: Main Room, sr: Second Room, kc: Kitchen, fd: Front Door, vd: Veranda, ... 66 | // secound one character is device - l: Lamp, s: Sensor, d: door, w: Window, ... 67 | if (!MDNS.begin(APname, WiFi.localIP())) { 68 | #ifdef USE_UART 69 | Serial.println("Error setting up MDNS responder!"); 70 | #endif 71 | while(1) { 72 | delay(1000); 73 | } 74 | } 75 | #ifdef USE_UART 76 | Serial.println("mDNS responder started"); 77 | #endif 78 | 79 | // Add service to MDNS-SD ################################################ 80 | MDNS.addService("http", "tcp", 80); 81 | } 82 | 83 | void OTA_action() { 84 | ArduinoOTA.handle(); 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/fonts.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * LED Matrix Font 9 | * ========================================================================= 10 | */ 11 | 12 | #ifndef FONT_H 13 | #define FONT_H 14 | 15 | const uint8_t dig3x8[] PROGMEM = { 4, 16 | 0x03, 0xFF, 0x81, 0xFF, 17 | 0x02, 0x02, 0xFF, 0x00, 18 | 0x03, 0xF9, 0x89, 0x8F, 19 | 0x03, 0x81, 0x89, 0xFF, 20 | 0x03, 0x1F, 0x10, 0xFC, 21 | 0x03, 0x8F, 0x89, 0xF9, 22 | 0x03, 0xFF, 0x89, 0xF9, 23 | 0x03, 0x01, 0xF1, 0x0F, 24 | 0x03, 0xFF, 0x89, 0xFF, 25 | 0x03, 0x9F, 0x91, 0xFF, 26 | }; 27 | 28 | const uint8_t dig6x8[] PROGMEM = { 7, 29 | 0x06, 0x7E, 0xFF, 0x81, 0x81, 0xFF, 0x7E, // 0 30 | 0x06, 0x00, 0x82, 0xFF, 0xFF, 0x80, 0x00, // 1 31 | 0x06, 0xC2, 0xE3, 0xB1, 0x99, 0x8F, 0x86, // 2 32 | 0x06, 0x42, 0xC3, 0x89, 0x89, 0xFF, 0x76, // 3 33 | 0x06, 0x38, 0x3C, 0x26, 0x23, 0xFF, 0xFF, // 4 34 | 0x06, 0x4F, 0xCF, 0x89, 0x89, 0xF9, 0x71, // 5 35 | 0x06, 0x7E, 0xFF, 0x89, 0x89, 0xFB, 0x72, // 6 36 | 0x06, 0x01, 0x01, 0xF1, 0xF9, 0x0F, 0x07, // 7 37 | 0x06, 0x76, 0xFF, 0x89, 0x89, 0xFF, 0x76, // 8 38 | 0x06, 0x4E, 0xDF, 0x91, 0x91, 0xFF, 0x7E, // 9 39 | 6, 0,0,0,0,0,0 // Clear 40 | }; 41 | 42 | const uint8_t dig4x8[] PROGMEM = { 5, 43 | 0x04, 0xFF, 0x81, 0x81, 0xFF, 44 | 0x04, 0x04, 0x02, 0xFF, 0x00, 45 | 0x04, 0xF9, 0x89, 0x89, 0x8F, 46 | 0x04, 0x81, 0x89, 0x89, 0xFF, 47 | 0x04, 0x1F, 0x10, 0x10, 0xFE, 48 | 0x04, 0x8F, 0x89, 0x89, 0xF9, 49 | 0x04, 0xFF, 0x89, 0x89, 0xF8, 50 | 0x04, 0x01, 0xC1, 0x31, 0x0F, 51 | 0x04, 0xFF, 0x89, 0x89, 0xFF, 52 | 0x04, 0x1F, 0x91, 0x91, 0xFF, 53 | }; 54 | 55 | const uint8_t dig3x7[] PROGMEM = { 4, 56 | 0x03, 0xFE, 0x82, 0xFE, 57 | 0x03, 0x08, 0x04, 0xFE, 58 | 0x03, 0xF2, 0x92, 0x9E, 59 | 0x03, 0x82, 0x92, 0xFE, 60 | 0x03, 0x3E, 0x20, 0xFC, 61 | 0x03, 0x9E, 0x92, 0xF2, 62 | 0x03, 0xFE, 0x92, 0xF2, 63 | 0x03, 0x02, 0xE2, 0x1E, 64 | 0x03, 0xFE, 0x92, 0xFE, 65 | 0x03, 0x9E, 0x92, 0xFE, 66 | }; 67 | 68 | const uint8_t dig3x6[] PROGMEM = { 4, 69 | 0x03, 0xFC, 0x84, 0xFC, 70 | 0x03, 0x10, 0x08, 0xFC, 71 | 0x03, 0xF4, 0x94, 0x9C, 72 | 0x03, 0x84, 0x94, 0xFC, 73 | 0x03, 0x3C, 0x20, 0xF8, 74 | 0x03, 0x9C, 0x94, 0xF4, 75 | 0x03, 0xFC, 0x94, 0xF4, 76 | 0x03, 0x04, 0xE4, 0x1C, 77 | 0x03, 0xFC, 0x94, 0xFC, 78 | 0x03, 0xBC, 0xA4, 0xFC, 79 | }; 80 | 81 | const uint8_t dig3x5[] PROGMEM = { 4, 82 | 0x03, 0xF8, 0x88, 0xF8, 83 | 0x02, 0x10, 0xF8, 0x00, 84 | 0x03, 0xE8, 0xA8, 0xB8, 85 | 0x03, 0x88, 0xA8, 0xF8, 86 | 0x03, 0x38, 0x20, 0xF8, 87 | 0x03, 0xB8, 0xA8, 0xE8, 88 | 0x03, 0xF8, 0xA8, 0xE8, 89 | 0x03, 0x08, 0x08, 0xF8, 90 | 0x03, 0xF8, 0xA8, 0xF8, 91 | 0x03, 0xB8, 0xA8, 0xF8, 92 | }; 93 | const uint8_t dig5x8rn[] PROGMEM = { 6, 94 | 0x05, 0x7E, 0x81, 0x81, 0xFF, 0x7E, 95 | 0x05, 0x04, 0x02, 0xFF, 0xFF, 0x00, 96 | 0x05, 0xF1, 0x89, 0x89, 0x8F, 0x86, 97 | 0x05, 0x81, 0x89, 0x89, 0xFF, 0x76, 98 | 0x05, 0x1F, 0x10, 0x10, 0xFE, 0xFE, 99 | 0x05, 0x8F, 0x89, 0x89, 0xF9, 0x71, 100 | 0x05, 0x7E, 0x89, 0x89, 0xF9, 0x70, 101 | 0x05, 0x01, 0xC1, 0xF1, 0x3F, 0x0F, 102 | 0x05, 0x76, 0x89, 0x89, 0xFF, 0x76, 103 | 0x05, 0x0E, 0x91, 0x91, 0xFF, 0x7E, 104 | }; 105 | 106 | const uint8_t dig5x8sq[] PROGMEM = { 6, 107 | 0x05, 0xFF, 0x81, 0x81, 0xFF, 0xFF, 108 | 0x04, 0x04, 0x02, 0xFF, 0xFF, 0x00, 109 | 0x05, 0xF9, 0x89, 0x89, 0x8F, 0x8F, 110 | 0x05, 0x81, 0x89, 0x89, 0xFF, 0xFF, 111 | 0x05, 0x1F, 0x10, 0x10, 0xFE, 0xFE, 112 | 0x05, 0x8F, 0x89, 0x89, 0xF9, 0xF9, 113 | 0x05, 0xFF, 0x89, 0x89, 0xF9, 0xF9, 114 | 0x05, 0x01, 0x01, 0x01, 0xFF, 0xFF, 115 | 0x05, 0xFF, 0x89, 0x89, 0xFF, 0xFF, 116 | 0x05, 0x9F, 0x91, 0x91, 0xFF, 0xFF, 117 | }; 118 | 119 | const uint8_t dweek_pl[] PROGMEM = { 11, 120 | 0x0A, 0xFC, 0x08, 0x10, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x94, 0x84, 121 | 0x09, 0xFC, 0x24, 0x24, 0x3C, 0x00, 0xFC, 0x84, 0x84, 0xFC, 0x00, 122 | 0x09, 0xFC, 0x80, 0xF0, 0x80, 0xFC, 0x00, 0x04, 0xFC, 0x04, 0x00, 123 | 0x09, 0xDC, 0x94, 0x96, 0xF5, 0x00, 0xFC, 0x24, 0x64, 0xBC, 0x00, 124 | 0x09, 0xFC, 0x84, 0x84, 0xCC, 0x00, 0xC4, 0xA4, 0x94, 0x8C, 0x00, 125 | 0x0A, 0xFC, 0x24, 0x24, 0x3C, 0x00, 0xFC, 0x00, 0xFC, 0x24, 0xFC, 126 | 0x09, 0xDC, 0x94, 0x94, 0xF4, 0x00, 0xFC, 0x84, 0x84, 0xFC, 0x00, 127 | 0x09, 0x07, 0x05, 0x07, 0x00, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x00, 128 | }; 129 | 130 | const uint8_t dweek_en[] PROGMEM = { 11, 131 | 0x09, 0x9C, 0x94, 0x94, 0xF4, 0x00, 0xFC, 0x80, 0x80, 0xFC, 0x00, 132 | 0x0A, 0xFC, 0x04, 0x3C, 0x04, 0xFC, 0x00, 0xFC, 0x84, 0x84, 0xFC, 133 | 0x0A, 0x04, 0x04, 0xFC, 0x04, 0x04, 0x00, 0xFC, 0x80, 0x80, 0xFC, 134 | 0x0A, 0xFC, 0x80, 0xF0, 0x80, 0xFC, 0x00, 0xFC, 0x94, 0x94, 0x84, 135 | 0x0A, 0x04, 0x04, 0xFC, 0x04, 0x04, 0x00, 0xFC, 0x10, 0x10, 0xFC, 136 | 0x09, 0xFC, 0x24, 0x24, 0x04, 0x00, 0xFC, 0x24, 0x64, 0xBC, 0x00, 137 | 0x09, 0x9C, 0x94, 0x94, 0xF4, 0x00, 0xFC, 0x24, 0x24, 0xFC, 0x00, 138 | 0x09, 0x07, 0x05, 0x07, 0x00, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x00, 139 | }; 140 | 141 | // Standard ASCII 5x8 font 142 | const uint8_t font[] PROGMEM = { 6, 143 | 2, B00000000, B00000000, B00000000, B00000000, B00000000, // space 144 | 1, B01011111, B00000000, B00000000, B00000000, B00000000, // ! 145 | 3, B00000011, B00000000, B00000011, B00000000, B00000000, // " 146 | 5, B00010100, B00111110, B00010100, B00111110, B00010100, // # 147 | 4, B00100100, B01101010, B00101011, B00010010, B00000000, // $ 148 | 5, B01100011, B00010011, B00001000, B01100100, B01100011, // % 149 | 5, B00110110, B01001001, B01010110, B00100000, B01010000, // & 150 | 1, B00000011, B00000000, B00000000, B00000000, B00000000, // ' 151 | 3, B00011100, B00100010, B01000001, B00000000, B00000000, // ( 152 | 3, B01000001, B00100010, B00011100, B00000000, B00000000, // ) 153 | 5, B00101000, B00011000, B00001110, B00011000, B00101000, // * 154 | 5, B00001000, B00001000, B00111110, B00001000, B00001000, // + 155 | 2, B10110000, B01110000, B00000000, B00000000, B00000000, // , 156 | 4, B00001000, B00001000, B00001000, B00001000, B00000000, // - 157 | 1, B01000000, B00000000, B00000000, B00000000, B00000000, // . 158 | 3, B01100000, B00011100, B00000011, B00000000, B00000000, // / 159 | 4, B00111110, B01000001, B01000001, B00111110, B00000000, // 0 160 | 3, B01000010, B01111111, B01000000, B00000000, B00000000, // 1 161 | 4, B01100010, B01010001, B01001001, B01000110, B00000000, // 2 162 | 4, B00100010, B01000001, B01001001, B00110110, B00000000, // 3 163 | 4, B00011000, B00010100, B00010010, B01111111, B00000000, // 4 164 | 4, B00100111, B01000101, B01000101, B00111001, B00000000, // 5 165 | 4, B00111110, B01001001, B01001001, B00110010, B00000000, // 6 166 | 4, B01100001, B00010001, B00001001, B00000111, B00000000, // 7 167 | 4, B00110110, B01001001, B01001001, B00110110, B00000000, // 8 168 | 4, B00100110, B01001001, B01001001, B00111110, B00000000, // 9 169 | 1, B01000100, B00000000, B00000000, B00000000, B00000000, // : 170 | 2, B10000000, B01010000, B00000000, B00000000, B00000000, // ; 171 | 3, B00010000, B00101000, B01000100, B00000000, B00000000, // < 172 | 3, B00010100, B00010100, B00010100, B00000000, B00000000, // = 173 | 3, B01000100, B00101000, B00010000, B00000000, B00000000, // > 174 | 4, B00000010, B01011001, B00001001, B00000110, B00000000, // ? 175 | 5, B00111110, B01001001, B01010101, B01011101, B00001110, // @ 176 | 4, B01111110, B00010001, B00010001, B01111110, B00000000, // A 177 | 4, B01111111, B01001001, B01001001, B00110110, B00000000, // B 178 | 4, B00111110, B01000001, B01000001, B00100010, B00000000, // C 179 | 4, B01111111, B01000001, B01000001, B00111110, B00000000, // D 180 | 4, B01111111, B01001001, B01001001, B01000001, B00000000, // E 181 | 4, B01111111, B00001001, B00001001, B00000001, B00000000, // F 182 | 4, B00111110, B01000001, B01001001, B01111010, B00000000, // G 183 | 4, B01111111, B00001000, B00001000, B01111111, B00000000, // H 184 | 3, B01000001, B01111111, B01000001, B00000000, B00000000, // I 185 | 4, B00110000, B01000000, B01000001, B00111111, B00000000, // J 186 | 4, B01111111, B00001000, B00010100, B01100011, B00000000, // K 187 | 4, B01111111, B01000000, B01000000, B01000000, B00000000, // L 188 | 5, B01111111, B00000010, B00001100, B00000010, B01111111, // M 189 | 5, B01111111, B00000100, B00001000, B00010000, B01111111, // N 190 | 4, B00111110, B01000001, B01000001, B00111110, B00000000, // O 191 | 4, B01111111, B00001001, B00001001, B00000110, B00000000, // P 192 | 4, B00111110, B01000001, B01000001, B10111110, B00000000, // Q 193 | 4, B01111111, B00001001, B00001001, B01110110, B00000000, // R 194 | 4, B00100110, B01001001, B01001001, B00110010, B00000000, // S 195 | 5, B00000001, B00000001, B01111111, B00000001, B00000001, // T 196 | 4, B00111111, B01000000, B01000000, B00111111, B00000000, // U 197 | 5, B00001111, B00110000, B01000000, B00110000, B00001111, // V 198 | 5, B00111111, B01000000, B00111000, B01000000, B00111111, // W 199 | 5, B01100011, B00010100, B00001000, B00010100, B01100011, // X 200 | 5, B00000111, B00001000, B01110000, B00001000, B00000111, // Y 201 | 4, B01100001, B01010001, B01001001, B01000111, B00000000, // Z 202 | 2, B01111111, B01000001, B00000000, B00000000, B00000000, // [ 203 | 4, B00000001, B00000110, B00011000, B01100000, B00000000, // \ backslash 204 | 2, B01000001, B01111111, B00000000, B00000000, B00000000, // ] 205 | 3, B00000010, B00000001, B00000010, B00000000, B00000000, // hat 206 | 4, B01000000, B01000000, B01000000, B01000000, B00000000, // _ 207 | 2, B00000001, B00000010, B00000000, B00000000, B00000000, // ` 208 | 4, B00100000, B01010100, B01010100, B01111000, B00000000, // a 209 | 4, B01111111, B01000100, B01000100, B00111000, B00000000, // b 210 | 4, B00111000, B01000100, B01000100, B00101000, B00000000, // c 211 | 4, B00111000, B01000100, B01000100, B01111111, B00000000, // d 212 | 4, B00111000, B01010100, B01010100, B00011000, B00000000, // e 213 | 3, B00000100, B01111110, B00000101, B00000000, B00000000, // f 214 | 4, B10011000, B10100100, B10100100, B01111000, B00000000, // g 215 | 4, B01111111, B00000100, B00000100, B01111000, B00000000, // h 216 | 3, B01000100, B01111101, B01000000, B00000000, B00000000, // i 217 | 4, B01000000, B10000000, B10000100, B01111101, B00000000, // j 218 | 4, B01111111, B00010000, B00101000, B01000100, B00000000, // k 219 | 3, B01000001, B01111111, B01000000, B00000000, B00000000, // l 220 | 5, B01111100, B00000100, B01111100, B00000100, B01111000, // m 221 | 4, B01111100, B00000100, B00000100, B01111000, B00000000, // n 222 | 4, B00111000, B01000100, B01000100, B00111000, B00000000, // o 223 | 4, B11111100, B00100100, B00100100, B00011000, B00000000, // p 224 | 4, B00011000, B00100100, B00100100, B11111100, B00000000, // q 225 | 4, B01111100, B00001000, B00000100, B00000100, B00000000, // r 226 | 4, B01001000, B01010100, B01010100, B00100100, B00000000, // s 227 | 3, B00000100, B00111111, B01000100, B00000000, B00000000, // t 228 | 4, B00111100, B01000000, B01000000, B01111100, B00000000, // u 229 | 5, B00011100, B00100000, B01000000, B00100000, B00011100, // v 230 | 5, B00111100, B01000000, B00111100, B01000000, B00111100, // w 231 | 5, B01000100, B00101000, B00010000, B00101000, B01000100, // x 232 | 4, B10011100, B10100000, B10100000, B01111100, B00000000, // y 233 | 3, B01100100, B01010100, B01001100, B00000000, B00000000, // z 234 | 3, B00001000, B00110110, B01000001, B00000000, B00000000, // { 235 | 1, B01111111, B00000000, B00000000, B00000000, B00000000, // | 236 | 3, B01000001, B00110110, B00001000, B00000000, B00000000, // } 237 | 4, B00001000, B00000100, B00001000, B00000100, B00000000, // ~ 238 | 239 | 5, B00100000, B01010100, B01010100, B11111000, B10000000, // a 240 | 4, B00111000, B01000100, B01000110, B00101001, B00000000, // c 241 | 4, B00111000, B01010100, B11010100, B10011000, B00000000, // e 242 | 3, B01010001, B01111111, B01000100, B00000000, B00000000, // l 243 | 4, B01111100, B00000100, B00000110, B01111001, B00000000, // n 244 | 4, B00111000, B01000100, B01000110, B00111001, B00000000, // o 245 | 4, B01001000, B01010100, B01010110, B00100101, B00000000, // s 246 | 3, B01100100, B01010110, B01001101, B00000000, B00000000, // z 247 | 3, B01100100, B01010101, B01001100, B00000000, B00000000, // z 248 | 5, B01111110, B00010001, B00010001, B11111110, B10000000, // A 249 | 4, B00111100, B01000010, B01000011, B00100101, B00000000, // C 250 | 5, B01111111, B01001001, B01001001, B11000001, B10000000, // E 251 | 4, B01111111, B01001000, B01000100, B01000000, B00000000, // L 252 | 5, B01111110, B00000100, B00001010, B00010001, B01111110, // N 253 | 4, B00111100, B01000110, B01000011, B00111100, B00000000, // O 254 | 4, B00100100, B01001010, B01001011, B00110000, B00000000, // S 255 | 4, B01100010, B01010110, B01001011, B01000110, B00000000, // Z 256 | 4, B01101001, B01011001, B01001101, B01001011, B00000000, // Z 257 | 258 | 5, B00111110, B01010101, B01100001, B01010101, B00111110, // :) 259 | 5, B00111110, B01100101, B01010001, B01100101, B00111110, // :( 260 | 5, B00111110, B01000101, B01010001, B01000101, B00111110, // :o 261 | 5, 0x06, 0x1F, 0x7E, 0x1F, 0x06, // heart 262 | 5, 0x04, 0x02, 0x7F, 0x02, 0x04, // arrow up 263 | 5, 0x10, 0x20, 0x7F, 0x20, 0x10, // arrow down 264 | 3, B00000010, B00000101, B00000010, B00000000, B00000000, // deg 265 | }; 266 | 267 | // Standard ASCII 5x7 font 268 | static const unsigned char font5x7[] PROGMEM = { 269 | 0x00, 0x00, 0x00, 0x00, 0x00, 270 | 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 271 | 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 272 | 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 273 | 0x18, 0x3C, 0x7E, 0x3C, 0x18, 274 | 0x1C, 0x57, 0x7D, 0x57, 0x1C, 275 | 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 276 | 0x00, 0x18, 0x3C, 0x18, 0x00, 277 | 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 278 | 0x00, 0x18, 0x24, 0x18, 0x00, 279 | 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 280 | 0x30, 0x48, 0x3A, 0x06, 0x0E, 281 | 0x26, 0x29, 0x79, 0x29, 0x26, 282 | 0x40, 0x7F, 0x05, 0x05, 0x07, 283 | 0x40, 0x7F, 0x05, 0x25, 0x3F, 284 | 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 285 | 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 286 | 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 287 | 0x14, 0x22, 0x7F, 0x22, 0x14, 288 | 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 289 | 0x06, 0x09, 0x7F, 0x01, 0x7F, 290 | 0x00, 0x66, 0x89, 0x95, 0x6A, 291 | 0x60, 0x60, 0x60, 0x60, 0x60, 292 | 0x94, 0xA2, 0xFF, 0xA2, 0x94, 293 | 0x08, 0x04, 0x7E, 0x04, 0x08, 294 | 0x10, 0x20, 0x7E, 0x20, 0x10, 295 | 0x08, 0x08, 0x2A, 0x1C, 0x08, 296 | 0x08, 0x1C, 0x2A, 0x08, 0x08, 297 | 0x1E, 0x10, 0x10, 0x10, 0x10, 298 | 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 299 | 0x30, 0x38, 0x3E, 0x38, 0x30, 300 | 0x06, 0x0E, 0x3E, 0x0E, 0x06, 301 | 0x00, 0x00, 0x00, 0x00, 0x00,// (space) 302 | 0x00, 0x00, 0x5F, 0x00, 0x00,// ! 303 | 0x00, 0x07, 0x00, 0x07, 0x00,// " 304 | 0x14, 0x7F, 0x14, 0x7F, 0x14,// # 305 | 0x24, 0x2A, 0x7F, 0x2A, 0x12,// $ 306 | 0x23, 0x13, 0x08, 0x64, 0x62,// % 307 | 0x36, 0x49, 0x55, 0x22, 0x50,// & 308 | 0x00, 0x05, 0x03, 0x00, 0x00,// ' 309 | 0x00, 0x1C, 0x22, 0x41, 0x00,// ( 310 | 0x00, 0x41, 0x22, 0x1C, 0x00,// ) 311 | 0x08, 0x2A, 0x1C, 0x2A, 0x08,// * 312 | 0x08, 0x08, 0x3E, 0x08, 0x08,// + 313 | 0x00, 0x50, 0x30, 0x00, 0x00,// , 314 | 0x08, 0x08, 0x08, 0x08, 0x08,// - 315 | 0x00, 0x60, 0x60, 0x00, 0x00,// . 316 | 0x20, 0x10, 0x08, 0x04, 0x02,// / 317 | 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0 318 | 0x00, 0x42, 0x7F, 0x40, 0x00,// 1 319 | 0x42, 0x61, 0x51, 0x49, 0x46,// 2 320 | 0x21, 0x41, 0x45, 0x4B, 0x31,// 3 321 | 0x18, 0x14, 0x12, 0x7F, 0x10,// 4 322 | 0x27, 0x45, 0x45, 0x45, 0x39,// 5 323 | 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6 324 | 0x01, 0x71, 0x09, 0x05, 0x03,// 7 325 | 0x36, 0x49, 0x49, 0x49, 0x36,// 8 326 | 0x06, 0x49, 0x49, 0x29, 0x1E,// 9 327 | 0x00, 0x36, 0x36, 0x00, 0x00,// : 328 | 0x00, 0x56, 0x36, 0x00, 0x00,// ; 329 | 0x00, 0x08, 0x14, 0x22, 0x41,// < 330 | 0x14, 0x14, 0x14, 0x14, 0x14,// = 331 | 0x41, 0x22, 0x14, 0x08, 0x00,// > 332 | 0x02, 0x01, 0x51, 0x09, 0x06,// ? 333 | 0x32, 0x49, 0x79, 0x41, 0x3E,// @ 334 | 0x7E, 0x11, 0x11, 0x11, 0x7E,// A 335 | 0x7F, 0x49, 0x49, 0x49, 0x36,// B 336 | 0x3E, 0x41, 0x41, 0x41, 0x22,// C 337 | 0x7F, 0x41, 0x41, 0x22, 0x1C,// D 338 | 0x7F, 0x49, 0x49, 0x49, 0x41,// E 339 | 0x7F, 0x09, 0x09, 0x01, 0x01,// F 340 | 0x3E, 0x41, 0x41, 0x51, 0x32,// G 341 | 0x7F, 0x08, 0x08, 0x08, 0x7F,// H 342 | 0x00, 0x41, 0x7F, 0x41, 0x00,// I 343 | 0x20, 0x40, 0x41, 0x3F, 0x01,// J 344 | 0x7F, 0x08, 0x14, 0x22, 0x41,// K 345 | 0x7F, 0x40, 0x40, 0x40, 0x40,// L 346 | 0x7F, 0x02, 0x04, 0x02, 0x7F,// M 347 | 0x7F, 0x04, 0x08, 0x10, 0x7F,// N 348 | 0x3E, 0x41, 0x41, 0x41, 0x3E,// O 349 | 0x7F, 0x09, 0x09, 0x09, 0x06,// P 350 | 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q 351 | 0x7F, 0x09, 0x19, 0x29, 0x46,// R 352 | 0x46, 0x49, 0x49, 0x49, 0x31,// S 353 | 0x01, 0x01, 0x7F, 0x01, 0x01,// T 354 | 0x3F, 0x40, 0x40, 0x40, 0x3F,// U 355 | 0x1F, 0x20, 0x40, 0x20, 0x1F,// V 356 | 0x7F, 0x20, 0x18, 0x20, 0x7F,// W 357 | 0x63, 0x14, 0x08, 0x14, 0x63,// X 358 | 0x03, 0x04, 0x78, 0x04, 0x03,// Y 359 | 0x61, 0x51, 0x49, 0x45, 0x43,// Z 360 | 0x00, 0x00, 0x7F, 0x41, 0x41,// [ 361 | 0x02, 0x04, 0x08, 0x10, 0x20,// "\" 362 | 0x41, 0x41, 0x7F, 0x00, 0x00,// ] 363 | 0x04, 0x02, 0x01, 0x02, 0x04,// ^ 364 | 0x40, 0x40, 0x40, 0x40, 0x40,// _ 365 | 0x00, 0x01, 0x02, 0x04, 0x00,// ` 366 | 0x20, 0x54, 0x54, 0x54, 0x78,// a 367 | 0x7F, 0x48, 0x44, 0x44, 0x38,// b 368 | 0x38, 0x44, 0x44, 0x44, 0x20,// c 369 | 0x38, 0x44, 0x44, 0x48, 0x7F,// d 370 | 0x38, 0x54, 0x54, 0x54, 0x18,// e 371 | 0x08, 0x7E, 0x09, 0x01, 0x02,// f 372 | 0x08, 0x14, 0x54, 0x54, 0x3C,// g 373 | 0x7F, 0x08, 0x04, 0x04, 0x78,// h 374 | 0x00, 0x44, 0x7D, 0x40, 0x00,// i 375 | 0x20, 0x40, 0x44, 0x3D, 0x00,// j 376 | 0x00, 0x7F, 0x10, 0x28, 0x44,// k 377 | 0x00, 0x41, 0x7F, 0x40, 0x00,// l 378 | 0x7C, 0x04, 0x18, 0x04, 0x78,// m 379 | 0x7C, 0x08, 0x04, 0x04, 0x78,// n 380 | 0x38, 0x44, 0x44, 0x44, 0x38,// o 381 | 0x7C, 0x14, 0x14, 0x14, 0x08,// p 382 | 0x08, 0x14, 0x14, 0x18, 0x7C,// q 383 | 0x7C, 0x08, 0x04, 0x04, 0x08,// r 384 | 0x48, 0x54, 0x54, 0x54, 0x20,// s 385 | 0x04, 0x3F, 0x44, 0x40, 0x20,// t 386 | 0x3C, 0x40, 0x40, 0x20, 0x7C,// u 387 | 0x1C, 0x20, 0x40, 0x20, 0x1C,// v 388 | 0x3C, 0x40, 0x30, 0x40, 0x3C,// w 389 | 0x44, 0x28, 0x10, 0x28, 0x44,// x 390 | 0x0C, 0x50, 0x50, 0x50, 0x3C,// y 391 | 0x44, 0x64, 0x54, 0x4C, 0x44,// z 392 | 0x00, 0x08, 0x36, 0x41, 0x00,// { 393 | 0x00, 0x00, 0x7F, 0x00, 0x00,// | 394 | 0x00, 0x41, 0x36, 0x08, 0x00,// } 395 | 0x08, 0x08, 0x2A, 0x1C, 0x08,// -> 396 | 0x08, 0x1C, 0x2A, 0x08, 0x08,// <- 397 | 0x1E, 0xA1, 0xA1, 0x61, 0x12, 398 | 0x3A, 0x40, 0x40, 0x20, 0x7A, 399 | 0x38, 0x54, 0x54, 0x55, 0x59, 400 | 0x21, 0x55, 0x55, 0x79, 0x41, 401 | 0x21, 0x54, 0x54, 0x78, 0x41, 402 | 0x21, 0x55, 0x54, 0x78, 0x40, 403 | 0x20, 0x54, 0x55, 0x79, 0x40, 404 | 0x0C, 0x1E, 0x52, 0x72, 0x12, 405 | 0x39, 0x55, 0x55, 0x55, 0x59, 406 | 0x39, 0x54, 0x54, 0x54, 0x59, 407 | 0x39, 0x55, 0x54, 0x54, 0x58, 408 | 0x00, 0x00, 0x45, 0x7C, 0x41, 409 | 0x00, 0x02, 0x45, 0x7D, 0x42, 410 | 0x00, 0x01, 0x45, 0x7C, 0x40, 411 | 0xF0, 0x29, 0x24, 0x29, 0xF0, 412 | 0xF0, 0x28, 0x25, 0x28, 0xF0, 413 | 0x7C, 0x54, 0x55, 0x45, 0x00, 414 | 0x20, 0x54, 0x54, 0x7C, 0x54, 415 | 0x7C, 0x0A, 0x09, 0x7F, 0x49, 416 | 0x32, 0x49, 0x49, 0x49, 0x32, 417 | 0x32, 0x48, 0x48, 0x48, 0x32, 418 | 0x32, 0x4A, 0x48, 0x48, 0x30, 419 | 0x3A, 0x41, 0x41, 0x21, 0x7A, 420 | 0x3A, 0x42, 0x40, 0x20, 0x78, 421 | 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 422 | 0x39, 0x44, 0x44, 0x44, 0x39, 423 | 0x3D, 0x40, 0x40, 0x40, 0x3D, 424 | 0x3C, 0x24, 0xFF, 0x24, 0x24, 425 | 0x48, 0x7E, 0x49, 0x43, 0x66, 426 | 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 427 | 0xFF, 0x09, 0x29, 0xF6, 0x20, 428 | 0xC0, 0x88, 0x7E, 0x09, 0x03, 429 | 0x20, 0x54, 0x54, 0x79, 0x41, 430 | 0x00, 0x00, 0x44, 0x7D, 0x41, 431 | 0x30, 0x48, 0x48, 0x4A, 0x32, 432 | 0x38, 0x40, 0x40, 0x22, 0x7A, 433 | 0x00, 0x7A, 0x0A, 0x0A, 0x72, 434 | 0x7D, 0x0D, 0x19, 0x31, 0x7D, 435 | 0x26, 0x29, 0x29, 0x2F, 0x28, 436 | 0x26, 0x29, 0x29, 0x29, 0x26, 437 | 0x30, 0x48, 0x4D, 0x40, 0x20, 438 | 0x38, 0x08, 0x08, 0x08, 0x08, 439 | 0x08, 0x08, 0x08, 0x08, 0x38, 440 | 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 441 | 0x2F, 0x10, 0x28, 0x34, 0xFA, 442 | 0x00, 0x00, 0x7B, 0x00, 0x00, 443 | 0x08, 0x14, 0x2A, 0x14, 0x22, 444 | 0x22, 0x14, 0x2A, 0x14, 0x08, 445 | 0xAA, 0x00, 0x55, 0x00, 0xAA, 446 | 0xAA, 0x55, 0xAA, 0x55, 0xAA, 447 | 0x00, 0x00, 0x00, 0xFF, 0x00, 448 | 0x10, 0x10, 0x10, 0xFF, 0x00, 449 | 0x14, 0x14, 0x14, 0xFF, 0x00, 450 | 0x10, 0x10, 0xFF, 0x00, 0xFF, 451 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 452 | 0x14, 0x14, 0x14, 0xFC, 0x00, 453 | 0x14, 0x14, 0xF7, 0x00, 0xFF, 454 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 455 | 0x14, 0x14, 0xF4, 0x04, 0xFC, 456 | 0x14, 0x14, 0x17, 0x10, 0x1F, 457 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 458 | 0x14, 0x14, 0x14, 0x1F, 0x00, 459 | 0x10, 0x10, 0x10, 0xF0, 0x00, 460 | 0x00, 0x00, 0x00, 0x1F, 0x10, 461 | 0x10, 0x10, 0x10, 0x1F, 0x10, 462 | 0x10, 0x10, 0x10, 0xF0, 0x10, 463 | 0x00, 0x00, 0x00, 0xFF, 0x10, 464 | 0x10, 0x10, 0x10, 0x10, 0x10, 465 | 0x10, 0x10, 0x10, 0xFF, 0x10, 466 | 0x00, 0x00, 0x00, 0xFF, 0x14, 467 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 468 | 0x00, 0x00, 0x1F, 0x10, 0x17, 469 | 0x00, 0x00, 0xFC, 0x04, 0xF4, 470 | 0x14, 0x14, 0x17, 0x10, 0x17, 471 | 0x14, 0x14, 0xF4, 0x04, 0xF4, 472 | 0x00, 0x00, 0xFF, 0x00, 0xF7, 473 | 0x14, 0x14, 0x14, 0x14, 0x14, 474 | 0x14, 0x14, 0xF7, 0x00, 0xF7, 475 | 0x14, 0x14, 0x14, 0x17, 0x14, 476 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 477 | 0x14, 0x14, 0x14, 0xF4, 0x14, 478 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 479 | 0x00, 0x00, 0x1F, 0x10, 0x1F, 480 | 0x00, 0x00, 0x00, 0x1F, 0x14, 481 | 0x00, 0x00, 0x00, 0xFC, 0x14, 482 | 0x00, 0x00, 0xF0, 0x10, 0xF0, 483 | 0x10, 0x10, 0xFF, 0x10, 0xFF, 484 | 0x14, 0x14, 0x14, 0xFF, 0x14, 485 | 0x10, 0x10, 0x10, 0x1F, 0x00, 486 | 0x00, 0x00, 0x00, 0xF0, 0x10, 487 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 488 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 489 | 0xFF, 0xFF, 0xFF, 0x00, 0x00, 490 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 491 | 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 492 | 0x38, 0x44, 0x44, 0x38, 0x44, 493 | 0x7C, 0x2A, 0x2A, 0x3E, 0x14, 494 | 0x7E, 0x02, 0x02, 0x06, 0x06, 495 | 0x02, 0x7E, 0x02, 0x7E, 0x02, 496 | 0x63, 0x55, 0x49, 0x41, 0x63, 497 | 0x38, 0x44, 0x44, 0x3C, 0x04, 498 | 0x40, 0x7E, 0x20, 0x1E, 0x20, 499 | 0x06, 0x02, 0x7E, 0x02, 0x02, 500 | 0x99, 0xA5, 0xE7, 0xA5, 0x99, 501 | 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 502 | 0x4C, 0x72, 0x01, 0x72, 0x4C, 503 | 0x30, 0x4A, 0x4D, 0x4D, 0x30, 504 | 0x30, 0x48, 0x78, 0x48, 0x30, 505 | 0xBC, 0x62, 0x5A, 0x46, 0x3D, 506 | 0x3E, 0x49, 0x49, 0x49, 0x00, 507 | 0x7E, 0x01, 0x01, 0x01, 0x7E, 508 | 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 509 | 0x44, 0x44, 0x5F, 0x44, 0x44, 510 | 0x40, 0x51, 0x4A, 0x44, 0x40, 511 | 0x40, 0x44, 0x4A, 0x51, 0x40, 512 | 0x00, 0x00, 0xFF, 0x01, 0x03, 513 | 0xE0, 0x80, 0xFF, 0x00, 0x00, 514 | 0x08, 0x08, 0x6B, 0x6B, 0x08, 515 | 0x36, 0x12, 0x36, 0x24, 0x36, 516 | 0x06, 0x0F, 0x09, 0x0F, 0x06, 517 | 0x00, 0x00, 0x18, 0x18, 0x00, 518 | 0x00, 0x00, 0x10, 0x10, 0x00, 519 | 0x30, 0x40, 0xFF, 0x01, 0x01, 520 | 0x00, 0x1F, 0x01, 0x01, 0x1E, 521 | 0x00, 0x19, 0x1D, 0x17, 0x12, 522 | 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 523 | 0x00, 0x00, 0x00, 0x00, 0x00 524 | }; 525 | 526 | #endif 527 | -------------------------------------------------------------------------------- /ESP8266/ESP8266_LED_Matrix_Bar_Weather_Station/max7219.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | * Author: Zalophus Dokdo (https://zddh.blogspot.com) 3 | * Date: 31/08/2017 (https://zalophus.tistory.com/) 4 | * License: GPL v2 5 | * ========================================================================= 6 | * LED Matrix Bar Weather Station V1.0.4 (Publish: 2018/01/02) 7 | * ========================================================================= 8 | * LED Matrix MAX7219 functions by Pawel A. Hernik 9 | * ========================================================================= 10 | * 2016.12.10 updated for rotated LED Martices, define ROTATE below (0,90 or 270) 11 | * ========================================================================= 12 | */ 13 | 14 | #ifndef MAX7219_H 15 | #define MAX7219_H 16 | 17 | // MAX7219 commands: 18 | #define CMD_NOOP 0 19 | #define CMD_DIGIT0 1 20 | #define CMD_DIGIT1 2 21 | #define CMD_DIGIT2 3 22 | #define CMD_DIGIT3 4 23 | #define CMD_DIGIT4 5 24 | #define CMD_DIGIT5 6 25 | #define CMD_DIGIT6 7 26 | #define CMD_DIGIT7 8 27 | #define CMD_DECODEMODE 9 28 | #define CMD_INTENSITY 10 29 | #define CMD_SCANLIMIT 11 30 | #define CMD_SHUTDOWN 12 31 | #define CMD_DISPLAYTEST 15 32 | 33 | byte scr[NUM_MAX*8 + 8]; // +8 for scrolled char 34 | 35 | void sendCmd(int addr, byte cmd, byte data) { 36 | digitalWrite(CS_PIN, LOW); 37 | for (int i = NUM_MAX - 1; i >= 0; i--) { 38 | shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, i == addr ? cmd : 0); 39 | shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, i == addr ? data : 0); 40 | } 41 | digitalWrite(CS_PIN, HIGH); 42 | } 43 | 44 | void sendCmdAll(byte cmd, byte data) { 45 | digitalWrite(CS_PIN, LOW); 46 | for (int i = NUM_MAX - 1; i >= 0; i--) { 47 | shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, cmd); 48 | shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, data); 49 | } 50 | digitalWrite(CS_PIN, HIGH); 51 | } 52 | 53 | void refresh(int addr) { 54 | for (int i = 0; i < 8; i++) 55 | sendCmd(addr, i + CMD_DIGIT0, scr[addr * 8 + i]); 56 | } 57 | 58 | void refreshAllRot270() { 59 | byte mask = 0x01; 60 | for (int c = 0; c < 8; c++) { 61 | digitalWrite(CS_PIN, LOW); 62 | for (int i = NUM_MAX - 1; i >= 0; i--) { 63 | byte bt = 0; 64 | for (int b = 0; b < 8; b++) { 65 | bt <<= 1; 66 | if (scr[i * 8 + b] & mask) bt |= 0x01; 67 | } 68 | shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, CMD_DIGIT0 + c); 69 | shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, bt); 70 | } 71 | digitalWrite(CS_PIN, HIGH); 72 | mask<<=1; 73 | } 74 | } 75 | 76 | void refreshAllRot90() { 77 | byte mask = 0x80; 78 | for (int c = 0; c < 8; c++) { 79 | digitalWrite(CS_PIN, LOW); 80 | for(int i = NUM_MAX - 1; i >= 0; i--) { 81 | byte bt = 0; 82 | for(int b = 0; b < 8; b++) { 83 | bt >>= 1; 84 | if(scr[i * 8 + b] & mask) bt|=0x80; 85 | } 86 | shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, CMD_DIGIT0 + c); 87 | shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, bt); 88 | } 89 | digitalWrite(CS_PIN, HIGH); 90 | mask>>=1; 91 | } 92 | } 93 | 94 | #define ROTATE 90 95 | 96 | void refreshAll() { 97 | #if ROTATE == 270 98 | refreshAllRot270(); 99 | #elif ROTATE == 90 100 | refreshAllRot90(); 101 | #else 102 | for (int c = 0; c < 8; c++) { 103 | digitalWrite(CS_PIN, LOW); 104 | for(int i = NUM_MAX - 1; i >= 0; i--) { 105 | shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, CMD_DIGIT0 + c); 106 | shiftOut(DIN_PIN, CLK_PIN, MSBFIRST, scr[i * 8 + c]); 107 | } 108 | digitalWrite(CS_PIN, HIGH); 109 | } 110 | #endif 111 | } 112 | 113 | void clr() { 114 | for(int i = 0; i < NUM_MAX * 8; i++) scr[i] = 0; 115 | } 116 | 117 | void scrollLeft() { 118 | for(int i = 0; i < NUM_MAX * 8 + 7; i++) scr[i] = scr[i+1]; 119 | } 120 | 121 | void invert() { 122 | for(int i = 0; i < NUM_MAX * 8; i++) scr[i] = ~scr[i]; 123 | } 124 | 125 | void initMAX7219() { 126 | pinMode(DIN_PIN, OUTPUT); 127 | pinMode(CLK_PIN, OUTPUT); 128 | pinMode(CS_PIN, OUTPUT); 129 | digitalWrite(CS_PIN, HIGH); 130 | sendCmdAll(CMD_DISPLAYTEST, 0); 131 | sendCmdAll(CMD_SCANLIMIT, 7); 132 | sendCmdAll(CMD_DECODEMODE, 0); 133 | sendCmdAll(CMD_INTENSITY, 0); // minimum brightness 134 | sendCmdAll(CMD_SHUTDOWN, 0); 135 | clr(); 136 | refreshAll(); 137 | } 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP8266 LED Matrix Bar Weather Station 2 | LED Matrix Bar Weather Station and Clock Massenger 3 |

4 | 5 | 6 | 7 |

8 |

9 | 10 | 11 | 12 |

13 |

14 | 15 | 16 | 17 |

18 |

19 | 20 | 21 | 22 |

23 | 24 | Firmware Version: V1.0.4b 25 | ========================= 26 | - Change WebApp scroll control (2021/01/11) 27 | - Added timer setting (2020/10/13) 28 | - Added alarm message setting function: 29 | .................Set scroll message to alarm message (2020/09/13) 30 | - Added alarm setting (2020/09/10) 31 | - AM-PM Mode, 24-hour clock, 12-hour clock (2020/09/09) 32 | - Google clock replaced with NTP clock (2020/09/07) 33 | - Resolved a problem that initialized when receiving Google clock 34 | - Added web page refresh time (2020/09/06) 35 | - Added RGB LED (2020/09/05) 36 | - Error: ets jan 8 2013,rst cause:2, boot mode:(3,6) (2020/09/05) 37 | - Added MQTT - Adafruit IO MQTT + IFTTT + Google Assistant (2020/07/30) 38 | - Update Count 7.5m to 60m (2020/07/22) 39 | - Added CHAR_SHIFT_DELAY - Config (2020/07/22) 40 | - Change DHT12 Library (2018/03/12) 41 | 42 | Video: 43 | - 44 | - https://youtu.be/NvMaL1UP2G4 - v1.0.4b 45 | - - https://youtu.be/KqBzKSkwXMY - RGB LED Lamp Testing 46 | - - https://youtu.be/YhxY4NB5p2Y - Dual LED Matix Display Testing 47 | - https://www.youtube.com/embed/51wum5p9660 - v1.0.1 48 | 49 | Features: 50 | - 51 | - ESP8266 WeMos D1 mini module which I finally found good application for (now you can buy better cheap ESPs) 52 | - 6 x LEDMatrix module with MAX7219 driver 53 | - supplied directly from USB port with USB plug 54 | - all data are synchronized every 7-8 minutes 55 | - time and date are taken from NTP 56 | - weather informations are grabbed from openweather.org JSON api 57 | - no hardware RTC clock is necessary 58 | + internal temperature, humidity sensor (options - DS18B20(Internal), DHT22(Indoor), DHT12(Outdoor)) 59 | + ESP8266 setup and control as a Wi-Fi Web Server (WiFiManager, OTA, mDNS) 60 | + receives a message input from a User Input page, then displays the message on a scrolling LED matrix display. 61 | 62 | * The interface for all the controls is designed as a webapp for internet browser. 63 | 64 | Fuctions: 65 | - 66 | - mDNS 67 | - WiFi Manager 68 | - Web Server (WebUI) 69 | - LED Matrix Clock 70 | - Open Weather Map Weather Forecast 71 | - Indoor and Outdoor temperature and Humidity sensor monitor 72 | - Scrolling message 73 | - Scroll Push Switch 74 | - Lamp Push Switch 75 | - Alarm time setting (WebUI) 76 | - Alarm On/Off and Switch 77 | - Google Assistant: Adafruit IO MQTT + IFTTT 78 | 79 | BOM 80 | - 81 | - 6 x MAX7219 8x8 Matrix LED 82 | - 1 x WeMos D1 mini 83 | - 1 x Interface shield 84 | Additional Parts: 85 | - 1 x DS18B20 temperature sensor (Option) 86 | - 1 x DHT22 temperature and humidity sensor (Option) 87 | - 1 x DHT12 temperature and humidity sensor (Option) 88 | - N x WS2812B RGB LED (Option) 89 | - 1 x Alarm On/Off button switch 90 | - 1 x Lamp Push button switch 91 | - 1 x Scroll Push button switch 92 | - 1 x Power On/Off switch 93 | - 1 x Buzzer 94 | 95 | Configuring the upload environment 96 | ================================== 97 | How to configure standard Arduino IDE to use as Arduino ESP8266 IDE. 98 | 99 | First download Arduino IDE and install it on computer. 100 | 101 | IMPORTANT: Download old version Arduino IDE Version 1.8.1. 102 | (Tested Version 1.8.9 and Version 1.8.13) 103 | 104 | ------------ 105 | Open Arduino IDE and go to File - Preferences. 106 | 107 | Enter http://arduino.esp8266.com/stable/package_esp8266com_index.json under Adittional boards manager. 108 | 109 | ------------ 110 | Select Boards Manager in Tools - Board 111 | 112 | Find ESP8266 and press Install 113 | 114 | IMPORTANT: Download old version esp8266 by ESP8266 Community Version 2.3.0. 115 | 116 | ------------ 117 | IMPORTANT: Additional Libraries 118 | 119 | go to Sketch - Include Library - Manage Libraries 120 | 121 | Find and Install 122 | - WiFiManager by tzapu,tablatronix Version 0.15.0 123 | - DHT Sensor library by Adafruit Version 1.3.0 124 | - ArduinoJson by Benoit Blanchon Version 5.11.1 125 | - Adafruit MQTT Client by Adafruit Version 1.3.0 126 | - Adafruit_NeoPixel by Adafruit Version 1.1.2 127 | 128 | -------------- 129 | After install select ESP8266 board. 130 | - Board: WeMos D1 R2 & mini 131 | - Upload Speed: "921600" 132 | - CPU Frequency: "80 MHz" 133 | - Flash Size: "4M (3M SPIFFS)" 134 | - Port: COM?? 135 | 136 | --------------- 137 | Schematic is available here: 138 | - Normal: https://easyeda.com/neoseven/led-matrix-bar-weather-station-normal 139 | - Expansion: https://easyeda.com/neoseven/led-matrix-bar-weather-station (Unfinished - Future plans) 140 |

141 | 142 | 143 | 144 |
145 | 146 | 147 | 148 |

149 | 150 | --------------- 151 | 3D Parts: 152 | - V2: http://shop.bluecomtech.com/ko_KR/product/led-matrix-bar-weather-station-v2-case-stnad 153 | - V3: http://shop.bluecomtech.com/ko_KR/product/led-matrix-bar-weather-station-v3-case-stnad 154 | - Pinshape : https://pinshape.com/items/46659-3d-printed-led-matrix-bar-weather-station-v1 155 | - Thingiverse : https://www.thingiverse.com/thing:2650808 156 | 157 | --------------- 158 | WebApp: 159 |

160 | 161 | 162 | 163 |
164 | 165 | 166 | 167 |

168 | 169 | -------------------------------------------------------------------------------- /images/Alarm_clock_digital_time_4732015_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/Alarm_clock_digital_time_4732015_128.png -------------------------------------------------------------------------------- /images/Alarm_clock_digital_time_4732015_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/Alarm_clock_digital_time_4732015_256.png -------------------------------------------------------------------------------- /images/Alarm_clock_digital_time_4732015_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/Alarm_clock_digital_time_4732015_512.png -------------------------------------------------------------------------------- /images/LEDMatrixBarWeatherStation-V2_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LEDMatrixBarWeatherStation-V2_01.png -------------------------------------------------------------------------------- /images/LEDMatrixBarWeatherStation-V2_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LEDMatrixBarWeatherStation-V2_02.png -------------------------------------------------------------------------------- /images/LEDMatrixBarWeatherStation-V2_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LEDMatrixBarWeatherStation-V2_03.png -------------------------------------------------------------------------------- /images/LEDMatrixBarWeatherStation-V2_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LEDMatrixBarWeatherStation-V2_24.png -------------------------------------------------------------------------------- /images/LEDMatrixBarWeatherStation-V3_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LEDMatrixBarWeatherStation-V3_01.png -------------------------------------------------------------------------------- /images/LEDMatrixBarWeatherStation-V3_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LEDMatrixBarWeatherStation-V3_02.png -------------------------------------------------------------------------------- /images/LEDMatrixBarWeatherStation-V3_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LEDMatrixBarWeatherStation-V3_03.png -------------------------------------------------------------------------------- /images/LEDMatrixBarWeatherStation-V3_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LEDMatrixBarWeatherStation-V3_24.png -------------------------------------------------------------------------------- /images/LEDMatrixBarWeatherStation_V1_01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LEDMatrixBarWeatherStation_V1_01.jpg -------------------------------------------------------------------------------- /images/LED_Matrix_Bar_Weather_Station_v104_Schematic_1of2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LED_Matrix_Bar_Weather_Station_v104_Schematic_1of2.png -------------------------------------------------------------------------------- /images/LED_Matrix_Bar_Weather_Station_v104_Schematic_2of2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/LED_Matrix_Bar_Weather_Station_v104_Schematic_2of2.png -------------------------------------------------------------------------------- /images/cloudy_weather_icon_128px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/cloudy_weather_icon_128px.png -------------------------------------------------------------------------------- /images/cloudy_weather_icon_256px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/cloudy_weather_icon_256px.png -------------------------------------------------------------------------------- /images/cloudy_weather_icon_512px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/cloudy_weather_icon_512px.png -------------------------------------------------------------------------------- /images/display_128px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/display_128px.png -------------------------------------------------------------------------------- /images/display_256px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/display_256px.png -------------------------------------------------------------------------------- /images/display_512px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/display_512px.png -------------------------------------------------------------------------------- /images/electronic_clock_0000_811469_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/electronic_clock_0000_811469_128.png -------------------------------------------------------------------------------- /images/electronic_clock_0000_811469_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/electronic_clock_0000_811469_256.png -------------------------------------------------------------------------------- /images/electronic_clock_0000_811469_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/electronic_clock_0000_811469_512.png -------------------------------------------------------------------------------- /images/electronic_clock_1200_811483_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/electronic_clock_1200_811483_128.png -------------------------------------------------------------------------------- /images/electronic_clock_1200_811483_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/electronic_clock_1200_811483_256.png -------------------------------------------------------------------------------- /images/electronic_clock_1200_811483_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/electronic_clock_1200_811483_512.png -------------------------------------------------------------------------------- /images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/favicon.ico -------------------------------------------------------------------------------- /images/favicon_display.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/favicon_display.ico -------------------------------------------------------------------------------- /images/favicon_electronic_clock_random_time_stopwatch.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/favicon_electronic_clock_random_time_stopwatch.ico -------------------------------------------------------------------------------- /images/favicon_electronic_clock_time.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/favicon_electronic_clock_time.ico -------------------------------------------------------------------------------- /images/favicon_if_home.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/favicon_if_home.ico -------------------------------------------------------------------------------- /images/favicon_if_home_40798.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/favicon_if_home_40798.ico -------------------------------------------------------------------------------- /images/favicon_time_management_clock.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/favicon_time_management_clock.ico -------------------------------------------------------------------------------- /images/google_home_5710541_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/google_home_5710541_128.png -------------------------------------------------------------------------------- /images/google_home_5710541_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/google_home_5710541_256.png -------------------------------------------------------------------------------- /images/google_home_5710541_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/google_home_5710541_512.png -------------------------------------------------------------------------------- /images/screencapture-ledmatrixbarweatherstation-mobile-2021-06-25-20_04_00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/screencapture-ledmatrixbarweatherstation-mobile-2021-06-25-20_04_00.png -------------------------------------------------------------------------------- /images/screencapture-ledmatrixbarweatherstation-pc-2021-06-25-20_23_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/screencapture-ledmatrixbarweatherstation-pc-2021-06-25-20_23_22.png -------------------------------------------------------------------------------- /images/time_management_clock_128px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/time_management_clock_128px.png -------------------------------------------------------------------------------- /images/time_management_clock_256px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/time_management_clock_256px.png -------------------------------------------------------------------------------- /images/time_management_clock_512px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/time_management_clock_512px.png -------------------------------------------------------------------------------- /images/weather_2_2682849_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/weather_2_2682849_128.png -------------------------------------------------------------------------------- /images/weather_2_2682849_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/weather_2_2682849_256.png -------------------------------------------------------------------------------- /images/weather_2_2682849_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZalophusDokdo/LED_Matrix_Bar_Weather_Station/af2c30e63afd97f4eac60292a5c650b5c4c5ed75/images/weather_2_2682849_512.png --------------------------------------------------------------------------------