From f665f78155047838dc924634ebe4128f7add5542 Mon Sep 17 00:00:00 2001 From: ars Date: Wed, 17 Jun 2020 15:59:52 +0100 Subject: Initial commit --- Datasheets/BME280-datasheet.pdf | Bin 0 -> 1587994 bytes Datasheets/SDS011-datasheet.pdf | Bin 0 -> 623790 bytes Datasheets/SEN15901-datasheet.pdf | Bin 0 -> 317837 bytes Datasheets/veml6075-datasheet.pdf | Bin 0 -> 464654 bytes dependencies.txt | 6 +++ dev_scripts/bme280_sensor.py | 26 +++++++++++ dev_scripts/sds011.py | 21 +++++++++ dev_scripts/sen15901anem.py | 49 ++++++++++++++++++++ dev_scripts/sen15901rain.py | 26 +++++++++++ dev_scripts/sen15901vane.py | 95 ++++++++++++++++++++++++++++++++++++++ dev_scripts/sen15901vanelive.py | 31 +++++++++++++ dev_scripts/vane_values.py | 11 +++++ weather_station.py | 52 +++++++++++++++++++++ 13 files changed, 317 insertions(+) create mode 100644 Datasheets/BME280-datasheet.pdf create mode 100644 Datasheets/SDS011-datasheet.pdf create mode 100644 Datasheets/SEN15901-datasheet.pdf create mode 100644 Datasheets/veml6075-datasheet.pdf create mode 100644 dependencies.txt create mode 100644 dev_scripts/bme280_sensor.py create mode 100644 dev_scripts/sds011.py create mode 100644 dev_scripts/sen15901anem.py create mode 100644 dev_scripts/sen15901rain.py create mode 100644 dev_scripts/sen15901vane.py create mode 100644 dev_scripts/sen15901vanelive.py create mode 100644 dev_scripts/vane_values.py create mode 100644 weather_station.py diff --git a/Datasheets/BME280-datasheet.pdf b/Datasheets/BME280-datasheet.pdf new file mode 100644 index 0000000..9bfdd17 Binary files /dev/null and b/Datasheets/BME280-datasheet.pdf differ diff --git a/Datasheets/SDS011-datasheet.pdf b/Datasheets/SDS011-datasheet.pdf new file mode 100644 index 0000000..31448aa Binary files /dev/null and b/Datasheets/SDS011-datasheet.pdf differ diff --git a/Datasheets/SEN15901-datasheet.pdf b/Datasheets/SEN15901-datasheet.pdf new file mode 100644 index 0000000..1b5fee4 Binary files /dev/null and b/Datasheets/SEN15901-datasheet.pdf differ diff --git a/Datasheets/veml6075-datasheet.pdf b/Datasheets/veml6075-datasheet.pdf new file mode 100644 index 0000000..c8b78d2 Binary files /dev/null and b/Datasheets/veml6075-datasheet.pdf differ diff --git a/dependencies.txt b/dependencies.txt new file mode 100644 index 0000000..1611cd4 --- /dev/null +++ b/dependencies.txt @@ -0,0 +1,6 @@ +python3-smbus +python3-gpiozero +python3-rpi.gpio +python3-bme280 + +i2c kernel driver needs to be enabled on Pi diff --git a/dev_scripts/bme280_sensor.py b/dev_scripts/bme280_sensor.py new file mode 100644 index 0000000..c117a40 --- /dev/null +++ b/dev_scripts/bme280_sensor.py @@ -0,0 +1,26 @@ +import bme280 +from smbus import SMBus +import time +port = 1 +address = 0x76 # BME280 address +bus = SMBus(port) +bme280.load_calibration_params(bus,address) +altitude = 97 + + +def bme280Read(): + bme280_data = bme280.sample(bus,address) + humidity = bme280_data.humidity + relPressure = bme280_data.pressure + ambient_temperature = bme280_data.temperature + absPressure = relPressure + (altitude/8.3) + #print(humidity, pressure, ambient_temperature) + # TODO calculate air pressure at sea level + return bme280_data.humidity, bme280_data.pressure, bme280_data.temperature, absPressure + +# test loop +""" +while True: + bme280Read() + time.sleep(1) +""" diff --git a/dev_scripts/sds011.py b/dev_scripts/sds011.py new file mode 100644 index 0000000..98abaa1 --- /dev/null +++ b/dev_scripts/sds011.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 + +import serial, time + +# SDS011 air quality sensor +ser = serial.Serial('/dev/ttyUSB0') + +while True: + data = [] + for index in range(0,10): + # read sensor + datum = ser.read() + data.append(datum) + + # extract bits 2 and 3 for PM2.5 and divide by 10 to get micrograms per metre^3 + pmTwoFive = int.from_bytes(b''.join(data[2:4]), byteorder='little') /10 + # extract bits 4 and 5 for PM10 and divide by 10 to get micrograms per metre^3 + pmTen = int.from_bytes(b''.join(data[4:6]), byteorder='little') /10 + print(pmTwoFive) + print(pmTen) + time.sleep(10) diff --git a/dev_scripts/sen15901anem.py b/dev_scripts/sen15901anem.py new file mode 100644 index 0000000..6294ea0 --- /dev/null +++ b/dev_scripts/sen15901anem.py @@ -0,0 +1,49 @@ +from gpiozero import Button +import time +import math +import statistics + +anem = Button(5) # setup GPIO 5 as a button +storeSpeeds = [] +windCount = 0 # counts half-rotations +radius_cm = 9.0 # radius of anemometer +circumference_cm = (2 * math.pi) * radius_cm +windInterval = 5 # how often to report speed +cmInKm = 100000.0 +secsInHour = 3600 +anemFactor = 1.18 # anemometer factor is the result of wind energy lost due to the arms turning + +# every half rotation, add one to count +def spin(): + global windCount + windCount += 1 + +# calculate wind speed +def calculateSpeed(timeSec): + global windCount + global circumference_cm + rotations = windCount / 2.0 + + # calculate distance travelled by anemometer in km + distKm = circumference_cm * rotations / cmInKm + speed = ((distKm / timeSec) * secsInHour) * anemFactor + return speed + +def resetWind(): + global wind_count + wind_count = 0 + +anem.when_pressed = spin + +# Loop to measure wind speed and report at 5 second intervals +while True: + startTime = time.time() + while time.time() - startTime <= windInterval: + resetWind() # reset count for next 5 second run + time.sleep(windInterval) + #finalSpeed = calculateSpeed(windInterval) + storeSpeeds.append(calculate(windInterval)) # store average speed over 5 seconds + + windGust = max(storeSpeeds) # maximum gust + windSpeed = statistics.mean(storeSpeeds) # running average wind speed + print(windSpeed, "km/h", windGust, "km/h") diff --git a/dev_scripts/sen15901rain.py b/dev_scripts/sen15901rain.py new file mode 100644 index 0000000..ed54189 --- /dev/null +++ b/dev_scripts/sen15901rain.py @@ -0,0 +1,26 @@ +from gpiozero import Button +import time + +rainCount = 0 +bucketSize = 0.2794 # size of bucket in ml +rain = Button(6) # setup GPIO 6 as a button + +# every tip add 1 to count +def tipped(): + global rainCount + rainCount +=1 + print (rainCount * bucketSize) + +def resetRainfall(): + global rainCount + rainCount = 0 + +rain.when_pressed = tipped + +""" +# test loop + +while True: + rain.when_pressed = tipped + time.sleep(1) +""" diff --git a/dev_scripts/sen15901vane.py b/dev_scripts/sen15901vane.py new file mode 100644 index 0000000..7c02723 --- /dev/null +++ b/dev_scripts/sen15901vane.py @@ -0,0 +1,95 @@ +from gpiozero import MCP3008 +import time +import math + +adc = MCP3008(channel=0) +count = 0 +""" +volts key pairs created with the below + known values from datasheet + # create voltage divider for use with MCP3008 ADC + def volt_div(r1, r2, vIn): + vOut = (vIn * r2)/(r1 + r2) + return round(vOut,3) + + # calculate vOut values for each wind direction using known resistances from datasheet, 3.3 V from RPi and 4.7K ohm resistor + + resistances = [33000, 6570, 8200, 891, 1000, 688, 2200, 1410, 390, 3140, 16000, 14120, 120000, 42120, 64900, 21880] + + for i in range(len(resistances)): + print(resistances[i],volt_div(4700, resistances[i], 3.3)) + +4.7K resistor +volts = {0.4: "0.0 N", + 1.4: "22.5 NNE", + 1.2: "45.0 NE", + 2.8: "67.5 ENE", + 2.7: "90.0 E", + 2.9: "112.5 ESE", + 2.2: "135.0 SE", + 2.5: "157.5 SSE", + 1.8: "180.0 S", + 2.0: "202.5 SSW", + 0.7: "225.0 SW", + 0.8: "247.5 WSW", + 0.1: "270.0 W", + 0.3: "292.5 WNW", + 0.2: "315.0 NW", + 0.6: "337.5 NNW"} +""" +# 5K resistor +volts = {1.87: 0.0, + 2.04: 22.5, + 0.79: 45.0, + 0.80: 45.0, + 0.88: 67.5, + 0.13: 90.0, + 0.36: 112.5, + 0.24: 135.0, + 0.62: 157.5, + 0.44: 180.0, + 1.44: 202.5, + 1.27: 225.0, + 2.81: 247.5, + 2.76: 270.0, + 2.91: 292.5, + 2.31: 315.0, + 2.59: 337.5} + +def getAverage(angles): + sinSum = 0.0 + cosSum = 0.0 + + for angle in angles: + r = math.radians(angle) + sinSum += math.sin(r) + cosSum += math.cos(r) + + flen = float(len(angles)) + s = sinSum / flen + c = cosSum / flen + arc = math.degrees(math.atan(s / c)) + average = 0.0 + + if s > 0 and c > 0: + average = arc + elif c <0: + average = arc + 180 + elif s < 0 and c > 0: + average = arc + 360 + + return 0.0 if average == 360 else average + +def getValue(length=5): + data = [] + startTime = time.time() + + while time.time() - startTime <= length: + wind = round(adc.value*3.3,2) + if not wind in volts: # keep only good measurements + print("Unknown value: " + str(wind)) + else: + data.append(volts[wind]) + + return getAverage(data) + +getValue() diff --git a/dev_scripts/sen15901vanelive.py b/dev_scripts/sen15901vanelive.py new file mode 100644 index 0000000..1c7c56e --- /dev/null +++ b/dev_scripts/sen15901vanelive.py @@ -0,0 +1,31 @@ +from gpiozero import MCP3008 +import time +import math + +adc = MCP3008(channel=0) +count = 0 + +# 5K resistor +volts = {1.87: 0.0, + 2.04: 22.5, + 0.79: 45.0, + 0.80: 45.0, + 0.88: 67.5, + 0.13: 90.0, + 0.36: 112.5, + 0.24: 135.0, + 0.62: 157.5, + 0.44: 180.0, + 1.44: 202.5, + 1.27: 225.0, + 2.81: 247.5, + 2.76: 270.0, + 2.91: 292.5, + 2.31: 315.0, + 2.59: 337.5} + + +while True: + wind = round(adc.value*3.3,2) + print(wind) + time.sleep(1) diff --git a/dev_scripts/vane_values.py b/dev_scripts/vane_values.py new file mode 100644 index 0000000..b6b6803 --- /dev/null +++ b/dev_scripts/vane_values.py @@ -0,0 +1,11 @@ +# create voltage divider for use with MCP3008 ADC +def volt_div(r1, r2, vIn): + vOut = (vIn * r2)/(r1 + r2) + return round(vOut,3) + +# calculate vOut values for each wind direction using known resistances from datasheet, 3.3 V from RPi and 4.7K ohm resistor + +resistances = [33000, 6570, 8200, 891, 1000, 688, 2200, 1410, 390, 3140, 16000, 14120, 120000, 42120, 64900, 21880] + +for i in range(len(resistances)): + print(resistances[i],volt_div(5000, resistances[i], 3.3)) diff --git a/weather_station.py b/weather_station.py new file mode 100644 index 0000000..986d6a5 --- /dev/null +++ b/weather_station.py @@ -0,0 +1,52 @@ +from gpiozero import Button +import time +import math +import statistics +import bme280_sensor +import wind_direction_byo +import ds18b20_therm + +anem = Button(5) # setup GPIO 5 as a button +storeSpeeds = [] +windCount = 0 # counts half-rotations +radius_cm = 9.0 # radius of anemometer +circumference_cm = (2 * math.pi) * radius_cm +windInterval = 5 # how often to report speed +cmInKm = 100000.0 +secsInHour = 3600 +anemFactor = 1.18 # anemometer factor is the result of wind energy lost due to the arms turning + +# every half rotation, add one to count +def spin(): + global windCount + windCount += 1 + +# calculate wind speed +def calculateSpeed(timeSec): + global windCount + global circumference_cm + rotations = windCount / 2.0 + + # calculate distance travelled by anemometer in km + distKm = circumference_cm * rotations / cmInKm + speed = ((distKm / timeSec) * secsInHour) * anemFactor + return speed + +def resetWind(): + global wind_count + wind_count = 0 + +anem.when_pressed = spin + +# Loop to measure wind speed and report at 5 second intervals +while True: + startTime = time.time() + while time.time() - startTime <= windInterval: + resetWind() # reset count for next 5 second run + time.sleep(windInterval) + #finalSpeed = calculateSpeed(windInterval) + storeSpeeds.append(calculate(windInterval)) # store average speed over 5 seconds + + windGust = max(storeSpeeds) # maximum gust + windSpeed = statistics.mean(storeSpeeds) # running average wind speed + print(windSpeed, "km/h", windGust, "km/h") -- cgit v1.2.3