Micro Dot pHAT to display clock and BME280 sensor data

I’ve built a mini-smart mirror that uses a BME280 sensor to read temperature, pressure and humidity and then displays the stats on the Micro Dot pHAT (it’ll soon be in the MagPi btw), but I’m struggling to get the MDpHAT to show the time as well.

To add more to the mix, I’m also pushing data to Beebotte to track the readings, but I’m also integrating Pushover notifications to warn us if the temperature rises above a set reading (the setup is in our baby son’s nursery).

I have got the majority of the above working, except displaying the time. I’m looking to display temperature, humidity (pressure is not that relevant really) then the time at 5 second intervals - i.e. temp -> (5s) -> humidity -> (5s) -> time (5s) -> repeat.

This is my code so far and I suspect the issue is around when the clock is called, but any help would be greatly appreciated:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import bme280
import time
import datetime
import sys
import threading
import httplib, urllib
from microdotphat import write_string, set_decimal, clear, show
from beebotte import *

### Replace CHANNEL_TOKEN with that of your Beebotte channel
### and YOUR_CHANNEL_NAME_HERE with the channel you create
bbt = BBT(token = 'CHANNEL_TOKEN')
chanName = "YOUR_CHANNEL_NAME_HERE"

### Change Beebotte channel name as suits you - in this instance, it is called BME280.
temp_resource   = Resource(bbt, chanName, 'temperature')
pressure_resource  = Resource(bbt, chanName, 'pressure')
humidity_resource = Resource(bbt, chanName, 'humidity')

# Sends data to your Beebotte channel
def beebotte():
    while True:
        temp_resource.write(round(temperature,1))
        pressure_resource.write(round(pressure,0))
        humidity_resource.write(round(humidity,0))
        time.sleep(900)    # 15 mins to prevent maxing API limit

# Experimental! Clock - may not work yet!
# Display time on Micro Dot pHAT for set time
showClock = 5 # Seconds

# Function for the clock
def clock():
    while True:
        clockEndTime = time.time() + showClock
        while time.time() < clockEndTime:
            clear()
            t = datetime.datetime.now()
            if t.second % 2 == 0:
                set_decimal(2, 1)
                set_decimal(4, 1)
            else:
                set_decimal(2, 0)
                set_decimal(4, 0)
            write_string(t.strftime('%H%M%S'), kerning=False)
            show()
            time.sleep(0.05)

# Experimental! Pushover notifications - should work
def pushover():
    conn = httplib.HTTPSConnection("api.pushover.net:443")
    conn.request("POST", "/1/messages.json",
      urllib.urlencode({
        "token": "APP_TOKEN",                       # Insert app token here
        "user": "USER_TOKEN",                       # Insert user token here
        "html": "1",
        "title": "High temperature!",
        "message": "It is "+str(temperature)+ "°C in the nursery!",
        "url": "https://beebotte.com/dash/RANDOM_ID_HERE",
        "url_title": "View Beebotte dashboard",
        "sound": "siren",
      }), { "Content-type": "application/x-www-form-urlencoded" })
    conn.getresponse()

# Display stats on the Micro Dot pHAT
def microdot():
    clear()
    write_string( "%.1f" % temperature + "C", kerning=False)
    show()
    time.sleep(5)
    # Uncomment to display pressure if needed
    #clear()
    #write_string( "%.0f" % pressure + "hPa", kerning=False)
    #show()
    #time.sleep(5)
    clear()
    write_string( "%.0f" % humidity + "% RH", kerning=False)
    show()
    time.sleep(5)
    clock()

try:
    # Get the first reading from the BME280 sensor
    temperature,pressure,humidity = bme280.readBME280All()
    # Start the Beebotte function as a thread so it works in the background
    beebotte_thread = threading.Thread(target=beebotte)
    beebotte_thread.daemon = True
    beebotte_thread.start()
    # Run a loop to collect data and display it on the Micro Dot pHAT
    # and send notifications via Pushover if it is too hot
    while True:
        temperature,pressure,humidity = bme280.readBME280All()
        if temperature >= 26:
            pushover()
        else:
            continue
        microdot()

# Attempt to exit cleanly - not quite there, needs work!
except (KeyboardInterrupt, SystemExit):
    sys.exit()
    pass

If it helps, my GitHub repo is here so happy to work in there if needed: https://github.com/raspberrycoulis/bme280-pi

Thanks!

So what does or doesn’t happen? As in, does it not show the Time, or show it incorrectly, or error out?

Sorry, that would be helpful to know I guess!

At the moment, it doesn’t seem to display anything on the Micro Dot pHAT - the Pushover notifications do work (if the temperature is above the threshold set (26), but I cannot get the clock to show properly.

If I remove the clock function from the code and make the while True look like the following, it works fine (except obviously there are no Pushover notifications or clock displayed):

while True:
    temperature,pressure,humidity = bme280.readBME280ALL()
    microdot()

Does this help?

On my sense hat I show a continuously scrolling message of Day, Date, Time , temp, humisidty and pressure on its LED matrix. I’m not sure if it will help but here is my code.

import os
import time, datetime
from sense_hat import SenseHat, ACTION_PRESSED, ACTION_HELD, ACTION_RELEASED
        
sense = SenseHat()
sense.set_rotation(180)
sense.set_imu_config(False, False, False)
sense.low_light = True

s=(0.065) # scroll speed
w=(0) # color all white toggle
x=(2) #shutdown variable

# is really stick down
def pushed_up(event):
    if event.action == ACTION_PRESSED:
       sense.low_light = True
        
# is really stick up
def pushed_down(event):
    if event.action == ACTION_PRESSED:
       sense.low_light = False

#is really stick right
def pushed_left(event):
    global w
    if event.action == ACTION_PRESSED:
        w = (255)
        
# is really stick left
def pushed_right(event):
    global w
    if event.action == ACTION_PRESSED:
        w = (0)

def pushed_middle(event):
    global x
    if event.action == ACTION_PRESSED:
        x = 0

sense.stick.direction_up = pushed_up
sense.stick.direction_down = pushed_down
sense.stick.direction_left = pushed_left
sense.stick.direction_right = pushed_right
sense.stick.direction_middle = pushed_middle

while True:

    dateString = "%A %B %-d %-I:%M:%p"
    msg = "It is %s" % (datetime.datetime.now().strftime(dateString))
    sense.show_message(msg, scroll_speed=s, text_colour=(w, 255, 255))

    t = sense.get_temperature()
    t = round(t)
          
    if t <= 0: 
        tc = [w, w, 255]  # Blue
    elif t > 0 and t < 13:
        tc = [255, 255, w]  # Yellow
    elif t >= 13 and t <= 25:
        tc = [w, 255, w]  # Green
    elif t > 25:
        tc = [255, w, w]  # Red                 
    msg = "and %sc" % (t)
    sense.show_message(msg, scroll_speed=s, text_colour=tc)

    h = sense.get_humidity()
    h = round(h)

    if h < 0:
        h = 0

    if h > 100:
        h = 100

    if h < 30:
        hc = [255, w, w]  # Red
        msg = "with %s%% Humidity" % (h)
        sense.show_message(msg, scroll_speed=s, text_colour=hc)
    elif h >= 30 and h <= 60:
        hc = [w, 255, w]  # Green
        msg = "with %s%% Humidity" % (h)
        sense.show_message(msg, scroll_speed=s, text_colour=hc)
    elif h > 60 and h < 80:
        hc = [255, 255, w]  # Yellow
        msg = "with %s%% Humidity" % (h)
        sense.show_message(msg, scroll_speed=s, text_colour=hc)
    elif h >= 80:
        hc = [255, w, w]  # Red
        msg = "with %s%% Humidity" % (h)
        sense.show_message(msg, scroll_speed=s, text_colour=hc)

    p = sense.get_pressure()
    p = round(p)
        
    if p > 0 and p < 985:
        pc = [255, w, w]  # Red
        msg = "- Barometer is Very Low @ %smb - Storm Watch" % (p)
        sense.show_message(msg, scroll_speed=s, text_colour=pc)
    elif p >= 985 and p < 1005:
        pc = [255, 255, w]  # Yellow
        msg = "- Barometer is Low @ %smb - Possible Percipitation" % (p)
        sense.show_message(msg, scroll_speed=s, text_colour=pc)
    elif p >= 1005 and p < 1025:
        pc = [w, 255, w]  # Green
        msg = "- Barometer is Mid Range @ %smb" % (p)
        sense.show_message(msg, scroll_speed=s, text_colour=pc)
    elif p >= 1025 and p < 1050:
        pc = [w, w, 255]  # Blue
        msg = "- Barometer is High @ %smb" % (p)
        sense.show_message(msg, scroll_speed=s, text_colour=pc)
    elif p >= 1050:
        pc = [255, w, w]  # Red
        msg = "- Barometer is Very High @ %smb - Expect Dry Conditions" % (p) 
        sense.show_message(msg, scroll_speed=s, text_colour=pc)
        
    if x == 0:
        sense.clear()
        os.system("sudo shutdown now -P")
        time.sleep(30)
    elif x == 1:
        sense.clear()
        raise SystemExit
        time.sleep(30)

Thanks - could you fix the formatting so it displays properly?

I would if I knew why it does that? The actual file is here in my onedrive folder. https://1drv.ms/f/s!AjOYwiwlwDtpgq8_0VrdS3_H5xL_AA
The THPUVBME file used a BME680 for temp, humidity and pressure.

Looks like the code at the top is missing an extra `:

.```

An extra ` or . got in there some how?

Sorted - can see it fine now. Thanks, just reading.

I think you need a dateStrig = in there to set the format? I’m by no means a python expert though.

I don’t get any errors in the terminal when running the code, so it looks like it is formatted fine, but I think the clock function I created is called properly. I also only want to show the time for 5s, not constantly as the display on the MDpHAT is cycling through temp, humidity, time and repeats constantly…

I see the “write_string(t.strftime(’%H%M%S’), kerning=False)”, now missed it first time through.
Try running your python file from idle or what ever editor you prefer. That might get you an error message your not seeing. idle also has the check module option I like to use to flag my inevitable typo’s.

I think the formatting is fine - it’s running, just not showing the clock.

With 6 digits to play with I can see why you’d do it one full message at a time. My sense hat only has an 8x8 LED matrix. My only real option is a scrolling message, plus I have some text messages in there.
I think you code is above my skill level. I posted mine because I’m doing a similar thing.

Ok, thanks anyway.

I wonder if @gadgetoid or @sandyjmacdonald might be able to shed some light?

So, when it doesn’t show the clock, does it show the temp or humidity etc?

No. It doesn’t display anything. But if I remove the clock function it works. I suspect the issue is around the part I highlighted above.

Should the “while true” be inside the “def”? Shouldn’t the while true call up the def?

I’m no expert, but I think I would do it as follows

Do all your imports

then

def time:
def temp:
def humidity:
def pressure:

then

While true:
time()
time sleep
temp()
timesleep
humidity()
timesleep
pressure()
timesleep

What I did with my BME680 is split the three readings up.
sensor = bme680.BME680()
t = (sensor.data.temperature)
h = (sensor.data.humidity)
p = (sensor.data.pressure)

That lets me deal with each one separately. The color of each element in my message is a different color based on conditions. The temperature message for example will be blue if the temp is below 0c. I didn’t post that code because there is a lot of other stuff going on.