ESPHome: GPS Time

In my previous post I used Homeassistant to get the current time and show it on a display. GPS sensors are pretty cheap and I have a few of them in my electronics box. So why not use GPS to get the current time for the display.

GPS chips are connected via UART. I used Pin 16 and 17 and connected the RX pin of the GPS with the TX pin of the Pico (Pin 16). And the TX pin of the GPS then to Pin 17 (RX) on the Pico.

GPS needs a bit time to find satellites, so the time starts at 01:00 until it is set to the correct time. The GPS module (at least the one I am using) is blinking blue when it gets new data. Per default the GPS ESPHome code is announcing Latitude, Longintude, Speed, Altitude, Course and Satellites. So these values could be added in Homeassistant easily.

On the display I wanted of course see the current time. But to show how to add values from the GPS I added the number of satellites.

img1

I moved the display to different pins, because I used a breadboard. So the I2C pins are 20 and 21.

ESPHome config of GPS with display (api, wifi, logger, ota removed)

uart:
  tx_pin: 16
  rx_pin: 17
  baud_rate: 9600

gps:
  satellites:
    # add id to reference it for the display
    id: num_sat

time:
  - platform: gps
    id: gpstime
    timezone: Europe/Berlin

font:
  - file: "gfonts://Roboto"
    id: font1
    size: 24
  - file: "gfonts://Roboto"
    id: font2
    size: 18

i2c:
  sda: 20
  scl: 21
  scan: false

display:
  - platform: ssd1306_i2c
    model: "SH1106 128x64"
    address: 0x3C
    lambda: |-
      it.strftime(0, 0, id(font1), "%H:%M", id(gpstime).now());
      it.printf(0, 31, id(font2), "Satellites: %1.0f", id(num_sat).state);

ESPHome: OLED Display

For my kitchen I want a display with the current temperature and humidity based on the Pico I already have deployed there. I get the current time, temperature and humidity from Homeassistant. If the same Pico is displaying the values of it's own sensors, fetching them again via Homeassistant is not needed.

I used a 128x64 I2C OLED display. The result looks like this:

img1

Some notes about the code below:

  • The Pico needs WiFi and an API to communicate with Homeassistant.

  • I disabled all logs that are not Errors because the display is spamming that it is too slow.

  • The Timezone of my local system is set to UTC, so I need to set it here to get the correct time on the display.

  • On the display I want to show temperature and humidity from a different Pico so the data is fetched from Homeassistant with their entity_ids.

  • Add internal: true to sensors you fetch from Homeassistant to not republish them.

  • For TTF fonts I didn't want to copy files around, so I used a Google Font that is fetched at buildtime.

  • I used Pin 1+2 from the Pico for I2C.

  • The default update_interval of the display is 1 second -- I changed it to 5 seconds.

  • The Code in the display lambda is C++. So be aware of semicolons and format strings.

  • Updating via OTA is still the best way to update a Pico (after the initial U2F file is copied to the device).

ESPHome config for my kitchen display (only the display, no attached sensors)

esphome:
  name: pico5

rp2040:
  board: rpipicow
  framework:
    platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git

api:
  password: ""

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

logger:
  logs:
    # disable log entries about the display updating too slow
    component: ERROR

time:
  - platform: homeassistant
    id: esptime
    timezone: Europe/Berlin

sensor:
  - platform: homeassistant
    id: temperature
    entity_id: sensor.pico2_bme280_temperature
    internal: true

  - platform: homeassistant
    id: humidity
    entity_id: sensor.pico2_bme280_humidity
    internal: true

font:
  - file: "gfonts://Roboto"
    id: font1
    size: 24

i2c:
  sda: 0
  scl: 1
  scan: false

display:
  - platform: ssd1306_i2c
    model: "SH1106 128x64"
    address: 0x3C
    update_interval: 5s
    lambda: |-
      it.strftime(0, 0, id(font1), "%H:%M", id(esptime).now());
      if (id(temperature).has_state()) {
        it.printf(0, 31, id(font1), "%.1f°", id(temperature).state);
      }
      if (id(humidity).has_state()) {
        it.printf(60, 31, id(font1), "%d%%", int(id(humidity).state));
      }

ota:
  platform: esphome
  password: !secret ota_password

I will merge the display into the Pico2 (the one with the sensor) and only run one device in the kitchen. But for development the decoupling via Homeassistant was very convenient. To get the current time the Homeassistant is always needed.

ESPHome: Reed Switch

This summer my living room window is open quite often and I would like to see if I forgot to close it, while I am not at home. I looted reed switches years ago somewhere and never tried using them.

First I experimented on a breadboard with a Pico. But when everything worked out I replaced the Pico with an unused cheap ESP8266 from years ago and deployed it to the living room window I open often.

Using a reed switch is as easy as it can get. When used with a Pico or an ESP connect one side to Ground and the other one to a Pin that can be pulled up. For the ESP8266 this doesn't work for all the Pins, I used D4.

The switch with a magnet attached looks like this:

img1

I setup at a window by attaching the magnet to the moving part (the window) and the electronics (the reed switch and the ESP/Pico) to the frame. My setup with the ESP8266 looks like this:

img2

I used multiple magnets to be sure the switch will work.

The ESPHome setup for the ESP8266 (I ommit the wifi, api, ota part here):

esphome:
  name: lolin1

esp8266:
  board: nodemcuv2
  framework:
    version: recommended

binary_sensor:
  - platform: gpio
    pin:
      number: D4
      mode:
        input: true
        pullup: true
    name: "Living Room Window"
    device_class: window

Important here is setting the pullup and input to true.

In Homeassistant:

img3

Of course this can be used to trigger actions in Homeassistant. I am thinking about an LED at the door to my appartment to immediatly see if the window is closed when leaving. But maybe this is a bit too much. :)