After a good deal of thought I went for:
Hardware
A Raspberry Pi Pico
https://shop.pimoroni.com/products/raspberry-pi-pico?variant=32402092326995 Breakout Garden
https://shop.pimoroni.com/products/pico-breakout-garden-packA BMP280 temperature & pressure sensor
https://shop.pimoroni.com/products/bmp280-breakout-temperature-pressure-altitude-sensorA USB C-A data cable to connect the Pico to the laptop.
Soldering iron not required. Assembled in 2 minutes. Micropython loaded in another 5 minutes.
Software:
Micropython from here:
https://github.com/pimoroni/pimoroni-pico/releases/tag/v1.18.0 Starter script from here:
https://github.com/pimoroni/pimoroni-pico/blob/v1.18.0/micropython/examples/breakout_bmp280/demo_bmp280.py The starter script ended up as this:
# Imports ##################################################################################
import time
from machine import Pin, UART # removed Timer,
from breakout_bmp280 import BreakoutBMP280
from pimoroni_i2c import PimoroniI2C
# Setup ####################################################################################
PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
# PINS_PICO_EXPLORER = {"sda": 20, "scl": 21}
led = Pin(25, Pin.OUT)
i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN)
bmp = BreakoutBMP280(i2c) # Pimoroni only provide read() and configure() methods so you might want to use your own driver for the BMP280
sR = 2.5 # Sample rate which matches that of weather station
# Initialize a UART object ###############################################################
uart = UART(0, baudrate=9600, rx=Pin(17), tx=Pin(16, Pin.OUT ),timeout=10)
# Run #####################################################################################
while True:
reading = bmp.read() # returns temperature (deg C), pressure (Pa)
# just send the digits eg 12.34, 10142.45
print(reading)
# send a fancier feed over the link
# print("temperature ,",reading[0],"\n")
# eg temperature , 12.34
# print("pressure ,",reading[1]/100, "\n") # for sensor used at home giving raw output converted from Pa to hPa
# eg pressure , 1014.245
# print("Pressure = ",(reading[1]/100)+43.4489, "hPa @ Sea Level\n") # corrected for altitude of 365M
# eg Pressure = 1057.693 hPa @ Sea Level
# print(time.gmtime()[3], ".", time.gmtime()[4], ":", time.gmtime()[5], " ", time.gmtime()[2], "/", time.gmtime()[1], "/", time.gmtime()[0], "\n\n", sep = '')
# eg a timestamp 9.45:26 4/2/2022
# flash the led on the pico to show the script is running
led.toggle()
# run loop again
time.sleep(sR)
On the laptop I can receive the data and parse it as follows:
import serial
ser = serial.Serial('/dev/ttyACM0')
ser.flushInput()
while True:
ser_bytes = ser.readline()
b = ser_bytes.decode('UTF-8')
b2 = b.rsplit("(")
b3 = b2[1]
b4 = b3.rsplit(")")
results = b4[0].rsplit(", ")
temperature = float(results[0])
pressure = float(results[1])
corPress = (pressure/100)+44
print("temperature = ", temperature)
print("pressure = ", pressure)
print("Corrected pressure = ", corPress)
But the next step is to somehow merge it into the rtldavis.py feed into weewx so I have barometric pressure. I bet this will be challenging for a novice python programmer
](https://www.wxforum.net/Smileys/default/eusa_wall.gif)
so if anyone has succeeded
please let me know!After 9 days, a lot of trial and error and a bit of grief from the other half I ended up with something that works and incorporates the pressure and indoor temperature into the weewx report. I suspect it is not very robust code as I am new to this but it's a start.
import sys
import syslog
import serial
import time
path_to_module = "/home/weewx/bin"
sys.path.append(path_to_module)
import weewx
from weewx.wxengine import StdService
class Add_temp_and_press(StdService):
def __init__(self, engine, config_dict):
super(Add_temp_and_press, self).__init__(engine, config_dict)
# d = config_dict.get('Add_temp_and_press', {})
# Use the loop packet event as that allows data to still get into the WeeWX database
self.bind(weewx.NEW_LOOP_PACKET, self.load_data)
def load_data(self, event):
self.get_BMPpress(event)
self.get_BMPtemp(event)
self.get_BMPbaro(event)
# Get inTemp data
def get_BMPtemp(self, event):
ser = serial.Serial('/dev/ttyACM0')
ser.flushInput()
ser_bytes = ser.readline()
b = ser_bytes.decode('UTF-8')
b2 = b.rsplit("(")
b3 = b2[1]
b4 = b3.rsplit(")")
results = b4[0].rsplit(", ")
inTemp = float(results[0])
# NOTE: stores as degC
event.packet['inTemp'] = float(inTemp)
syslog.syslog(syslog.LOG_DEBUG, "Add_temp_and_press: found temperature value of %s C" % inTemp)
# Get pressure data
def get_BMPbaro(self, event):
ser = serial.Serial('/dev/ttyACM0')
ser.flushInput()
ser_bytes = ser.readline()
b = ser_bytes.decode('UTF-8')
b2 = b.rsplit("(")
b3 = b2[1]
b4 = b3.rsplit(")")
results = b4[0].rsplit(", ")
barometer = (float(results[1])/100)+44
event.packet['barometer'] = float(barometer)
syslog.syslog(syslog.LOG_DEBUG, "Add_temp_and_press: found barometer value of %s hPa" % barometer)
# Get absolute pressure data
def get_BMPpress(self, event):
ser = serial.Serial('/dev/ttyACM0')
ser.flushInput()
ser_bytes = ser.readline()
b = ser_bytes.decode('UTF-8')
b2 = b.rsplit("(")
b3 = b2[1]
b4 = b3.rsplit(")")
results = b4[0].rsplit(", ")
pressure = (float(results[1])/100)
event.packet['pressure'] = float(pressure)
syslog.syslog(syslog.LOG_DEBUG, "Add_temp_and_press: found pressure value of %s hPa" % pressure)
