LIS331 problem

Hello,

I am using a LIS331HH accelerometer breakout board, SparkFun Triple Axis Accelerometer Breakout - LIS331 - SEN-10345 - SparkFun Electronics , on an Arduino UNO R3. I have written this code

/* Wiring:
UNO LIS331

3.3V VCC
GND GND
10 CS
11 SDA/SDI
12 SA0/SDO
13 SCL/SPC
*/

#include <SPI.h>
#include <stdlib.h>
#include <stdio.h>

#define SS 10 // Serial Select -> CS on LIS331
#define MOSI 11 // MasterOutSlaveIn -> SDI
#define MISO 12 // MasterInSlaveOut -> SDO
#define SCK 13 // Serial Clock -> SPC on LIS331

#define SCALE 0.0007324; // approximate scale factor for full range (+/-24g)
// scale factor: +/-24g = 48G range. 2^16 bits. 48/65536 = 0.0007324

// global acceleration values
double xAcc, yAcc, zAcc;

void setup()
{
  Serial.begin(9600);
  
  // Configure SPI
  SPI_SETUP();
  
  // Configure accelerometer
  Accelerometer_Setup();
}


void loop()
{
  readVal(); // get acc values and put into global variables
  
  Serial.print(xAcc, 1);
  Serial.print(",");
  Serial.print(yAcc, 1);
  Serial.print(",");
  Serial.println(zAcc, 1);
  
  delay(1000);
}

// Read the accelerometer data and put values into global variables
void readVal()
{
  byte xAddressByteL = 0x28; // Low Byte of X value (the first data register)
  byte readBit = B10000000; // bit 0 (MSB) HIGH means read register
  byte incrementBit = B01000000; // bit 1 HIGH means keep incrementing registers
  // this allows us to keep reading the data registers by pushing an empty byte
  byte dataByte = xAddressByteL | readBit | incrementBit;
  byte b0 = 0x0; // an empty byte, to increment to subsequent registers
  
  digitalWrite(SS, LOW); // SS must be LOW to communicate
  delay(1);
  SPI.transfer(dataByte); // request a read, starting at X low byte
  byte xL = SPI.transfer(b0); // get the low byte of X data
  byte xH = SPI.transfer(b0); // get the high byte of X data
  byte yL = SPI.transfer(b0); // get the low byte of Y data
  byte yH = SPI.transfer(b0); // get the high byte of Y data
  byte zL = SPI.transfer(b0); // get the low byte of Z data
  byte zH = SPI.transfer(b0); // get the high byte of Z data
  delay(1);
  digitalWrite(SS, HIGH);
  
  // shift the high byte left 8 bits and merge the high and low
  int xVal = (xL | (xH << 8));
  int yVal = (yL | (yH << 8));
  int zVal = (zL | (zH << 8));
  
  // scale the values into G's
  xAcc = xVal * SCALE;
  yAcc = yVal * SCALE;
  zAcc = zVal * SCALE;
}

void SPI_SETUP()
{
  pinMode(SS, OUTPUT);
  
  // wake up the SPI bus
  SPI.begin();
  
  // This device reads MSB first:
  SPI.setBitOrder(MSBFIRST);
  
  /*
  SPI.setDataMode()
  Mode Clock Polarity (CPOL) Clock Phase (CPHA)
  SPI_MODE0 0 0
  SPI_MODE1 0 1
  SPI_MODE2 1 0
  SPI_MODE3 1 1
  */
  SPI.setDataMode(SPI_MODE0);
  
  /*
  SPI.setClockDivider()
  sets SPI clock to a fraction of the system clock
  Arduino UNO system clock = 16 MHz
  Mode SPI Clock
  SPI_CLOCK_DIV2 8 MHz
  SPI_CLOCK_DIV4 4 MHz
  SPI_CLOCK_DIV8 2 MHz
  SPI_CLOCK_DIV16 1 MHz
  SPI_CLOCK_DIV32 500 Hz
  SPI_CLOCK_DIV64 250 Hz
  SPI_CLOCK_DIV128 125 Hz
  */
  
  SPI.setClockDivider(SPI_CLOCK_DIV16); // SPI clock 1000Hz
}

void Accelerometer_Setup()
{
  // Set up the accelerometer
  // write to Control register 1: address 20h
  byte addressByte = 0x20;
  /* Bits:
  PM2 PM1 PM0 DR1 DR0 Zen Yen Xen
  PM2PM1PM0: Power mode (001 = Normal Mode)
  DR1DR0: Data rate (00=50Hz, 01=100Hz, 10=400Hz, 11=1000Hz)
  Zen, Yen, Xen: Z enable, Y enable, X enable
  */
  byte ctrlRegByte = 0x37; // 00111111 : normal mode, 1000Hz, xyz enabled
  
  // Send the data for Control Register 1
  digitalWrite(SS, LOW);
  delay(1);
  SPI.transfer(addressByte);
  SPI.transfer(ctrlRegByte);
  delay(1);
  digitalWrite(SS, HIGH);
  
  delay(100);
  
  // write to Control Register 2: address 21h
  addressByte = 0x21;
  // This register configures high pass filter
  ctrlRegByte = 0x00; // High pass filter off
  
  // Send the data for Control Register 2
  digitalWrite(SS, LOW);
  delay(1);
  SPI.transfer(addressByte);
  SPI.transfer(ctrlRegByte);
  delay(1);
  digitalWrite(SS, HIGH);
  
  delay(100);
  
  // Control Register 3 configures Interrupts
  // Since I'm not using Interrupts, I'll leave it alone
  
  // write to Control Register 4: address 23h
  addressByte = 0x23;
  /* Bits:
  BDU BLE FS1 FS0 STsign 0 ST SIM
  BDU: Block data update (0=continuous update)
  BLE: Big/little endian data (0=accel data LSB at LOW address)
  FS1FS0: Full-scale selection (00 = +/-6G, 01 = +/-12G, 11 = +/-24G)
  STsign: selft-test sign (default 0=plus)
  ST: self-test enable (default 0=disabled)
  SIM: SPI mode selection(default 0=4 wire interface, 1=3 wire interface)
  */
  ctrlRegByte = 0x30; // 00110000 : 24G (full scale)
  
  // Send the data for Control Register 4
  digitalWrite(SS, LOW);
  delay(1);
  SPI.transfer(addressByte);
  SPI.transfer(ctrlRegByte);
  delay(1);
  digitalWrite(SS, HIGH);
}

and it is working fine,except for when the robot is moving. Anyone know what I could do?

What exactly does it do when the robot is moving, and what do you expect it to do?

Does the Robot use the SPI interface? If so, have you used the select line correctly?

dc42:
What exactly does it do when the robot is moving, and what do you expect it to do?

When the robot is standing still and it is not standing on a tilted platform, the accelerometer constantly indicates a certain value. When I tilt it, the value changes,according to how much I have tilt it. However, when the robot is moving, the accelerometer gives very different values even if it is or not tilted.

WillR:
Does the Robot use the SPI interface? If so, have you used the select line correctly?

Yes, the robot does use the SPI interface.

Amirra:

Two issues. It could be related to current draw by the robot causing some unreliability.

It could also be that two peripherals contending for the SPI interface are causing an issue. This would likely be caused by not handling interrupts correctly... Unfortunately with out looking at all the code it is not easy to say what exactly "not correct" might mean.

Whether it is an interrupt priority issue or not completing an action or not allowing an action to be interrupted I don't know. There are many ways to handle this -- but my guess is that you should not use the SPI interface -- at least I would make that design call.

The Ethernet board uses the SPI -- it processes a lot of information -- so using another peripheral on the SPI is likely to cause issues. So my design choice is that I always use I2C peripherals since I always use the Ethernet board as a UDP device to upload data to my PC.

It might be easier to use the I2C interface if there is a library to make your life easy.

Amirra:
When the robot is standing still and it is not standing on a tilted platform, the accelerometer constantly indicates a certain value. When I tilt it, the value changes,according to how much I have tilt it. However, when the robot is moving, the accelerometer gives very different values even if it is or not tilted.

When the robot is accelerating, slowing down or cornering, the accelerometer should of course return different values. If the accelerometer is returning different values even when robot is moving in a straight line at a constant speed, there could be a number of reasons:

  1. The accelerometer is picking up vibration from the motors.

  2. If you are powering the Arduino and the motors from the same power supply, the motors may be creating noise on the power supply wires that is affecting the Arduino.

  3. If the code you posted is not the entire sketch you are running, and the sketch you are running also uses the SPI pins to communicate with something else, then the signals on the SPI lines may be getting garbled if the two parts of the sketch do not cooperate properly.

Thanks for the ideas, I managed to solve this issue by doing a hundred readings per second and outputing their average.

Sound to me like a vibration issue then. Try mounting the accelerometer on piece of rubber or foam.

I will try doing this too. Thanks for the idea :slight_smile:

Good Troubleshooting. A good engineer fixes their own problems. Sounds like you will do fine. :smiley:

Don't take this next part as criticism -- it's not.

A point worth noting is that you were troubleshooting a non-existent problem -- because you did not understand a system that you built. It happens all the time -- DAMHIKT

It's obvious now -- after the fact -- it always is. Instead of reporting in detail -- you reported what you thought the problem was. -- see previous.

Telling us: "That when moving the system produces these accelerometer values..." -- followed by the list would have made it more obvious to us -- but then you would likely have seen it anyway.

I always told students -- "Any fool can answer a question!" But, "The person who asks the right question is a wise person indeed!"

It took you a while -- but then you started asking the right questions.

We expect to hear that your name is on the honors list. 8)

Congratulations, now I at least look forward to learning from you.