Connecting LSM303 pins 1 (SCL), 2 (SDA), 6 (GND) and 8 (V3V) to pins 5 (SCL), 3 (SDA), 6 (GND) and 1 (V3V) on the Pi board.
On my ArchlinuxARM OS I had to install i2c-tools:
> pacman -S i2c-tools
And add i2c modules:
> echo i2c-dev > /etc/modules-load.d/ i2c.conf
> echo i2c-bcm2708 >> /etc/modules-load.d/ i2c.conf
> reboot
now to check it works:
> i2cdetect -y 1
got a message like this:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- 19 -- -- -- -- 1e --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Now, following this, I test it and it works. Now I'm up for creating my own code.
Made some changes to the code:
main.cpp
#include"LSM303DLHC.h"
#include<stdio.h>
#include <unistd.h>
/*
getHeading() calculates a tilt-compensated heading.
A float between 0 and 360 degrees is returned. You need
to pass this function both a magneto and acceleration array.
Headings are calculated as specified in AN3192:
http://www.sparkfun.com/datasheets/Sensors/Magneto/Tilt%20Compensated%20Compass.pdf
*/
float getHeading(LSM303& lsm303dlhc);
#define PI 3.141592654
int main(void)
{
uint8_t bajt;
const char *fileN = "/dev/i2c-1";
LSM303 lsm303dlhc(fileN);
lsm303dlhc.enalbe();
while(1)
{
lsm303dlhc.readAccelerationRaw();
lsm303dlhc.readMagnetometerRaw();
printf("acc [m/s^2]: \e[27;1;31m %f \e[m \e[27;1;32m %f \e[m \e[27;1;34m %f \e[m mag: \e[27;1;31m %d \e[m \e[27;1;32m %d \e[m \e[27;1;34m %d\e[m %fdeg\n",
(int16_t)lsm303dlhc.acc_x_raw*0.00957,(int16_t)lsm303dlhc.acc_y_raw*0.00957,-(int16_t)lsm303dlhc.acc_z_raw*0.00957,
(int16_t)lsm303dlhc.mag_x_raw, (int16_t)lsm303dlhc.mag_y_raw, (int16_t)lsm303dlhc.mag_z_raw,getHeading(lsm303dlhc));
usleep(10);
}
}
float getHeading(LSM303& lsm303dlhc)
{
float heading,pitch,roll,xh,yh,zh;
// see section 1.2 in app note AN3192
int magValue[3];
float accelValue[3];
magValue[0] = (int16_t)lsm303dlhc.mag_x_raw;
magValue[1] = (int16_t)lsm303dlhc.mag_y_raw;
magValue[2] = (int16_t)lsm303dlhc.mag_z_raw;
accelValue[0] = (int16_t)lsm303dlhc.acc_x_raw*0.000976531;
accelValue[1] = (int16_t)lsm303dlhc.acc_y_raw*0.000976531;
accelValue[2] = -(int16_t)lsm303dlhc.acc_z_raw*0.000976531;
// see appendix A in app note AN3192
pitch = asin(-accelValue[0]);
roll = asin(accelValue[1]/cos(pitch));
xh = magValue[0] * cos(pitch) + magValue[2] * sin(pitch);
yh = magValue[0] * sin(roll) * sin(pitch) + magValue[1] * cos(roll) - magValue[2] * sin(roll) * cos(pitch);
zh = -magValue[0] * cos(roll) * sin(pitch) + magValue[1] * sin(roll) + magValue[2] * cos(roll) * cos(pitch);
heading = 180*atan2(yh,xh)/PI;
if (heading <0)
heading += 360;
return heading;
}
#include<stdio.h>
#include <unistd.h>
/*
getHeading() calculates a tilt-compensated heading.
A float between 0 and 360 degrees is returned. You need
to pass this function both a magneto and acceleration array.
Headings are calculated as specified in AN3192:
http://www.sparkfun.com/datasheets/Sensors/Magneto/Tilt%20Compensated%20Compass.pdf
*/
float getHeading(LSM303& lsm303dlhc);
#define PI 3.141592654
int main(void)
{
uint8_t bajt;
const char *fileN = "/dev/i2c-1";
LSM303 lsm303dlhc(fileN);
lsm303dlhc.enalbe();
while(1)
{
lsm303dlhc.readAccelerationRaw();
lsm303dlhc.readMagnetometerRaw();
printf("acc [m/s^2]: \e[27;1;31m %f \e[m \e[27;1;32m %f \e[m \e[27;1;34m %f \e[m mag: \e[27;1;31m %d \e[m \e[27;1;32m %d \e[m \e[27;1;34m %d\e[m %fdeg\n",
(int16_t)lsm303dlhc.acc_x_raw*0.00957,(int16_t)lsm303dlhc.acc_y_raw*0.00957,-(int16_t)lsm303dlhc.acc_z_raw*0.00957,
(int16_t)lsm303dlhc.mag_x_raw, (int16_t)lsm303dlhc.mag_y_raw, (int16_t)lsm303dlhc.mag_z_raw,getHeading(lsm303dlhc));
usleep(10);
}
}
float getHeading(LSM303& lsm303dlhc)
{
float heading,pitch,roll,xh,yh,zh;
// see section 1.2 in app note AN3192
int magValue[3];
float accelValue[3];
magValue[0] = (int16_t)lsm303dlhc.mag_x_raw;
magValue[1] = (int16_t)lsm303dlhc.mag_y_raw;
magValue[2] = (int16_t)lsm303dlhc.mag_z_raw;
accelValue[0] = (int16_t)lsm303dlhc.acc_x_raw*0.000976531;
accelValue[1] = (int16_t)lsm303dlhc.acc_y_raw*0.000976531;
accelValue[2] = -(int16_t)lsm303dlhc.acc_z_raw*0.000976531;
// see appendix A in app note AN3192
pitch = asin(-accelValue[0]);
roll = asin(accelValue[1]/cos(pitch));
xh = magValue[0] * cos(pitch) + magValue[2] * sin(pitch);
yh = magValue[0] * sin(roll) * sin(pitch) + magValue[1] * cos(roll) - magValue[2] * sin(roll) * cos(pitch);
zh = -magValue[0] * cos(roll) * sin(pitch) + magValue[1] * sin(roll) + magValue[2] * cos(roll) * cos(pitch);
heading = 180*atan2(yh,xh)/PI;
if (heading <0)
heading += 360;
return heading;
}
LSM303DLHC.cpp:
#include"LSM303DLHC.h"
#include<math.h>
#include<stdio.h>
/*Conection to Raspberry PI:
LSM303 Raspberry PI
VDD -> 3V3(PIN 1)
SDA -> SDA(PIN 3)
SCL -> SCL(PIN 5)
GND -> GND(PIN 6)
*/
#define LSM303DLHC_MAG_ADDRESS (0x3C >> 1)
#define LSM303DLHC_ACC_ADDRESS (0x32 >> 1)
LSM303::LSM303(const char * i2cDeviceName) : i2c_lsm303(i2cDeviceName)
{
}
uint8_t LSM303::readAccRegister(uint8_t regAddr)
{
i2c_lsm303.addrSet(LSM303DLHC_ACC_ADDRESS);
return i2c_lsm303.readByte(regAddr);
}
uint8_t LSM303::readMagRegister(uint8_t regAddr)
{
i2c_lsm303.addrSet(LSM303DLHC_MAG_ADDRESS);
return i2c_lsm303.readByte(regAddr);
}
void LSM303::writeAccRegister(uint8_t regAddr,uint8_t byte)
{
i2c_lsm303.addrSet(LSM303DLHC_ACC_ADDRESS);
i2c_lsm303.writeByte(regAddr, byte);
}
void LSM303::writeMagRegister(uint8_t regAddr, uint8_t byte)
{
i2c_lsm303.addrSet(LSM303DLHC_MAG_ADDRESS);
i2c_lsm303.writeByte(regAddr, byte);
}
void LSM303::enalbe(void)
{
writeAccRegister(LSM303_CTRL_REG1, 0b10010111);
writeAccRegister(LSM303_CTRL_REG4, 0b00001000);
writeMagRegister(LSM303_MR_REG, 0x00);
}
void LSM303::readAccelerationRaw(void)
{
uint8_t block[6];
i2c_lsm303.addrSet(LSM303DLHC_ACC_ADDRESS);
i2c_lsm303.readBlock(0x80 | LSM303_OUT_X_L_A, sizeof(block), block);
acc_x_raw = (int16_t)(block[0] | (block[1] << 8)) >> 4;
acc_y_raw = (int16_t)(block[2] | block[3] << 8) >> 4;
acc_z_raw = (int16_t)(block[4] | block[5] << 8) >> 4;
}
void LSM303::readMagnetometerRaw(void)
{
uint8_t block[6];
i2c_lsm303.addrSet(LSM303DLHC_MAG_ADDRESS);
i2c_lsm303.readBlock(0x80 | LSM303_OUT_X_H_M, sizeof(block), block);
mag_x_raw = (int16_t)(block[1] | block[0] << 8);
mag_y_raw = (int16_t)(block[5] | block[4] << 8);
mag_z_raw = (int16_t)(block[3] | block[2] << 8);
}
void LSM303::readAcceleration(void)
{
readAccelerationRaw();
}
#include<math.h>
#include<stdio.h>
/*Conection to Raspberry PI:
LSM303 Raspberry PI
VDD -> 3V3(PIN 1)
SDA -> SDA(PIN 3)
SCL -> SCL(PIN 5)
GND -> GND(PIN 6)
*/
#define LSM303DLHC_MAG_ADDRESS (0x3C >> 1)
#define LSM303DLHC_ACC_ADDRESS (0x32 >> 1)
LSM303::LSM303(const char * i2cDeviceName) : i2c_lsm303(i2cDeviceName)
{
}
uint8_t LSM303::readAccRegister(uint8_t regAddr)
{
i2c_lsm303.addrSet(LSM303DLHC_ACC_ADDRESS);
return i2c_lsm303.readByte(regAddr);
}
uint8_t LSM303::readMagRegister(uint8_t regAddr)
{
i2c_lsm303.addrSet(LSM303DLHC_MAG_ADDRESS);
return i2c_lsm303.readByte(regAddr);
}
void LSM303::writeAccRegister(uint8_t regAddr,uint8_t byte)
{
i2c_lsm303.addrSet(LSM303DLHC_ACC_ADDRESS);
i2c_lsm303.writeByte(regAddr, byte);
}
void LSM303::writeMagRegister(uint8_t regAddr, uint8_t byte)
{
i2c_lsm303.addrSet(LSM303DLHC_MAG_ADDRESS);
i2c_lsm303.writeByte(regAddr, byte);
}
void LSM303::enalbe(void)
{
writeAccRegister(LSM303_CTRL_REG1, 0b10010111);
writeAccRegister(LSM303_CTRL_REG4, 0b00001000);
writeMagRegister(LSM303_MR_REG, 0x00);
}
void LSM303::readAccelerationRaw(void)
{
uint8_t block[6];
i2c_lsm303.addrSet(LSM303DLHC_ACC_ADDRESS);
i2c_lsm303.readBlock(0x80 | LSM303_OUT_X_L_A, sizeof(block), block);
acc_x_raw = (int16_t)(block[0] | (block[1] << 8)) >> 4;
acc_y_raw = (int16_t)(block[2] | block[3] << 8) >> 4;
acc_z_raw = (int16_t)(block[4] | block[5] << 8) >> 4;
}
void LSM303::readMagnetometerRaw(void)
{
uint8_t block[6];
i2c_lsm303.addrSet(LSM303DLHC_MAG_ADDRESS);
i2c_lsm303.readBlock(0x80 | LSM303_OUT_X_H_M, sizeof(block), block);
mag_x_raw = (int16_t)(block[1] | block[0] << 8);
mag_y_raw = (int16_t)(block[5] | block[4] << 8);
mag_z_raw = (int16_t)(block[3] | block[2] << 8);
}
void LSM303::readAcceleration(void)
{
readAccelerationRaw();
}