I’m trying to write a program that uses an accelerometer (LIS331HH, https://www.sparkfun.com/products/10345) as the input to light LEDs. There are 6 LEDs, and each time the accelerometer records a bump, I want the interrupt to trigger, then calling a function to light the next LED in the chain and turn the previous one off. I found some code online already to read the accelerometer fine, but it didn’t use interrupts so I’ve been trying to configure those on my own. The datasheet is here (https://www.sparkfun.com/datasheets/Sen … S331HH.pdf). Also, I’m using a Pro Mini (3.3V, 8MHz, ATmega328).
Since I’m watching for a bump, I want to monitor if the inputs are either positive or negative, so I’m using interrupt 1 for high events and interrupt 2 for low events. The problem is setting the threshold that triggers the interrupt. The accelerometer provides raw readings between ±5500, which I then convert to Gs in the program. In the register that holds the threshold value of the interrupt, I only have 7 bits, giving me a maximum value of 127, so I don’t know how to get a meaningful threshold from it. Right now, the interrupt stays high all the time, even when the values are negative, so that isn’t right either. I think that might involve reading the INT1_SRC register, which I believe clears the interrupt event, but I’m not sure. My code is below (doesn’t involve LED lighting right now, just basic reading accelerometer and configuring interrupt so I can measure the interrupt on my own with a DMM and see if it gets set high on bumps). Any help would be appreciated!
// 3-axis Accelerometer
// Sparkfun Electronics Triple Axis Accelerometer Breakout - LIS331
// Arduino UNO
/* 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 .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, total;
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.print(zAcc, 1);
Serial.print(",");
Serial.println(total, 1);
total = zAcc + yAcc + xAcc;
delay(10);
}
// 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
addressByte = 0x22;
/* Bits:
IHL PP_OD LIR2 I2_CFG1 I2_CFG0 LIR1 I1_CFG1 I1_CFG0
IHL: interrupt high low (0=active high)
PP_OD: push-pull/open drain selection (0=push-pull)
LIR2: latch interrupt request on INT2_SRC register (0=interrupt request not latched)
I2_CFG1, I2_CFG0: data signal on INT 2 pad control bits
LIR1: latch interrupt request on INT1_SRC register (0=interrupt request not latched)
I1_CFG1, I1_CFG0: data signal on INT 1 pad control bits
Data signal on pad
I1(2)_CFG1 I1(2)_CFG0 INT 1(2) pad
0 0 interrupt 1(2) source
0 1 interrupt 1 source or interrupt 2 source
1 0 data ready
1 1 boot running
*/
ctrlRegByte = 0x24; // 00100100 : interrupt request latched to interrupt source 1 and interrupt source 2
digitalWrite(SS, LOW);
delay(1);
SPI.transfer(addressByte);
SPI.transfer(ctrlRegByte);
delay(1);
digitalWrite(SS, HIGH);
delay(100);
// 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);
delay(100);
// Control Register for interrupt configuration (INT1_CFG)
addressByte = 0x30;
ctrlRegByte = 0x2A; // 00101010 : interrupt request enabled on high Z, high Y, high X events
digitalWrite(SS, LOW);
delay(1);
SPI.transfer(addressByte);
SPI.transfer(ctrlRegByte);
delay(1);
digitalWrite(SS, HIGH);
delay(100);
// Control Register for interrupt threshold for high events (INT1_THS)
addressByte = 0x32;
ctrlRegByte = 0x7F; // 0 0000000 : value TBD
digitalWrite(SS, LOW);
delay(1);
SPI.transfer(addressByte);
SPI.transfer(ctrlRegByte);
delay(1);
digitalWrite(SS, HIGH);
delay(100);
// Control Register for interrupt duration for high events (INT1_DURATION)
addressByte = 0x33;
ctrlRegByte = 0x02; // 0 0000010 : value TBD
digitalWrite(SS, LOW);
delay(1);
SPI.transfer(addressByte);
SPI.transfer(ctrlRegByte);
delay(1);
digitalWrite(SS, HIGH);
delay(100);
// Control Register for interrupt configuration (INT2_CFG)
addressByte = 0x34;
ctrlRegByte = 0x15; // 00010101 : interrupt request enabled on low Z, low Y, low X events
digitalWrite(SS, LOW);
delay(1);
SPI.transfer(addressByte);
SPI.transfer(ctrlRegByte);
delay(1);
digitalWrite(SS, HIGH);
delay(100);
// Control Register for interrupt threshold (INT2_THS)
addressByte = 0x36;
ctrlRegByte = 0x00; // 00000000 : value TBD
digitalWrite(SS, LOW);
delay(1);
SPI.transfer(addressByte);
SPI.transfer(ctrlRegByte);
delay(1);
digitalWrite(SS, HIGH);
delay(100);
}