Skip to content

Instantly share code, notes, and snippets.

@smittytone
Last active Aug 29, 2015
Embed
What would you like to do?
SPI on the Electric Imp using Analog Devices' ADXL345 accelerometer
// ADXL345 Register Values
const DEVICE_ID = 0x00; // Device ID register
const POWER_CTL = 0x2D; // Power Control register
const DATA_FORMAT = 0x31; // Data storage format register
const DATAX0 = 0x32; //X-Axis Data 0
const DATAX1 = 0x33; //X-Axis Data 1
const DATAY0 = 0x34; //Y-Axis Data 0
const DATAY1 = 0x35; //Y-Axis Data 1
const DATAZ0 = 0x36; //Z-Axis Data 0
const DATAZ1 = 0x37; //Z-Axis Data 1
// Program constants
const HIGH = 1;
const LOW = 0;
const READING_INTERVAL = 1.0;
// Global Variables
// SPI bus and the SS pin
spi <- hardware.spi257;
ss <- hardware.pin8;
// SPI input buffer
data <- blob(6);
// SPI Functions
function spi_write_reg(register, value)
{
// Write the value to the specified register on the SPI bus
// Lower the SS (CS) to signal start of transmission
ss.write(LOW);
// Now send the data. First write the register value to the bus
// by converting it to a blob
local b1 = blob();
b1.writen(register, 'b');
spi.write(b1);
// Now write the value that register will take, again by first
// converting the integer value to a blob
local b2 = blob();
b2.writen(value, 'b');
spi.write(b2);
// Finally, we've done sending, so put SS high again
// to signal end-of-transaction
ss.write(HIGH);
}
function spi_read_reg(register, num_bytes)
{
// Read the value at the specified register via the SPI bus
local b = blob();
local r = register;
// Lower the SS (CS) to signal start of transmission
ss.write(LOW);
// The ADXL345 requires certain flag bits to be set in the register address
// First, set the 'multi-byte read/write bit' (bit 6) in address, if we are
// reading more than one byte of data
if (num_bytes > 1) r = r | 0x40;
// Second, read operations require address bit 7 to be set
r = r | 0x80;
// Convert address to blob and write it to the bus
b.writen(r, 'b');
spi.write(b);
// Now read in the data
data = spi.readblob(num_bytes);
// Finally, we've done sending, so put SS high again
// to signal end-of-transaction
ss.write(HIGH);
}
// ADXL345 Functions
function init_adxl345()
{
local x = 0, y = 0, z = 0;
// Send 0x08 to the ADXL345's power register to turn it on
// and apply the level of sensitivity we want
spi_write_reg(POWER_CTL, 0x08);
// As a check, read the value in register 0x00, the device ID
// This should log 'E5' if the ADXL345 is working
spi_read_reg(DEVICE_ID, 1);
server.log(format("ADXL345 Fixed ID: %X",data[0]));
// Put the ADXL345 into measurement mode, for reading real movement
spi_write_reg(DATA_FORMAT, 0x00);
}
// Program Functions
function loop()
{
// Schedule the next reading
imp.wakeup(READING_INTERVAL, loop);
// Take a reading
spi_read_reg(DATAX0, 6);
// Get X, Y and Z values from SPI reading
local x = (data[1] << 8)|data[0];
local y = (data[3] << 8)|data[2];
local z = (data[5] << 8)|data[4];
// Subtract the values from the saved standard values and display
server.log(format("X: %u, Y: %u, Z:%u", x , y, z));
}
// START OF PROGRAM
// The ADXL345 uses SPI Mode 3, ie. CPOL 1, CPHA 1
// The imp API docs translate this to (CLOCK_IDLE_HIGH | CLOCK_2ND_EDGE)
spi.configure((CLOCK_IDLE_HIGH | CLOCK_2ND_EDGE), 100);
// Configure the SS pin and set it high
ss.configure(DIGITAL_OUT);
ss.write(HIGH);
// Initialise the accelerometer
init_adxl345();
// Take the first reading
loop();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment