Example of reading an accelerometer sensor (BMA180)

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
jose_claudiojr
Date:
Tue May 21 13:51:07 2013 +0000
Commit message:
Example of reading an accelerometer sensor (BMA180)

Changed in this revision

Accelerometer.cpp Show annotated file Show diff for this revision Revisions of this file
Accelerometer.h Show annotated file Show diff for this revision Revisions of this file
BMA180.cpp Show annotated file Show diff for this revision Revisions of this file
BMA180.h Show annotated file Show diff for this revision Revisions of this file
SerialBuffered.cpp Show annotated file Show diff for this revision Revisions of this file
SerialBuffered.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r d493a3003022 Accelerometer.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Accelerometer.cpp	Tue May 21 13:51:07 2013 +0000
@@ -0,0 +1,100 @@
+
+#include "Accelerometer.h"
+
+Accelerometer::Accelerometer(BMA180* acceleHardware, float sensitivity)
+{
+    this->acceleHardware = acceleHardware; 
+    this->sensitivity = sensitivity;   
+    updateZeroRates();
+}
+
+Accelerometer::~Accelerometer(void)
+{
+}
+
+void Accelerometer::updateZeroRates()
+{
+    update(253, 10); // Utilizando filtro passa baixa, é necessário 253 amostras para estabilização do filtro.
+    update(200, 10);
+    zeroRateX = rawX;
+    zeroRateY = rawY;
+    zeroRateZ = rawZ;
+    //zeroRateX = 0.0;
+    //zeroRateY = 0.0;
+    //zeroRateZ = 0.0;
+}
+
+void Accelerometer::update()
+{    
+    update(1, 1);
+}
+
+void Accelerometer::update(int samplesSize, int sampleDataRate)
+{   
+    int axes[3] = {0, 0, 0};
+    rawX = 0;
+    rawY = 0;
+    rawZ = 0;
+    
+    for (int i = 0; i < samplesSize; i++)
+    {
+                
+        rawX += (this->acceleHardware->getX() / samplesSize);
+        rawY += (this->acceleHardware->getY() / samplesSize);
+        rawZ += (this->acceleHardware->getZ() / samplesSize);
+        
+        //this->acceleHardware->getOutput(axes);
+        
+        //rawX += ((float)axes[0] / samplesSize);
+        //rawY += ((float)axes[1] / samplesSize);
+        //rawZ += ((float)axes[2] / samplesSize);
+        wait_ms(sampleDataRate);
+    }
+}
+
+float Accelerometer::getAccelerationX()
+{
+    //( * Vref / 1023 – VzeroG) / Sensitivity
+    return ((rawX - zeroRateX) / sensitivity); //Devido a posição da plaquinha, quando se define o zeroRateX, tem que adicionar novamente a gravidade, que está influenciando o X
+}
+
+float Accelerometer::getAccelerationY()
+{
+    return ((rawY - zeroRateY) / sensitivity);
+}
+
+float Accelerometer::getAccelerationZ()
+{
+    return (((rawZ - zeroRateZ) / sensitivity) + 1.0);
+}
+
+float Accelerometer::getRadiansAngleX()
+{
+    float x = getAccelerationX();
+    float z = getAccelerationZ();
+    
+    return (float)atan2(x, z);
+}
+
+float Accelerometer::getRadiansAngleY()
+{
+    float x = getAccelerationX();
+    float y = getAccelerationY();
+    float z = getAccelerationZ();
+    return (float)atan2(y, z);
+}
+
+float Accelerometer::getDegreesAngleX()
+{
+    return (getRadiansAngleX() / Accelerometer::getPI()) * 180.0;
+}
+
+float Accelerometer::getDegreesAngleY()
+{
+    return (getRadiansAngleY() / Accelerometer::getPI()) * 180.0;
+}
+
+float Accelerometer::getPI()
+{
+    return 3.14159265;
+}
diff -r 000000000000 -r d493a3003022 Accelerometer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Accelerometer.h	Tue May 21 13:51:07 2013 +0000
@@ -0,0 +1,42 @@
+#ifndef ACCELEROMETER_H
+#define ACCELEROMETER_H
+
+#include <math.h>
+
+#include "BMA180.h"
+
+class Accelerometer
+{
+    public:
+        Accelerometer(BMA180* acceleHardware, float sensitivity);
+        ~Accelerometer(void);
+        
+        void updateZeroRates();
+        
+        void update();
+        void update(int samplesSize, int sampleDataRate);
+        
+        float getAccelerationX();
+        float getAccelerationY();
+        float getAccelerationZ();
+        
+        float getRadiansAngleX();
+        float getRadiansAngleY();
+        
+        float getDegreesAngleX();
+        float getDegreesAngleY();
+        
+        static float getPI();
+    
+    private:
+        BMA180* acceleHardware;
+        
+        float sensitivity;        
+        float zeroRateX, zeroRateY, zeroRateZ;
+        
+        float rawX;
+        float rawY;
+        float rawZ;
+};
+
+#endif
diff -r 000000000000 -r d493a3003022 BMA180.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BMA180.cpp	Tue May 21 13:51:07 2013 +0000
@@ -0,0 +1,173 @@
+#include "mbed.h"
+#include "BMA180.h"
+/* Range em default value: 2g (010) / Resolução do ADC 0.25mg/LSB sensibilidade 4096 (LSBadc/g)
+ * Range Register: 0x35 
+ * Valor Range Resolução ADC (mg/LSB)                                              =================================
+ * 000    1g     0.13                                                              || Prestar atenção nas unidades||
+ * 001  1.5g     0.19                                                              =================================
+ * 010    2g     0.25
+ * 011    3g     0.38
+ * 100    4g     0.50
+ * 101    8g     0.99
+ * 110   16g     1.98
+ */
+BMA180::BMA180(PinName sda, PinName scl): i2c(sda, scl)
+{
+    char rx, temp1, temp2;
+    i2c.frequency(100000);
+    //Testar depois com 400KHz
+    //==========================================================================================================
+    // Read chip_id
+    //==========================================================================================================
+    rx = Read(BMA180_WHO_AM_I);
+    if (rx != BMA180_ID)//ID do chip 
+        printf("\ninvalid chip id %d\r\n", rx);
+    //==========================================================================================================
+    // Set CTRLREG0 0x0D, bit ee_w (0001 0000) to update image and make it possible write in to the chip eeprom
+    //==========================================================================================================
+    rx = Read(BM180_CTRLREG0);
+    rx |= 0x10;   
+    Write(BM180_CTRLREG0, rx);    
+    //Let's confirm
+    rx = Read(BM180_CTRLREG0);
+    temp1 = rx | 0x10;
+    if(rx != temp1)
+        printf("\nee_w bit wasn't changed %d\r\n", rx);  
+    // ee_w bit set, OK
+    //==========================================================================================================
+    // Let's define the low-pass filter's bandwidth to 10Hz (bw<3:0> -> 0000), to reduce noise in the signal
+    // To set the bw bit, we will have to acces the bw_tcs register (0x20) 
+    //==========================================================================================================
+    rx = Read(BM180_BWTCS);
+                                                   // procedure: readed value: i.e 0101 0101     
+    temp1 = 0x00;                                  //                        (AND) 0000 1111 -> (~BWMask)
+    temp1 = temp1 << 4;                            //                              ---------
+    rx &= (~0xF0); //Mask                          //                        (OR)  0000 0101
+    rx |= temp1;                                   //              Wanted Value <-[0000]0000 -> Wanted value with 4's complement
+    Write(BM180_BWTCS, rx);                        //                              --------- 
+    //Let's confirm                                //                              0000 0101 -> Final Value
+    rx = Read(BM180_BWTCS);
+    temp2 = rx;
+    temp1 = 0x00;
+    temp1 = temp1 << 4;
+    temp2 &= (~0xF0); //Mask
+    temp2 |= temp1;
+    if(rx != temp2)
+        printf("\nbw bit wasn't changed %d\r\n", rx);  
+    // low-pass filter's bandwidth defined, OK
+    
+    //==========================================================================================================
+    // Let's set the range to 2g (0x02) in the 
+    //==========================================================================================================
+    rx = Read(BMA180_OLSB1);                       // procedure: value to set with 1's complement 0000 [010]0
+    temp1 = 0x02;                                  //            readed value: i.e 0101 0101 
+    temp1 = temp1 << 1;                            //                        (AND) 1111 0001 -> RangeMask
+    rx &= (~0x0E);                                 //                              ---------
+    rx |= temp1;                                   //                              0101 0001
+    Write(BMA180_OLSB1, rx);                        //                         (OR) 0000 0100 -> Shifted value
+    // Let's confirm                               //                              ---------
+    rx = Read(BMA180_OLSB1);                       //                              0101 0101 -> Final Value
+    temp2 = rx;
+    temp1 = 0x02;
+    temp1 = temp1 << 1;
+    temp2 &= (~0x0E);
+    temp2 |= temp1;
+    if(rx != temp2)
+        printf("\nRange not set %d\r\n", rx); 
+}
+
+void BMA180::Write(char reg, char data)
+{
+    char c_data[2];
+    c_data[0] = reg;
+    c_data[1] = data;
+    i2c.write(BMA180_ADDR, c_data, 2);
+}
+
+char BMA180::Read(char data)
+{       
+    char tx = data;
+    char rx;
+    
+    i2c.write((BMA180_ADDR) & 0xFE, &tx, 1); // 0xFE ensure that the MSB bit is being set to zero (RW=0 -> Writing)
+    i2c.read((BMA180_ADDR) | 0x01, &rx, 1);  // 0x01 ensure that the MSB bit is being set to one  (RW=1 -> Reading)
+                                             // The read/write method of I2C does this automatically, so it's useless to set manually                                           
+    return rx;
+}
+
+void BMA180::MultiByteRead(char address, char* output, int size) 
+{
+    i2c.write( (BMA180_ADDR) & 0xFE, &address, 1);      //tell it where to read from
+    i2c.read( (BMA180_ADDR) | 0x01 , output, size);     //tell it where to store the data read
+}
+
+float BMA180::getX()
+{
+    char lsb_byte = 0;
+    signed short msb_byte;
+    float acc;
+    
+    while (lsb_byte != 1)
+    {
+        lsb_byte = Read(BMA180_XLSB) & 0x01;
+    }
+        
+    lsb_byte = Read(BMA180_XMSB);
+    msb_byte = lsb_byte << 8;
+    msb_byte |= Read(BMA180_XLSB);
+    msb_byte = msb_byte >> 2; // Get rid of two non-value bits in LSB
+    //printf("%d \t", msb_byte);
+    acc = (float)msb_byte;
+    return acc;
+}
+
+float BMA180::getY()
+{
+    char lsb_byte = 0;
+    signed short msb_byte;
+    float acc;
+    
+    while (lsb_byte != 1)
+    {
+        lsb_byte = Read(BMA180_YLSB) & 0x01;
+    }
+        
+    lsb_byte = Read(BMA180_YMSB);
+    msb_byte = lsb_byte << 8;
+    msb_byte |= Read(BMA180_YLSB);
+    msb_byte = msb_byte >> 2; // Get rid of two non-value bits in LSB
+    //printf("%d \t", msb_byte);
+    acc = (float)msb_byte;
+    return acc;
+}
+
+float BMA180::getZ()
+{
+    char lsb_byte = 0;
+    signed short msb_byte;
+    float acc;
+    
+    while (lsb_byte != 1)
+    {
+        lsb_byte = Read(BMA180_ZLSB) & 0x01;
+    }
+        
+    lsb_byte = Read(BMA180_ZMSB);
+    msb_byte = lsb_byte << 8;
+    msb_byte |= Read(BMA180_ZLSB);
+    msb_byte = msb_byte >> 2; // Get rid of two non-value bits in LSB
+    //printf("%d \t", msb_byte);
+    acc = (float)msb_byte;
+    return acc;
+}
+
+void BMA180::getOutput(int* readings)
+{
+    char buffer[6];    
+    MultiByteRead(BMA180_XLSB, buffer, 6);
+    
+    readings[0] = (int)buffer[1] << 8 | (int)buffer[0];
+    readings[1] = (int)buffer[3] << 8 | (int)buffer[2];
+    readings[2] = (int)buffer[5] << 8 | (int)buffer[4];
+
+}
\ No newline at end of file
diff -r 000000000000 -r d493a3003022 BMA180.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BMA180.h	Tue May 21 13:51:07 2013 +0000
@@ -0,0 +1,38 @@
+#ifndef MBED_BMA180_H
+#define MBED_BMA180_H
+
+#define BMA180_WHO_AM_I 0x00
+#define BMA180_ID       0x03
+#define BMA180_ADDR     0x80 //datasheet says 0x40 !
+#define BMA180_XLSB     0x02 //LSB
+#define BMA180_XMSB     0x03 //MSB
+
+#define BMA180_YLSB     0x04 //LSB
+#define BMA180_YMSB     0x05 //MSB
+
+#define BMA180_ZLSB     0x06 //LSB
+#define BMA180_ZMSB     0x07 //MSB
+
+#define BM180_CTRLREG0  0x0D
+#define BM180_BWTCS     0x20
+#define BMA180_OLSB1    0x35
+
+#include "mbed.h"
+
+class BMA180 {
+public:
+    BMA180(PinName sda, PinName scl);
+    
+    float getX();
+    float getY();
+    float getZ();
+    void getOutput(int* readings);  
+private:
+    void Write(char reg, char data);
+    char Read(char);
+    void MultiByteRead(char address, char* output, int size); 
+    I2C i2c;
+    int16_t x,y,z;
+};
+
+#endif
diff -r 000000000000 -r d493a3003022 SerialBuffered.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialBuffered.cpp	Tue May 21 13:51:07 2013 +0000
@@ -0,0 +1,180 @@
+#include "SerialBuffered.h"
+
+/**
+ * Create a buffered serial class.
+ *
+ * @param tx A pin for transmit.
+ * @param rx A pin for receive.
+ */
+SerialBuffered::SerialBuffered(PinName tx, PinName rx) : Serial(tx, rx)
+{
+    indexContentStart = 0;
+    indexContentEnd = 0;
+    timeout = 1;
+    
+    attach(this, &SerialBuffered::handleInterrupt);
+}
+
+/**
+ * Destroy.
+ */
+SerialBuffered::~SerialBuffered()
+{
+}
+
+/**
+ * Set timeout for getc().
+ *
+ * @param ms milliseconds. (-1:Disable timeout)
+ */
+void SerialBuffered::setTimeout(int ms)
+{
+    timeout = ms;
+}
+
+/**
+ * Read requested bytes.
+ *
+ * @param bytes A pointer to a buffer.
+ * @param requested Length.
+ *
+ * @return Readed byte length.
+ */
+size_t SerialBuffered::readBytes(uint8_t *bytes, size_t requested)
+{
+    int i = 0;
+    
+    while (i < requested)
+    {
+        int c = getc();
+        
+        if (c < 0)
+        {
+            break;
+        }
+        
+        bytes[i] = c;
+        i++;
+    }
+    
+    return i;
+}
+
+/**
+ * Get a character.
+ *
+ * @return A character. (-1:timeout)
+ */
+int SerialBuffered::getc()
+{
+    timer.reset();
+    timer.start();
+    
+    while (indexContentStart == indexContentEnd)
+    {
+        wait_ms(1);
+        
+        if ((timeout > 0) && (timer.read_ms() > timeout))
+        {
+            /*
+             * Timeout occured.
+             */
+            // printf("Timeout occured.\n");
+            return EOF;
+        }
+    }
+    
+    timer.stop();
+
+    uint8_t result = buffer[indexContentStart++];
+    indexContentStart =  indexContentStart % BUFFERSIZE;
+
+    return result;
+}
+
+/**
+ * Returns 1 if there is a character available to read, otherwise.
+ */
+int SerialBuffered::readable()
+{
+    return indexContentStart != indexContentEnd;
+}
+
+void SerialBuffered::handleInterrupt()
+{
+    while (Serial::readable())
+    {
+        if (indexContentStart == ((indexContentEnd + 1) % BUFFERSIZE))
+        {
+            /*
+             * Buffer overrun occured.
+             */
+            // printf("Buffer overrun occured.\n");
+            Serial::getc();
+        }
+        else
+        {
+            buffer[indexContentEnd++] = Serial::getc();
+            indexContentEnd = indexContentEnd % BUFFERSIZE;
+        }
+    }
+}
+
+float SerialBuffered::f_readIntTo(char delimiter)
+{
+    char buffer[16];
+    int i;
+    float result;
+    for (i = 0;; i++)
+    {
+        //while (!readable());
+        
+        char number = getc();
+        
+        if (number == delimiter)
+            break;
+            
+        buffer[i] = number;     
+    }
+    
+    buffer[i-1] = '\0';
+    
+    result = atof(buffer);
+    
+    return result;
+}
+
+
+int SerialBuffered::i_readIntTo(char delimiter)
+{
+    char buffer[16];
+    int i;
+    float result;
+    for (i = 0;; i++)
+    {
+        //while (!readable());
+        
+        char number = getc();
+        
+        if (number == delimiter)
+            break;
+            
+        buffer[i] = number;     
+    }
+    
+    buffer[i-1] = '\0';
+    
+    result = atoi(buffer);
+    
+    return result;
+}
+
+void SerialBuffered::writeText(char* text)
+{
+    for (int i = 0; text[i] != '\0' && i < BUFFER_TEXT_SIZE; i++)
+    {    
+        while (!Serial::writeable());
+
+        Serial::putc(text[i]);
+    }
+}
diff -r 000000000000 -r d493a3003022 SerialBuffered.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialBuffered.h	Tue May 21 13:51:07 2013 +0000
@@ -0,0 +1,71 @@
+#ifndef _SERIAL_BUFFERED_H_
+#define _SERIAL_BUFFERED_H_
+
+#include "mbed.h"
+
+/**
+ * Buffered serial class.
+ */
+class SerialBuffered : public Serial
+{
+    public:
+        /**
+         * Create a buffered serial class.
+         *
+         * @param tx A pin for transmit.
+         * @param rx A pin for receive.
+         */
+        SerialBuffered(PinName tx, PinName rx);
+
+        /**
+         * Destroy.
+         */
+        virtual ~SerialBuffered();
+
+        /**
+         * Get a character.
+         *
+         * @return A character. (-1:timeout)
+         */
+        int getc();
+
+        /**
+         * Returns 1 if there is a character available to read, otherwise.
+         */
+        int readable();
+
+        /**
+         * Set timeout for getc().
+         *
+         * @param ms milliseconds. (-1:Disable timeout)
+         */
+        void setTimeout(int ms);
+
+        /**
+         * Read requested bytes.
+         *
+         * @param bytes A pointer to a buffer.
+         * @param requested Length.
+         *
+         * @return Readed byte length.
+         */
+        size_t readBytes(uint8_t *bytes, size_t requested);
+        
+        float f_readIntTo(char delimiter);
+        int i_readIntTo(char delimiter);
+        void writeText(char* text);
+
+    private:
+        void handleInterrupt();
+        
+        static const int BUFFERSIZE = 2048;
+        static const int BUFFER_TEXT_SIZE = 255;
+        
+        uint8_t buffer[BUFFERSIZE];            // points at a circular buffer, containing data from m_contentStart, for m_contentSize bytes, wrapping when you get to the end
+        uint16_t indexContentStart;   // index of first bytes of content
+        uint16_t indexContentEnd;     // index of bytes after last byte of content
+        int timeout;
+        Timer timer;
+};
+
+#endif
diff -r 000000000000 -r d493a3003022 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue May 21 13:51:07 2013 +0000
@@ -0,0 +1,43 @@
+#include "mbed.h"
+#include "BMA180.h"
+#include "Accelerometer.h"
+
+#define SDA      p9
+#define SCL      p10
+Serial pc(USBTX, USBRX);
+//Serial pc(p28, p27);
+int main() 
+{
+    float x,y,z, AngleX, AngleY;
+    pc.printf("Inicializing...\r\n");
+    BMA180 *bma180 = new BMA180(SDA, SCL);
+    Accelerometer acc(bma180, 4096);
+    
+    pc.printf("OK...\r\n");
+    wait(1);
+    //max G
+    
+    //y = bma180->getY();
+    //z = bma180->getZ();
+     
+    //printf("%f\n%f\n%f", x,y,z);
+    
+    
+    //acc->updateZeroRates();
+    
+    while(1) 
+    {
+        acc.update();
+        x = acc.getAccelerationX();
+        y = acc.getAccelerationY();
+        z = acc.getAccelerationZ(); 
+        
+        AngleX = acc.getDegreesAngleX();
+        AngleY = acc.getDegreesAngleY();
+        
+        pc.printf("x: %.2f \t\ty: %.2f \t\tz: %.2f \t\tAngleX: %.2f \t\tAngleY: %.2f \t\r\n", x, y, z, AngleX, AngleY); 
+        //x = bma180->getX();
+        //printf("%f\r\n", x);
+        wait_ms(200);
+    }
+}
diff -r 000000000000 -r d493a3003022 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue May 21 13:51:07 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/10b9abbe79a6
\ No newline at end of file