|
Reading the Crossbow ADXL202EB-232 on a Linux platform |
|
||
|
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 |
|||
The output should look something like this:
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.