df

Dependencies:   mbed

Fork of APP1 by Team APP

Committer:
dupm2216
Date:
Tue Jan 17 20:01:40 2017 +0000
Revision:
19:f5aa0ce5546b
Parent:
9:12519f9dd3cd
Child:
21:a111be2582be
Integrate moving average filter in accelerometer

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dupm2216 1:7becb0e903e3 1 #include "Accelerometer.hpp"
dupm2216 6:3facf0329142 2 #include "Utility.hpp"
dupm2216 1:7becb0e903e3 3
dupm2216 8:862e28c7f6f6 4 #include <cmath>
dupm2216 8:862e28c7f6f6 5
dupm2216 7:1e00dfecc92d 6 namespace accelerometer
dupm2216 5:f59b51ac4b40 7 {
dupm2216 7:1e00dfecc92d 8 //Compute inverse two's complement to obtain a signed value
dupm2216 7:1e00dfecc92d 9 //See page 21: https://www.gel.usherbrooke.ca/s5info/h17/doc/app1/file/MMA8452Q.pdf
dupm2216 7:1e00dfecc92d 10 //See: https://en.wikipedia.org/wiki/Two's_complement
dupm2216 7:1e00dfecc92d 11 //Turns out, the signed char does it for free
dupm2216 7:1e00dfecc92d 12 //We have to specify "signed char" because the "standard does not specify if plain char is signed or unsigned"
dupm2216 7:1e00dfecc92d 13 //http://stackoverflow.com/a/2054941/3212785
dupm2216 7:1e00dfecc92d 14 int raw_axis_data_to_int(signed char raw_axis_data)
dupm2216 7:1e00dfecc92d 15 {
dupm2216 7:1e00dfecc92d 16 return raw_axis_data;
dupm2216 7:1e00dfecc92d 17 }
dupm2216 7:1e00dfecc92d 18
dupm2216 7:1e00dfecc92d 19 char get_axis_register(Axis axis)
dupm2216 7:1e00dfecc92d 20 {
dupm2216 7:1e00dfecc92d 21 switch(axis)
dupm2216 7:1e00dfecc92d 22 {
dupm2216 7:1e00dfecc92d 23 case AXIS_X: return OUT_X_MSB_REGISTER;
dupm2216 7:1e00dfecc92d 24 case AXIS_Y: return OUT_Y_MSB_REGISTER;
dupm2216 7:1e00dfecc92d 25 case AXIS_Z: return OUT_Z_MSB_REGISTER;
dupm2216 7:1e00dfecc92d 26 default: return AXIS_INVALID;
dupm2216 7:1e00dfecc92d 27 }
dupm2216 7:1e00dfecc92d 28 }
dupm2216 8:862e28c7f6f6 29
dupm2216 7:1e00dfecc92d 30 double g_force_from_int_axis_data(const int axis_data)
dupm2216 1:7becb0e903e3 31 {
dupm2216 7:1e00dfecc92d 32 return (double)axis_data / 64.0;
dupm2216 7:1e00dfecc92d 33 }
dupm2216 7:1e00dfecc92d 34
dupm2216 7:1e00dfecc92d 35 //Z axis is perpendicular to the horizontal plane, towards the floor when the accelerometer is flat
dupm2216 7:1e00dfecc92d 36 //Therefore,
dupm2216 7:1e00dfecc92d 37 // - if the Z force is +1g, the accelerometer is flat
dupm2216 7:1e00dfecc92d 38 // - if the Z force is -1g, the accelerometer is upside down
dupm2216 7:1e00dfecc92d 39 // - if the Z force is 0g, the accelerometer 90 degree from the horizontal
dupm2216 8:862e28c7f6f6 40 //cos(theta) = Z force in g
dupm2216 7:1e00dfecc92d 41 double angle_from_int_axis_data(const int axis_data)
dupm2216 7:1e00dfecc92d 42 {
dupm2216 7:1e00dfecc92d 43 const double z_g_force = g_force_from_int_axis_data(axis_data);
dupm2216 8:862e28c7f6f6 44 const double absolute_z_g_force = std::fabs(z_g_force);
dupm2216 8:862e28c7f6f6 45 if(absolute_z_g_force > 1.0)
dupm2216 8:862e28c7f6f6 46 {
dupm2216 8:862e28c7f6f6 47 return 0.0;
dupm2216 8:862e28c7f6f6 48 }
dupm2216 8:862e28c7f6f6 49
dupm2216 8:862e28c7f6f6 50 const double angle_radian = std::acos(absolute_z_g_force);
dupm2216 7:1e00dfecc92d 51 return utility::degree_from_radian(angle_radian);
dupm2216 1:7becb0e903e3 52 }
dupm2216 7:1e00dfecc92d 53
dupm2216 7:1e00dfecc92d 54 Accelerometer::Accelerometer(
dupm2216 7:1e00dfecc92d 55 PinName sda_pin,
dupm2216 7:1e00dfecc92d 56 PinName scl_pin,
dupm2216 19:f5aa0ce5546b 57 const int filter_size,
dupm2216 7:1e00dfecc92d 58 const int slave_address
dupm2216 7:1e00dfecc92d 59 ) :
dupm2216 7:1e00dfecc92d 60 device(sda_pin, scl_pin),
dupm2216 19:f5aa0ce5546b 61 filter(filter_size),
dupm2216 7:1e00dfecc92d 62 slave_address(slave_address)
dupm2216 7:1e00dfecc92d 63 {
dupm2216 7:1e00dfecc92d 64 }
dupm2216 7:1e00dfecc92d 65
dupm2216 7:1e00dfecc92d 66 void Accelerometer::write_register(const char register_address, const char new_value)
dupm2216 7:1e00dfecc92d 67 {
dupm2216 7:1e00dfecc92d 68 const int left_shifted_slave_address = slave_address << 1;
dupm2216 7:1e00dfecc92d 69 char data[2];
dupm2216 7:1e00dfecc92d 70 data[0] = register_address;
dupm2216 7:1e00dfecc92d 71 data[1] = new_value;
dupm2216 7:1e00dfecc92d 72
dupm2216 7:1e00dfecc92d 73 const int write_return = device.write(left_shifted_slave_address, data, 2);
dupm2216 7:1e00dfecc92d 74 if(write_return < 0)
dupm2216 7:1e00dfecc92d 75 {
dupm2216 7:1e00dfecc92d 76 printf("Write error: I2C error");
dupm2216 7:1e00dfecc92d 77 }
dupm2216 7:1e00dfecc92d 78 }
dupm2216 7:1e00dfecc92d 79
dupm2216 7:1e00dfecc92d 80 char Accelerometer::read_register(const char register_address)
dupm2216 1:7becb0e903e3 81 {
dupm2216 7:1e00dfecc92d 82 char result;
dupm2216 7:1e00dfecc92d 83 const int left_shifted_slave_address = slave_address << 1;
dupm2216 7:1e00dfecc92d 84
dupm2216 7:1e00dfecc92d 85 const int write_return = device.write(left_shifted_slave_address, &register_address, 1, true);
dupm2216 7:1e00dfecc92d 86 if(write_return < 0)
dupm2216 7:1e00dfecc92d 87 {
dupm2216 7:1e00dfecc92d 88 printf("Write error: I2C error");
dupm2216 7:1e00dfecc92d 89 }
dupm2216 7:1e00dfecc92d 90
dupm2216 7:1e00dfecc92d 91 const int read_return = device.read(left_shifted_slave_address, &result, 1);
dupm2216 7:1e00dfecc92d 92 if(read_return != 0)
dupm2216 7:1e00dfecc92d 93 {
dupm2216 7:1e00dfecc92d 94 printf("Read error: I2C error (nack)");
dupm2216 7:1e00dfecc92d 95 }
dupm2216 7:1e00dfecc92d 96
dupm2216 7:1e00dfecc92d 97 return result;
dupm2216 1:7becb0e903e3 98 }
dupm2216 7:1e00dfecc92d 99
dupm2216 7:1e00dfecc92d 100 //axis_data must be an array of 6 bytes
dupm2216 7:1e00dfecc92d 101 void Accelerometer::read_all_axis(signed char* axis_data)
dupm2216 1:7becb0e903e3 102 {
dupm2216 7:1e00dfecc92d 103 for(int i = 0; i < NUMBER_OF_DATA_REGISTERS; ++i)
dupm2216 7:1e00dfecc92d 104 {
dupm2216 7:1e00dfecc92d 105 const char current_register = OUT_X_MSB_REGISTER + i;
dupm2216 7:1e00dfecc92d 106 axis_data[i] = read_register(current_register);
dupm2216 7:1e00dfecc92d 107 }
dupm2216 1:7becb0e903e3 108 }
dupm2216 7:1e00dfecc92d 109
dupm2216 7:1e00dfecc92d 110 void Accelerometer::print_all_axis_data()
dupm2216 1:7becb0e903e3 111 {
dupm2216 7:1e00dfecc92d 112 signed char axis_data[NUMBER_OF_DATA_REGISTERS];
dupm2216 7:1e00dfecc92d 113 for(int i=0; i<NUMBER_OF_DATA_REGISTERS; i++)
dupm2216 7:1e00dfecc92d 114 {
dupm2216 7:1e00dfecc92d 115 axis_data[i] = 0;
dupm2216 7:1e00dfecc92d 116 }
dupm2216 7:1e00dfecc92d 117
dupm2216 7:1e00dfecc92d 118 read_all_axis(axis_data);
dupm2216 7:1e00dfecc92d 119
dupm2216 7:1e00dfecc92d 120 printf("Register content: ");
dupm2216 7:1e00dfecc92d 121 for(int i=0; i<NUMBER_OF_DATA_REGISTERS; i++)
dupm2216 7:1e00dfecc92d 122 {
dupm2216 7:1e00dfecc92d 123 const int current_data = (int)(axis_data[i]);
dupm2216 7:1e00dfecc92d 124 printf("%d, ", current_data);
dupm2216 7:1e00dfecc92d 125 }
dupm2216 7:1e00dfecc92d 126 printf("\r\n");
dupm2216 7:1e00dfecc92d 127 }
dupm2216 7:1e00dfecc92d 128
dupm2216 7:1e00dfecc92d 129 void Accelerometer::set_standby()
dupm2216 7:1e00dfecc92d 130 {
dupm2216 7:1e00dfecc92d 131 const char previous_ctrl_reg1 = read_register(CTRL_REG1_REGISTER_ADDRESS);
dupm2216 7:1e00dfecc92d 132 const char new_ctrl_reg1_value = previous_ctrl_reg1 & ~(0x01);
dupm2216 7:1e00dfecc92d 133 write_register(CTRL_REG1_REGISTER_ADDRESS, new_ctrl_reg1_value);
dupm2216 1:7becb0e903e3 134 }
dupm2216 7:1e00dfecc92d 135
dupm2216 7:1e00dfecc92d 136 void Accelerometer::set_active()
dupm2216 7:1e00dfecc92d 137 {
dupm2216 7:1e00dfecc92d 138 const char previous_ctrl_reg1 = read_register(CTRL_REG1_REGISTER_ADDRESS);
dupm2216 7:1e00dfecc92d 139 const char new_ctrl_reg1_value = previous_ctrl_reg1 | 0x01;
dupm2216 7:1e00dfecc92d 140 write_register(CTRL_REG1_REGISTER_ADDRESS, new_ctrl_reg1_value);
dupm2216 7:1e00dfecc92d 141 }
dupm2216 7:1e00dfecc92d 142
dupm2216 7:1e00dfecc92d 143 void Accelerometer::init()
dupm2216 7:1e00dfecc92d 144 {
dupm2216 7:1e00dfecc92d 145 set_active();
dupm2216 7:1e00dfecc92d 146 }
dupm2216 7:1e00dfecc92d 147
dupm2216 7:1e00dfecc92d 148 int Accelerometer::read_axis_data_8_bits(Axis axis)
dupm2216 7:1e00dfecc92d 149 {
dupm2216 7:1e00dfecc92d 150 const char axis_register = get_axis_register(axis);
dupm2216 7:1e00dfecc92d 151 const char register_value = read_register(axis_register);
dupm2216 7:1e00dfecc92d 152 return raw_axis_data_to_int(register_value);
dupm2216 7:1e00dfecc92d 153 }
dupm2216 7:1e00dfecc92d 154
dupm2216 7:1e00dfecc92d 155 double Accelerometer::get_angle_from_horizontal()
dupm2216 7:1e00dfecc92d 156 {
dupm2216 19:f5aa0ce5546b 157 const int z_axis_data = read_axis_data_8_bits(AXIS_Z);
dupm2216 19:f5aa0ce5546b 158 const int filtered_z_axis_data = this->filter.calculate(z_axis_data);
dupm2216 19:f5aa0ce5546b 159 return angle_from_int_axis_data(filtered_z_axis_data);
dupm2216 7:1e00dfecc92d 160 }
dupm2216 9:12519f9dd3cd 161 }