![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Example of reading an accelerometer sensor (BMA180)
Revision 0:d493a3003022, committed 2013-05-21
- 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
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