WIFI Week: Communicating with Computers

Wifi sensor connects with TCP and we can now connect to computers and other internet stuff.One of the most exciting things you can do with the Wifi Sensor is to send and receive data from a computer or other internet-enabled device.  For example, you can send information or commands to a robot, or gather data from the robot.

One of the easiest ways to do this is with a TCP connection.  TCP is a two-way communication protocol that operates over the internet.  The WIFI sensor can serve as both a server (handling multiple connections coming in) and a client (connecting to one server).

Setting up a TCP Server

Setting up a TCP Server is short and simple with the Wifi Sensor.

  1. Start TCP – Starting the TCP is easy.  You must specify which TCP port to start the server on.  The newly setup TCP server’s CID will be returned.  In our example, we show how this CID is captured into a variable and used later.

Sending and Receiving Information on the Server

In the TCP protocol, messages are surrounded by tags that indicate when the information starts and stops.  The message starts with the tag <ESC>S<CID> where ESC is the escape character, “S” is . . .  well, S, and <CID> is the CID the TCP server is working on.  A message ends with <ESC>E.

For example, a message that says “Hello Dexter Industries” on CID number 1 would look like this: <ESC>S0 Hello Dexter Industries! <ESC>E

Incoming data into the server is also surrounded by these two tags.  When we start our server, we wait for something to connect to the server we just set up.  Then we “parse” or “listen” for the <ESC>S.

In the below RobotC example below, when we receive the <ESC>S, we print the value out on the NXT screen and play a sound.  Thus we have a very crude Musical Instant Messaging program (first ever, we claim it!).

Connecting to our Server with a Computer

You can now connect to your NXT using a terminal program such as Putty or Teraterm.  We will use Teraterm (Teraterm is free for download here).  We type in the IP the NXT got when it connected to the wifi network, and we specify Port 20.

Now, when we type in Teraterm terminal, the message shows up on the screen of the NXT, along with some beautiful music.

Video:

See a short video of us connecting to the NXT and sending it a wonderful note via our Musical G Chat program.



Example Programs in RobotC

DIWIFI_TCP.c

[sourcecode language=”cpp”] //
// TCP Server Example for Dexter Industries Wifi Sensor
//
// This program will setup a TCP server on the Dexter Industries Wifi Server.
// You can connect to it with a Terminal emulator such as Telnet or Tera Term.
// Simply connect to the IP on Port 20 (after connecting to a wifi network).
//
// After connecting with a terminal, everything you type will be shown on
// the screen of the NXT and a musical noise will play after each character.
//
// For more information on the Dexter Industries WIFI sensor,
// visit http://dexterindustries.com/manual/wifi/
//
// This project relies heavily on code from Xander Soldaat.
// See some of his brilliant projects at http://www.botbench.com
////////////////////////////////////////////////////////////////////////////////////
#include "drivers/common.h"
#include "DIWIFI-TCP_Server.h"

task main()
{
closeAllConns(); // Close all connections. If any other CID’s are open, close them.
int cid = startTCP(20); // Start TCP on Port 20. Gets a CID for the connection.
// *A CID is a connection identification.
writeDebugStreamLine("CID:%i", cid); // Write the CID assigned by the sensor.
clear_read_buffer(); // Clean up.
echo_tcp(cid); // Wait for a response and run.
}

[/sourcecode]

DIWIFI_TPC.h

[sourcecode language=”cpp”] ubyte BytesRead[8];
ubyte newline[] = {0x0D};
ubyte rxbuffer[1500];
typedef ubyte buff_t[128];
buff_t buffer;

void debugnxtWriteRawHS(const ubyte &pData, const short nLength)
{
string tmpString;
ubyte buff[30];
memset(buff[0], 0, 30);
memcpy(buff[0], pData, nLength);
StringFromChars(tmpString, buff);
writeDebugStream("%s", tmpString);
nxtWriteRawHS(pData, nLength);
}

int appendToBuff(buff_t &buf, const long index, const ubyte &pData, const long nLength)
{
if (index == 0) memset(buf, 0, sizeof(buf));
memcpy(buf[index], pData, nLength);
return index + nLength;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Receive Bytes
// Reads whatever is in the buffer and prints to debug
////////////////////////////////////////////////////////////////////////////////////////////////////////

void Receive(bool wait=false)
{
if (wait)
while (nxtGetAvailHSBytes() == 0) wait1Msec(5);

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

////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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};
debugnxtWriteRawHS(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);
}

void closeAllConns() {
writeDebugStreamLine("closeAllCons");
ubyte close_cmd[] = {‘A’,’T’,’+’,’N’,’C’,’L’,’O’,’S’,’E’,’A’,’L’,’L’,0x0D};
debugnxtWriteRawHS(close_cmd[0], sizeof(close_cmd)); // Send the command, byte by byte.
Receive(true);
}

// Starts up a TCP server gets the CID.
int startTCP(long port) {
int index = 0;
int cid = 0;
ubyte listen_cmd[] = {‘A’,’T’,’+’,’n’,’s’,’t’,’c’,’p’,’=’,’2′,’0′};
index = appendToBuff(buffer, index, listen_cmd, sizeof(listen_cmd));
index = appendToBuff(buffer, index, newline, sizeof(newline));
debugnxtWriteRawHS(buffer[0], index);
while (nxtGetAvailHSBytes() == 0) wait1Msec(5);
while (nxtGetAvailHSBytes() > 0) {
nxtReadRawHS(BytesRead[0], 1);
writeDebugStream("%c", BytesRead[0]);
if(BytesRead[0] < 58 && BytesRead > 47){ // So if it’s a number . . .
cid = BytesRead[0]-48; // Works for connections 0 through 9.
}
wait1Msec(2);
}

return cid;
}

void parseTCP(int cid_connection)
{
writeDebugStreamLine("Parse TCP");

ubyte BytesRead[20];
ubyte currByte[] = {0};
ubyte prevByte[] = {0};
ubyte conn[] = {0};
int tone = 0;
int lineNum = 6;
int colNum = 0;
string tmpString;

int index = 0;
while(true)
{
alive();
if (nxtGetAvailHSBytes() > 0)
{
nxtReadRawHS(currByte[0], 1);
if ((prevByte[0] == 27) && (currByte[0] == ‘S’)) {
index = 0;
memset(rxbuffer, 0, sizeof(rxbuffer));
wait1Msec(1);
nxtReadRawHS(conn[0], 1);
while (true) {
while (nxtGetAvailHSBytes() == 0) EndTimeSlice();
nxtReadRawHS(currByte[0], 1);
if ((prevByte[0] == 27) && (currByte[0] == ‘E’)) {
rxbuffer[index–] = 0;
rxbuffer[index–] = 0;
break;
}
prevByte[0] = currByte[0];
rxbuffer[index++] = currByte[0];
}
for (int i = 0; i < ((index / 19) + 1); i++) {
memset(BytesRead[0], 0, 20);
memcpy(BytesRead[0], rxbuffer[i*19], 19);
StringFromChars(tmpString, BytesRead);
tone = (int)BytesRead[0];
tone = tone*10;
PlayTone(tone, 10);
while(bSoundActive) EndTimeSlice();
writeDebugStream(tmpString);

colNum++;
if(colNum > 12) {
colNum = 0;
lineNum–;
}
if(lineNum == 0) lineNum = 6;
nxtDisplayStringAt(colNum*6, lineNum*10, tmpString);
}
}
prevByte[0] = currByte[0];
}
wait1Msec(1);
}
}

void echo_tcp(int cid){
writeDebugStream("TCP Server Started.");
writeDebugStreamLine("Listening.");
parseTCP(cid);
}

[/sourcecode]

0 Comments

Leave a reply