├── SourceSansPro-Light.ttf ├── materialdesignicons-webfont.ttf ├── README.md └── display-trial.yaml /SourceSansPro-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tejasitraj/esphome-tiny-display/HEAD/SourceSansPro-Light.ttf -------------------------------------------------------------------------------- /materialdesignicons-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tejasitraj/esphome-tiny-display/HEAD/materialdesignicons-webfont.ttf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esphome-tiny-display 2 | A simple config for a 0.96" OLED Display used with an ESP8266 D1 Mini. 3 | 4 | ![20220104_102143](https://user-images.githubusercontent.com/14822776/148037988-04984019-3352-4794-b4c5-d45863e9fa47.jpg)![20220110_204443](https://user-images.githubusercontent.com/14822776/148831975-dc762b1d-53c9-431e-a534-1e084da5b4df.jpg) 5 | 6 | 7 | 8 | I recently created this project to learn how to use a simple display with esphome. I use a few entities from Home Assistant to fetch the current weather as well as forecast weather. 9 | 10 | # What you will need 11 | - [Wemos D1 Mini](https://www.banggood.com/Geekcreit-D1-Mini-V3_0_0-WIFI-Internet-Of-Things-Development-Board-Based-ESP8266-4MB-MicroPython-Nodemcu-p-1264245.html?cur_warehouse=CN&ID=522225&rmmds=search) (ESP8266) (you could use any esp8266 or esp32 board - modify the yaml code accordingly!) 12 | - A 0.96" OLED Display - I have used a [Geekcreit OLED Display from Banggood](https://www.banggood.com/Geekcreit-0_96-Inch-4Pin-Blue-Yellow-IIC-I2C-OLED-Display-Module-Geekcreit-for-Arduino-products-that-work-with-official-Arduino-boards-p-969144.html?cur_warehouse=CN&rmmds=search) 13 | - [Dupont connectors](https://www.banggood.com/40pcs-10cm-Female-To-Female-Jumper-Cable-Dupont-Wire-p-994059.html?cur_warehouse=CN&rmmds=search) if needed (you can actually connect the display directly to the female header on the D1 Mini!) 14 | - Micro USB Power Supply 15 | 16 | # How to get started 17 | 18 | - Solder pin headers onto the display as well as the D1 Mini. A tip is to solder on female headers onto the D1 Mini, so you can plug in the male headers from the display directly into the female headers of the D1 Mini. 19 | ![20220104_102159](https://user-images.githubusercontent.com/14822776/148038098-6871cd17-0e73-4678-afc7-144d456f119e.jpg) 20 | - Copy the yaml file as well as the font files into your esphome folder 21 | - Ensure your Secrets file in Esphome is up to date 22 | - Modify the yaml file substitutions fields according to your parameters 23 | - Your device name 24 | - Your Static IP Details. If you dont want to set a static IP, comment out this line as well as the lines for manual_ip under the wifi section! 25 | - Entities for an internal temperature sensor and an external temperature sensor 26 | - An entity for the current weather condition - I use SMHI in Sweden, you could select your local weather service 27 | - Entities to show the forecast low and forecast high for today. See forecast section below. 28 | - Compile and upload to your hardware! 29 | 30 | # Make the right connections 31 | 32 | | D1 Mini Pin | Display Pin | 33 | | ----------- | ----------- | 34 | |5V|VCC| 35 | |GND|GND| 36 | |D4|SCL| 37 | |D3|SDA| 38 | 39 | # Weather and Forecast using weather service 40 | 41 | I use the [SMHI integration](https://www.home-assistant.io/integrations/smhi/) in Home Assistant since I live in Sweden as my default weather service. You can use whichever local weather service you have in your area. 42 | 43 | By default, the state of the weather service corresponds to the current weather condition (cloudy, clear etc.), as per the Home Assistant [weather](https://www.home-assistant.io/integrations/weather/) page. 44 | 45 | ![weather entity](https://user-images.githubusercontent.com/14822776/146213303-7249f18f-b541-4f75-974c-10d9c841d7f2.JPG) 46 | 47 | 48 | The forecast high and low for the day are contained as state attributes within the weather entity in Home Assistant. I created template sensors in Home Assistant to extract these into their own entities. 49 | 50 | Here is the code I added to my configuration.yaml to make this happen: 51 | 52 | ``` 53 | template: 54 | - sensor: 55 | - name: Todays Forecast High 56 | state: > 57 | {{ states.weather.smhi_home.attributes.forecast.0.temperature }} 58 | - name: Todays Forecast Low 59 | state: > 60 | {{ states.weather.smhi_home.attributes.forecast.0.templow }} 61 | ``` 62 | These entities are then called out from the esphome yaml to fetch forecast data. 63 | 64 | Spend some time to examine your weather entity under Developer Tools --> States. If your weather entity is formatted differently or has different attributes, make changes to your template code for the sensors and try it out under Developer Tools --> Template before inserting into your configuration.yaml. 65 | 66 | # Case 67 | 68 | I worked with my friend Magnus Skärström to design a case for the display and D1 Mini. The case also has a hole for a 6mm push button which I plan to add soon. 69 | ![20220110_204443](https://user-images.githubusercontent.com/14822776/148832183-4940f038-b1c8-4db9-91cf-731494d26b2d.jpg) 70 | -------------------------------------------------------------------------------- /display-trial.yaml: -------------------------------------------------------------------------------- 1 | substitutions: #substitute your own values in this section 2 | device_name: display-trial 3 | static_ip: 192.168.1.245 4 | gateway: 192.168.1.1 5 | subnet: 255.255.255.0 6 | internal_temp_sensor: sensor.air_quality_meter_temperature #entity from Home Assistant 7 | outside_temp_sensor: sensor.outside_temperature #entity from Home Assistant 8 | weather_entity: weather.smhi_home #entity from Home Assistant 9 | todays_forecast_high_entity: sensor.todays_forecast_high #entity from Home Assistant 10 | todays_forecast_low_entity: sensor.todays_forecast_low #entity from Home Assistant 11 | sda_pin: D3 12 | scl_pin: D4 13 | 14 | #--------------------------------------------------------------------------------------------- 15 | 16 | esphome: 17 | name: '${device_name}' 18 | platform: ESP8266 19 | board: d1_mini 20 | 21 | wifi: 22 | ssid: !secret wifi_ssid 23 | password: !secret wifi_password 24 | manual_ip: 25 | static_ip: $static_ip 26 | gateway: $gateway 27 | subnet: $subnet 28 | 29 | # Enable fallback hotspot (captive portal) in case wifi connection fails 30 | ap: 31 | ssid: '${device_name}' 32 | password: !secret fallback_password 33 | 34 | # Enable logging 35 | logger: 36 | 37 | # Enable Home Assistant API 38 | api: 39 | password: !secret esphome_api_password 40 | 41 | ota: 42 | safe_mode: true 43 | reboot_timeout: 10min 44 | num_attempts: 5 45 | 46 | captive_portal: 47 | 48 | web_server: 49 | port: 80 50 | auth: 51 | username: !secret esphome_web_username 52 | password: !secret esphome_web_password 53 | 54 | time: 55 | - platform: homeassistant 56 | id: esptime 57 | 58 | binary_sensor: 59 | - platform: status 60 | name: "Display Status" 61 | 62 | sensor: 63 | - platform: homeassistant 64 | id: inside_temperature 65 | entity_id: $internal_temp_sensor 66 | internal: true 67 | 68 | - platform: homeassistant 69 | id: outside_temperature 70 | entity_id: $outside_temp_sensor 71 | internal: true 72 | 73 | - platform: homeassistant 74 | id: todays_forecast_high 75 | entity_id: $todays_forecast_high_entity 76 | internal: true 77 | 78 | - platform: homeassistant 79 | id: todays_forecast_low 80 | entity_id: $todays_forecast_low_entity 81 | internal: true 82 | 83 | text_sensor: 84 | - platform: homeassistant 85 | id: weather_state 86 | name: "Current Weather Icon" 87 | entity_id: $weather_entity 88 | internal: true 89 | 90 | font: 91 | - file: 'SourceSansPro-Light.ttf' 92 | id: font1 93 | size: 16 94 | - file: 'SourceSansPro-Light.ttf' 95 | id: font2 96 | size: 26 97 | - file: 'materialdesignicons-webfont.ttf' 98 | id: font3 99 | size: 18 100 | glyphs: 101 | - "\U000F13D5" #mdi:home-minus-outline 102 | - file: 'materialdesignicons-webfont.ttf' 103 | id: font4 104 | size: 40 105 | glyphs: 106 | - "\U000F0594" #"clear-night" 107 | - "\U000F0590" #"cloudy" 108 | - "\U000F0591" #"fog" 109 | - "\U000F0592" #"hail" 110 | - "\U000F0593" #"lightning" 111 | - "\U000F067E" #"lightning-rainy" 112 | - "\U000F0595" #"partlycloudy" 113 | - "\U000F0596" #"pouring" 114 | - "\U000F0597" #"rainy" 115 | - "\U000F0598" #"snowy" 116 | - "\U000F067F" #"snowy-rainy" 117 | - "\U000F0599" #"sunny" 118 | - "\U000F059D" #"windy" 119 | - "\U000F059E" #"windy-variant" 120 | 121 | i2c: 122 | sda: $sda_pin 123 | scl: $scl_pin 124 | scan: false 125 | 126 | display: 127 | - platform: ssd1306_i2c 128 | model: "SSD1306 128x64" 129 | reset_pin: D0 130 | address: 0x3C 131 | lambda: |- 132 | 133 | if (id(weather_state).has_state()) { 134 | std::map weather_icon_map 135 | { 136 | {"clear-night", "\U000F0594"}, 137 | {"cloudy", "\U000F0590"}, 138 | {"fog", "\U000F0591"}, 139 | {"hail", "\U000F0592"}, 140 | {"lightning", "\U000F0593"}, 141 | {"lightning-rainy", "\U000F067E"}, 142 | {"partlycloudy", "\U000F0595"}, 143 | {"pouring", "\U000F0596"}, 144 | {"rainy", "\U000F0597"}, 145 | {"snowy", "\U000F0598"}, 146 | {"snowy-rainy", "\U000F067F"}, 147 | {"sunny", "\U000F0599"}, 148 | {"windy", "\U000F059D"}, 149 | {"windy-variant", "\U000F059E"}, 150 | }; 151 | it.printf(0, it.get_height(), id(font4), TextAlign::BASELINE_LEFT, weather_icon_map[id(weather_state).state.c_str()].c_str()); 152 | } 153 | 154 | // Print time in HH:MM format 155 | it.strftime(0, 0, id(font1), TextAlign::TOP_LEFT, "%H:%M %a", id(esptime).now()); 156 | 157 | //Print day of week 158 | //it.strftime(40, 0, id(font1), TextAlign::TOP_LEFT, "%a", id(esptime).now()); 159 | 160 | it.line(0, 20, it.get_width(), 20); 161 | 162 | //Print home icon 163 | //it.printf(70, 0, id(font3), "\U000F13D5"); 164 | 165 | // Print inside temperature (from homeassistant sensor) 166 | if (id(inside_temperature).has_state()) { 167 | it.printf(it.get_width(), 0, id(font1), TextAlign::TOP_RIGHT , "%7.1f°", id(inside_temperature).state); 168 | } 169 | 170 | // Print outside temperature (from homeassistant sensor) 171 | if (id(outside_temperature).has_state()) { 172 | it.printf(42, 32, id(font2), "%.1f°", id(outside_temperature).state); 173 | } 174 | 175 | // Print Forecast High 176 | if (id(todays_forecast_high).has_state()) { 177 | it.printf(it.get_width(), 32, id(font1), TextAlign::TOP_RIGHT, "%7.1f°", id(todays_forecast_high).state); 178 | } 179 | 180 | // Print Forecast Low 181 | if (id(todays_forecast_low).has_state()) { 182 | it.printf(it.get_width(), 48, id(font1), TextAlign::TOP_RIGHT, "%7.1f°", id(todays_forecast_low).state); 183 | } --------------------------------------------------------------------------------