Contents
3. Warp7 Sensors demo - mpl3115a2
4. Warp7 Sensors demo - fxos8700cq
5. Warp7 IoT demo <-- You are here
Back in May i created a simple IoT for Warp7Warp7 while the BSP was still under development..
Incidentally FTF2016 was round the corner and we thought to demonstrate warp7 progress.
In this blog I will pen down the details simple enough for a begineer to understand.
The setup uses Wifi, Sensors and a Cloud Platform. ThingSpeak Cloud platform is used for this as i found it simple, you can use any other platform available.
A simple bare-metal sensor application and python script is all that's required to get the warp7 data to the cloud.
The applications perform a push-pull operations between warp7 hardware and the Cloud Platform at regular intervals.
1. Sensor Application : The data from MEMS sensors is retrieved using a bare-metal C program directly reading I2C bus. The data coming at 200Hz is pushed into the bi-directional pipe used by this application. Linux pipes is used so that both the Sensor and Thingspeak application can read/write the file at same time without crashing either application.
2. Thingspeak Application: This application will read data from pipe and update thingspeak IoT interface using a python application and standard API interfaces. The application starts automatically (refer /etc/rc.local) once board is powered on.
The Sensor Application :
#include <stdio.h> #include <stdint.h> #include <linux/i2c.h> #include <linux/i2c-dev.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <string.h> static int write_register(int file,unsigned char address,unsigned char reg,unsigned char data) { unsigned char output_buffer[2]; struct i2c_rdwr_ioctl_data packets; struct i2c_msg messages[1]; messages[0].addr = address; messages[0].flags = 0; messages[0].len = sizeof(output_buffer); messages[0].buf = output_buffer; output_buffer[0] = reg; output_buffer[1] = data; packets.msgs = messages; packets.nmsgs = 1; if(ioctl(file, I2C_RDWR, &packets) < 0) { perror("Error sending data"); return 1; } return 0; } static int read_register(int file, unsigned char address, unsigned char reg, unsigned char *data) { unsigned char input_buffer, output_buffer; struct i2c_rdwr_ioctl_data packets; struct i2c_msg messages[2]; output_buffer = reg; messages[0].addr = address; messages[0].flags = 0; messages[0].len = sizeof(output_buffer); messages[0].buf = &output_buffer; messages[1].addr = address; messages[1].flags = I2C_M_RD; messages[1].len = sizeof(input_buffer); messages[1].buf = &input_buffer; packets.msgs = messages; packets.nmsgs = 2; if(ioctl(file, I2C_RDWR, &packets) < 0) { perror("Error sending data"); return 1; } *data = input_buffer; return 0; } int main() { int file, i; unsigned char data; char data256[256]; unsigned char data1; unsigned char data2; int val1; int val2; int t_m; int x_value; int y_value; int z_value; if ((file = open("/dev/i2c-3", O_RDWR)) < 0) { perror("Error openning file!"); exit(1); } //0x00 whoami verify if(read_register(file, 0x1E, 0x0D, &data)) exit(1); else { /* printf("GET:WHOAMI[0x%02X]: 0x%02X\n" , 13 , data);*/ } // set to active mode if(write_register(file, 0x1E, 0x2A, 0x01)) exit(1); else { /* printf("FXOS8700CQ is active");*/ } //enable accelerometer & magnetometer if(write_register(file, 0x1E, 0x5B, 0x03)) exit(1); else { /* printf("enabling accelerometer and magnetometer");*/ } // setup mpl3115 temperature //0x0C whoami verify if(read_register(file, 0x60, 0x0C, &data)) exit(1); else { } //0x26 set ctrlreg1 ACTIVE if(write_register(file, 0x60, 0x26, 0x03)) exit(1); int counter=0; while(1) { ///////////////////////////////////////////////////////Accelerometer // X value if(read_register(file, 0x1E, 0x01, &data1)) exit(1); else { } if(read_register(file, 0x1E, 0x02, &data2)) exit(1); else { } val1 = (int)data1; val1 <<=8; val2 = (int)data2; x_value = val1 | val2; // Y value if(read_register(file, 0x1E, 0x03, &data1)) exit(1); else { } if(read_register(file, 0x1E, 0x04, &data2)) exit(1); else { } val1 = (int)data1; val1 <<=8; val2 = (int)data2; y_value = val1 | val2; // Z value if(read_register(file, 0x1E, 0x05, &data1)) exit(1); else { } if(read_register(file, 0x1E, 0x06, &data2)) exit(1); else { } val1 = (int)data1; val1 <<=8; val2 = (int)data2; z_value = val1 | val2; //write terminal /*printf("\n\nx-value :%d:\n",x_value);*/ /*printf("y-value :%d:\n",y_value);*/ /*printf("z-value :%d:\n",z_value);*/ //write file snprintf(data256, 256, "echo -n %d %d %d > /opt/file1.txt", x_value, y_value, z_value); system(data256); ///////////////////////////////////////////////////////Magnetometer // X value if(read_register(file, 0x1E, 0x33, &data1)) exit(1); else { } if(read_register(file, 0x1E, 0x34, &data2)) exit(1); else { } val1 = (int)data1; val1 <<=8; val2 = (int)data2; x_value = val1 | val2; // Y value if(read_register(file, 0x1E, 0x35, &data1)) exit(1); else { } if(read_register(file, 0x1E, 0x36, &data2)) exit(1); else { } val1 = (int)data1; val1 <<=8; val2 = (int)data2; y_value = val1 | val2; // Z value if(read_register(file, 0x1E, 0x37, &data1)) exit(1); else { } if(read_register(file, 0x1E, 0x38, &data2)) exit(1); else { } val1 = (int)data1; val1 <<=8; val2 = (int)data2; z_value = val1 | val2; //write terminal /*printf("\n\nx-value :%d:\n",x_value);*/ /*printf("y-value :%d:\n",y_value);*/ /*printf("z-value :%d:\n",z_value);*/ //write file snprintf(data256, 256, "echo -n %d %d %d > /opt/file2.txt", x_value, y_value, z_value); system(data256); /////////////////////////////////////////////////////////////////TEMPERATURE //read temperature MSB/LSB if(read_register(file, 0x60, 0x04, &data)) exit(1); val2 = (int)data; /* if(DBG_ENABLE == 1) printf("val2: initial :%d:\n",val2);*/ val2 <<=8; /* if(DBG_ENABLE == 1) printf("val2: shift :%d:\n",val2);*/ if(read_register(file, 0x60, 0x05, &data)) exit(1); else { /* if(DBG_ENABLE == 1)*/ /* printf("Register[0x%02X]: 0x%02X\n" , 5 , data);*/ } val2 = val2+ (int)data; /* if(DBG_ENABLE == 1)*/ /* { printf("val2 :%d:\n",val2);*/ /* }*/ t_m = (val2 >> 8) & 0xff; /* printf("temperature :%d: \n",t_m);*/ snprintf(data256, 256, "echo -n %d > /opt/file3.txt", t_m); system(data256); usleep(100000); counter++; } close(file); return 0; }
The Thingspeak Cloud Application.
import sys
from time import sleep
import urllib2
import os
import time
def getSensorData():
with open('/opt/file1.txt') as f:
line1 = f.readline()
str1 = str(line1)
list1 = str1.split()
x,y,z = list1
return (str(x), str(y), str(z))
def getSensorData2():
with open('/opt/file2.txt') as f:
line1 = f.readline()
str1 = str(line1)
list1 = str1.split()
x,y,z = list1
return (str(x), str(y), str(z))
def getSensorData3():
with open('/opt/file3.txt') as f:
line1 = f.readline()
str1 = str(line1)
x = str1
return (str(x))
def main():
print "Starting Warp7 Iot Platform"
print "activating sensor application"
os.system("killall a.out")
os.system("sync")
time.sleep(1)
os.system("/opt/a.out &")
baseURL = 'https://api.thingspeak.com/update?api_key=<YOUR_API_KEY_HERE>'
x=0
y=0
z=0
x2=0
y2=0
z2=0
x3=0
while True:
try:
x,y,z = getSensorData()
x2,y2,z2 = getSensorData2()
x3 = getSensorData3()
except ValueError:
print "get: Sensor Data Failed"
try:
print "x,y,z:",x,y,z
print "x2,y2,z2:",x2,y2,z2
print "x3",x3
os.system("echo -n 100 > /opt/status1")
f = urllib2.urlopen(baseURL+"&field1=%s&field2=%s&field3=%s&field4=%s&field5=%s&field6=%s&field7=%s" %(x,y,z,x2,y2,z2,x3))
print "THINGSPEAK: Updated"
os.system("echo -n 100 > /opt/status2")
print f.read()
f.close()
except urllib2.HTTPError, e:
print "urllib2.HTTPError"
except urllib2.URLError, e:
print "urllib2.URLError" #print e.args
time.sleep(1)
# call main
if __name__ == '__main__':
main()
First things first:
Before trying the demo , please use a terminal program like gnu screen/minicom to verify the wireless connectivity and sensor application running status. I believe both will work fine.
Download all FTF demo bundle.
The default wifi ssid and password as set in the bundle is:
ssid: “warp7ssid”
password: “warp7pwd”
If you don't want to edit wireless setting in the above bundle, change your router ssid and password (as above) for demo purposes.
Alternatively, edit “/etc/network/interfaces” & “/etc/wpa_supplicant.conf” files and replace the text “warp7ssid” with your SSID and “warp7pwd” with your password.
Note:
1. The wireless interfaces might breaks sometimes, hence you might find the application updating the “last recorded sensor values” to thingspeak.
2. add “#” symbol to line14 in /etc/rc.local to disable python application logs during testing. Mount the rootfs on PC to perform this step. “ums 0 mmc 0” does the thing - Check user manual section 5.2 for more.
The sensor application pushes continuous values to terminal. If you want to perform debugging follow below steps to stop the app.
Step1. Power on warp board & wait till you similar values as below in screen:
Step2.
Its difficult to see the prompt, as the sensor application starts dumping values to screen every second. so just do as below.
then type “root”, hit Enter.
Again type “root”, hit enter.
We are logged in now.
Step3.
Now type “./stop”, hit enter.
The sensor app will stop, don't worry, the apps will start once board reboots.
The First connection to router might take several mins depending on wifi-router connectivity. Updates to “thingspeak” page happens every 3-10 seconds.
If updates are not visible, restart warp7 .
Next create a channel in your thingspeak.com account and get the api key required to push data.
To view sensor data check this channel - https://thingspeak.com/channels/113986.
You will find 4 Graphs that show the calibrated values from MEMS sensors.
What are the Graphs for ???
Graph1 : Warp7 accelerometer(FXOS8700CQR1) Roll values.
Tilting warp7 to left and right (as shown) will show recorded data (in spikes) in graph based on the direction of tilt.
Roll Left.
Roll Right.
Graph2 : Warp7 accelerometer(FXOS8700CQR1) Pitch values.
Tilting warp7 up and down will record data in thingspeak as above.
Pitch Up.
Pitch Down.
Graph3 : Warp7 Magnetometer (FXOS8700CQR1) values
Warp7 magnetometer and Android Phone both facing north.
if magnetometer pointed NORTH, y-axis value in graph3 will be 0.
Graph4 MPL3115A2MPL3115A2 temperature values
Self Explanatory
Snapshot of thingspeak page (10-may-2016):
https://thingspeak.com/channels/113986
Let me know challenges if any.