The Internet of Things: Thingspeak With DIWIFI and LEGO MINDSTORMS NXT

WIFI Week 2 Header LEGO MINDSTORMS

The INTERNET of Things for LEGO MINDSTORMS NXT

Thingspeak with LEGO™ MINDSTORMS™ NXT

More on the internet of things today!  This post shows you how to use the WIFI Sensor for LEGO MINDSTORMS to post data to Thingspeak.com.

Thingspeak is “an open application platform designed to enable meaningful connections between things and people”.  In other words, meaningful connections between robots and people.

Thingspeak is very similar to Pachube.  The major difference we’ve found is that it’s easier to display data on Thingspeak.  You can make graphs, process data, and visualize data a little easier.

Thingspeak: now for LEGO MINDSTORMS NXT

Is your robot telling you something?

Thingspeak can be used for

  • Sensor monitoring
  • Energy monitoring
  • Connecting devices and systems
  • Geo location tracking
  • Interfacing with social networks

These are some simple ideas, but you can do a lot more with Thingspeak.  Cloud Computing is all the rage these days, and Thingspeak allows you to use the cloud to store data and do calculations.  This could be especially powerful for the NXT:  with its limited memory and processing, the cloud could be used for some really impressive algorithms and functions.

We have developed an example in RobotC for posting information up on Thingspeak with the WIFI Module for LEGO MINDSTORMS NXT.  The example posts static data, but can be easily changed to fit your project.  The code is well documented and commented so it should be easy to follow along and, if you’d like, convert to other languages.

Like our previous post, we’ve left the data channel information in this code.  Go ahead and post something.  Thingspeak offers free accounts, so you can setup your own channel and start sharing your data with the world for free.

[iframe_loader src=”https://thingspeak.com/channels/1927/charts/1?timescale=1440&days=300&dynamic=true&title=WIFI%20for%20LEGO%20MINDSTORMS”]

You can view our channel here:  https://thingspeak.com/channels/1927?public=true

See the RobotC code below to get started:

DIWIFI-Thingspeak.c

[sourcecode language=”cpp”]

// Connect to Thingspeak!
//
// DIWIFI-Thingspeak posts information on the "Internet of Things" to Thingspeak information online.
//
// "Creat your Internet of Things application with ThingSpeak. An open application platform designed
// to enable meaningful connections between things and people."
// – http://thingspeak.com
//
// This program uses the HTTP client in the Dexter Industries DIWIFI sensor to send information to Thingspeak.
// We have left our account information on this example to provide a complete example. Post whatever you
// want to this channel, it’s just meant to allow you to try the service out.
//
// To setup your own Thingspeak feed, just change the variables at the tope of the Thingspeak.h file, and change the
// API Key.
//
// See more about the Dexter Industries Wifi Sensor for the Lego Mindstorms NXT here: http://www.dexterindustries.com/wifi.html
//
// Run this program with the RobotC Debugging Stream On to view any errors.
// For more information visit http://www.dexterindustries.com/
// Dexter Industries, 2012. Feel free to use as you see the need to but give credit where credit is due.
//////////////////////////////////////////////////////////////////////////////////////////////////////

#include "drivers/common.h"
#include "DIWIFI-Thingspeak.h"

task main()
{
clear_read_buffer();
int CID = 0;

closeAllConns(); // Housekeeping: Close any open connections.
clear_read_buffer(); // Housekeeping: Clear out the buffer.
CID = TCP_client(); // Connect to an IP number. This will connect us to Thingspeak.com’s site.
writeDebugStreamLine("%i", CID); // Spit out the CID. Mostly a debuggin information.
TCP_Send(CID); // This kicks off the meat of the project. Send information out!
while(true){ // Listen for a response, show it on the screen.
Receive(true);
}
}
[/sourcecode]

DIWIFI-Thingspeak.h

[sourcecode language=”cpp”] #include "drivers/DTMP-driver.h"

string postinfo = "126"; // This is where we’re going to put information. Put whatever number you like here.
string channel = "sensor1"; // This is the channel name. You can setup your own at Thingspeak.com

string API_Key = "VFCVSDCNSX4HLOZB"; // Obtain API Key
string IP_num = "184.106.153.149"; // The IP number of thingspeak.com
ubyte BytesRead[8]; // Important for getting information from responses. Don’t change this.

ubyte byteStart[] = {27, ‘S’, ‘0’}; // The escape sequence to start TCP. Don’t change this.
ubyte byteEnd[] = {27, ‘E’}; // The escape sequence to end the TCP. Don’t change this!

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Clear Read Buffer
// Run this to clear out the reading buffer. Simply sends a carriage return, then clears the buffer out.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void clear_read_buffer()
{
ubyte nData[] = {13};
nxtWriteRawHS(nData[0], 1); // Send the carriage return
wait10Msec(100);
while(BytesRead[0] < 0){
nxtReadRawHS(BytesRead[0], 1); // Read the response. Probably an error.
}
wait10Msec(100);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// WriteStr
// This function writes a string to the DebugStream and Port4. We wrote this out because it is easier to recognize and see
// strings; easier than working with arrays of characters.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void writeStr(string sData)
{
// writeDebugStream(sData);
ubyte byteData = 0;
for(int i = 0; i < strlen(sData); i++)
{
byteData = strIndex(sData, i);
nxtWriteRawHS(byteData, 1);
writeDebugStream("%c", byteData); // Critical for debugging. Make sure you’re getting some time in there
// to read what you wrote.
while(nxtHS_Status < 6) wait1Msec(1);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// WriteLineBreak
// This function just writes a line break to DebugStream and Port4. It is necessary to have this in
// RobotC because strings are limited to 17 characters and sometimes you will need to send commands
// longer than 17 characters.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void writeLineBreak()
{
writeDebugStream("%c", 13);
ubyte newline = 0x0D;
nxtWriteRawHS(newline, 1);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Write CRLN
// This function writes a carriage return and line break to DebugStream and Port4. This is used
// in HTTP communications and ends any line in a HTTP GET or PUT or POST.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void crln()
{
writeDebugStream("%c", 13);
writeDebugStream("%c", 10); // Display this on the debug for our information.
ubyte newline[] = {0x0D, 0x0A}; // Carriage return and then line feed.
nxtWriteRawHS(newline, 2);
wait1Msec(5); // ABSOLUTELY CRITICAL. We added this because
// we found that in line-feeds, the first bytes of the next transmission get
// dropped. VERY IMPORTANT TO HAVE THIS DELAY IN HERE.
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Receive Bytes
// Reads whatever is in the buffer and prints to debug.
// if you set the bool input to true, the functio will wait for something to happen on Port 4.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void Receive(bool wait=false)
{
if (wait)
while (nxtGetAvailHSBytes() == 0) wait1Msec(5);

while (nxtGetAvailHSBytes() > 0) {
nxtReadRawHS(BytesRead[0], 1);
writeDebugStream("%c", BytesRead[0]);
wait1Msec(1);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// CloseAllCons
// Closes any connections that are open (CID’s).
////////////////////////////////////////////////////////////////////////////////////////////////////////
void closeAllConns() {
writeDebugStreamLine("closeAllCons");
clear_read_buffer();
writeStr("at+ncloseall");
writeLineBreak();
wait10Msec(10);
Receive(true); // Wait for your response. Pray?
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Start TCP client
// Connects to an IP number. Note that the IP number is defined at the top.
////////////////////////////////////////////////////////////////////////////////////////////////////////
int TCP_client(){
int cid = 0;
string port = ",80"; // We’re going to connect on Port 80, standard for HTTP

writeStr("AT+NCTCP="); // Command to start a connection with TCP
writeStr(IP_num); // Connect to the IP number.
writeStr(port); //
writeLineBreak(); // Send it to the Wifi sensor.

// Don’t replace the following code with a Receive function.
// This code picks out the CID number.
while (nxtGetAvailHSBytes() == 0) wait1Msec(5);
while (nxtGetAvailHSBytes() > 0) {
nxtReadRawHS(BytesRead[0], 1);
writeDebugStream("%c", BytesRead[0]);
if(BytesRead[0] < 58 && BytesRead[0] > 47){ // So if it’s a number . . .
cid = BytesRead[0]-48; // Works for connections 0 through 9.
}
wait1Msec(2);
}
return cid; // Sends back the CID in integer form.
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// TCP Send Data
// Sends data to the server Thingspeak server. YOu need to be connected before using this function.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void TCP_Send(int CID){
wait1Msec(250);
byte byteCID = CID+48; // Turn the CID into a character value.
byteStart[2] = byteCID; // Replace the O with the cahracter value of the CID.
nxtWriteRawHS(byteStart, 3);
nxtWriteRawHS(byteCID, 1);
writeDebugStream("%c", byteStart, 2);
writeDebugStreamLine("%c", byteCID);
Receive(true); // Wait for the response. HOpefully it’s <esc> O.

writeStr("POST "); // Send the post information.
writeStr("/update "); // Generally won’t need to be changed.
writeStr("HTTP/1.1");
crln();

wait10Msec(1);
writeStr("Host: "); // Generally won’t need to be changed.
writeStr("api.thingspeak");
writeStr(".com");
crln();

writeStr("Connection: "); // Generally won’t be changed.
writeStr("close");
crln();

writeStr("X-"); // Generally won’t be changed.
writeStr("THINGSPEAKAPIKEY:");
writeStr(API_Key); // API key is defined above at the top.
crln();

writeStr("Content-Type: "); // Won’t be changed!
writeStr("application/x-");
writeStr("www-form-");
writeStr("urlencoded");
crln();

writeStr("Content-Length: "); // Send the content length of your post
string length = ""; // The code below automatically caculates this value for you.
StringFormat(length, "%i", (strlen(postinfo)+1+strlen(channel)));
writeStr(length); // This sends the value along.
crln(); // VERY IMPORTANT: need to send to Carriage Return / New Line, before sending data.
crln();

writeStr(channel); // Sends the channel information on where the data is headed.
writeStr(","); // Put a comma in between.
writeStr(postinfo); // Send the post information along. this is the data you want to send.

wait1Msec(100); // A bit of protocol. Just wait for a second.
nxtWriteRawHS(byteEnd, 2); // Send the byte end; this ends TCP session sending and sends info to server.

while (nxtGetAvailHSBytes() == 0) wait1Msec(5);
while (nxtGetAvailHSBytes() > 0) {
nxtReadRawHS(BytesRead[0], 1);
writeDebugStream("%c", BytesRead[0]);
wait1Msec(2);
}
}
[/sourcecode]

3 Comments

  1. Joraaver May 18, 2012

    Hi, it’s me again. Sorry to have to point this out again, but it says the “Receive” function doesn’t exist. And again, I think it is right. I tried copying and pasting the Receive function based on the Pachube one, but I just wanted to post that here to ensure that it is the same code.

    Thanks!

  2. Dexter Industries May 24, 2012

    Joraaver,
    Again, thanks for pointing this out! We are now back in business and the code should be whole. Thanks!

  3. Joraaver May 24, 2012

    Awesome. Again, thanks for the cool projects and support

Leave a reply