Search Microcontrollers

Monday, September 17, 2012

MSP430G2 & Wifly - The internet of things

In the previous two posts I explained how to interface an RN XV wifly module with a Launchpad (MSP430G2553).
In the last post I discussed an easier method that can be used to connect to a remote webserver (or any TCP based service), and today I will implement it with the Launchpad.

First thing I created a simple php page, named pp.php which looks something like this :

<?
 // connect to databse
 //...
 // get $mn and $mv from the request
 // ...
 $sql = "insert into test (tstamp,measureName,measureValue) values (now(),'".$mn."',".$mv.")";
 // execute query
 echo "[[[[ok]]]]";
?>

this page inserts a record into a mysql table called "test".
Suppose my server is http://www,myserver.com, to test the page we need to open a browser and call :

http://www,myserver.com/pp.php?mn=wifly&mv=2.32

Using the technique illustrated in the previous post, I stored the server address into the wifly configuration :


set ip proto 18
set dns name www.myserver.com
set ip address 0
set ip remote 80
set com remote 0
save
reboot

We will use the wifly gpio lines 4,5 and 6 to detect if the module is associated with a ssid, then to ask it to connect with the TCP address stored in the config and once gpio6 is high (tcp connected) we will send the get command via uart.

I connected the pins 2.0, 2.1,2.2 on the launchpad respectively to gpio4,gpio6,gpio5 on the wifly

P2.0 -> gpio4 (associated) - input
P2.1 -> gpio6 (connected) - input
P2.2 -> gpio5 (connect) - output

Let's configure the P2 port on the launchpad :

void configGpio()
{
 P2DIR |=BIT2; // P2.2 output
 // P2.2 is connected to wifly gpio5
 P2DIR &= ~(BIT0 + BIT1); // P2.0 and P2.1 input
 // P2.0 is connected to wifly gpio4
 // P2.1 is connected to wifly gpio6
 P2REN |=BIT0 + BIT1;
 // pulldown resistors
 P2OUT &= ~(BIT2);
}

Then we need a procedure to send  the GET request.
In my case I had to use HTTP/1.1 specifications and chances are that you will have to do the same unless you are working with you local webserver.
The GET command for version 1.1 of the HTTP protocol requires that the Host is always specified at each request, so the GET is someting like :

GET /pp.php?mn=wifly&mv=123.45 HTTP/1.1
Host: www.myserver.com

And this is the procedure I use


void wifly_TCPsend(char *text)
{
 if ((P2IN & BIT0)>0) // wifly is associated
 {
  if ((P2IN & BIT1)>0) // wifly is connected
  {
    UART_TX(text);
    __delay_cycles(16000000); //wait 1 second
      P2OUT &= ~BIT2; // close connection
     __delay_cycles(16000000); //wait 1 second
    wifly_enterCommandMode();
    UART_TX("sleep\0");
    __delay_cycles(160000000); //wait 10 seconds
  } else 
   // associated, but not connected -> let's connect
   P2OUT |= BIT2;  // pulls wifly gpio5 high
 } else
 { // the module is not associated
wifly_enterCommandMode();
UART_TX("join\0");
__delay_cycles(16000000); //wait 1 second
 }
}


This implementation is pretty basic, it works this way :
1) we check if the module is associated to a ssid, if not we try to send a join command. It should not be needed as we pre-configured the module to automatically join the stored ssid
2) Once the module is associated (gpio4 -P2.0- is high) we raise gpio5 (P2.2) to initiate a tcp connection
3) Once the connection has been successfully established, the gpio6 (2.1) goes high and we can send the get request via uart

The main  procedure becomes :


void main(void)
{ // stop the watchdog
 WDTCTL = WDTPW + WDTHOLD; // allow debugging
 configClock();
 configUART();
  configGpio();
 while (1)
 {  
  // do whatever you need here, like getting values from the ADC 
  // or reading sensors via SPI or I2C...
 // then customize the get call according to your needs 
   wifly_TCPsend("GET /pp.php?m=wifly&v=123.45 HTTP/1.1\nHost: www.myserver.com\n\0");
  // you may want to place this in an interrupt timer routine and sleep while waiting 
 }
}

.. and sue enough I have the values logged in my mysql table in my remote webserver. 

One tricky issue is to actually read data from the webserver.
Data is coming back, no issues with that, but the server will send you also some header information, which will force you to parse the content.
Again, parsing a text is no the best thing to do with a device with minim memory, so you may want to use some kind of TAG to identify the only part of text that should be considered.
My php webpage uses

echo "[[[[ok]]]]";

to pass back the "ok" message, so, the launchpad will disregard the incoming uart data until a series of four consecutive "[" are received.
Why would we want to pass data back to the launchpad?
Imagine you store in your webserver the configuration to manage the heating system of your Chalet.
When you decide it's a good weekend to go there, you may want to turn the heating on (or increase the temperature) few hours before, then to turn it off automatically at the end of the weekend.
Your launchpad, installed in your chalet, will read the current temperature (it has a temp sensor inside), every minute it will check with your webserver what it has to do with that temperature.
The webserver will check and will send back a "ON" or "OFF" response.


There are plenty of possible implementations, let me know your ideas! 

2 comments:

pemozo said...

Hi,

i am trying to make a put request but it doesn't work.
Here is the code:

void main(void)
{ // stop the watchdog
WDTCTL = WDTPW + WDTHOLD; // allow debugging
configClock();
configUART();
configGpio();
while (1)
{
// do whatever you need here, like getting values from the ADC
// or reading sensors via SPI or I2C...
// then customize the get call according to your needs
wifly_TCPsend("PUT /api/newdeveloper/lights/1/state HTTP/1.1\n"
"Host: 192.168.1.6\n"
"Connection: keep-alive\n"
"Content-Length: 45\n"
"Origin: http://192.168.1.6\n"
"Content-Type: text/plain;charset=UTF-8\n"
"Accept: */*\n"
"Referer: http://192.168.1.6/debug/clip.html\n"
"Accept-Encoding: gzip,deflate,sdch\n"
"Accept-Language: en-US,en;q=0.8\n\n"
"{\"on\":true}\0");
// you may want to place this in an interrupt timer routine and sleep while waiting
}
}

Maybe you know where the mistake could be?

Thanks in advance

Franz said...

Hello,
you are sending data in a while(1) loop, with no delay.
In that way you flood the device.

Besides that I noticed I had issues when using long urls, never understood why actually, does not seem to be an issue with the parameter buffer itself in the wifly_TPCsend function.
That might be the issue, I managed to work around by using shorter urls, so I stopped investigating further.
At the moment I do not have a working wifly I can use for experiments, unfortunately.