M5Unified
BMI270_Class.cpp
Go to the documentation of this file.
1 // Copyright (c) M5Stack. All rights reserved.
2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 
4 #if defined (ESP_PLATFORM)
5 
6 #include "BMI270_Class.hpp"
7 #include <freertos/FreeRTOS.h>
8 #include <freertos/task.h>
9 
10 namespace m5
11 {
12  #include "BMI270_config.inl"
13 
15  BMI270_Class::BMI270_Class(std::uint8_t i2c_addr, std::uint32_t freq, I2C_Class* i2c)
16  : IMU_Base ( i2c_addr, freq, i2c )
17  {}
18 
19  bool BMI270_Class::_upload_file(const uint8_t *config_data, size_t index, size_t write_len)
20  {
21  uint8_t addr_array[2] = {
22  (uint8_t)((index >> 1) & 0x0F),
23  (uint8_t)(index >> 5)
24  };
25 
26  if (config_data != nullptr
27  && writeRegister( INIT_ADDR_0, addr_array, 2 )
28  && writeRegister( INIT_DATA_ADDR, (uint8_t *)config_data, write_len))
29  {
30  return true;
31  }
32  return true;
33  }
34 
35  IMU_Base::imu_spec_t BMI270_Class::begin(I2C_Class* i2c)
36  {
37  if (i2c)
38  {
39  _i2c = i2c;
40  }
41 
42  WhoAmI();
43  if (WhoAmI() != 0x24)
44  {
45  return imu_spec_none;
46  }
47 
48  writeRegister8(CMD_REG_ADDR, SOFT_RESET_CMD); // software reset.
49  {
50  int retry = 16;
51  do { vTaskDelay(1); }
52  while (0 == readRegister8(PWR_CONF_ADDR) && --retry);
53  }
54 
55  writeRegister8(PWR_CONF_ADDR, 0x00); // Power save disabled.
56  vTaskDelay(1);
57  bool res = _upload_file(bmi270_config_file, 0, sizeof(bmi270_config_file));
58  writeRegister8(INIT_CTRL_ADDR, 0x01);
59  writeRegister8(INT_MAP_DATA_ADDR, 0xFF);
60 
61  _init = res;
62  if (!res)
63  {
64  return imu_spec_none;
65  }
66 
67  imu_spec_t spec = (imu_spec_t)(imu_spec_accel | imu_spec_gyro);
68  int retry = 16;
69  do { vTaskDelay(1);}
70  while (0 == readRegister8(INTERNAL_STATUS_ADDR) && --retry);
71  res = retry > 0;
72 
73 // 以下は AUXセンサとしてBMM150が接続されている想定の設定
74  auxSetupMode(0x10); // 0x10 = BMM150 I2C Addr
75  auxWriteRegister8(0x4B, 0x83); // software reset + power on
76  auxReadRegister8(0x40); // 0x40 = WhoAmI
77  auto who_am_i = auxReadRegister8(0x40); // 0x40 = WhoAmI
78  if (who_am_i == 0x32)
79  {
80  auxWriteRegister8(0x4C, 0x38); // normal mode / ODR 30Hz
81  spec = (imu_spec_t)(imu_spec_accel | imu_spec_gyro | imu_spec_mag);
82  writeRegister8(AUX_IF_CONF_ADDR, 0x4F); // FCU_WRITE_EN + Manual BurstLength 8 + BurstLength 8
83  writeRegister8(AUX_RD_ADDR , 0x42); // 0x42 = BMM150 I2C Data X LSB reg
84  writeRegister8(PWR_CTRL_ADDR, 0x0F); // temp en | ACC en | GYR en | AUX en
85  }
86  return spec;
87  }
88 
89  bool BMI270_Class::auxSetupMode(std::uint8_t i2c_addr)
90  {
91  writeRegister8(IF_CONF_ADDR, 0x20); // AUX I2C enable.
92  writeRegister8(PWR_CONF_ADDR, 0x00); // Power save disabled.
93  writeRegister8(PWR_CTRL_ADDR, 0x0E); // AUX sensor disable.
94  writeRegister8(AUX_IF_CONF_ADDR, 0x80);
95  return writeRegister8(AUX_DEV_ID_ADDR , i2c_addr << 1);
96  }
97 
98  bool BMI270_Class::auxWriteRegister8(std::uint8_t reg, std::uint8_t data)
99  {
100  writeRegister8(AUX_WR_DATA_ADDR, data); // AUXセンサに書き込む値
101  writeRegister8(AUX_WR_ADDR, reg); // AUXセンサに書き込むレジスタ番号
102  int retry = 3;
103  while ((readRegister8(STATUS_ADDR) & 0b100) && --retry) { vTaskDelay(1); }
104  return retry;
105  }
106 
107  std::uint8_t BMI270_Class::auxReadRegister8(std::uint8_t reg)
108  {
109  writeRegister8(AUX_IF_CONF_ADDR, 0x80); // enable read write. Burst length 1
110  writeRegister8(AUX_RD_ADDR, reg); // AUXセンサから読み取るレジスタ番号
111  int retry = 3;
112  while ((readRegister8(STATUS_ADDR) & 0b100) && --retry) { vTaskDelay(1); }
113  return readRegister8(AUX_X_LSB_ADDR);
114  }
115 
116  std::uint8_t BMI270_Class::WhoAmI(void)
117  {
118  return readRegister8(CHIP_ID_ADDR);
119  }
120 
121  IMU_Base::imu_spec_t BMI270_Class::getImuRawData(imu_raw_data_t* data) const
122  {
123  imu_spec_t res = imu_spec_none;
124  std::uint8_t intstat = readRegister8(INT_STATUS_1_ADDR);
125  if (intstat & 0xE0)
126  {
127  std::int16_t buf[10];
128  if (readRegister(AUX_X_LSB_ADDR, (std::uint8_t*)buf, 20))
129  {
130  if (intstat & 0x80u)
131  {
132  data->accel.x = buf[4];
133  data->accel.y = buf[5];
134  data->accel.z = buf[6];
135  res = (imu_spec_t)(res | imu_spec_accel);
136  }
137  if (intstat & 0x40u)
138  {
139  data->gyro.x = buf[7];
140  data->gyro.y = buf[8];
141  data->gyro.z = buf[9];
142  res = (imu_spec_t)(res | imu_spec_gyro);
143  }
144  if (intstat & 0x20u)
145  {
146  data->mag.x = buf[0] >> 2;
147  data->mag.y = buf[1] >> 2;
148  data->mag.z = buf[2] & 0xFFFE;
149  res = (imu_spec_t)(res | imu_spec_mag);
150  }
151  }
152  }
153  return res;
154  }
155 
156  void BMI270_Class::getConvertParam(imu_convert_param_t* param) const
157  {
158  param->mag_res = 10.0f * 4912.0f / 32760.0f;
159  param->temp_offset = 23.0f;
160  param->temp_res = 1.0f / 512.0f;
161  }
162 
163  bool BMI270_Class::getTempAdc(int16_t *t) const
164  {
165  std::int16_t buf;
166  bool res = readRegister(TEMPERATURE_0_ADDR, (std::uint8_t*)&buf, 2);
167  if (res) { *t = buf; }
168  return res;
169  }
170 
171 /*
172  bool BMI270_Class::getAccelAdc(std::int16_t* ax, std::int16_t* ay, std::int16_t* az) const
173  {
174  std::int16_t buf[3];
175  bool res = readRegister(ACC_X_LSB_ADDR, (std::uint8_t*)buf, 6);
176  *ax = buf[0];
177  *ay = buf[1];
178  *az = buf[2];
179  return res;
180  }
181 
182  bool BMI270_Class::getGyroAdc(std::int16_t* gx, std::int16_t* gy, std::int16_t* gz) const
183  {
184  std::int16_t buf[3];
185  bool res = readRegister(GYR_X_LSB_ADDR, (std::uint8_t*)buf, 6);
186  *gx = buf[0];
187  *gy = buf[1];
188  *gz = buf[2];
189  return res;
190  }
191 
192  bool BMI270_Class::getAccel(float* ax, float* ay, float* az) const
193  {
194  static constexpr float aRes = 8.0f / 32768.0f;
195  std::int16_t buf[3];
196  bool res = readRegister(ACC_X_LSB_ADDR, (std::uint8_t*)buf, 6);
197  *ax = buf[0] * aRes;
198  *ay = buf[1] * aRes;
199  *az = buf[2] * aRes;
200  return res;
201  }
202 
203  bool BMI270_Class::getGyro(float* gx, float* gy, float* gz) const
204  {
205  static constexpr float gRes = 2000.0f / 32768.0f;
206  std::int16_t buf[3];
207  bool res = readRegister(GYR_X_LSB_ADDR, (std::uint8_t*)buf, 6);
208  *gx = buf[0] * gRes;
209  *gy = buf[1] * gRes;
210  *gz = buf[2] * gRes;
211  return res;
212  }
213 
214  bool BMI270_Class::getTemp(float *t) const
215  {
216  std::int16_t buf;
217  bool res = readRegister(TEMPERATURE_0_ADDR, (std::uint8_t*)&buf, 2);
218  *t = 23.0f + buf / 512.0f;
219  return res;
220  }
221 //*/
222 }
223 
224 #endif
virtual ~BMI270_Class()
BMI270_Class(std::uint8_t i2c_addr=DEFAULT_ADDRESS, std::uint32_t freq=400000, I2C_Class *i2c=&In_I2C)
Definition: M5Unified.cpp:48