Skip to content

Commit

Permalink
First working version of the Cellular ExpressLink WeatherStation
Browse files Browse the repository at this point in the history
  • Loading branch information
n9wxu committed Apr 29, 2022
1 parent 27ae375 commit fe877a2
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 0 deletions.
110 changes: 110 additions & 0 deletions examples/python/sara_example/code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import json
import time
import board
import adafruit_bme680
import busio
from countio import Counter, Edge
from digitalio import DigitalInOut, Direction, Pull
from analogio import AnalogIn

from expresslink import ExpressLink

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

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))

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

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

lastTime = 0
oldSpeed = 0
def getSpeed(pin:Counter)->float:
global lastTime, oldSpeed
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
previousTipCount = 0
def getRainDepth(pin:Counter)->float:
global lastTip, previousTipCount
now = time.time()
tips = pin.count
if previousTipCount != tips:
lastTip = now
previousTipCount = tips
else:
if now - lastTip > (24*3600): # if there are no tips for 24 hours,
pin.reset() # reset the count
previousTipCount = 0
tips = 0
return tips * 0.2794 # depth in mm


windDirection = AnalogIn(board.A0)

uart = busio.UART(board.UART_TX1, board.UART_RX1, baudrate=115200, timeout=30)
el = ExpressLink(uart, DigitalInOut(board.G5), DigitalInOut(board.G2), DigitalInOut(board.G6) )

el.begin()

print("ExpressLink Started")

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

temperature_offset=-5

rain = Counter(board.D1, edge=Edge.FALL, pull=Pull.UP)
rain.reset()
wind = Counter(board.PWM0, edge=Edge.FALL, pull=Pull.UP)
wind.reset()

response = el.sendCommand('AT+CONF? ThingName')
thingName = response[3:]
response = el.sendCommand("AT+CONF Topic1=weather/sensor/" + thingName)

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)
79 changes: 79 additions & 0 deletions examples/python/sara_example/expresslink.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import busio
import time
from digitalio import DigitalInOut, Direction, Pull

class ExpressLink:
event_pin:DigitalInOut # change to be an input pin with a callback
powerOn_pin:DigitalInOut
powerCheck_pin:DigitalInOut
_connected:bool
port:serial

def __init__(self, port, event, powerOn, powerCheck):
self.port = port
self.event_pin = event
self.powerOn_pin = powerOn
self.powerCheck_pin = powerCheck
self.event_pin.direction = Direction.INPUT
self.powerCheck_pin.direction = Direction.INPUT
self.powerOn_pin.direction = Direction.OUTPUT
self.powerOn_pin.value = False

# This function relies upon the SARA_ON signal to work
def _powerOn(self)->bool:
while self.powerCheck_pin.value == True:
self.powerOn_pin.value = True
time.sleep(.50)
self.powerOn_pin.value = False
time.sleep(.1)
print("ExpressLink Powered")
return True

def _comCheck(self)->bool:
print("Checking Communications")
response = ""
while response.find("OK") != 0:
time.sleep(.5)
response = self.sendCommand("AT")
return True

def begin(self):
self._connected = False
self._powerOn()
self._comCheck()
print("ExpressLink Up")

def connect(self)->bool:
response = self.sendCommand("AT+CONNECT?")
print("connect_check : " + response)
code = response.find("OK 1")
if code == -1:
self._connected = False
response = self.sendCommand("AT+CONNECT")
print("connect:"+response)
if self.checkResponse(response) == 0:
self._connected = True
else:
self._connected = True
return self._connected

def sendCommand(self, command:str)->str:
command += '\n'
self.port.write(command.encode("utf-8"))
time.sleep(1)
response = self.port.readline()
if response != None:
return response.decode("utf-8")
else:
return ""

def checkResponse(self, response:str)->int:
if response.find("OK") == 0:
return 0
else:
if response.find("ERR") == 0:
return int(response[3:])
else:
return -1


24 changes: 24 additions & 0 deletions examples/python/sara_example/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# U-Blox SARA R5 ExpressLink CircuitPython Demo

# ExpressLink Configuration
Execute manual steps in the expresslink getting started guide to get the Ublox ExpressLink connected to your AWS account.

# HW Configuration
The SARA R5 ExpressLink board must be configured to enable the power state feedback. This signal is labeled SARA_ON on the schematic.
On the back of the board, you must apply a solder blob to the two pads labeled SARA_ON to connect that signal to G6 on the micromod.

The tipping bucket is connected to signal D1 on the right side of the expresslink board.
The wind speed is connected to signal PWM0 on the right side of the expresslink board.
The wind direction is connected to signal A1 on the right side of the expresslink board.
The wind direction is also connected to 3.3v via a 10k resistor. I was able to bridge A1 to the QWICC 3v3 pin with a surface mount resistor and a bit of wire.

Attach the QWICC BME680 cable between the BME680 and the ExpressLink bkard.

# SW Configuration
Install the CircuitPython image from this location: https://circuitpython.org/board/sparkfun_micromod_rp2040/

Install the BME680 CircuitPython library from this location: https://github.com/adafruit/Adafruit_CircuitPython_BME680
The BME680 library can be simply copied into the LIB folder present on the CIRCUITPY filesystem after the CircuitPython image is installed.
Connect a USB cable to the board and open a terminal. 115200 8N1
copy expresslink.py and code.py into the CIRCUITPY filesystem and watch the data.

0 comments on commit fe877a2

Please sign in to comment.