Tufty 2040 weather station

Not terribly experienced with micro python and only self taught when it comes to computers but I enjoy working through the projects.

I’m trying to blend my Tufty with a bme280 to create a weather station. I have no problems getting the two working and viewing current data. I am looking for an example that allows me to chart the data over time. I’m particularly interested in the barometer function being charted but would like to do all three or even include the light sensor and make it four charts. Anyone make such an animal yet?

I haven’t tried to do it in Micro Python, but would like to try it. I’ve done it in Python with Pi Enviro+ code. The pressure changes so slowly that you need to graph it over a long period. A 2mb change over 2 hours is considered as “changing rapidly”.
I have wired up a BME280 to my Tufty to display weather info.

'''
pimoroni-pico-v1.19.0-micropython
pico lipo 16mb
Pico Display Pack, 1.14” 240x135 pixel IPS LCD screen
BME280
'''
import utime
import picographics

from breakout_bme280 import BreakoutBME280
from pimoroni_i2c import PimoroniI2C
from picographics import PicoGraphics, DISPLAY_TUFTY_2040, PEN_RGB332
from machine import ADC, Pin

vsys = ADC(29)              
charging = Pin(24, Pin.IN)
conversion_factor = 3 * 3.3 / 65535
full_battery = 4.5
empty_battery = 2.8

display = PicoGraphics(display=DISPLAY_TUFTY_2040, rotate=270, pen_type=PEN_RGB332)
display.set_backlight(1.0)
display.set_font("bitmap8") 

from pimoroni_i2c import PimoroniI2C
i2c = PimoroniI2C(sda=(4), scl=(5))

bme = BreakoutBME280(i2c,0x77)

# lets set up some pen colors to make drawing easier
tempcolor = display.create_pen(0, 255, 0)  # this colour will get changed in a bit
humidcolor = display.create_pen(0, 255, 0)  # this colour will get changed in a bit
presscolor = display.create_pen(0, 255, 0)  # this colour will get changed in a bit
white = display.create_pen(255, 255, 255)
black = display.create_pen(0, 0, 0)
red = display.create_pen(255, 0, 0)
green = display.create_pen(0, 255, 0)
blue = display.create_pen(0, 0, 255)
yellow = display.create_pen(255, 255, 0)
orange = display.create_pen(255, 140, 0)
grey = display.create_pen(120, 120, 120)
violet = display.create_pen(255, 0, 255)

# converts the temperature into a description and pen colour
def describe_temperature(temperature):
    global tempcolor
    if temperature < 0:
        description = "Very Cold"
        tempcolor = blue
    elif 0 <= temperature < 12:
        description = "Cold"
        tempcolor = yellow
    elif 12 <= temperature < 17:
        description = "Cool"
        tempcolor = green
    elif 17 <= temperature < 25:
        description = "Warm"
        tempcolor = green      
    elif 25 <= temperature < 30:
        description = "Hot"
        tempcolor = orange
    elif temperature >= 30:
        description = "Very Hot"
        tempcolor = red
    else:
        description = ""
        tempcolor = black
    return description

# converts humidity into good/bad description and pen color
def describe_humidity(humidity):
    global humidcolor
    if humidity < 30:
        description = "Low - Dry"
        humidcolor = orange
    elif 30 <= humidity < 61:
        description = "OK"
        humidcolor = green
    elif 61 <= humidity < 81:
        description = "High"
        humidcolor = yellow
    elif humidity >= 81:
        description = "Very High"
        humidcolor = red        
    else:
        description = ""
        humidcolor = black        
    return description

# converts pressure into barometer-type description and pen color
def describe_pressure(pressure):
    global presscolor
    if pressure < 982:
        description = "Very Low"
        presscolor = red
    elif 982 <= pressure < 1004:
        description = "Low"
        presscolor = yellow
    elif 1004 <= pressure < 1026:
        description = "Unsettled"
        presscolor = green
    elif 1026 <= pressure < 1048:
        description = "High"
        presscolor = blue
    elif pressure >= 1048:
        description = "Very High"
        presscolor = orange
    else:
        description = ""
        presscolor = black
    return description

start_time = utime.time()

while True:

    time_elapsed = utime.time() - start_time
    
    # read the sensors
    temperature, pressure, humidity = bme.read() 
            
    # convert pressure to mb
    pressuremb = pressure / 100

    # drawing the temperature reading
    display.set_pen(tempcolor)
    display.text('{:.1f}'.format(temperature) + '`c', 10, 10, scale=4)
    display.text(describe_temperature(temperature), 10, 45, scale=4)
    
    # drawing the humidity reading
    display.set_pen(humidcolor)
    display.text('{:.0f}'.format(int(humidity)) + '%', 10, 90, scale=4)
    display.text(describe_humidity(int(humidity)), 10, 125, scale=4)
    
    # drawing the pressure reading
    display.set_pen(presscolor)
    display.text('{:.0f}'.format(pressuremb) + 'mb', 10, 165, scale=4)
    display.text(describe_pressure(pressuremb), 10, 200, scale=4)
        
    # draw a thermometer
    display.set_pen(grey)
    display.circle(210, 170, 20)
    display.rectangle(199, 14, 24, 140)
    display.set_pen(tempcolor)
    display.circle(210, 170, 10)
    thermometerheight = int((temperature) * 5)
    if thermometerheight > 150:
        thermometerheight = 150
    if thermometerheight < 1:
        thermometerheight = 1
    display.rectangle(206, 60 + 120 - thermometerheight, 10, thermometerheight)
         
    if charging.value() == 1:         # if it's plugged into USB power...
        display.set_pen(blue)
        display.text("USB Powered", 5, 240, scale=4)
    else:
        display.set_pen(red)
        display.text("On Battery", 25, 240, scale=4)
            
    voltage = vsys.read_u16() * conversion_factor
    percentage = 100 * ((voltage - empty_battery) / (full_battery - empty_battery))
    if percentage > 100:
        percentage = 100.00
    
    display.set_pen(green)
    display.text('{:.2f}'.format(voltage) + "v", 5, 280, scale=4)
    display.text('{:.0f}%'.format(percentage), 150, 280, scale=4)
    
    # time to update the display
    if time_elapsed < 2:
        temperature, pressure, humidity = bme.read()
        display.set_pen(black)
        display.clear()
        display.update()
        utime.sleep(1)
    else:
        display.update()
        utime.sleep(1)
        display.set_pen(black)
        display.clear()        

I am trying to run a four chart format as below but somewhere I have an error. I live in a hurricane zone and realize the value of a time tracked barometer. I am thinking one reading every 15-20 minutes on the whole thing.

# Pico Dashboard
# Kevin McAleer
# June 2022

# import picodisplay2 as display
from pichart import Chart, Card, Container
from Colour import hsv2rgb, rgb2hsv, fade
from picographics import PicoGraphics, DISPLAY_TUFTY_2040, PEN_RGB332
display = PicoGraphics(display=DISPLAY_TUFTY_2040, rotate=180, pen_type=PEN_RGB332)
import gc 
import machine
from time import sleep
import utime
from random import randint
import jpegdec
from pimoroni_i2c import PimoroniI2C
from breakout_bme280 import BreakoutBME280
PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
PINS_PICO_EXPLORER = {"sda": 20, "scl": 21}
i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN)

bme = BreakoutBME280(i2c)
temperature, pressure, humidity = bme.read() 
#     pressuremb = pressure / 100
#     temperature = temperature * 9/5+ 32
#     scaled_temp = int(temperature + 40)  # Range from -40 to +60 = 1-100
#     scaled_press = int((pressure - 87000) / ((108400 - 87000) / 100))  # Range 108400 - 87000 = 1 -100
#     scaled_humid = int(humidity)  # Range 1 - 100

#  WIDTH, HEIGHT = 320, 240 # Pico Display 2.0
# WIDTH, HEIGHT = display.get_bounds()
WIDTH, HEIGHT = 240,240

#  display = ST7789(WIDTH, HEIGHT, rotate180=False)

gc.collect()

data = bme.read()
temperature, pressure, humidity = bme.read()
pressuremb = pressure / 100
temperature = temperature * 9/5+ 32
scaled_temp = int(temperature + 40)  # Range from -40 to +60 = 1-100
scaled_press = int((pressure - 87000) / ((108400 - 87000) / 100))  # Range 108400 - 87000 = 1 -100
scaled_humid = int(humidity)  # Range 1 - 100

# Set the theme colour
THEME = {'red': 255, 'green': 171, 'blue': 57}
THEME2 = {'red': 252, 'green': 193, 'blue': 109}
THEME3 = {'red': 151, 'green': 250, 'blue': 121}
WHITE = {'red': 255, 'green': 255, 'blue': 255}
LIGHT_GREY = {'red': 240, 'green': 240, 'blue': 240}
BLUE = {'red': 20, 'green': 155, 'blue': 206}
LIGHT_BLUE = {'red': 55, 'green': 170, 'blue': 213}
BLACK = {'red': 0, 'green': 0, 'blue': 0}
GREEN = {'red': 0, 'green': 220, 'blue': 0}

LIGHT_GREEN = fade(GREEN, WHITE, 0.15)
DARK_GREEN = fade(GREEN, BLACK, 0.15)
ORANGE = {'red': 255, 'green': 171, 'blue': 57}
LIGHT_ORANGE = {'red': 255, 'green': 195, 'blue': 110}

# Frame background colour
BACKGROUND = {'red': 255, 'green': 171, 'blue': 57}

border = 20
# frame(border,border,width-(border*2),height-(border*2),BACKGROUND)

chart1 = Chart(display, title='Temprature', x_values=data)
chart2 = Chart(display, title='Humidity')
chart3 = Chart(display, title="Pressure", x_values=data)
chart4 = Chart(display, title="Humidity", x_values=data)

chart1.background_colour = BLACK
chart1.data_colour = WHITE
chart1.title_colour = WHITE
chart1.border_colour = WHITE
chart1.grid_colour = DARK_GREEN

chart1.border_width = 1
chart2.border_width = 1
chart3.border_width = 1
chart4.border_width = 1

container = Container(display)
container.add_chart(chart1)
container.add_chart(chart2)
container.add_chart(chart3)
container.add_chart(chart4)

container.background_colour = BLACK
container.grid_colour = DARK_GREEN
container.data_colour = WHITE
container.title_colour = WHITE
container.border_colour = GREEN

container.border_width = 1
chart1.show_bars = True
chart1.show_lines = False
chart1.data_point_radius = 2
chart1.show_datapoints = True
chart1.show_labels = True
chart2.show_bars = False
chart2.show_lines = True
chart3.data_point_radius = 2

chart3.show_datapoints = True
chart3.show_bars = False
chart3.show_labels = True
chart3.show_lines = True

chart4.show_labels = True

container.cols = 2

container.update()

# sensor_temp = machine.ADC(4)
# conversion_factor = 3.3 / (65535)

data = [20,34]
chart1.x_values = data
chart2.x_values = data
chart3.x_values = data
chart4.x_values = [0,50]

chart1.scale_data()
chart2.scale_data()
chart3.scale_data()
chart4.scale_data()

data = []
air_quality_data = []

chart1.x_values = data
chart3.x_values = data
chart4.x_values = air_quality_data

while True or KeyboardInterrupt:
    temperature, pressure, humidity = bme.read() 
    pressuremb = pressure / 100
    temperature = temperature * 9/5+ 32
    scaled_temp = int(temperature + 40)  # Range from -40 to +60 = 1-100
    scaled_press = int((pressure - 87000) / ((108400 - 87000) / 100))  # Range 108400 - 87000 = 1 -100
    scaled_humid = int(humidity)  # Range 1 - 100
#     draw_graph(temperature, pressure, humidity)
#     print("{:0.2f}F, {:0.2f}mb, {:0.2f}%".format(
#     temperature, pressuremb, humidity))
#     utime.sleep (1)
    reading = data
    temperature = int(temperature + 40)  # Range from -40 to +60 = 1-100
    temperature = temperature * 9/5+ 32
    data.append(temperature)
    air_quality_data.append(randint(0, 50))
    print(data)
#     if len(data) == 15:
#         data.pop(0)
#     if len(air_quality_data) == 15:
#         air_quality_data.pop(0)
    chart1.x_values = data
    chart2.title = str(data[-1])
    chart3.x_values = data
    chart4.x_values = air_quality_data

    container.update()
    
    sleep(5)

Code tags are three ` before and after your code. What error message are you getting?

I’m on the coast, about a 5 min drive from the ocean. I also like to keep an eye on the barometer. I’m just getting into trying stuff like this on a Pico. I haven’t done a whole lot so far though. Really interested to see what you come up with.

The temperature and humidity show 13 minute plots and the pressure is 2 hours. I modified an Enviro + example.

1 Like

The error I get is I’m not getting the actual data as output but random numbers currently. I’ve spent the afternoon studying and going over how some of this works again. I’ve also messed around the the example @alphanumeric kindly posted as well. I realize it’s likely something simple but I can’t crack it yet.

I’m maybe average skill wise in Python. I’m self taught. And I’m “can just barely get by” skill wise with Micro Python.
@hel or @gadgetoid may be able to help sort it out though.

1 Like

I’m fooling with both which may be contributing to my issue. Thankfully it’s a hobby.
Thanks for your help

I got the sensor readings correct today but the data heights have me stumped now. Below is what I’m getting. I also cane figure out what the 156.2425 I after the 59,76 lines I am calling for data

69.02F, 1019.28mb, 45.45%
[59, 76, 156.2425]
data height: 0, title:Temperature
data height: 102, title:Temperature
data height: 583, title:Temperature
data height: 0, title:Humidity
data height: 102, title:Humidity
data height: 583, title:Humidity
data height: 0, title:Pressure
data height: 102, title:Pressure
data height: 583, title:Pressure

I haven’t tried Kevin’s pichart code so I’m not quite sure what data is keeping track of there (looks like there’s a lot going on!), but something that jumped out at me is that you’ve got WIDTH and HEIGHT set as 240 x 240 which is incorrect for Tufty. Providing you specify the correct display when you init picographics WIDTH, HEIGHT = display.get_bounds() will grab the correct screen dimensions.

There’s some simpler examples of graph functions in pimoroni-pico in the Enviro+ Pack examples that might be of use?