Reading the Crossbow ADXL202EB-232 on a Linux platform

back to notes

 

The Crossbow ADXL202EB-232

The Crossbow ADXL202EB-232 is an evaluation board of the ADXL202 by Analog Devices, a very popular dual axis accelerometer, sensing tilt and acceleration in a plane (on the X- and Y-axes). You could use it for detecting and recognizing motions or positions of whatever you attach the device to. See here for some applications.

The board has a serial port that can be connected to a PC to read, store or analyse the sensor data. The protocol is very simple: send an ASCII 'G' over the serial line, and the board will send back four bytes: 2 bytes per sensor. The serial port is set to 38400, 8 data bits, no stop bits, no parity, no flow control. You can use these settings for instance in HyperTerminal (MS Windows) or Minicom (Linux) to test the Crossbow board.

 

   

The serial port in Linux

In order to read the values from the board within a C or C++ program, we must program a serial port to be able to send the 'G' and receive the values. Detailed information can be found in the serial howto and the serial programming howto.

Also make sure that you have the right permissions to access the serial ports in Linux (/dev/ttyS0, /dev/ttyS1, and so on) . To change the permissions of first serial port (COM1 or ttyS0) for instance, type: "chmod a+rw /dev/ttyS0".

 

   

The Sourcecode of xbow.cpp

////////////////////////////////////////////////////////////////////////////////////////////
//
//	   Xbow reader for linux
//
//			   by Kristof Van Laerhoven, kristof@comp.lancs.ac.uk
//
//	   version history: its too simple.. thanks to the serial programming howto
//
////////////////////////////////////////////////////////////////////////////////////////////

///// includes /////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/signal.h>
#include <sys/types.h>

///// defines //////////////////////////////////////////////////////////////////////////////

#define MODEMDEVICE "/dev/ttyS0"	 /* /dev/ttySA0 uses a different UART */

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE  1
#endif

///// globals //////////////////////////////////////////////////////////////////////////////

struct termios	orig, new_t;			// new and old terminal

static int	peek = -1;					// kbhit/getch

////// check for a key-pressed event //////////////////////////////////////////////////////

int  kbhit(void)
{
	char ch;
	int nread;

	if (peek != -1) {
		return 1;
	}

	new_t.c_cc[VMIN]=0;
	tcsetattr(0,TCSANOW, &new_t);
	nread = read(0, &ch, 1);
	new_t.c_cc[VMIN]=1;
	tcsetattr(0, TCSANOW, &new_t);

	if (nread==1) {
		peek = ch;
			return 1;
	}

	return 0;
}

////// get character from input ///////////////////////////////////////////////////////////

int  getch(void)
{
	char ch;

		if (peek != -1) {
		   ch = peek;
		   peek = -1;
		   return ch;
		}

		read(0,&ch,1);
		return ch;
}

////// main function //////////////////////////////////////////////////////////////////////

int main(int ac, char **args) {

	 int fd,c,i, res, baudrate;
	 unsigned char ch;
	 FILE *fp;
	 unsigned int bufsize,interval;

	 struct termios oldtio,newtio;

	 if (ac>1)
		interval = atoi(args[1]);
	 else
		interval = 0;

	 // terminal input properties (for getch & kbhit)
	  tcgetattr(0, &orig);
	  new_t = orig;
	  new_t.c_lflag &= ~ICANON; 		// no canonical input
	  new_t.c_lflag &= ~ECHO;		// no echo
	  new_t.c_lflag &= ~ISIG;		// no ISIG
	  new_t.c_cc[VMIN] = 1;
	  new_t.c_cc[VTIME] = 0;
	  tcsetattr(0, TCSANOW, &new_t);

	 baudrate = B38400; // default
	 bufsize = 1024;

	 unsigned char *buf;
	 buf = new unsigned char [bufsize];

	 // open the device to be non-blocking (read will return immediatly)
	 printf("Opening the serial port... ");
	 fd = open(MODEMDEVICE, O_RDWR | O_NDELAY);
	 if (fd <0) {
			perror(MODEMDEVICE);
			exit(-1);
	 }
	 else {
			printf("Success.\n\r");
	 }

	 tcgetattr(fd,&oldtio); // save current port settings
	 printf("Saved current port settings.\n\r");

	 // set new port settings for canonical input processing
	 newtio.c_cflag = baudrate | CS8 | CLOCAL | CREAD;
	 newtio.c_iflag = IGNPAR ;
	 newtio.c_oflag = 0;
	 newtio.c_lflag = 0;
	 newtio.c_cc[VMIN]=0;
	 newtio.c_cc[VTIME]=0;
	 res = tcflush(fd, TCIFLUSH);			printf("flush returned %i\n\r",res);
	 res = tcsetattr(fd,TCSANOW,&newtio);		printf("set attr returned %i\n\r",res);

	 ch = 0;

	 while (ch!='q' && ch!='Q') {

		 // send a 'G' (asking for data)
		 res = write(fd,"G",1);
				 usleep(interval); // wait a while
				 printf("?");
		 // read values from serial port
		 res = read(fd,buf,bufsize);		// read buffer

		 if (res==-1) {
			//debug: perror(MODEMDEVICE);
						printf("-\n\r");
		 }
		 else {
			 if (res>3) {
				// see the xbow datasheet for these formula:
				 printf("%3.2f ", (float)(256*buf[0]+buf[1])/100);
				 printf("%3.2f \n\r", (float)(256*buf[2]+buf[3])/100);
			 }
		 }

		 // check for input
		 if (kbhit()) {
			ch = getch();
		 }

	 } //while no q or Q has been typed

	 // restore old settings
	 tcsetattr(fd,TCSANOW,&oldtio);
	 tcsetattr(0, TCSANOW, &orig);

	 delete []buf;

}

 

   

Building the executable

  • Copy the source from the previous section in a file called xbow.cpp
  • and build the executable, by typing: "gcc xbow.cpp -o xbow"
  • connect the crossbow to COM1 (/dev/ttyS0)
  • run xbow: "./xbow"
  • if you want to set the program to a lower speed, add a parameter for the delay: "./xbow 1000"

The output should look something like this:

Opening the serial port... Success.

Saved current port settings.

flush returned 0

set attr returned 0

 51.78  48.12

 51.78  48.21

 51.54  48.12

and so on. The values will be between 0 and 100.

 

   

Matlab Sourcecode

function [output] = xbow(comport,num)
% Reads, stores and plots data coming from the 
% XBow ADXL202EB-RS232.
% example:
%   A = xbow('COM2',100)
%
% by Kristof Van Laerhoven (kristof@comp.lancs.ac.uk)
%

s = serial(comport);
set(s, 'BaudRate', 38400);
set(s, 'Parity', 'none');
set(s, 'ReadAsyncMode', 'continuous');
set(s, 'DataBits', 8);
set(s, 'StopBits', 1);
set(s, 'BytesAvailableActionMode', 'byte');
set(s, 'FlowControl', 'none');
set(s, 'TimeOut', 1);
set(s, 'Tag', 'XBow' );
set(s, 'RequestToSend', 'on');

fopen(s)

output = [ 0 0 ];
    
for l=1:num,
        
        fwrite(s,'G')       % ask for accel. data
	
        out = fread(s,4,'uchar');    % read 4 bytes 
        
        output = [ output; [ (256*out(1)+out(2))/100 (256*out(3)+out(4))/100] ];
       
end
    
plot(output);
drawnow;
  
fclose(s)
delete(s)
clear s

 

   
 

Compiled by Kristof Van Laerhoven.