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']['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']['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.