Welcome to our IoT session at Data Science Africe 2017! If you have any questions, please just give a shout. We are here to help.
Over the next two days we'll be diving into the Internet of Things by building some smar devices, introducing you to:
- Sensors and actuators.
- Connecting devices to the internet.
- Interacting with devices through the mbed Device Connector API.
- Using Python to retrieve data from these devices.
- Visualizing data.
We will demonstrate everything on stage, but in case you're stuck this document will help you get back on track. We've also listed some additional excercises if you want a challenge.
If you happen to be much faster than everyone else, help your neighbors.
You should have:
- A development board (NUCLEO-F401RE or NUCLEO-F411RE).
- A USB cable.
- Some jumper wires.
- A WiFi chip.
- A soil moisture sensor.
- An accelerometer.
- A temperature sensor.
We need to install a few pieces of software that we'll be using.
On your computer:
- Install a recent version of node.js (4.x or higher).
- Download the source code for this workshop from here - and unpack in a convenient location.
If you are on Windows, also install:
- ST Link - serial driver for the board.
- Run
dpinst_amd64
on 64-bits Windows,dpinst_x86
on 32-bits Windows. - Afterwards, unplug your board and plug it back in.
- (Not sure if it configured correctly? Look in 'Device Manager > Ports (COM & LPT)', should list as STLink Virtual COM Port.
- Run
- Tera term - to see debug messages from the board.
- Take your NUCLEO board out of the box.
- Connect a mini-USB cable to the board.
- The board mounts as a mass-storage device (like a USB drive). Verify that you can see it (the drive name will be NUCLEO).
- Double-click on
mbed.htm
- you'll be redirected to the F411RE platform page.- If prompted to sign in, sign in or create an account.
- Click the Add to your mbed Compiler button.
- Click the Compiler button.
- An IDE should open. Congratulations!
Local development: If you like things locally, you can do so by using mbed CLI. I very much recommend to just use the online IDE, as it makes it easier for us, but if you want to continue hacking in the future, this is a nice way.
There is a button (the blue one) on your board. Let's see if your board actually works by responding to a click on this button.
- Make sure that you have the online compiler open.
- Click the Import button, then click Click Here to import from URL.
- Paste the following URL: https://github.com/ARMmbed/dsa-2017
- Do NOT tick the 'Update libraries' checkbox.
- Click the Import button.
- In the top right corner, verify that the right development board is selected (NUCLEO-F411RE or NUCLEO-F401RE).
Next, we will select which program we will build. This step needs to be repeated every time we progress to the next example.
- In the tree, locate 'select_project.h'.
- Change the number in this file to the project you want to build. In this case
1
.
Now we can implement the code to make the button do something. Open 1_button/main.h
and under 'YOUR CODE HERE' add the following code:
// A DigitalOut object has a state on or off (only two states)
DigitalOut led(LED1);
void toggle_led() {
// When this function gets executed we toggle the state of the LED
led = !led;
}
- Now press Compile.
- A file downloads.
- Drag the file to the 'NUCLEO' disk.
- The device flashes red/yellow when it's updating the software.
- Press the
RESET
button on the board (only needed sometimes).
Now click the blue button and see the LED toggle.
Change the code so that the LED will only be on when you're holding the button, and turns off when you release the button (hint: fall
has a brother called rise
).
To make things more interesting, let's read data from a soil moisture sensor. You can use this sensor to monitor whether your plant needs to be watered, but it can also detect when you touch it (because your fingers are more moist than the air). Let's turn the soil moisture sensor into a capacitive touch sensor!
- Take the moisture sensor.
- Attach the grove connector.
- Click in three wires at the bottom of the grove connector (leading to red, black, yellow).
- Connect to the board as follows (the actual colors of the wires does not matter, but where you connect them does!).
We can now write a small program that checks on the moisture sensor, and responds when it detects a moist environment (like your hands).
-
In the tree, locate 'select_project.h' and change the number in this file to
2
. -
Open
2_capacitive\main.h
and underYOUR CODE HERE
add:// Read the value of the sensor float moist = moisture.read(); // Print it back to the computer printf("Moisture value is %f\r\n", moist); // If we're > 10% moist, then toggle the LED if (moist > 0.10) { led = 1; } else { led = 0; } // Pause between readings wait_ms(100);
-
Compile and flash the program.
-
When you now touch the sensor the LED should turn on.
All nice, but you have no insight in how well the program works. Debug messages to the rescue! To show debug messages we need a serial monitor. Follow the instructions below. Your output should be similar to:
Moisture value is 0.000733
Moisture value is 0.001465
Moisture value is 0.001465
Moisture value is 0.000733
Moisture value is 0.000244
Moisture value is 0.000488
Moisture value is 0.000488
To see debug messages, install,
- ST Link - serial driver for the board.
- See above for more instructions.
- Tera term - to see debug messages from the board.
When you open Tera Term, select Serial, and then select the STLink COM Port. Make sure to select 115200
as baud rate.
No need to install a driver. Open a terminal and run:
screen /dev/tty.usbm # now press TAB to autocomplete, then add 115200
# f.e.
# screen /dev/tty.usbmodem1423 115200
To exit, press: CTRL+A
then CTRL+\
then press y
.
If it's not installed, install GNU screen (sudo apt-get install screen
). Then open a terminal and find out the handler for your device:
$ ls /dev/ttyACM*
/dev/ttyACM0
Then connect to the board using screen:
sudo screen /dev/ttyACM0 115200 # might not need sudo if set up lsusb rules properly
To exit, press CTRL+A
then type :quit
.
Now that we have a basic program running, we can connect it to the internet through mbed Device Connector.
First, we need to connect the WiFi module to the board. Connect the following pins on the WiFi module to the dev board using female->male header wires.
The pins that you need to use are highlighted here:
Next, we need to obtain a security certificate:
- Go to connector.mbed.com and sign in with your mbed credentials.
- Click on 'Security credentials'.
- Click on Get my device security credentials.
- Copy the content of the gray box.
- Create a new file
security.h
in the root folder of the project in the online compiler, and paste.
Now change the project and write some code:
- Open
mbed_app.json
and add the WiFi SSID and password. - In the tree, locate 'select_project.h' and change the number in this file to
3
. - This program is essentially the same as the last one, only:
- It contains code to connect to the internet.
- It uses a 'cloud variable', a variable that automatically syncs with the cloud to store data.
- Open
3_connected\main.h
. - Under
YOUR CODE HERE
paste:
// Moisture sensor
AnalogIn moistureSensor(A0);
// Cloud variable. If you update this variable, it will automatically stream it's new value to the cloud.
SimpleResourceFloat moistureResource = client.define_resource("moisture/0/value", 0.0f);
void update_moisture() {
moistureResource = moistureSensor.read();
}
- Compile and run this program.
- When connection to the internet succeeded the built-in LED will burn.
- LED should still go on when moving in front of the sensor.
Your device should now show as registered on: Connected devices in mbed Device Connector (type: dsa-sensor).
We can now control the device from the mbed Device Connector API Console. In the previous section we created one cloud variable:
moisture/0/value
- Value of the moisture sensor.
We can interact with these variables through the API Console.
- In the API Console select 'Endpoint directory lookup'.
- Select 'GET /endpoints/{endpoint-name}/{resource-path}'.
- Under 'endpoint' select your device.
- Under 'resource-path' select '/motion/0/value'.
- Click TEST API.
- Touch the moisture sensor.
- Click TEST API again.
- Verify that the number changed.
We can also write some code to interact with this device.
- First make sure that you have installed Python 2.7 or Python 3 and pip.
- Download the source code for this workshop from here - and unpack in a convenient location.
- Open a terminal or a command window.
- Change directory to the folder where you download the
dsa-2017
repository. - Run
cd 5_from_code
. - Run
pip install -U mbed-connector-api
. - Open
moisture.py
in a text editor.
Now we need an access key (API key).
- Go to the Access Keys page.
- Click Generate new key
- Copy the key, and paste it in
moisture.py
on the first line. - Go back to the terminal.
- Run
python moisture.py
.
Output should be something like:
Found 1 moisture sensors [ { name: '2bffcc03-05a6-4921-b345-ebddb52f6f71',
type: 'dsa-sensor',
status: 'ACTIVE' } ]
- Data should now start streaming into your terminal.
Optionally, you can also run a web app to see live data flowing from the device. For this you'll need a recent version of node.js installed.
- In your terminal navigate to the
6_an_app
folder. - Run
npm install
. - Open
main.js
and paste your access key in again. - Run
node main.js
. - Output should be something like:
connected to mbed Cloud, retrieving initial device model
got devices [ { name: '2bffcc03-05a6-4921-b345-ebddb52f6f71',
type: 'dsa-sensor',
status: 'ACTIVE',
endpoint: '2bffcc03-05a6-4921-b345-ebddb52f6f71' } ]
subscribed to 2bffcc03-05a6-4921-b345-ebddb52f6f71 /moisture/0/value
en0 192.168.1.11
Web server listening on port 5265!
- Go to http://localhost:5265 and you can now interact with your devices.
This should give you enough basic information on how you can connect sensors to the internet, how to get data back from the sensors and then process it through Python or node.js. But this was only a single sensor! We also have temperature sensors and accelerometers (enough for everyone). Gather together and see if you can connect these to the internet as well!
- 3-axis accelerometer 16G
- Connect black->GND, red->3.3V (any will do), yellow->SCL, white->SDA. See the pinout for your board.
- For the test code, see how we read the value of the moisture sensor every second. Do something similar.
- To add the library to your project, right click on your project, select 'Add library' > 'From URL' and select https://developer.mbed.org/users/peterswanson87/code/ADXL345_I2C/.
- Then, in the library folder remove 'mbed' and 'main.cpp'.
- Initialize using
ADXL345_I2C accelerometer(D14, D15);
.
- 3-axis accelerometer 3G
- Connect black->GND, red->3.3V (any will do), yellow->SCL, white->SDA. See the pinout for your board.
- For the test code, see how we read the value of the moisture sensor every second. Do something similar.
- To add the library to your project, right click on your project, select 'Add library' > 'From URL' and select https://developer.mbed.org/users/edodm85/code/MMA7660FC.
- Initialize using
MMA7660FC accelerometer(D14, D15, ADDR_MMA7660);
- Temperature sensor
- Works the same as the moisture sensor (analog sensor).
- Connect black->GND, red->3.3V, yellow to A1.
- Returns a value between 0 and 1.
- Code example is in the component page, no library required.
If you want to gather a lot of data (e.g. movement data from accelerometer), better not use a cloud variable for every action, as they are slow. Gather a few seconds of data, concat it, and then upload it all in one go.
E.g.:
#include <sstream>
std::stringstream ss;
AnalogIn temp(A3);
int readings_done = 0;
void read_sensor() {
// add the value to the stringstream
ss << temp.read_u16();
ss << ",";
readings_done = readings_done + 1;
if (readings_done > 100) {
some_cloud_var = ss.str(); // assign the total string to a cloud variable
ss.str(""); // clear the stringstream
readings_done = 0; // and reset the number of readings done again
}
}
Note: By default you can store about 1000 bytes in a cloud variable.
We can also show temperature data. Take your program from 2_capacitive
(or 3_connected
if you managed to get internet connectivity).
-
Connect the temperature sensor in the same way as the soil moisture sensor.
-
In
select_project.h
, change the project to2
. -
Replace the code under
YOUR_CODE_HERE
with:unsigned int a, beta = 3975, units, tens; float temperature, resistance; a = moisture.read_u16(); /* Read analog value */ /* Calculate the resistance of the thermistor from analog votage read. */ resistance = (float) 10000.0 * ((65536.0 / a) - 1.0); /* Convert the resistance to temperature using Steinhart's Hart equation */ temperature =(1/((log(resistance/10000.0)/beta) + (1.0/298.15)))-273.15; printf("temperature is %f\n", temperature); wait_ms(1000);
-
Compile and flash the application, and connect the terminal monitor to the board to see temperature.
Extra credit: You can run both soil moisture sensor and temperature sensor at the same time. Connect Yellow->A1, Red->3.3V, Black->GND for this. Find a free 3.3V and a free GND port for this. See the pinout. You'll also need another variable to read the temperature sensor's data.
Let's gather some data and see if we can draw conclusions from it!
- Take a 16G accelerometer.
- Attach Yellow->SCL, White->SDA, Red->3.3V, Black->GND.
- Right click on your project in the online compiler and select 'Update'.
- If prompted, click
Commit
to not lose your previous work. - Type a message and click 'OK'.
- Open
select_project.h
and change the project to8
. - Compile and flash the application.
Now we can gather data from this device. Connect a terminal monitor (Tera Term or screen) to the board.
- Press the blue button.
- After five seconds data gathering starts.
- Move the sensor around.
- After three seconds data gathering stops and data is shown in the terminal.
- Copy the data and paste in Excel (make sure X, Y, Z are on separate lines, you should have three lines in total).
- In Excel:
- Select Column A.
- Click Data > Text to Columns.
- Select 'Comma' as a delimiter.
- Data should be shown cleanly now
- Then select row 1, 2 and 3 and make a graph. Your accelerometer data is now plotted.
Questions and homework:
- Can you see how you moved the sensor?
- Could you feed this data into a model?
- Experiment with different movements, could you distinguish the movement based on the raw data?
- Could you use a machine learning model to train on this data and then use a model to distinguish movement?
Extra credit: If your board is connected to the internet you can do the visualization live from Python when data comes in. Take the program in 3_connected and add a new cloud variable that sends the data from the sensor to the cloud (make 3 SimpleResourceString
's named accel_x
, accel_y
, accel_z
). Then from Python grab the data when it comes in and plot it using one of the visualization techniques you learned.