Monday, June 9, 2014

Arduino + Internet of Things - Part I

...IoT...

The term "Internet of Things" is used to describe a system where the Internet is connected to the physical world via ubiquitous sensors [1]. In an article dated June 22, 2009 in the RFID Journal Kevin Ashton said - 

Today computers—and, therefore, the Internet—are almost wholly dependent on human beings for information. Nearly all of the roughly 50 petabytes (a petabyte is 1,024 terabytes) of data available on the Internet were first captured and created by human beings—by typing, pressing a record button, taking a digital picture or scanning a bar code. Conventional diagrams of the Internet include servers and routers and so on, but they leave out the most numerous and important routers of all: people. The problem is, people have limited time, attention and accuracy—all of which means they are not very good at capturing data about things in the real world.

And that's a big deal. We're physical, and so is our environment. Our economy, society and survival aren't based on ideas or information—they're based on things. You can't eat bits, burn them to stay warm or put them in your gas tank. Ideas and information are important, but things matter much more. Yet today's information technology is so dependent on data originated by people that our computers know more about ideas than things.

We need to empower computers with their own means of gathering information, so they can see, hear and smell the world for themselves, in all its random glory. RFID and sensor technology enable computers to observe, identify and understand the world—without the limitations of human-entered data.


Gartner Inc. states that the Internet of Things will grow to 26 billion units installed in 2020, representing an almost 30-fold increase from 2009. Furthermore, Gartner said that IoT product and service suppliers will generate incremental revenue exceeding $300 billion, mostly in services, in 2020. The market research firm further states IoT will result in $1.9 trillion in global economic value-add through sales into diverse end markets.Is IoT the latest hype ? Most of the opportunities predicted from IoT are nothing new. Everything will be connected but most those items like cars, appliances, printers, etc. have been talked about for more than a decade. The big differentiator this time is advanced sensor technology, but how long before these sensors become commodities? OK, so most of these devices will be IPv6, but what's the big deal about what standards they use to communicate? Most of the chatter about IoT seems to be evolutionary, not revolutionary. [2]

Data is all around us, data we cannot see - Dark Data. If harnessed properly this data can be quantified and utilized to make this planet a better place to live (jeezz...). Unless people make smart use of IoT it will just remain in the evolutionary stage.  Everthing will just remain an Internet-of-Thermostats...

Allright, i am fed up gathering data visit this link to read further.

That Temperature Thing...

Now to the real content for which this post is meant for. In a nutshell - i've used the Sparkfun Weather shield connected to the Arduino to send the temperature, humidity and luminosity data of my room to a Xively server using a Adafruit CC3000 TI WiFi sheld. This is the stacked up assembly. The bottom board is an Arduino Uno R3, in the center there is the Adafruit  WiFi shield and the Sparkfun weather shield on top. Pretty neat arrangement eh ? Rapid prototyping at it's finest with such boards available...


The data is displayed on the Xively website. Surprisingly i have observed that the data transmission to the server is slow. It takes approximately 40 seconds after a connection has been established with the server to upload the JSON formatted data using the UNO R3. The entire code for the Arduino sketch is shown below and some screenshots from the Xively site. Most of the code has been adapted from Adafruit's learning site with minor modifications by me for the weather shield. Does a demo like this come under the hood of IoT ? Well, right now, if i stop this project here, then No, it does not. The data is merely being displayed, it does not control any-thing or talks to any other thing to modify that thing's behavior. This just validates the platform on which future IoT applications aspire to run on...


The light levels started to increase from 05:53 hrs in the morning as seen in above graph.
The sunrise time as per local weather station data was indeed 05:53 A.M

It is pretty hot out here. Those spikes you see are me turning off the air cooling of my room. 37.99 degrees celcius was the maximum temperature hit inside my room...after which i turned on the air conditioning

If you are reading this post and have some information to share on the CC3000 as to why it takes so much time to push data to the website, leave a comment below. Thanks for reading through...



#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
#include <Wire.h> // I2C needed for sensors
#include "MPL3115A2.h" // Pressure sensor
#include "HTU21D.h" // Humidity sensor
// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ 3 // MUST be an interrupt pin!
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIVIDER); // you can change this clock speed but DI
#define WLAN_SSID "YourNetwork" // cannot be longer than 32 characters!
const char WLAN_PASS[] = "YourPass"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY "YourSecurityMode"
MPL3115A2 myPressure; //Create an instance of the pressure sensor
HTU21D myHumidity; //Create an instance of the humidity sensor
const byte STAT1 = 7;
const byte STAT2 = 8;
const byte LIGHT = A1;
const byte REFERENCE_3V3 = A3;
float humidity = 0; // [%]
float tempf = 0; // [temperature F]
float pressure = 0;
float light_lvl = 455; //[analog value from 0 to 1023]
#define WEBSITE F("api.xively.com")
#define API_key F("YourKey")
#define feedID F("YourFeedID")
uint32_t ip = 0;
/**************************************************************************/
/*!
@brief Displays the driver mode (tiny of normal), and the buffer
size if tiny mode is not being used
@note The buffer size and driver mode are defined in cc3000_common.h
*/
/**************************************************************************/
void displayDriverMode(void)
{
#ifdef CC3000_TINY_DRIVER
Serial.println(F("CC3000 is configure in 'Tiny' mode"));
#else
#ifdef SERDEBUG
Serial.print(F("RX Buffer : "));
Serial.print(CC3000_RX_BUFFER_SIZE);
Serial.println(F(" bytes"));
Serial.print(F("TX Buffer : "));
Serial.print(CC3000_TX_BUFFER_SIZE);
Serial.println(F(" bytes"));
#endif
#endif
}
/**************************************************************************/
/*!
@brief Tries to read the CC3000's internal firmware patch ID
*/
/**************************************************************************/
uint16_t checkFirmwareVersion(void)
{
uint8_t major, minor;
uint16_t version;
#ifndef CC3000_TINY_DRIVER
if(!cc3000.getFirmwareVersion(&major, &minor))
{
Serial.println(F("Unable to retrieve the firmware version!\r\n"));
version = 0;
}
else
{
Serial.print(F("Firmware V. : "));
Serial.print(major); Serial.print(F(".")); Serial.println(minor);
version = major; version <<= 8; version |= minor;
}
#endif
return version;
}
/**************************************************************************/
/*!
@brief Tries to read the 6-byte MAC address of the CC3000 module
*/
/**************************************************************************/
void displayMACAddress(void)
{
uint8_t macAddress[6];
if(!cc3000.getMacAddress(macAddress))
{
#ifdef SERDEBUG
Serial.println(F("Unable to retrieve MAC Address!\r\n"));
#endif
}
else
{
Serial.print(F("MAC Address : "));
cc3000.printHex((byte*)&macAddress, 6);
}
}
/**************************************************************************/
/*!
@brief Tries to read the IP address and other connection details
*/
/**************************************************************************/
bool displayConnectionDetails(void)
{
uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
{
Serial.println(F("Unable to retrieve the IP Address!\r\n"));
return false;
}
else
{
Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
Serial.println();
return true;
}
}
//Returns the voltage of the light sensor based on the 3.3V rail
//This allows us to ignore what VCC might be (an Arduino plugged into USB has VCC of 4.5 to 5.2V)
float get_light_level()
{
float operatingVoltage = analogRead(REFERENCE_3V3);
float lightSensor = analogRead(LIGHT);
operatingVoltage = 3.3 / operatingVoltage; //The reference voltage is 3.3V
lightSensor = operatingVoltage * lightSensor;
return(lightSensor);
}
//Calculates each of the variables that wunderground is expecting
void calcWeather()
{
//Calc humidity
humidity = myHumidity.readHumidity();
//float temp_h = myHumidity.readTemperature();
//Serial.print(" TempH:");
//Serial.print(temp_h, 2);
//Calc tempf from pressure sensor
tempf = myPressure.readTempF();
// converting to centigrade.
// did not care to change variable name
tempf = (tempf - 32.0)/1.8000;
//Calc pressure
// Could not use this due to memory limitations on Arduino
// when forming the JSON string.
pressure = (myPressure.readPressure())/100000;
//Calc light level
// Multipled by 100 to get proper display on Xiv
// values were too small
light_lvl = get_light_level() * 100;
}
void setup(void)
{
Serial.begin(9600);
Serial.println(F("Hello, CC3000!\n"));
displayDriverMode();
Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);
/* Initialise the module */
Serial.println(F("\nInitialising the CC3000 ..."));
if (!cc3000.begin())
{
Serial.println(F("Unable to initialise the CC3000! Check your wiring?"));
while(1);
}
uint16_t firmware = checkFirmwareVersion();
if (firmware < 0x113) {
Serial.println(F("Wrong firmware version!"));
for(;;);
}
displayMACAddress();
/* Delete any old connection data on the module */
Serial.println(F("\nDeleting old connection profiles"));
if (!cc3000.deleteProfiles()) {
Serial.println(F("Failed!"));
while(1);
}
/* Attempt to connect to an access point */
char *ssid = WLAN_SSID; /* Max 32 chars */
Serial.print(F("\nAttempting to connect to ")); Serial.println(ssid);
/* NOTE: Secure connections are not available in 'Tiny' mode! */
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
while(1);
}
Serial.println(F("Connected!"));
/* Wait for DHCP to complete */
Serial.println(F("Request DHCP"));
while (!cc3000.checkDHCP())
{
delay(100); // ToDo: Insert a DHCP timeout!
}
/* Display the IP address DNS, Gateway, etc. */
while (! displayConnectionDetails()) {
delay(1000);
}
Serial.println();
ip = cc3000.IP2U32(216,52,233,120);
cc3000.printIPdotsRev(ip);
Serial.println();
Serial.println(F("Wi-Fi Online"));
Serial.println(F("Initializing Weather Shield"));
pinMode(STAT1, OUTPUT); //Status LED Blue
pinMode(REFERENCE_3V3, INPUT);
pinMode(LIGHT, INPUT);
//Configure the pressure sensor
myPressure.begin(); // Get sensor online
myPressure.setModeBarometer(); // Measure pressure in Pascals from 20 to 110 kPa
myPressure.setOversampleRate(7); // Set Oversample to the recommended 128
myPressure.enableEventFlags(); // Enable all three pressure and temp event flags
//Configure the humidity sensor
myHumidity.begin();
Serial.println(F("Weather Shield online!"));
/* You need to make sure to clean up after yourself or the CC3000 can freak out */
/* the next time you try to connect ... */
// Serial.println(F("\n\nClosing the connection"));
// cc3000.disconnect();
}
void loop() {
digitalWrite(STAT1, HIGH); //Blink stat LED
calcWeather();
// Prepare JSON for Xively & get length
int length = 0;
String data = "";
//data = data + "\n" + "{\"version\":\"1.0.0\",\"datastreams\" : [ {\"id\" : \"Temperature\",\"current_value\" : \"" + String((int)tempf) + "\"}," + "{\"id\" : \"Humidity\",\"current_value\" : \"" + String((int)humidity) + "\"}," + "{\"id\" : \"Pressure\",\"current_value\" : \"" + String((int)pressure) + "\"}," + "{\"id\" : \"Luminosity\",\"current_value\" : \"" + String((int)light_lvl) + "\"}]}";
data = data + "\n" + "{\"version\":\"1.0.0\",\"datastreams\" : [ {\"id\" : \"Temperature\",\"current_value\" : \"" + String(tempf) + "\"},"
+ "{\"id\" : \"Humidity\",\"current_value\" : \"" + String(humidity) + "%" + "\"}," //]}";
+ "{\"id\" : \"Luminosity\",\"current_value\" : \"" + String(light_lvl) + "\"}]}";
length = data.length();
#ifdef SERDEBUG
// Print request for debug purposes
Serial.print("PUT /v2/feeds/");
Serial.print(feedID);
Serial.println(".json HTTP/1.0");
Serial.println("Host: api.xively.com");
Serial.print("X-ApiKey: ");
Serial.println(API_key);
Serial.print("Content-Length: ");
Serial.println(length, DEC);
Serial.print("Connection: close");
Serial.println();
Serial.print(data);
Serial.println();
#endif
// Send request
Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);
if (client.connected()) {
Serial.println("Connected!");
// Starting here, till...
client.println("PUT /v2/feeds/" + String(feedID) + ".json HTTP/1.0");
client.println("Host: api.xively.com");
client.println("X-ApiKey: " + String(API_key));
client.println("Content-Length: " + String(length));
client.print("Connection: close");
client.println();
client.print(data);
client.println();
// ... here, the process takes approx. 40 seconds !!!
digitalWrite(STAT1, LOW); //Blink stat LED
} else {
Serial.println(F("Connection failed"));
return;
}
//Serial.println(F("-------------------------------------"));
while (client.connected()) {
while (client.available()) {
char c = client.read();
//Serial.print(c);
}
}
client.close();
// Serial.println(F("-------------------------------------"));
delay(100);
// Yep, i do not disconnect.
}
view raw Arduino_IoT.ino hosted with ❤ by GitHub


And that's a big deal. We're physical, and so is our environment. Our economy, society and survival aren't based on ideas or information—they're based on things. You can't eat bits, burn them to stay warm or put them in your gas tank. Ideas and information are important, but things matter much more. Yet today's information technology is so dependent on data originated by people that our computers know more about ideas than things. - See more at: http://www.rfidjournal.com/articles/view?4986#sthash.uvAv1voe.dpuf
Today computers—and, therefore, the Internet—are almost wholly dependent on human beings for information. Nearly all of the roughly 50 petabytes (a petabyte is 1,024 terabytes) of data available on the Internet were first captured and created by human beings—by typing, pressing a record button, taking a digital picture or scanning a bar code. Conventional diagrams of the Internet include servers and routers and so on, but they leave out the most numerous and important routers of all: people. The problem is, people have limited time, attention and accuracy—all of which means they are not very good at capturing data about things in the real world. - See more at: http://www.rfidjournal.com/articles/view?4986#sthash.uvAv1voe.dpuf
Today computers—and, therefore, the Internet—are almost wholly dependent on human beings for information. Nearly all of the roughly 50 petabytes (a petabyte is 1,024 terabytes) of data available on the Internet were first captured and created by human beings—by typing, pressing a record button, taking a digital picture or scanning a bar code. Conventional diagrams of the Internet include servers and routers and so on, but they leave out the most numerous and important routers of all: people. The problem is, people have limited time, attention and accuracy—all of which means they are not very good at capturing data about things in the real world. - See more at: http://www.rfidjournal.com/articles/view?4986#sthash.uvAv1voe.dpuf
Today computers—and, therefore, the Internet—are almost wholly dependent on human beings for information. Nearly all of the roughly 50 petabytes (a petabyte is 1,024 terabytes) of data available on the Internet were first captured and created by human beings—by typing, pressing a record button, taking a digital picture or scanning a bar code. Conventional diagrams of the Internet include servers and routers and so on, but they leave out the most numerous and important routers of all: people. The problem is, people have limited time, attention and accuracy—all of which means they are not very good at capturing data about things in the real world. - See more at: http://www.rfidjournal.com/articles/view?4986#sthash.uvAv1voe.dpuf
Today computers—and, therefore, the Internet—are almost wholly dependent on human beings for information. Nearly all of the roughly 50 petabytes (a petabyte is 1,024 terabytes) of data available on the Internet were first captured and created by human beings—by typing, pressing a record button, taking a digital picture or scanning a bar code. Conventional diagrams of the Internet include servers and routers and so on, but they leave out the most numerous and important routers of all: people. The problem is, people have limited time, attention and accuracy—all of which means they are not very good at capturing data about things in the real world. - See more at: http://www.rfidjournal.com/articles/view?4986#sthash.uvAv1voe.dpuf

1 comment:

Anonymous said...

Hello, I have a question regarding the weather shield. I am using the weather shield to be placed on top of the Arduino Uno R3 to capture data such as temperature and display it on a website. Most of the time, the data is not displayed on the website because it is being captured very slowly and I have no idea what's the problem. There was also an instance whereby for 1 whole day, no data was captured at all even though it did a few days ago.

Do you have any idea what could be the problem?