
Building an IoT Weather Station with Zerynth and Ubidots
From the “Hello World” of the microcontroller to the edge of IoT, and beyond! In a few simple steps we’ll go from flashing an RGB LED on and off, to building a weather station sharing data over Wi-Fi in real time with an IoT platform.
In this workshop we will learn how to send weather data to the Ubidots cloud with XinaBox and Zerynth. We will use xChips IP01 (USB Programming Interface), CW02 (Wi-Fi & BLE Core), and SW01 (Advanced Weather Sensor). The xChip CW02 is Wi-Fi module based on ESP32 core, through which we can connect to the internet. The xChip SW01 can give us Temperature, Humidity and Barometric Pressure. Using these two xChips you will learn how to build your own Weather Station that can be used to monitor your environment. Finally, we use two xBus connectors to assemble our device.
Level 1: We begin by blinking the LED on the CW02, using threads to introduce multi-tasking.
Level 2: We’ll add the SW01 weather sensor and read data from that, which we’ll display on the Serial Monitor.
Level 3: Introduces the basic concepts of IoT - our SW01 weather sensor and CW02 become an edge device sharing data with the Ubidots IoT platform. What you learn will extend easily to using other xChips in the range.
Here are some tutorials if you want to extend your device:
- Controlling the XinaBox OC03 Relay Module in Python
- Build a Temperature Controlled Desk Fan in Python
- Introduction to XinaBox xChip AH01(ATECC508A) with Zerynth
- Remote Proximity Sensing with XinaBox, Zerynth and Ubidots
- Ambient Light Sensing with XinaBox, Zerynth and Ubidots
- Remote Gesture Sensing with XinaBox CW02-SL06 and Ubidots
- Make Your Remote Control with XinaBox, Zerynth and Ubidots
- Prototyping with WolkAbout IoT Platform, Zerynth and XinaBox
Level 1 - Blinker
1. Start Zerynth Studio
2. Create New Project and name it:
3. Select XinaBox CW02 (ESP32) from devices list:
4. Register your device by clicking on the Z button. Redeem your coupon by entering Zerynth license.
5. Click on Z button second time and Create New Virtual Machine (Select VM of latest patch).
6. Click on Z button third time and virtualize your device.
7. Let’s go!
#Add library to enable serial communication
import streams
streams.serial()
print("^_^ Welcome ^_^") #This should be displayed on Serial monitor
pinMode(D25, OUTPUT) #RED
pinMode(D26, OUTPUT) #GREEN
pinMode(D27, OUTPUT) #BLUE
#Function to blink RGB LEDs
def blink(pin, timeON=100, timeOFF=100):
while True:
digitalWrite(pin, HIGH)
sleep(timeON)
digitalWrite(pin, LOW)
sleep(timeOFF)
#Threads enables us to multi-task
thread(blink, D25,prio=PRIO_LOW)
thread(blink, D26, 200,prio=PRIO_LOW)
thread(blink, D27, 500, 200,prio=PRIO_LOW)
8. Compile
9. Upload
10. Result:
The threads work in a round-robin fashion, and the processor will give equal time to each thread, unless a priority is set.
Level 2 - I2C Communication
Now we add the xChip SW01. This weather station will provide Temperature, Humidity and Barometric Pressure readings.
PRO TIP: You can add other XinaBox xChips - such as a gesture sensor, capacitor touch input, particle sensor and many others. There is a full listing of supported xChips in the Zerynth catalogue.
Update the code from earlier with the additional items below:
# Enable Serial communication
import streams
streams.serial()
# Add the library needed to interface with xChip SW01
from xinabox.sw01 import sw01
print("^_^ Welcome ^_^") # This displays in the Console serial monitor
pinMode(D25, OUTPUT) # RED
pinMode(D26, OUTPUT) # GREEN
pinMode(D27, OUTPUT) # BLUE
# create an instance of the SW01:
SW01=sw01.SW01(I2C0)
# Function to get Weather Values
def weather():
while True:
TempC=SW01.getTempC()
Hum=SW01.getHumidity()
Pres=SW01.getPressure()
print("Temperature: ", TempC, "C")
print("Humidity: ", Hum, "%")
print("Pressure: ", Pres, "kPa")
sleep(1000)
#Function to Blink LEDs
def blink(pin, timeON=100, timeOFF=100):
while True:
digitalWrite(pin, HIGH)
sleep(timeON)
digitalWrite(pin, LOW)
sleep(timeOFF)
# Threads Enable us to multi-task
# Note we can set the priority of threads using “prio” parameter
thread(blink, D25,prio=PRIO_LOW)
thread(blink, D26, 200,prio=PRIO_LOW)
thread(blink, D27, 500, 200,prio=PRIO_LOW)
thread(weather,prio=PRIO_HIGH)
# We have set the weather function highest priority
You can set priorities for threads. The three colors on the RGB LED are given the same priority, but the weather sensor is given high priority.
Compile and load the program as before.
Result: Every second the microcontroller queries the SW01 for new Temperature, Humidity and Pressure values via the I2C bus and prints the result in the console.
Level 3 – Connecting to IoT Cloud
Next we will connect and transmit our Weather Station data to the Ubidots IoT cloud. Learn about Ubidots, and how to set up devices and dashboards here.
First we will add the helpers.py file to configure device to connect to Ubidots:
Helpers.py:
import json
def load_device_conf():
confstream = open("resource://device.conf.json")
conf=""
while True:
line=confstream.readline()
if not line:
break
conf += line
return json.loads(conf)
Enter the main code, put your Wi-Fi Credentials and Ubidots TOKEN where indicated:
#Add library to enable serial communication
import streams
#Add XinaBox SW01 library to get data from it
from xinabox.sw01 import sw01
#Add JSON library to interpret JSON data
import json
from wireless import wifi
# choose a wifi chip supporting secure sockets
from espressif.esp32net import esp32wifi as wifi_driver
# import ubidots iot module
from ubidots.iot import iot
# import helpers functions to easily device configuration
import helpers
streams.serial()
print("^_^ Welcome ^_^") #This should be displayed on Serial monitor
#SW01 instance
SW01=sw01.SW01(I2C0)
#Open Wi-Fi driver
wifi_driver.auto_init()
print('connecting to wifi...')
# place here your wifi configuration
wifi.link("SSID",wifi.WIFI_WPA2,"PSK")
print("Wi-Fi Connected")
#Callback functions is to execute when there is a change in variable
def callback(value):
global update
update=True #Variable to indicate change is made
print("updated")
#Put here your DEVICE_LABEL, ACCOUNT TYPE and Ubidots TOKEN
device = iot.Device('device_label', 'educational','api_token')
print('connecting to mqtt broker...')
device.mqtt.connect() #Connect to Ubidots over MQTT
#Specifying the variable to execute callback function when changed
device.on_variable_update('WeatherStation', 'temperature', callback, json=True)
device.mqtt.loop() #Keep device connected to Ubidots MQTT broker
update=False
while True:
#Keep sending messages until variable is updated
while not update:
TempC=SW01.getTempC() #Temperature in Celsius
Hum=SW01.getHumidity() #Humidity
Pres=SW01.getPressure() #Pressure in kPa
print("Temperature: ", TempC, "C")
print("Humidity: ", Hum, "%")
print("Pressure: ", Pres, "kPa")
device.publish({ 'value': TempC }, variable='temperature')
device.publish({ 'value': Hum }, variable='humidity')
device.publish({ 'value': Pres }, variable='pressure')
update=False
sleep(1000)
Compile and upload the code as before.
You can now see your Weather Station on the Ubidots Cloud.
Leave a comment