Processing Serial Input Example
Last Modified: 2006-11-08
find:

basket

Acroname Robotics PDF webpage version Processing Serial Input Example PDF

Related
Products

Product image for Brainstem GP 1.0 Module
Brainstem GP 1.0 Module

Contents

Introduction

This example illustrates techniques for processing serial input in a TEA program.  Developing a TEA program to process serial input can be tricky when using only one BrainStem module since a module has only one serial port.  A user must switch back and forth between programming through the serial port and sending data to the TEA program through the serial port.  The user must also figure out some way to get debugging information.  Networking two modules together makes things much easier.  The user can connect one module to a host running the Console application.  The other module may be connected to a serial device.  With the I2C network connection, the Console program can download code into the module connected to the serial device.  That module can issue print statements to send debugging data back to the Console. 

Create a BrainStem Network for Additional Serial Ports

This example was developed with two GP modules networked together via their I2C bus connectors.  One module is connected to a host computer running the Console application.  A few cmdVAL_SET and cmdVAL_SAV commands are necessary to configure the network. 

A GP module has a default I2C address of 2.  One module will need a different address.  When a GP module is connected to the host, the following Console commands will change its address to 4 and make it the router in the network:

2 18 1 4 2 18 0 4 4 19

These commands will set the other module's serial port to operate at 4800 baud and make it route through module 4:

2 18 4 1 2 18 1 4 2 19

To apply the baud rate change, cycle power or send a cmdRESET command to module 2.  Now a serial device can be connected to module 2.  TEA programs can be loaded into either module by picking the module's address.  When either module runs a TEA program with print statements, the text will be displayed in the Console. 

The Serial Input Data

For this example, a test program simulates a serial device by sending out the following 20-character ASCII data packet every second:

@-1234,+5678,+0054,N

The test program is also configured for 4800 baud and uses 8 data bits, no parity, and 1 stop bit.  A computer with two serial ports works well for testing.  On a PC, a test program can run on one COM port and send data to the Stem that is acting as the serial device interface.  The Console can communicate with the other Stem through the other COM port. 

Note

If you have a C compiler and are already familiar with writing projects that use the BrainStem C libraries, you can use the following C program to generate test packets on a host computer.  This source file uses the aIO library.  Proper configuration of the project is left to the user. 

Source Code - C File to Create Serial Data

/* filename: serialtest.c */ #include "aIO.h" #define aPORTNAME "COM1" #define aPORTSPEED 4800 void loop(); void loop(aIOLib ioRef, aStreamRef streamRef) { int n = 0; aErr err; char buff[24]; aStringCopy(buff, "@-1234,+5678,+0054,N"); while (1) { printf("ping %i\n", n++); aStream_Write(ioRef, streamRef, buff, 20, &err); aIO_MSSleep(ioRef, 1000, NULL); } } void main(int argc, void argv[]) { aErr err; aIOLib ioLib; aStreamRef serialStream; /* Get the references to the aIO object. */ aIO_GetLibRef(&ioLib, &err); /* Build a link stream to communicate serially. */ if (err == aErrNone) aStream_CreateSerial(ioLib, aPORTNAME, aPORTSPEED, &serialStream, &err); loop(ioLib, serialStream); /* release the libraries now that we are done */ aStream_Destroy(ioLib, serialStream, &err); aIO_ReleaseLibRef(ioLib, NULL); }

Source Code - TEA Program to Process Serial Data

With a fixed-size serial data packet, the code for receiving and storing a packet can be quite compact.  Using native BrainStem VM opcodes provides extra efficiency.  In the example program, the get_packet routine does all the serial input work.  A loop continually checks incoming serial bytes for a '@' delimiter that signals the start of a packet.  When the routine sees this character, it executes a command to read the 19 remaining characters in the packet.  Then it stores the bytes in a global buffer for further processing.  A series of two-byte popssa operations make the data transfer as efficient as possible.  A final single-byte popbsa operation transfers the final odd byte.  This technique is similar to that used in the Nod example.  Due to the overhead of the delimiter loop, the program will only work at baud rates of 9600 baud or lower.  At higher baud rates, data bytes may be missed after the delimiter. 

The arrayRdChar routine is taken direcly from the array example.  It may be used to grab characters from the global buffer.  Some simple calculations and loop logic can convert the numeric strings into integer values.  The extractIntFromArray routine constructs an int variable from a sign character and a four-digit value padded with leading zeros.  The dumpArray routine is useful for debugging.  It prints the contents of the buffer.  The loop in the main routine grabs a data packet, prints the data buffer, extracts integer variables from the buffer, and prints them. 

/* filename: serialin.tea */ #include <aCore.tea> #include <aPrint.tea> #define PACKET_SIZE 19 // create and initialize a global array #define gl_ARRAY_START 0 #define gl_ARRAY1 gl_ARRAY_START + 0 #define gl_ARRAY1_SIZE 20 char c00 = 0; char c01 = 0; char c02 = 0; char c03 = 0; char c04 = 0; char c05 = 0; char c06 = 0; char c07 = 0; char c08 = 0; char c09 = 0; char c10 = 0; char c11 = 0; char c12 = 0; char c13 = 0; char c14 = 0; char c15 = 0; char c16 = 0; char c17 = 0; char c18 = 0; char c19 = 0; void get_packet() { asm { // loop looking for start delimiter loop1: pushlb '@' pushlb 1 popbm aPortSerialNRX popb subb popb brnz loop1 // read fixed size packet into stack buffer pushlb PACKET_SIZE popbm aPortSerialNRX popb // move bytes to global buffer // (move 2 at time when possible for efficiency) popssa 18 popssa 16 popssa 14 popssa 12 popssa 10 popssa 8 popssa 6 popssa 4 popssa 2 popbsa 1 } } char arrayRdChar(int addr, int x) { char val=0; asm { pushss 7 // push addr pushss 7 // push x adds // calculate addr+x pushsbax // get byte at stack[addr+x] popbs 1 // put byte in val } return val; } int extractIntFromArray(int addr, int x) { int sign = 1; int num = 0; int fac = 1000; int i; if (arrayRdChar(addr, x) == '-') sign = -1; for (i = 1; i <= 4; i++) { num = num + (arrayRdChar(addr, x + i) - 48) * fac; fac = fac / 10; } return sign * num; } void dump_array(int addr, int n) { int i; char c; for (i = 0; i < n; i++) { c = arrayRdChar(addr, i); if (c == 0) c = '#'; aPrint_Char(c); } aPrint_Char('\n'); aCore_Sleep(100); } void main() { int a = 0; int b = 0; int c = 0; while (1) { get_packet(); dump_array(gl_ARRAY1 + 1, PACKET_SIZE); a = extractIntFromArray(gl_ARRAY1, 1); b = extractIntFromArray(gl_ARRAY1, 7); c = extractIntFromArray(gl_ARRAY1, 13); aPrint_IntDec(a); aPrint_Char(','); aPrint_IntDec(b); aPrint_Char(','); aPrint_IntDec(c); aPrint_Char('\n'); } }

Revision History:

  • 2004-05-10: Example Created.
 
 
voice: 720-564-0373, email: sales@acroname.com, address: 4822 Sterling Dr., Boulder CO, 80301-2350, privacy
© Copyright 1994-2008 Acroname, Inc., Boulder, Colorado. All rights reserved.