From afb0ec4bf9b06382d118d9e67a4504c28a05e636 Mon Sep 17 00:00:00 2001 From: Joseph Julicher Date: Tue, 3 May 2022 06:21:42 -0700 Subject: [PATCH] Updated the reconnection strategy --- .../weather_station.cpython-39.pyc | Bin 0 -> 2363 bytes .../__pycache__/expresslink.cpython-39.pyc | Bin 0 -> 1911 bytes .../weather_station.cpython-39.pyc | Bin 0 -> 2383 bytes examples/python/sara_example/code.py | 90 ++++++++++------- examples/python/sara_example/station_test.py | 80 +++++++++++++++ .../python/sara_example/weather_station.py | 95 ++++++++++++++++++ 6 files changed, 231 insertions(+), 34 deletions(-) create mode 100644 examples/__pycache__/weather_station.cpython-39.pyc create mode 100644 examples/python/sara_example/__pycache__/expresslink.cpython-39.pyc create mode 100644 examples/python/sara_example/__pycache__/weather_station.cpython-39.pyc create mode 100644 examples/python/sara_example/station_test.py create mode 100644 examples/python/sara_example/weather_station.py diff --git a/examples/__pycache__/weather_station.cpython-39.pyc b/examples/__pycache__/weather_station.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c80ff9b12bc445cac1413710b16d53c0ae56615a GIT binary patch literal 2363 zcmZuyTWj1#6rRyYd-JYu@nzkljY|{SeP|r#rF}51OAHC6Spp^mwiKc6jBTy8+Vw~q zyG9EIr~e`kaUTkW{)qmLdF?~-Unms%osqmO6t9^S7fy#uzRz0j71mk1OLY2iA?#u#e}E_kYu0gI zFeQ{L`A$ANJM55kJd6@XSyiwmutu|6*m%WUD&}%ASBkk>%(WdR=Vbjg>s0X#AscTT zIWHGpyPeuZUX)9a=SYUd@*5#<$rWhoa#gNjXG5;zMoqJDs)F=LX+KGWG#tcc^)!s- zlTngx_rv(P3Xb=ON=dUZtKJK>>e?L(hp^rY(%|u66sJnVCtOS`s-(#MH0;`B?=p#x zo`vx@uapiB)wAbMO>;)~|CbhNW&0t_>40Rrc0)6<>~cin`XS!Ic#M&J1d<}e7n~!& z8S}XmppJAwg=7H5Yo9lPhEBuyaI=7Cvw-JsY`4$V4yLO!kd|w_p$_9zQyyuLNQv~^ zxQU7merI|a;y>SQy-1W!wtBr$6n2lc_6FTiU&U#%bvn?;_|{f9NIzF+L#>h|3ghD~ zbr$r8k%Ga^7(E#NWGcQN#$oFFx8OUefG}R+CA{a&S@UbtmSeocMzbofBhaNoUq5tq zN@k1HZ(uTrJ)rd^0Q6bLGuGqBuD(Z{&ojag0~XG)qkpwXVoy)J1)4pwb`G4&3DT)Y zYZqL)@X@n&C27}B+R_^%4n48QerS%}%$3dt%LGx_rkOhyCuuI@n`Lku>&&m%h?Uw` z6l875Jh&?=_?Dv^q$Sd-=7F&xqAQvTWe%m0DFwr!ilq^eij5c!hI)>+)oGijmxx~_ zvIf#|DcKD_v@y*IMF8=T1M+5jNU{kP#%-UFa6U*WMSW!o`i4(1|B8 zc?IF!m`p{2kmrOru=K!NbTjt0gortpj@9SU(s{JfvUI5yU{kqd#lC96iMN(3szR^h z>p8{?;5yZA5OqgUkg8VAX1p$w0p+5}%N#wyR=uXiYL*CbY73Jx)l`jokrwMdd3%{B zy79V^3Uo`%pg#+GIgs)toIZeuqzOWpQw`L4-KksLE2s)!y*^tL#m<&6wMi{(Pw|gT zNvm|E;~T-CKulW6LkI+GlOc7HkjG3nDMi=OL@)~^?q?)7t-Oyv3;jddhjdQ%^TD6t z5%Tp~+O>CUx%rLn!9w2$>3C8_=ta~)rn0T!AE8amg2vW1)`#~HJ@}Fzs`}uV?@nyXMVg&s-=p=b9d_tVP z9UXJ(=r#eU(`d>+Y6=M@NzKOF#VuUooJstNFE6evE-hE>4)lIE4g1Op@AGRaJNZq% LqAr@yS1Qhb-KG_* literal 0 HcmV?d00001 diff --git a/examples/python/sara_example/__pycache__/expresslink.cpython-39.pyc b/examples/python/sara_example/__pycache__/expresslink.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7dbdbc0ef5070484f1f0946ace78e7b9aa7295ea GIT binary patch literal 1911 zcmZuy&u<$=6rR~%-mLBXZc70ngbv-qLW4)B@e7js{ic!h>T(G|L zh)Gv^f^XElGwWUSKE^%t0eXLfi9j??Sid1cv4B35zKC9M(G;x{ufHH88Hx4_M=XjZ z#7)GmSVp`eRuQ+vnpnqMZE+1dyl$HJpNy2Os&BGlV8WwhAmdS1m<9P*7P@vZEo(Q5 z)3PXJs--aAs8l-j=Wvnl;Mu}cy$v(vQx>zS1Iwo#tTT0CUBU2a-s^a(fh==15Iu9ID1m{a?rJ)7S2N)q zV_thxe$0iBnR_CjnIfor@Zth@OvGdW^cCUATYiD!fZ9jbXRCIxi3m%;jbNe(qwF52mVOb6e}YE%}L?6{T<6GB6Fz<6mXI6aHKLVO&|+`(g(Cepnx$VB#q24tGDn; z^#&PI@thXc5t1%v!d?Z!h)-_JBl-^be;ClYh*oVs;wLa7&VU7=KwZg2mm^3MTPbX>9|rv2~|q{DJCzk6kCN?uasF@ud_(kP>~E}9GfVPhouweP8fvk#ny7L94N|x;7Cq26EyI;)l9fiBe+ZFP?2!3obxa4 C*QXo+ literal 0 HcmV?d00001 diff --git a/examples/python/sara_example/__pycache__/weather_station.cpython-39.pyc b/examples/python/sara_example/__pycache__/weather_station.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2fc3730f3ed8783db141538db0fd0dbb120319b0 GIT binary patch literal 2383 zcmZuy-EJF26rS1Hb=HoZzcz_OTL@4DMgljzfs3drG*S_$79y%DSwhR=nI!AjYiD*% z(r6v1k{cvYAA;wYTP{#ufh)cw0>WdA$DC;bQ;C`n*~Ih1w{YgDEnM*W4b;8X?VsP>L^Y%<&yS@l!#Dj zG`MjS)!X}n=@p3o{?vS)D4jIB-BB;<95iSU-@lJuhZ zu&GYM{;;Q#=I~{DFo>H;sKcO8HfI9(`S7LjgCL5dGzf0vzN8AmxX(+)ds?5}GB$5G z#!GC-%W@p54tX?w$R~2iLi#6|3}P3sehH)lmhp^r`Jt=t6BqD|fX0A@bLi;bE#%nK zB|B%&IYS7#;?m8;)g&ybN4j$^U7Qo!^^$aG{pbhjogrLZvBQ3>pLv-loeh>DY#R)= zCmB|cPI4Ld&Vl1tXMry%q@~t1WrVh50o*lpg@&VRq$ScQ=aI89BsYyuX+}9`O5t#* zVrfKA#YPMVLyb1EQpVlJ|Vh3TL#6x zhA@>$`fp9~4^2s{bfn`OkQ3aKHuC@ifmdh9Z6Wy~({;?wIx-NmK%Ra=a^1?i_}kEb zrL|9A$$s7YD>^`Wj-|)evxb}ddmk41BapTyRS&(1n#ojF)dGC~1i!DbIH`Oe)sNRX zy*KOfjXgKICq<2hE%gkHPHbI8dr*cm^nWIVO{bAE@4jmjO4Zx8@u&K50x zr|dVBD)!$+@j{1;!+b^OpaoOs5-rmEc?+_^y*(CBY z5nIxEJ+`a1l@&i2!;g(fMt#F~43{(5>G!esJB)-HCbMOS!b7T5_zDUT$#VA%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: @@ -35,21 +39,19 @@ def getDirection(pin)->str: 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 @@ -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) @@ -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) @@ -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) \ No newline at end of file + 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) \ No newline at end of file diff --git a/examples/python/sara_example/station_test.py b/examples/python/sara_example/station_test.py new file mode 100644 index 0000000..2a22ed9 --- /dev/null +++ b/examples/python/sara_example/station_test.py @@ -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)) diff --git a/examples/python/sara_example/weather_station.py b/examples/python/sara_example/weather_station.py new file mode 100644 index 0000000..243be87 --- /dev/null +++ b/examples/python/sara_example/weather_station.py @@ -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) + + +