Skip to content

Commit

Permalink
Merge pull request #12 from aws/grafana_demo_updates
Browse files Browse the repository at this point in the history
Updated the weather station math to more closely match the Sparkfun reference code
  • Loading branch information
n9wxu authored May 16, 2022
2 parents 77214e9 + afb0ec4 commit 62bbbe2
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 34 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
90 changes: 56 additions & 34 deletions examples/python/sara_example/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,52 @@
from countio import Counter, Edge
from digitalio import DigitalInOut, Direction, Pull
from analogio import AnalogIn
from weather_station import weather_station

from expresslink import ExpressLink

time.sleep(2)
print("WeatherStation Startup")

def celsius2fahrenheit(celsius:float)->float:
return ((celsius * 9.0)/5.0) + 32.0

def GetVoltage(pin):
return (pin.value * 3.3) / 65536

# Resistor table
resistorTable = (('N',33000), ('NNE',6570), ('NE',8200), ('ENE',891), ('E',1000), ('ESE',688), ('SE',2200),('SSE',1410),('S',3900),('SSW',3140),('SW',16000),('WSW', 14120),('W',120000),('WNW',42120),('NW',64900), ('NNW', 21880))
resistorTable = ((0,33000), (22.5,6570), (45,8200), (67.5,891), (90,1000), (112.5,688), (135,2200),(157.5,1410),(180,3900),(202.5,3140),(225,16000),(247.5, 14120),(270,120000),(292.5,42120),(315,64900), (337.5, 21880))

# Compute correct Resistance
# Top resistor 10k
# Supply voltage is 3.3v
# R = (v * 10000)/(3.3-v)

def getDirection(pin)->str:
def getDirection(pin)->float:
v = GetVoltage(pin)
r = (v * 10000.0) / (3.3 - v)
smallestValue = 10000000
direction = ""
direction = 0.0
for entry in resistorTable:
distance = abs(r - entry[1])
if distance < smallestValue:
direction = entry[0]
smallestValue = distance
return direction

lastTime = 0
oldSpeed = 0
lastTime = time.time()
def getSpeed(pin:Counter)->float:
global lastTime, oldSpeed
global lastTime
thisTime = time.time()
deltaTime = thisTime - lastTime
if deltaTime > 10:
windCount = pin.count
pin.reset()
lastTime = thisTime
hz = windCount / deltaTime
oldSpeed = 2.4 * hz # km/hr
return oldSpeed

lastTip = 0
windSpeed = pin.count / deltaTime
pin.reset()
lastTime = thisTime
windSpeed *= 1.492
return windSpeed # return wind speed in mph

# todo: fix rain reset for 24 hours. use absolute time from expreslink
lastTip = time.time()
previousTipCount = 0
def getRainDepth(pin:Counter)->float:
global lastTip, previousTipCount
Expand All @@ -63,8 +65,9 @@ def getRainDepth(pin:Counter)->float:
pin.reset() # reset the count
previousTipCount = 0
tips = 0
return tips * 0.2794 # depth in mm
return ( tips * 0.2794 ) / 25.4 # depth in in

ws = weather_station()

windDirection = AnalogIn(board.A0)

Expand All @@ -75,6 +78,10 @@ def getRainDepth(pin:Counter)->float:

print("ExpressLink Started")

led = DigitalInOut(board.G10)
led.direction = Direction.OUTPUT


i2c = board.I2C()
bme680 = adafruit_bme680.Adafruit_BME680_I2C(i2c,debug=False)

Expand All @@ -89,22 +96,37 @@ def getRainDepth(pin:Counter)->float:
thingName = response[3:]
response = el.sendCommand("AT+CONF Topic1=/weather/sensor/" + thingName)

reportCounter = 60
while True:

if el.connect():
report = {}
report["temperature"] = bme680.temperature+temperature_offset
report["gas"] = bme680.gas
report["humidity"] = bme680.relative_humidity
report["pressure"] = bme680.pressure
report["wind direction"] = getDirection(windDirection)
report["wind speed"] = getSpeed(wind)
report["rain"] = getRainDepth(rain)
data = json.dumps(report)
print("Reporting : " + data)
el.sendCommand("AT+SEND1 " + data)
else:
print("No connection")
el.begin()

time.sleep(1)
led.value = True
reportCounter -= 1

ws.addWind(getSpeed(wind), getDirection(windDirection))

if reportCounter == 0:
if el.connect() and reportCounter == 0:
reportCounter = 60
report = {}
report["tempf"] = celsius2fahrenheit( bme680.temperature+temperature_offset )
report["humidity"] = bme680.relative_humidity
report["pressure"] = bme680.pressure
report["winddir"] = ws.windDirection
report["windspeedmph"] = ws.windSpeed
report["windgustmph"] = ws.windGust1minSpeed
report["windgustdir"] = ws.windGust1minDirection
report["windspdmph_avg2m"] = ws.wind2MinAverageMPH
report["winddir_avg2m"] = ws.wind2MinAverageDirection
report["windgustmph_10m"] = ws.wind10MinGustMPH
report["windgustdir_10m"] = ws.wind10MinGustDirection
report["dailyrainin"] = getRainDepth(rain)
data = json.dumps(report)
print("Reporting : " + data)
el.sendCommand("AT+SEND1 " + data)
else:
reportCounter = 2 # try again in 2 seconds
print("No connection")

# ensure the LED blink is noticable
time.sleep(.5)
led.value = False
time.sleep(.5)
80 changes: 80 additions & 0 deletions examples/python/sara_example/station_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from weather_station import weather_station
import random
import time

direction = [ 350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,350.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
]

ws= weather_station()

for d in direction:
ws.addWind( random.random() * 50.0, d )

print("gust speed " + str(ws.windGust1minSpeed))
print("gust direction " + str(ws.windGust1minDirection))
print("10 min gust speed " + str(ws.wind10MinGustMPH))
print("10 min gust direction " + str(ws.wind10MinGustDirection))
95 changes: 95 additions & 0 deletions examples/python/sara_example/weather_station.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import time

class weather_station:
windGust1minSpeed:float
windGust1minDirection:float
windDataSpeed = []
windDataDirection = []
windGust = []
gustDataCounter:int
windDataCounter:int

# report this information
windSpeed:float
windDirection:float
wind2MinAverageMPH:float
wind2MinAverageDirection:float
wind10MinGustMPH:float
wind10MinGustDirection:float

def __init__(self):
print("starting weather station")
self.windGust1minSpeed = 0.0
self.gustDataCounter = 60
self.windDataCounter = 120
self.windGust1minDirection = 0.0
self.windGust1minSpeed = 0.0
self.wind2MinAverageMPH = 0.0
self.wind2MinAverageDirection = 0.0
self.wind10MinGustDirection = 0.0
self.wind10MinGustMPH = 0.0
self.windSpeed = 0.0
self.windDirection = 0.0

# run every 1 minute assumes it is called every second
def _doGusts(self, speed: float, direction:float):
self.gustDataCounter -= 1
if speed > self.windGust1minSpeed:
self.windGust1minSpeed = speed
self.windGust1minDirection = direction

if self.gustDataCounter == 0:
self.gustDataCounter = 60
# update the 10 minute wind gust statistics every minute
gdata = (self.windGust1minSpeed, self.windGust1minDirection)
self.windGust.append( gdata )
self.windGust1minSpeed = 0
while len(self.windGust) > 10: # ensure we only have 10 minutes of data
self.windGust.pop(0)
gust = (0.0,0.0)
for g in self.windGust:
if g[0] > gust[0]:
gust = g
self.wind10MinGustMPH = gust[0]
self.wind10MinGustDirection = gust[1]

def addWind(self, speed: float , direction:float):
self.windDataCounter -= 1
self.windSpeed = speed
self.windDirection = direction
self.windDataSpeed.append( speed )
self.windDataDirection.append( direction )

self._doGusts(speed,direction)

if self.windDataCounter == 0:
self.windDataCounter = 120
# time to compute wind statistics (every 2 minutes)
self._calcWeather()
self.windDataDirection.clear()
self.windDataSpeed.clear()

def _addDirection(self, direction1:float, direction2:float )->float:
delta = direction1 - direction2
if delta < -180.0:
return delta + 360
elif delta > 180.0:
return delta - 360
else:
return delta

def _calcWeather(self):
speedAverage = 0
for w in self.windDataSpeed:
speedAverage += w
self.wind2MinAverageMPH = speedAverage / len(self.windDataSpeed)

sum = self.windDataDirection[0]
D = self.windDataDirection[0]
for d in self.windDataDirection[1:]:
D += self._addDirection(d, D)
sum += D
self.wind2MinAverageDirection = sum / len(self.windDataDirection)



0 comments on commit 62bbbe2

Please sign in to comment.