Tuto. 15 - Digital Accel.
PIC tutorial 15 - Digital accelerometer
Fig. 1 Board 4 with I2C/SPI accelerometer in I2C mode
Description:
This second accelerometer tutorial will implement a chip with digital output, on I2C or SPI interface. The chip used is a LIS302D, a 3-axis, ± 2g/± 8g MEMS sensor. The project will display the acceleration on the 3 axis in g.
You will need a processor board, a power supply, the graphical or alphanumeric display on port B and the I2C accelerometer board on the I2C connector.
The boards can be powered by one of the PSU boards (powered from USB port), or between 2.5 to 3.6V.
Requirements:
Processor boardAny board (board 4 in example)
Extension(s)I2C/SPI accelerometer
alphanumeric or graphic LCD display
Power supplyPSU 1, 2 or 3. Max 3.6V
LanguageCCS C
ProgrammerPicKIT 2
Program:
#define board_id 5
#define I2C_LIS302 // Use I2C interface if defined, comment out to use SPI interface
//#define CS_LIS302 CS_SPI0 // CS pin for MEMS sensor
#include "LIS302_on_LCD.h" // load header and libraries
signed int16 accX, accY, accZ;
void main() {
boot_up(); // initialise processor board
init_display(); // initialise display
init_302(); // initialise sensor
while (true) {
poll_302(); // wait until sensor has new data
accX = read_axis_302(LIS302_outX); // read the 3 axis in mG
accY = read_axis_302(LIS302_outY);
accZ = read_axis_302(LIS302_outZ);
display_gotoxy(0,0);
printf(display_putc, "Accelleration:");
display_gotoxy(0,1);
printf(display_putc, "X: %2.2w ",accX/10); // display the 3 axis
display_gotoxy(0,2);
printf(display_putc, "Y: %2.2w ",accY/10);
display_gotoxy(0,3);
printf(display_putc, "Z: %2.2w ",accZ/10);
delay_ms(500);
}
}
The first line defines the processor board used.
The following 2 lines will tell the compiler how the sensor will be connected to the processor board:
If I2C_LIS302 is defined, then the library will use I2C functions to control the chip. If the line is commented out, it will use SPI functions.
The CS_LIS302 defines the chip select line used for the chip on the SPI connector: it can be CS_SPI0, 1 or 2. If not defined, it will default to CS_SPI0.
The header file is then loaded, with the libraries.
The main program initialise the processor board, the display and the sensor.
Then the main loop waits for the sensor to have new data available, and reads each axis. Their values is then displayed on the screen.
The value returned from the read_axis_302 is in mG. The value display is converted to G. the value is divided by 10, which gives hundreth of G, displayed as a number with 2 decimal points.
The header file simply loads the libraries required:
#ifndef _CONFIG_APP_H
#define _CONFIG_APP_H
#if ((board_id == 1) | (board_id == 2)) // use alphanumeric display for board 1 or 2
#define DISPLAY_TYPE "Alpha"
#else // else use Nokia graphic LCD
#define DISPLAY_TYPE "3310"
#endif
#include "../lib/Boards/mainboard.c" // Load processor board library
#include "../lib/Display/lcd_display.c" // Load display library
#include "../lib/Sensors/LIS302.c" // Load accelerometer library
#endif
Most of the functionality is in the LIS302 library:
#ifndef _LIS302_LIB
#define _LIS302_LIB // flag to indicate library is loaded
#include "..\lib\Sensors\LIS302.h" // Load header file
BYTE read_302(BYTE reg) { // Read reg register from LIS302
BYTE datain;
#ifdef I2C_LIS302 // if using I2C interface
i2c_start();
i2c_write(I2C_Accel); // Device address
i2c_write(reg); // Register to read
i2c_start(); // Restart
i2c_write(I2C_Accel+1); // address chip in read mode
datain=i2c_read(0); // Read register
i2c_stop();
#else
reg &= 0x3f; // set bit 6 to 0 for no increment of address
reg |= 0x80; // set bit 7 to 1 for read operation
output_low(CS_LIS302); // Enable LIS302 spi
SPI_out(reg); // send register address
datain = SPI_in(0); // read register
output_high(CS_LIS302);
#endif
return(datain);
}
void write_302(BYTE reg, BYTE data) { // Write data in register at address reg
#ifdef I2C_LIS302
i2c_start();
i2c_write(I2C_Accel);
i2c_write(reg);
i2c_write(data);
i2c_stop();
#else // if using I2C interface
reg &= 0x3f; // set bit 7 and 6 to 0 for write operation with no increment of address
output_low(CS_LIS302); // Enable LIS302 spi
SPI_out(reg); // send register address
SPI_out(data); // send data
output_high(CS_LIS302);
#endif
}
void poll_302(void) { // Poll LIS302 to see if new data available
BYTE sta302 = 0;
while ((sta302 && 0x08) == 0 )
sta302 = read_302(0x27); // check bit ZYXDA from status
}
void config_302(BYTE reg,BYTE data) { // Send data to CTRL_REG reg
write_302(0x1f+reg, data); // reg = 1, 2 or 3
delay_us(10);
}
void init_302() { // Initialise LIS302
#ifndef I2C_LIS302
Init_SPI();
output_high(CS_LIS302);
#endif
delay_ms(100); // power up delay
config_302(2, 0x40); // reboot memory content, 4-wire SPI interface
#if (LIS302_RANGE == 2) // set the range
config_302(1, 0x47); // +/-2g, chip on, enable X,Y,Z
#else
config_302(1, 0x67); // +/-8g, chip on, enable X,Y,Z
#endif
}
signed int16 read_axis_302(BYTE axis){ // returns axis value in mg
signed int8 read;
read = read_302(axis); // read digital value
return ((signed int16)read + offset_LIS) * sensitivity_LIS; // correct it with offset and convert it using sensitivity
}
#endif
The library loads the I2C or SPI library in the header file.
The functions available are:
- read_302: returns the byte from the register in the chip at address reg.
- write_302: writes a byte in the register reg of the chip.
- poll_302: waits for the chip to have new data available (finished conversions)
- config_302: writes config register 1, 2 or 3 with byte.
- init_302: initialise the interface, set the range and start conversions of the chip.
- read_axis_302: returns the value of the axis in mG as a 16 bits signed value.
The library header's file defines a few variables:
#ifndef _LIS302_H
#define _LIS302_H // flag to indicate library is loaded
#ifdef I2C_LIS302 // loads I2C library
#include "../lib/Common/I2C.c"
#else // or SPI library
#include "../lib/Common/SPI.c"
#ifndef CS_LIS302 // check chip select signal defined
#define CS_LIS302 CS_SPI2 // Define CS pin for LIS302 module
#endif
#endif
#ifndef LIS302_RANGE // check if range is defined, and default it to +-2g
#define LIS302_RANGE 2 // range values are 2 or 8
#endif
#if !(LIS302_RANGE ==2 || LIS302_RANGE == 8) // check range is +- 2 or 8
#undef LIS302_RANGE
#define LIS302_RANGE 2
#endif
#if (LIS302_RANGE ==2) // sensitivity (mg/digit) and offset
#define sensitivity_LIS 18 // typical sensitivity from datasheet, for +- 2g range
#define offset_LIS 0 // offset used to correct centre point
#else
#define sensitivity_LIS 72
#define offset_LIS 0
#endif
#define LIS302_outX 0x29 // register address in LIS302 for X, Y and Z axis
#define LIS302_outY 0x2B
#define LIS302_outZ 0x2D
// Functions prototypes
BYTE read_302(BYTE reg);
void write_302(BYTE reg, BYTE data);
void poll_302(void); void init_302();
signed int16 read_axis_302(BYTE axis);
#endif
Fig. 2 Board 4 with I2C/SPI accelerometer in SPI mode
It loads the required library for the connection selected (I2C or SPI).
The range is then defined if not already. It can be set to 2 or 8. If set to anything else, it will default back to 2.
Then come some variables to make implementation and calibration easier:
- sensitivity_LIS: this is the sensitivity of the sensor, as described in the datasheet. It changes with the sensitivity. power supply. It is typically 18mG/digit for +-2 sensitivity, or 72mG/digit for +-8G sensitivity.
- offset_LIS is the offset added to the digital value read from the chip to compensate and get 0g when the sensor is flat (Find the middle point for each axis). The sensor is soldered by hand on the board, so it might not be exactly parallel to the PCB.
Compile the project and program the target with a PicKIT 2 programmer for example. Connect the processor board to the accelerometer on the I2C port and the graphical display on port B. Power up the boards.
The screen will display the acceleration of the 3 axis on 3 lines.
To change the connection type, just comment out the line I2C_LIS302 and recompile the program. It is now ready for SPI connection, like in fig. 2.
Acceleration:
X: 0.05
Y: -0.01
Z: -1.00
Files and links:
Tutorial 15 source files.Processor board 4.
Graphic LCD display.
I2C/SPI accelerometer.

