Weather Station

2022-12-22

Raspberry Pi Zero W

As the holidays fell, I forgot that I failed to put a weather station on my list. I had been wanting one for quite some time now, mostly just to check the pressure for fishing. Well, I realized that I could just build a mini on-line weather station using an old Raspberry Pi Zero W I had taking up space in my drawer. So I set forth to build it.

The first step was acquiring a sensor. I opted for a kit of sensors from Amazon that included the BMP180. I decided to start by connecting the sensor to an Arduino Uno that I could quickly get prototyping with. Then I found some good resources for wiring it to the Uno such as https://microcontrollerslab.com/arduino-bmp180-barometric-sensor-oled/ . It was fairly easy to check with the Arduino that everything worked as it should.

Jumping to the Raspberry Pi Zero W, I quickly realized that the sensor required a bus that had to be enabled. This can be done within raspi-config itself. Here is a good resource on the topic: https://tutorials-raspberrypi.com/raspberry-pi-and-i2c-air-pressure-sensor-bmp180/ . Once that was enabled, then I co-opted some code from https://www.kitflix.com/raspberrypi-bmp180-python -

import bmpsensor
import time
from datetime import datetime
while True:
    dt = datetime.now()
    temp, pressure, altitude = bmpsensor.readBmp180()
    # conversions
    temp_f = temp * 1.8 + 32.0 # C to F
    press_inhg = pressure * 0.0002953 # Pa to inHg
    tp = ','.join([str(dt),str(temp_f),str(press_inhg)])
    tp2 = ''.join([tp,'\n'])
    alt_f = altitude * 3.28084 # meters to feet
    print("Temperature is ", temp_f, " F")  # deg
    print("Pressure is ", press_inhg, " inHg") # Pressure 
    print("Altitude is ",alt_f, " ft") # Altitude
    print("\n")
    with open('pressure_data.txt', 'a') as f:
        f.write(tp2)
    time.sleep(600)

This code appends data to a text file that I can then send to my webserver for some data processing. Using plotly express, I create a couple rolling PNG files that contain the last 600 data points, 1 every 15 minutes.

#! /usr/bin/python

import pandas as pd
import plotly.express as px

df = pd.read_csv('pressure_data.txt')
data = df.tail(600)
#print(data)

fig_temp = px.line(data, x = 'datetime', y = 'temp_f', title = 'Temp deg F')
fig_temp['data'][0]['line']['color'] = 'red'
fig_press = px.line(data, x = 'datetime', y = 'press_inhg', title = 'Pressure inHg' )
fig_temp.write_image("temp.png")
fig_press.write_image("pressure.png")

This code is run every 15 minutes using a Linux cron job. The output can be found here: https://ydna.dev/weather.html

While these PNG’s give a great snapshot for trends over time, I thought it would be nice to have a more interactive graph. This can be done a number of ways, but I thought I would make use of Streamlit (https://streamlit.io/) , which is a great way to turn a Python script into an interactive “app”. Here’s the code:

#! /usr/bin/python

import pandas as pd
import plotly.express as px
import streamlit as st

df = pd.read_csv('pressure_data.txt')

fig_temp = px.line(df, x = 'datetime', y = 'temp_f', title = 'Temp deg F')
fig_temp['data'][0]['line']['color'] = 'red'
fig_press = px.line(df, x = 'datetime', y = 'press_inhg', title = 'Pressure inHg' )

tab1,tab2 = st.tabs(["temperature", "pressure"])
with tab1:
    st.plotly_chart(fig_temp, theme="streamlit", use_container_width=True)
with tab2:
    st.plotly_chart(fig_press, theme="streamlit", use_container_width=True)

Unfortunately, I have not yet set any DNS rules for this page yet, but the output can be seen here (WARNING TLS NOT supported at the moment)- Streamlit

Now, I can easily see when the fish might be biting in my neck of the woods.

tech

Network Analysis