Intel Edison Or Arduino Control Using Windows Azure Mobile Services

Connect your Edison or Arduino with Azure mobile services. The mobile services will act as a bridge between a windows phone app and your device (Edison/Arduino).

Introduction

This article will guide you through the process of hooking up your Edison with Windows Azure, and how to do some cool stuff, such as controlling it. This example will just switch on and off an LED connected to any of the digital pins on the Edison board paired up with the Arduino breakout board. Let's see how it really works. An Azure mobile service will act as a bridge between the Edison and the controller (a Windows phone app is used here). The Edison will read the value of an attribute from the table of the mobile service. A Windows phone app will update the value in the table, and thus we will make changes in the Edison code depending on the value.

Prerequisites

It is assumed that the reader has basic knowledge on Windows phone app development and can hook up the app with an Azure mobile service. If you are unfamiliar with creating a back end for your app, then go through this link

Things Required (Hardware)

  1. Intel Edison with the Arduino breakout board
  2. A LED

Required Software

  1. Visual Studio
  2. Arduino IDE 

Services required

   1: Azure mobile service

Firstly, let's create an Azure mobile service. There are lots of article on creating an Azure mobile service. Follow this link and create a mobile service that will contain a single table and let's name it as controltable. The table will contain a column named "status" and another named "name". The value of the status column will either be 1 or 0, while the value for name will be set to Edison/Arduino.
 
 

Now we will develop a Windows phone app that will add/modify the value of the attribute. The picture below shows us the screenshot of the Azure sql table. Please note that the value of the attribute for “device” doesn’t matter. You can even exclude this attribute if you want to.

The next section will deal with the development of the Windows phone app.

Windows Phone App

Our app will consist of only two buttons: An on button and an off button. The screenshot of the app is shown below. 

 

You can ignore the logout button, Actually, I was trying to add some features. Now what will these these buttons? This will update the value of the “status” attribute. When we press on button, the value of “status” will be 1, else it will be 0.

There is a bit of a problem though. What to update if nothing is created? For that we will deploy the app two times. The first time, we will create the table and assign some default values. The next time we will just update the previously updated values.

Now, our app is ready. Test the app and check whether the value of “status” is getting updated or not. Once it works, then there you go. The app is ready. The next part will concentrate on the Edison code.

Edison Code

Let’s get into Edison. Before kick starting your code for your Edison, follow the initial steps mentioned here for configuring your Edison. After connecting your Edison, note your comport number. Then open up your Arduino IDE and select Intel Edison from the board. If you don’t find the Intel Edison option, then you need to download the necessary files from the "Boards Manager" option.

 

Once you open up the Arduino IDE, two functions will be mentioned from before: Void setup() and void loop(). The Edison has an buikt-in Wi-Fi. We will use the Wi-Fi to connect it to the Internet. So our first action is to include a library for Wi-Fi. Go to Sketch, include library, then Wi-Fi. After that, let’s add up this code to connect it to Wi-Fi. 
  1. #include <ArduinoJson.h>  
  2. #include <SPI.h>  
  3. #include <WiFi.h>  
  4.   
  5. char ssid[] = "avirup171"//  your network SSID (name)   
  6. char pass[] = "avirupbasu";    // your net ork password (use for WPA, or use as key for WEP)  
  7. int keyIndex = 0;            // your network key Index number (needed only for WEP)  
  8.   
  9. void setup()  
  10. {  
  11.   pinMode(13,OUTPUT);  
  12.   digitalWrite(13,HIGH);  
  13.   Serial.begin(115200);  
  14.   while (!Serial) {  
  15.     ; // wait for serial port to connect. Needed for Leonardo only  
  16.   }  
  17.     
  18.   // check for the presence of the shield:  
  19.   if (WiFi.status() == WL_NO_SHIELD) {  
  20.     Serial.println("WiFi shield not present");   
  21.     // don't continue:  
  22.     while(true);  
  23.   }   
  24.   
  25.   String fv = WiFi.firmwareVersion();  
  26.   if( fv != "1.1.0" )  
  27.     Serial.println("Please upgrade the firmware");  
  28.     
  29.   // attempt to connect to Wifi network:  
  30.   while (status != WL_CONNECTED) {   
  31.     Serial.print("Attempting to connect to SSID: ");  
  32.     Serial.println(ssid);  
  33.     // Connect to WPA/WPA2 network. Change this line if using open or WEP network:      
  34.     status = WiFi.begin(ssid, pass);  
  35.     
  36.   }  
  37. }   
The above code is responsible for connecting the Edison to internet by Wi-Fi. Also, we have set PIN 13 to output mode and the current status is off. We will use the serial monitor of the IDE to monitor the process. Now, let's go to void loop(). Retrieving data from Azure is done by http get method. 
  1. void loop()  
  2. {
  3.   send_request();  
  4.   wait_response();  
  5.   read_response();  
  6.   end_request();  
  7.   delay(100);  
  8. }  
These functions will retrieve the data from the Azure table. But before deep diving into the methods, we need to add some global variables to link our Edison to Azure service. Add these global variables: 
  1. const char* server= "genesis-iot-control.azure-mobile.net";  //service URL  
  2. const char* table_name= "cloudcontroller"; //Table name  
  3. const char* ams_key="Your application key";  
  4. char buffer[150];
 The application key can be found in the manage keys button at your Azure portal. Now, we will write the code for the methods in void loop(). 
  1. void send_request()  
  2. {  
  3.   Serial.println("\nconnecting...");  
  4.   
  5.   if (client.connect(server, 80)) {  
  6.   
  7.   
  8.     // POST URI  
  9.     sprintf(buffer, "GET /tables/%s HTTP/1.1", table_name);  
  10.     client.println(buffer);  
  11.   
  12.     // Host header  
  13.     sprintf(buffer, "Host: %s", server);  
  14.     client.println(buffer);  
  15.   
  16.     // Azure Mobile Services application key  
  17.     sprintf(buffer, "X-ZUMO-APPLICATION: %s", ams_key);  
  18.     client.println(buffer);  
  19.   
  20.     // JSON content type  
  21.     client.println("Content-Type: application/json");  
  22.   
  23.     client.print("Content-Length: ");  
  24.     client.println(strlen(buffer));  
  25.   
  26.     // End of headers  
  27.     client.println();  
  28.   
  29.     // Request body  
  30.     client.println(buffer);  
  31.       
  32.   } else {  
  33.     Serial.println("connection failed");  
  34.   }  
  35. }  
We performed an HTTP request and called GET where we have indicated the name of the table previously, the name of the Server and code key; this to allow the correct retrieval of the data. Then we specified in what format the data needs to be retrieved and specified it as JSON. Let's write the code for wait_response(). 
  1. void wait_response()  
  2. {  
  3.   while (!client.available())   
  4.   {  
  5.     if (!client.connected())   
  6.     {  
  7.       return;  
  8.     }  
  9.   }  
  10. }  

Then we need to read the data retrieved. Since it's in JSON format, we need to parse the JSON string to get our desired value. Below is the example of a sample string.

{"id":"2492D996-C471-48F0-B3C9-F33E3B37477F","status":"0","name":"arduino"}

A very efficient library known as the ArduinoJson exist. This will do most of the parsing. But the retrieved JSON string is enclosed within '[' and ']'. These must be removed for the library to work. So, firstly you need to include the library in your code and add the following global variables and add:

  1. #include <ArduinoJson.h>    
  2.    
  3. #define RESPONSE_JSON_DATA_LINENNO 10    
  4.     
  5. int charIndex=0;    
  6. StaticJsonBuffer<200> jsonbuffer;     
Then write the following code in your read_response() method: 
  1. void read_response()  
  2. {  
  3.   boolean bodyStarted;  
  4.   int jsonStringLength;  
  5.   int jsonBufferCntr=0;  
  6.   int numline=RESPONSE_JSON_DATA_LINENNO;  
  7.   //Ignore the response except for the 10th line  
  8.   while (client.available())   
  9.   {  
  10.     //Serial.println("Reading:");  
  11.     char c = client.read();    
  12.     if (c == '\n')  
  13.     {  
  14.       numline -=1;  
  15.     }  
  16.     else   
  17.     {  
  18.       if (numline == 0 && (c!='[')&& (c!=']') )  
  19.       {  
  20.         buffer[jsonBufferCntr++] = c;   
  21.         buffer[jsonBufferCntr] = '\0';   
  22.       }  
  23.     }  
  24.   }  
  25.   Serial.println("Received:");  
  26.   Serial.println(buffer);  
  27.   Serial.println("");  
  28.   parse();  
  29. }  
The above code will read the response and the parse method is responsible for decoding the string. The parse() method is shown below. In the parse() method itself, we will change the status of the PIN13. 
  1. void parse()  
  2. {  
  3.   StaticJsonBuffer<150> jsonbuffer;  
  4.   JsonObject& root = jsonbuffer.parseObject(buffer);  
  5.   if(!root.success())  
  6.   {  
  7.     Serial.println("PARSING FAILED!!!");  
  8.     return;  
  9.   }  
  10.   int f= root["status"];  
  11.   Serial.println("Decoded: ");  
  12.   Serial.println(f);  
  13.   if(f==0)  
  14.     digitalWrite(13,LOW);  
  15.   else  
  16.     digitalWrite(13,HIGH);  
  17. } 

Here, in the above code, f stores the value of the attribute of status. Then, we check the value of f and ultimately set the PIN either to HIGH or LOW.

For a detailed documentation on ArduinoJson library visit this link. However, there is a bit of problem with this library. It will be discussed later on. Now, we will write the remaining method's code. 

Now, you will see that when you compile the code, you will most likely encounter some errors. These errors needs to be removed. Before moving further have a look over this issue. The file WString.h misses some lines of code. The difference can be seen here. You need to update the file located here.

C:\Users\Username\AppData\Roaming\Arduino15\packages\Intel\hardware\i686\1.6.2+1.0\cores\arduino\WString.h

After updating your errors will be resolved. After you compile the code, burn it into your Edison and then you are done. When the code is burnt in your Edison, take a LED, and attach the longer leg of the LED to PIN13 and the shorter leg to Gnd. An optional 233 ohm resistor can be added with the longer leg. Thus, our Windows Phone controlled Edison via Windows Azure is ready. The screenshot of the serial window while the Edison is in action is shown below.

The first stage is when the Edison is attempting to connect to the Wi-Fi network.

 
 
The next stage is when the Edison is trying to connect to the Azure mobile service. After connecting, it obtains the JSON data which is then decoded by the JSON library and then we obtain the decoded result. The decoded result is responsible for the status of the PIN13 on the Edison.
 
 

Conclusion

Thus we have learnt in this article how to control your Edison using Azure mobile services. The Mobile service acts as a bridge. The Windows phone app alters data in Azure tables and ultimately the Edison is controlled. The article didn't cover the Windows phone development but a look at the links will provide you the info required. The entire Edison code is uploaded as a text file. The YouTube link for the video is here. If any problem regarding Wstring is encountered, then please leave a comment about the error.

Note: The pink lines in the article appears as it was copied from another article written by me at Intel Software for IoT. Link is here. Please ignore that.