Dezibot 4
MotionDetection.cpp
Go to the documentation of this file.
1 #include "MotionDetection.h"
2 #include <math.h>
3 
5  handler = new SPIClass(FSPI);
6 };
7 
9  pinMode(34,OUTPUT);
10  digitalWrite(34,HIGH);
11  handler->begin(36,37,35,34);
12  // set Accel and Gyroscop to Low Noise
13  this->writeRegister(PWR_MGMT0,0x1F);
14  //busy Wait for startup
15  delayMicroseconds(250);
16  //set accelconfig
17  this->writeRegister(0x21,0x05);
18  //set Gyroconfig
19  this->writeRegister(0x20,0x25);
20  //set Gyro Filter
21  this->writeRegister(0x23,0x37);
22  //Prepare FIFO to take Accel and Gyro data
23  this->initFIFO();
24  this->stopFIFO();
25 
26 };
27 
29  this->writeRegister(PWR_MGMT0,0x00);
30 };
31 
33  IMUResult result;
37  return result;
38 };
39 
41  IMUResult result;
42  result.x = readRegister(GYRO_DATA_X_HIGH) <<8;
43  result.x |= readRegister(GYRO_DATA_X_LOW);
44  result.y = readRegister(GYRO_DATA_Y_HIGH)<<8;
45  result.y |= readRegister(GYRO_DATA_Y_LOW);
46  result.z = readRegister(GYRO_DATA_Z_HIGH)<<8;
47  result.z |= readRegister(GYRO_DATA_Z_LOW);
48  return result;
49 };
51  int16_t raw_temperatur = readRegister(REG_TEMP_HIGH)<<8;
52  raw_temperatur |= readRegister(REG_TEMP_LOW);
53  return raw_temperatur/128 +25;
54 };
55 
57  return readRegister(WHO_AM_I);
58 };
59 
60 bool MotionDetection::isShaken(uint32_t threshold ,uint8_t axis){
61  IMUResult measurment1;
62  IMUResult measurment2;
63  uint count = 0;
64  for(uint i = 0;i<20;i++){
65  measurment1 = this->getAcceleration();
66  delayMicroseconds(10);
67  measurment2 = this->getAcceleration();
68  if(
69  (((axis && xAxis) > 0) && (abs(abs(measurment1.x)-abs(measurment2.x))>threshold)) ||
70  (((axis && yAxis) > 0) && (abs(abs(measurment1.y)-abs(measurment2.y))>threshold)) ||
71  (((axis && zAxis) > 0) && (abs(abs(measurment1.z)-abs(measurment2.z))>threshold))){
72  count++;
73  }
74  delayMicroseconds(15);
75  }
76  return (count > 6);
77 };
78 
79 void MotionDetection::calibrateZAxis(uint gforceValue){
80  this->gForceCalib = gforceValue;
81 };
82 
84  uint tolerance = 200;
85  IMUResult reading = this->getAcceleration();
86  bool flipped = reading.z < 0;
87  float accelrationStrenght = sqrt(reading.x*reading.x+reading.y*reading.y+reading.z*reading.z);
88  //check if reading is valid
89  if (abs(accelrationStrenght-this->gForceCalib) > tolerance ){
90  //total accelration is not gravitational force, error
91  return Orientation{INT_MAX,INT_MAX};
92  }
93 
94  //calculates the angle between the two axis, therefore value between 0-90
95  int yAngle;
96  int xAngle;
97  if(reading.z != 0){
98  yAngle = atan(float(reading.x)/reading.z)*180/3.1415+0.5;
99  xAngle = atan(float(reading.y)/reading.z)*180/3.1415+0.5;
100  } else {
101  yAngle = 90*(reading.x > 0) - (reading.x < 0);
102  xAngle = 90*(reading.y > 0) - (reading.y < 0);
103  }
104 
105  //shift quadrants depending on signum
106  //esp is facing down (normal position)
107  if (reading.z > 0){
108  if(reading.y < 0){
109  xAngle = xAngle+180;
110  } else{
111  xAngle = -1*(180-xAngle);
112  }
113 
114  if(reading.x < 0){
115  yAngle = yAngle+180;
116  } else{
117  yAngle = -1*(180-yAngle);
118  }
119  }
120 
121 
122  return Orientation{xAngle,yAngle};
123 
124 };
125 
127  if (this->getAcceleration().z > 0){
128  return Flipped;
129  }
130  Orientation Rot = this->getTilt();
131  if ((Rot.xRotation == INT_MAX)){
132  return Error;
133  }
134  if(abs(abs(Rot.xRotation)-abs(Rot.yRotation))>tolerance){
135  //determine which axis is more tiltet
136  if (abs(Rot.xRotation)>abs(Rot.yRotation)){
137  //test if dezibot is tilted left or right
138  if (Rot.xRotation > 0){
139  return Right;
140  } else {
141  return Left;
142  }
143  } else {
144  //test if robot is tilted front or back
145  if (Rot.yRotation > 0){
146  return Front;
147  } else {
148  return Back;
149  }
150  }
151  } else {
152  //dezibot is (with tolerance) leveled
153  return Neutral;
154  }
155 };
156 
157 uint8_t MotionDetection::cmdRead(uint8_t reg){
158  return (CMD_READ | (reg & ADDR_MASK));
159 };
160 uint8_t MotionDetection::cmdWrite(uint8_t reg){
161  return (CMD_WRITE | (reg & ADDR_MASK));
162 };
163 
164 uint8_t MotionDetection::readRegister(uint8_t reg){
165  handler->beginTransaction(SPISettings(frequency,SPI_MSBFIRST,SPI_MODE0));
166  digitalWrite(34,LOW);
167  uint8_t result;
168  result = handler->transfer(cmdRead(reg));
169  result = handler->transfer(0x00);
170  digitalWrite(34,HIGH);
171  handler->endTransaction();
172  return result;
173 };
174 
176  uint8_t result = 0;
177  switch(bank){
178  case(MREG1):
179  this->writeRegister(BLK_SEL_R,0x00);
180  break;
181  case(MREG2):
182  this->writeRegister(BLK_SEL_R,0x28);
183  break;
184  case(MREG3):
185  this->writeRegister(BLK_SEL_R,0x50);
186  break;
187  }
188  this->writeRegister(MADDR_R,reg);
189  delayMicroseconds(10);
190  result=this->readRegister(M_R);
191  delayMicroseconds(10);
192  this->resetRegisterBankAccess();
193  return result;
194 };
195 
196 void MotionDetection::writeToRegisterBank(registerBank bank, uint8_t reg, uint8_t value){
197  while((this->readRegister(MCLK_RDY))&0x08!=0x08){
198  Serial.println("CLK not rdy");
199  delay(100);
200  }
201  uint8_t result = this->readRegister(PWR_MGMT0);
202  //set Idle Bit
203  this->writeRegister(PWR_MGMT0,result|0x10);
204  switch(bank){
205  case(MREG1):
206  this->writeRegister(BLK_SEL_W,0x00);
207  break;
208  case(MREG2):
209  this->writeRegister(BLK_SEL_W,0x28);
210  break;
211  case(MREG3):
212  this->writeRegister(BLK_SEL_W,0x50);
213  break;
214  }
215  this->writeRegister(MADDR_W,reg);
216  this->writeRegister(M_W,value);
217  delayMicroseconds(10);
218  this->writeRegister(PWR_MGMT0,result&0xEF);
219  this->resetRegisterBankAccess();
220 };
221 
223  this->writeRegister(BLK_SEL_R,0x00);
224  this->writeRegister(BLK_SEL_W,0x00);
225  this->writeRegister(MADDR_R,0x00);
226  this->writeRegister(MADDR_W,0x00);
227 };
228 
230  //set TMST_CONFIG1_MREG1 TMST_CONFIIG1_TMST_EN
232  //set FiFO config 5 GYRO_EN,TMST_FSYNC, ACCEL_EN, WM_GT_TH_EN
234  //set FOF_CONFIG2 0x1 (INT triggerd each packaged)
235  this->writeRegister(FIFO_CONFIG2,0x0A);
236 };
237 
239  //set INTF_CONFIG0 FIFO_COUNT_FORMAT to Records and SENSOR_DATA_ENDIAN to Big Endian
240  this->writeRegister(INTF_CONFIG0,0x60);
241  //set FIFO_CONFIG1 to BYPASS Off
242  this->writeRegister(FIFO_CONFIG1,0x00);
243 }
244 
246  //set INTF_CONFIG0 FIFO_COUNT_FORMAT to bytes and SENSOR_DATA_ENDIAN to Little Endian (default)
247  this->writeRegister(INTF_CONFIG0,0x30);
248  //set FIFO_CONFIG1 BYPASS On
249  this->writeRegister(FIFO_CONFIG1,0x01);
250 }
251 
253  int16_t fifocount = 0;
254  int8_t fifohigh = this->readRegister(FIFO_COUNTH);
255  int8_t fifolow = this->readRegister(FIFO_COUNTL);
256  fifocount = (fifohigh<<8)|fifolow;
257  handler->beginTransaction(SPISettings(frequency,SPI_MSBFIRST,SPI_MODE0));
258  digitalWrite(34,LOW);
259  handler->transfer(cmdRead(FIFO_DATA));
260  handler->transfer(buf,16*fifocount);
261  digitalWrite(34,HIGH);
262  handler->endTransaction();
263 
264  writeRegister(0x02,0x04);
265  delayMicroseconds(10);
266 
267  for(int i = 0; i<fifocount;i++){
268  buffer[i].header = buf[0x00+16*i];
269  buffer[i].accel.x = (buf[0x02+16*i]<<8)|buf[0x01+16*i];
270  buffer[i].accel.y = (buf[0x04+16*i]<<8)|buf[0x03+16*i];
271  buffer[i].accel.z = (buf[0x06+16*i]<<8)|buf[0x05+16*i];
272  buffer[i].gyro.x = (buf[0x08+16*i]<<8)|buf[0x07+16*i];
273  buffer[i].gyro.y = (buf[0x0A+16*i]<<8)|buf[0x09+16*i];
274  buffer[i].gyro.z = (buf[0x0C+16*i]<<8)|buf[0x0B+16*i];
275  buffer[i].temperature = buf[0x0D+16*i];
276  buffer[i].timestamp = (buf[0x0F+16*i]<<8)|buf[0x0E +16*i];
277  }
278  return fifocount;
279 };
280 
281 void MotionDetection::writeRegister(uint8_t reg, uint8_t value){
282  handler->beginTransaction(SPISettings(frequency,SPI_MSBFIRST,SPI_MODE0));
283  digitalWrite(34,LOW);
284  handler->transfer(reg);
285  handler->transfer(value);
286  digitalWrite(34,HIGH);
287  delayMicroseconds(10);
288  handler->endTransaction();
289 };
#define GYRO_DATA_Z_LOW
Definition: IMU_CMDs.h:26
#define PWR_MGMT0
Definition: IMU_CMDs.h:28
#define FIFO_CONFIG1
Definition: IMU_CMDs.h:43
#define ADDR_MASK
Definition: IMU_CMDs.h:6
#define MADDR_R
Definition: IMU_CMDs.h:36
#define BLK_SEL_W
Definition: IMU_CMDs.h:33
#define M_W
Definition: IMU_CMDs.h:37
#define TMST_CONFIG1
Definition: IMU_CMDs.h:48
#define ACCEL_DATA_Z_HIGH
Definition: IMU_CMDs.h:18
#define FIFO_CONFIG2
Definition: IMU_CMDs.h:44
#define REG_TEMP_LOW
Definition: IMU_CMDs.h:11
#define ACCEL_DATA_X_LOW
Definition: IMU_CMDs.h:15
#define MADDR_W
Definition: IMU_CMDs.h:35
#define CMD_WRITE
Definition: IMU_CMDs.h:5
#define GYRO_DATA_X_HIGH
Definition: IMU_CMDs.h:21
#define FIFO_DATA
Definition: IMU_CMDs.h:42
#define MCLK_RDY
Definition: IMU_CMDs.h:9
#define INTF_CONFIG0
Definition: IMU_CMDs.h:31
#define FIFO_CONFIG5
Definition: IMU_CMDs.h:47
#define CMD_READ
Definition: IMU_CMDs.h:4
#define WHO_AM_I
Definition: IMU_CMDs.h:29
#define BLK_SEL_R
Definition: IMU_CMDs.h:34
#define REG_TEMP_HIGH
Definition: IMU_CMDs.h:12
#define ACCEL_DATA_Y_HIGH
Definition: IMU_CMDs.h:16
#define GYRO_DATA_Y_LOW
Definition: IMU_CMDs.h:24
#define GYRO_DATA_X_LOW
Definition: IMU_CMDs.h:22
#define ACCEL_DATA_Z_LOW
Definition: IMU_CMDs.h:19
#define FIFO_COUNTH
Definition: IMU_CMDs.h:40
#define FIFO_COUNTL
Definition: IMU_CMDs.h:41
#define GYRO_DATA_Y_HIGH
Definition: IMU_CMDs.h:23
#define ACCEL_DATA_X_HIGH
Definition: IMU_CMDs.h:14
#define ACCEL_DATA_Y_LOW
Definition: IMU_CMDs.h:17
#define M_R
Definition: IMU_CMDs.h:38
#define GYRO_DATA_Z_HIGH
Definition: IMU_CMDs.h:25
This component controls the IMU (Accelerometer & Gyroscope) ICM-42670-P.
Direction
@ Front
@ Neutral
@ Back
@ Error
@ Left
@ Flipped
@ Right
@ yAxis
@ zAxis
@ xAxis
void stopFIFO(void)
stops writing results to FIFO-Storage needs to be called before Data Registers (such as GYRO_DATA_*,...
uint getDataFromFIFO(FIFO_Package *buffer)
will read all availible packages from fifo, after 40ms Fifo is full Only works when startFIFO was cal...
uint16_t cmdWrite(uint8_t regHigh, uint8_t regLow)
bool isShaken(uint32_t threshold=defaultShakeThreshold, uint8_t axis=xAxis|yAxis|zAxis)
Detects if at the time of calling is shaken. Therefore the sum over all accelerationvalues is calcula...
uint8_t readFromRegisterBank(registerBank bank, uint8_t reg)
uint16_t cmdRead(uint8_t regHigh, uint8_t regLow)
uint8_t readRegister(uint8_t reg)
void resetRegisterBankAccess()
Orientation getTilt()
calculates how the robot is tilted. It is set, that when the robot is placed normally on a flat table...
int8_t getWhoAmI(void)
Returns the value of reading the whoAmI register When IMU working correctly, value should be 0x67.
static const uint frequency
IMUResult getRotation(void)
Triggers a new reading of the gyroscope and reads the values from the imu.
Direction getTiltDirection(uint tolerance=10)
Checks in which direction (Front, Left, Right, Back) the robot is tilted.
void calibrateZAxis(uint gforceValue)
void startFIFO(void)
starts writing the measurment results to the FIFO-Storage
void end(void)
stops the component Sets the IMU to Low-Power-Mode
void writeRegister(uint8_t reg, uint8_t value)
void writeToRegisterBank(registerBank bank, uint8_t reg, uint8_t value)
void begin(void)
initialized the IMU Component. Wakes the IMU from Standby Set configuration
SPIClass * handler
void initFIFO(void)
makes all settings necessary so it is possible to use the FIFO, but does not actually start writing p...
IMUResult getAcceleration(void)
Triggers a new Reading of the accelerationvalues and reads them from the IMU.
float getTemperature(void)
Reads the current On Chip temperature of the IMU.
IMUResult accel
int16_t timestamp
IMUResult gyro
int16_t temperature