# Weather station with pysense sensors
By Andreas Bergsten (ab226ep)
This tutorial will show how I got started with IoT by making a simple weatherstation using a FiPy and a Pysense board. Since there is not much wiering to be done in this projekt it can likely be done in around 4 hours or less by following this guide. The thing that takes the most time is flashing the hardware and setting up the programming enviroment. After that it is mostely writing a program and setting up a webservice where you can view your gathered data.
## Objective
I had originally another project in mind where I would use the accelerometer together with the light sensor to monitor if somone passed through a door and turned the light on inside a cellar room that is used as a gaming club. But it turned out that the only way to get a signal down there was through LTE and that solution didn't really fit. So I decided to do something simpler first.
My house is placed in such a way that it is hard to get an accurate temperaure reading on the front side of the house. Firstly beacuse I cant really hide it from the morning sun or that it will get a lot of ambient heat from the house itself giving improper readings. The best place to put a sensor would be on the backside of the house but that means that it will be hard to see a regular temperature gauge. So by sending the data to a website I can still look at the temperature outside from my breakfast table just using my phone. I had no prior experience with sensors and IoT so I expected to learn a lot from this project. Some of the questions I had from the start was:
* How do you read sensor data?
* What kind of sensors is there?
* How do you send data remotely?
* Where should the data be collected to be able to be shown?
* How to visualize the data?
So I had a lot of questions that I wanted answers to.
## Material
I ordered a starterkit from electrokit.com that included the fipy and a selection of sensors as well as other things that was needed to test different things and solutions like wires, a breadboard and antenaes (Elektrokit art.no: 41019065, price 1499.00 SKr.). I was originally going to use sensor parts and connect them to a pycom expansion board. But the supplier ran out of expansionboards so we got the Pysense board instead. This Pysense have all the sensors needed for this application allready integrated into the board so there is no need to add any external sensors or connecting cables.
So the parts you will need for this project is:
| Item | Description |
| -------- | -------- |
| Fipy 1.0 | Programmable development platform that contains ability to connect to several different newtworks; WiFi, LTE, LoRa e.t.c. |
| Pysense 2.0 | Development board with built in sensors for humidity, temperature, light, pressure and an accelerometer. You can also attach more sensors if needed. |
| Powersupply | Either with batteries or through a micro-USB connection to a powersupply |
I had not thought of getting a battery to use as a powersupply so I just used an old phone charger. This works for me since it will be used close to the house. But I will likely order som batteries later to reduce the need of cables.
## Computer setup
The first thing that you must do before writig and sending your program to the pycom device is to flash it. You do this to ensure that the hardware is running on firmware that is up to date. For this project there are two things that need to be flashed, the Fipy and the Pysense. These two need different approaches to make work. After that you need to get your programming enviroment to work so that it can connect to your device. I will go through each process step by step.
### Update FiPy
In order to update your FiPy you need to first connect it to your Pysense. Connect it so that the LED light is towards the micro-USB port. Then do the following steps:
* Connect the device with a USB to micro-USB cable to your computer.
* Download the [Windows Pycom update tool](https://software.pycom.io/findupgrade?product=pycom-firmware-updater&type=all&platform=win32&redirect=true).
* Before running the installer make sure that any other program that might be connected to your Pycom device is closed. This might otherwise interfere with the update procedure that follows.
* Install the update tool and run it.
* Press **Continue** until you reach the **Communications** page where you do the following:
* Port: Choose the USB-port on your computer that the device is connected to (if unsure you can check your windows device manager and see which port that is activated when you plug in your USB-device).
* Checkmark the 'High speed transfer' and 'Show Advanced Settings' checkboxes.
* Type: Choose **development**
* Then press **Continue**
* Now You should be on the **Advanced Settings** page and you need to apply the following settings:
* Information: Device Type: **FiPy**
* Type / Version: **development** and the latest version.
* File System: **FatFS** and check **Erase during update**
* Leave the other fields empty. I didn't bother with LoRa region since I didnt have any coverage where I live.
* Press **Continue**
* Now you should be in the **Results** page. Hopefully you will see that your FiPy has been successfully updated.
With that your FiPy is done. Make sure you close the Update Tool as it might otherwise cause connection problems with Atom later.
### Update Pysense
To use the sensors on the pysense I had to upgrade the firmware to do that do the following:
* Unconnect your Pysense from your computer.
* If your FiPy is connected you should carefully remove it so that you are only left with the Pysense.
* Download the latest DFU (Device Firmware Upgrade) file for Pysense 2 [right here](https://software.pycom.io/findupgrade?key=pysense2.dfu&type=all&redirect=true)
* Download and install [dfu-util-0.9](http://dfu-util.sourceforge.net/releases/dfu-util-0.9-win64.zip). It is an installation manager that you run from the command prompt in Windows.
* Move the DFU-file that you downloaded in the first step and place it in the same directory that you installed the dfu-util-0.9 installation manager.
* Open the Command Manager (CMD) in Windows.
* In the Command manager navigate to the folder where you installed the dfu-util. Use `cd <path>` to change directory and once you are there try typing `dfu-util.exe`. If you get a message with all the options listed, you know you are in the right place. Type `dir` to make sure that the DFU-file, In my case *pysense2_v16.dfu*, is locted in that directory.
* Try typing `dfu-util-static.exe -D pysense2_v16.dfu` and you should get a message ending with something like
`Match vendor ID from file: 04d8`
`Match product ID from file: f011`
`No DFU capable USB device available`
If you do then you are ready for the next step.
* The Pysense-board need to be manually put into update-mode.
* With the Pysense disconected from the computer, **press and hold** the button on the Pysense called *MCLR*, it is located in the middle of the right side of the board (If you hold it so that the USB faces up).
* Plug in the USB-cable and connect it with the computer while still pressing the button.
* After about 1 second release the button. You are now in DFU-mode for about 7 seconds.
* While still in DFU-mode you need to run the `dfu-util-static.exe -D pysense2_v16.dfu` command from the command prompt. If you get a message looking somthing like this:
> Match vendor ID from file: 04d8
> Match product ID from file: f014
> Opening DFU capable USB device...
> ID 04d8:f014
> Run-time device DFU version 0100
> Claiming USB DFU Runtime Interface...
> Determining device status: state = dfuIDLE, status = 0
> dfu-util: WARNING: Runtime device already in DFU state ?!?
> Claiming USB DFU Interface...
> Setting Alternate Setting #0 ...
> Determining device status: state = dfuIDLE, status = 0
> dfuIDLE, continuing
> DFU mode device DFU version 0100
> Device returned transfer size 64
> Copying data from PC to DFU device
> Download [=========================] 100% 16384 bytes
> Download done.
> state(2) = dfuIDLE, status(0) = No error condition is present
> Done!
Then you are done!
* You can now disconnect the Pysense from your computer and reattach your FiPy.
### Install Atom and packages
In order to program your device you need an IDE (Integrated Development Enviroment) that can handle Python. FiPy can interpet pyton sourcecode without it needing to be pre compiled first through its own micropython interpeter. So for this project you need a code editor that can connect to the Pysense and update the FiPy through a USB-cable.
I choose **Atom** (https://atom.io/) for this project. I have previously used Thonny but after trying Atom it felt a little bit better so I decided to try it out.
In order to get all utility out of Atom you need to install **node.js** first. This is needed to install certain additions to Atom called packages. You can find an installer for node.js [here](https://nodejs.org/en/download/current/).
After installing Atom and node.js you can start atom and then install a package called **pymakr**, this will give you tools to easily connect and upload code to your pycom device.
* You can install packages from the *Welcome Guide*.
* If you can't se it you can find it from the menu bar by choosing 'help' and 'Welcome Guide'.
* In the Welcome Guide there is an option to *Install a Package* choose that and then press 'Open Installer'.
* Search for *pymakr* and install it.
* pymakr will add a REPL console to Atom that will allow it too connect and run code on your pycom devices.
#### Uploading and running code on FiPy
When all hardware is upgraded and Atom is installed with the pymakr package you can try and run a testcode just to verify that you can connect properly to your device.
* In Atom, on the left side there is a project bar, *right click* your mouse and choose `Add Project Folder` then choose or create a folder that will contain your files.
* Once you have a project folder *right click* on that folder and choose `New File`. Name your file **main.py** since that filename will be a default starting file when the Pycom device is started.
* You should now get a tab with that filename where you can start writing code. The following code can be used to check that you are able to connect and upload code to your Pycom device:
```python=
import pycom # Import pycom to control the built in LED on Pysense
import time # Import time to make the device sleep
# Disable LED heartbeat because we will change it manually.
pycom.heartbeat(False)
# This loop will change the color of the LED and wait a short while
while True:
pycom.rgbled(0xFFFF00) # Yellow
time.sleep(1)
pycom.rgbled(0xFF00FF) # Pink
time.sleep(1)
pycom.rgbled(0x00FFFF) # Cyan
time.sleep(1)
```
* Once the code is typed in, don´t forget to **save** your file before moving on.
* In order to upload this file to your FiPi you will need to connect the FiPy to the Pysense and then connect the Pysense to your computer. Here it is a good idea to make sure that you use the same USB port as when you flashed your FiPy.
* The REPL-console that you got when installing pymakr should be located in the lower part on your Atom screen. In the top of that window you have a menubar that shows your project and connected device. Make sure your project folder's name is choosen, and that you are trying to connect to the right USB-port.
* On the left side of the REPL-console there are buttons to *Connect/Disconnect*, *Play*, *Upload*, *Download* and *Get device info*. To upload your file press the **Upload** button.
* Your file should now be uploaded to your FiPy and it should automaticly run. The LED on the device should now switch between Yellow, Pink and Cyan with about 1 second interval.
Now your Atom environment should be set up and working. If you still have problems connecting and uploading check that you have chosen the right project folder, that the filename is main.py and located in the correct folder, and that you have connected the Pysense board to the same USB-port that you used when fashing the device. Then try again.
## Putting everything together.
Since this project does not contain any exterior sensors there is really not much connecting needed. Just mount the FiPy on the Pysense and attach a powersupply and you are done.
## Platform
This Weather Station will just be close to my house so will communicate through WiFi and then send the data to Datacake through their inbuilt MQTT-broker. Datacake is a cloud service that will host my sensor readings and also be able to display them through a nice interface. I am using Datacakes free plan that will allow me to keep my data for seven days as well as adding up to 500 datapoints each day. This is enough for this project, but Datacake gives me room to expand for a small fee if more data or longer data retention time is needed in the future.
## The Code and transmitting data
The code consists of three distinkt parts. The first is to get the device connected to the Wifi, the second part is to make sure you can read the sensor data, then the third part is customisation of the sensor data and uploading it to Datacake. The code can be divided up into different python files, this makes it a bit easier to read. When the Pycom device is started it will first look for a file named boot.py and run that. After that file is done it will automatically run main.py, this is the main program file. But you can also from main.py choose to run other files or import those files to run functions located in those files.
### Connecting to WiFi
The connection to the WiFi is something that should normaly just happen once and then not be run again. So this code is best located in the boot.py file. In order to connect to WiFi you need the name of the WiFi you are connecting to as well as the password. Just change those in the following code to make it work:
```python=
import network
import time
# setup as a station
wlan = network.WLAN(mode=network.WLAN.STA)
wlan.connect('yourWiFiName', auth=(network.WLAN.WPA2, 'YourPassword'))
while not wlan.isconnected():
time.sleep_ms(50)
print(wlan.ifconfig())
print("Connected to WiFi!")
```
Once you see the printout "Connected to WiFi" in the console you are connected. Once the boot.py file has come to it´s end main.py will start automaticly.
### Sensors
To get the sensors built in to the Pysense board to work you need to first find the correct drivers for these sensors. We can find these at [the Pycom website](https://github.com/pycom/pycom-libraries/releases/). These driver files are just python files that you need to add to your project directory.

The blue marked files in the image above are placed in a lib-folder that will contain all sensor files. I added all but the three-axis linear accelerometer LIS2HH12 and Lightsensor LTR329ALS01 are not used in this project. These files contains functions that lets us retrieve the data we want to get from the sensors.
### Sending data
In order to send data from your Pycom device you need som kind of protocol to handle this. MQTT is a lighteight protocol that can handle this efficiently. In order to make your device a MQTT client you need to add the [mqtt.py file](https://github.com/pycom/pycom-libraries/tree/master/lib/mqtt). This contains a class that you can use to connect to a MQTT-broker. You can add this in the lib-folder or just beside your main.py file in your project folder.
### Connecting the dots
Finaly we need to make all our custom settings, read the sensor data and make sure we send them to the MQTT-broker. This is done in the main.py file:
```python=
from mqtt import MQTTClient #To connect to datacake
import time # To be able to sleep
from pycoproc_2 import Pycoproc # To read from correct ports to get sensor data.
from SI7006A20 import SI7006A20 # Humidity and temperature sensor.
from MPL3115A2 import MPL3115A2,PRESSURE # Barometric pressure and temperature sensor.
def sub_cb(topic, msg):
print(msg)
# MQTT Setup (Use your own serialnumber, user, password)
client = MQTTClient('serialNumber',
'mqtt.datacake.co',
user='user',
password='password',
port=1883)
client.set_callback(sub_cb)
client.connect()
print('Connected by MQTT-datacake')
# Starting sensors
py = Pycoproc()
mpp = MPL3115A2(py,mode=PRESSURE) # Returns pressure in Pa.
si = SI7006A20(py)
#Send data to 🍰 Datacake
my_topic_temp = "dtck-pub/pysense-wifi/855d7098-2cb8-4b80-b486-0e18cabfaafe/TEMPERATURE"
my_topic_humidity = "dtck-pub/pysense-wifi/855d7098-2cb8-4b80-b486-0e18cabfaafe/HUMIDITY"
my_topic_pressure = "dtck-pub/pysense-wifi/855d7098-2cb8-4b80-b486-0e18cabfaafe/PRESSURE"
while True:
temp2 = mpp.temperature() # This temperature value is from MPL3115A2 and not used.
temp = si.temperature() # Temperature
humidity = si.humidity() #Humidity
pressure = mpp.pressure()/100 # Pressure from sensor is in Pa but I want it in hPa
print("+---+---+---+---+---+---+---+---+",temp2)
print("| Temp: ",temp, "deg C","\t|",)
print("| Humidity: ",humidity, "%RH","\t|")
print("| Pressure:",pressure,"hPa","\t|")
client.publish(topic=my_topic_temp, msg=str(temp))
client.publish(topic=my_topic_humidity, msg=str(humidity))
client.publish(topic=my_topic_pressure, msg=str(pressure))
time.sleep(600) # wait 10 min
```
The first lines are there to import the needed libraries. Client data is setup so that Datacakes MQTT-broker knows who is sending the data. Here you need to add your own data that you get when creating an account at Datacake. Once the connection is setup the sensors are defined. Once that is done I am setting up the topics that I want to send my data to in order to ensure that the correct values goes into the correct data-tables at Datacake. The while loop reads the sensor data, proints it to the console and sends it to the MQTT-broker. When everything is done it waits for 10 minutes then repeats reading and sending the sensors data.
As you can see in the code I have divided the pressure with 100. That is because the sensor reads the data in Pa but I want the value in hPa since that is the normal unit used for checking air pressure.
I had problems getting the correct temperature readings. The value was always higher than it should be. This was true for both temperature sensors. I did try to find a formula to get the values closer to what I could meassure with my old indoors termometer. But I could not find any good corrolation values. So I just left it as it was to get som nice curves in my charts. A close approximate value was to multiply the temperature with 0.78 but that still was not good enough as the temperature rose. I think it might be that the board itself gives off some heat when it is connected to the powersupply. I will continue to experiment with this though.
## Presenting the data
I built two dashboards in Datacake. One for desktop and one mobile version.


The data presented are the things I am measuring. Since the free version of Datacake only allows me to keep one week of data there is no use to show any longer periods in the charts. I put the humidity and pressure in the same chart because I wanted to see how they matched. Usually when we have high pressure the weather is nice and dry and onse the pressure drops it will rain and be more damp in the air. It kind of showed that... but not really, more datapoints are needed. :wink:
The data should be updated once every 10 minutes, but I had some problems with the device crashing after a while so there are a lot of "flat" areas in the graph where the device stopped working and just stayed on the last value. I have tried to figure out these crashes but all I can see is that it has something with the mqtt.py file to do. It is like there is some problem connecting with the right socket. Further investigation might be needed.
## Final

My project is not very visual in its appearence. The Pysense and FiPy is just connected together and then there is a USB cable that is used as a powersupply. I wanted to make something better but since I was very new to both sensors and small devices I really had no idea what to get before I started this project. Another problem was that the hardware showed up late so I had a bit of panik at the start. I was hoping to be able to use LoRa, but there was no LoRa gateways in my area. So after a few changes to the plans this was what I ended up with.
I would have like to experiment a little more with sensors. I did connect a few sensors with the breadboard during the course and that was fun. That is most likely something I will continue to try out.
I hope you could follow my ranting in this "tutorial". :laughing: