Tuto. 15 - Digital Accel.

PIC tutorial 15 - Digital accelerometer

Print
Category: PIC Tutorials
Published Date Written by Francois

Tutorial 15

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. 

You can download the files for this tutorial in the zip file pic_tutorial15.zip.

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


Tutorial 15b

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.

Post your comments...

    Copyright 2011. Poker Games. Copyright © 2012 riaDesign