M5Unified
SH200Q_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 "SH200Q_Class.hpp"
7 #include <freertos/FreeRTOS.h>
8 #include <freertos/task.h>
9 #include <string.h>
10 
11 namespace m5
12 {
14  SH200Q_Class::SH200Q_Class(std::uint8_t i2c_addr, std::uint32_t freq, I2C_Class* i2c)
15  : IMU_Base ( i2c_addr, freq, i2c )
16  {}
17 
18  IMU_Base::imu_spec_t SH200Q_Class::begin(I2C_Class* i2c)
19  {
20  if (i2c)
21  {
22  _i2c = i2c;
23  }
24 
25  // WHO_AM_I : IMU Check
26  if (WhoAmI() != 0x18)
27  {
28  return imu_spec_none;
29  }
30  vTaskDelay(1);
31 
32  bitOn(0xC2, 0x04);
33  vTaskDelay(1);
34 
35  bitOff(0xC2, 0x04);
36  vTaskDelay(1);
37 
38  bitOn(0xD8, 0x80);
39  vTaskDelay(1);
40 
41  bitOff(0xD8, 0x80);
42  vTaskDelay(1);
43 
44  static constexpr std::uint8_t init_cmd[] =
45  { 0x78, 0x61
46  , 0x78, 0x00
47  , 0x0E, 0x91 // ACC_CONFIG(0x0E) : 256Hz
48  , 0x0F, 0x13 // GYRO_CONFIG(0x0F) : 500Hz
49  , 0x11, 0x03 // GYRO_DLPF(0x11) : 50Hz
50  , 0x12, 0x00 // FIFO_CONFIG(0x12)
51  // , 0x12, 0x80 // FIFO_CONFIG(0x12) : FIFO MODE
52 , 0x14, 0x20 // data ready interrupt en
53  , 0x16, 0x01 // ACC_RANGE(0x16) : +-8G
54  , 0x2B, 0x00 // GYRO_RANGE(0x2B) : +-2000
55  , 0xBA, 0xC0 // REG_SET1(0xBA)
56  , 0xFF, 0xFF
57  };
58 
59  for (int idx = -1;;)
60  {
61  std::uint8_t reg = init_cmd[++idx];
62  std::uint8_t val = init_cmd[++idx];
63  if ((reg & val) == 0xFF) { break; }
64  writeRegister8(reg, val);
65  vTaskDelay(1);
66  }
67 
68  // REG_SET2(0xCA)
69  bitOn(0xCA, 0x10);
70  vTaskDelay(1);
71 
72  // REG_SET2(0xCA)
73  bitOff(0xCA, 0x10);
74  vTaskDelay(1);
75 
76  _init = true;
77  return (imu_spec_t)(imu_spec_accel | imu_spec_gyro);
78  }
79 
80  IMU_Base::imu_spec_t SH200Q_Class::getImuRawData(imu_raw_data_t* data) const
81  {
82  // static constexpr float aRes = 8.0f / 32768.0f;
83  // static constexpr float gRes = 2000.0f / 32768.0f;
84  uint8_t st = readRegister8(0x2C);
85 // printf("st:%d\n",st);
86  if (st & 0x20u)
87  {
88  std::int16_t buf[6];
89  bool res = readRegister(0x00, (std::uint8_t*)buf, 14);
90  if (res)
91  {
92  memcpy(data->value, buf, 12);
93  return (imu_spec_t)(imu_spec_accel | imu_spec_gyro);
94  }
95  }
96  return imu_spec_none;
97  }
98 /*
99  bool SH200Q_Class::getImuRawData(imu_raw_data_t* data) const
100  {
101  // static constexpr float aRes = 8.0f / 32768.0f;
102  // static constexpr float gRes = 2000.0f / 32768.0f;
103  std::uint8_t state[2];
104  std::int16_t buf[6];
105 
106  if (readRegister(0x2E, (std::uint8_t*)state, 2))
107  {
108  // 0x2E:accel FIFO Status
109  // 0x2F:gyro FIFO Status
110  uint32_t len = 7;
111  uint32_t idx = 0;
112  if (0 == (state[0] & 0x3F))
113  {
114  idx += 3;
115  len -= 3;
116  }
117  if (0 == (state[1] & 0x3F))
118  {
119  len -= 4;
120  }
121  if (len > 2)
122  {
123  if (readRegister(idx << 1, (std::uint8_t*)(&buf[idx]), len << 1))
124  {
125  if (idx == 0)
126  {
127  data->accel.x = buf[0];
128  data->accel.y = buf[1];
129  data->accel.z = buf[2];
130 printf("idx:%d len:%d ax:%d ay:%d az:%d gx:%d gy:%d gz:%d\n", idx, len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
131  }
132  if (len > 3)
133  {
134  data->gyro.x = buf[3];
135  data->gyro.y = buf[4];
136  data->gyro.z = buf[5];
137  data->temp = buf[6];
138  return true;
139  }
140  }
141  }
142  }
143  return false;
144  }
145 
146 */
147 
148  std::uint8_t SH200Q_Class::WhoAmI(void)
149  {
150  return readRegister8(0x30);
151  }
152 /*
153  bool SH200Q_Class::getAccelAdc(std::int16_t* ax, std::int16_t* ay, std::int16_t* az) const
154  {
155  std::int16_t buf[3];
156  bool res = readRegister(0x00, (std::uint8_t*)buf, 6);
157  *ax = buf[0];
158  *ay = buf[1];
159  *az = buf[2];
160  return res;
161  }
162 
163  bool SH200Q_Class::getGyroAdc(std::int16_t* gx, std::int16_t* gy, std::int16_t* gz) const
164  {
165  std::int16_t buf[3];
166  bool res = readRegister(0x06, (std::uint8_t*)buf, 6);
167  *gx = buf[0];
168  *gy = buf[1];
169  *gz = buf[2];
170  return res;
171  }
172 
173  bool SH200Q_Class::getAccel(float* ax, float* ay, float* az) const
174  {
175  static constexpr float aRes = 8.0f / 32768.0f;
176  std::int16_t buf[3];
177  bool res = readRegister(0x00, (std::uint8_t*)buf, 6);
178  *ax = buf[0] * aRes;
179  *ay = buf[1] * aRes;
180  *az = buf[2] * aRes;
181  return res;
182  }
183 
184  bool SH200Q_Class::getGyro(float* gx, float* gy, float* gz) const
185  {
186  static constexpr float gRes = 2000.0f / 32768.0f;
187  std::int16_t buf[3];
188  bool res = readRegister(0x06, (std::uint8_t*)buf, 6);
189  *gx = buf[0] * gRes;
190  *gy = buf[1] * gRes;
191  *gz = buf[2] * gRes;
192  return res;
193  }
194 
195  bool SH200Q_Class::getTemp(float *t) const
196  {
197  std::int16_t buf;
198  bool res = readRegister(0x0C, (std::uint8_t*)&buf, 2);
199  *t = 21.0f + buf / 333.87f;
200  return res;
201  }
202 //*/
203  void SH200Q_Class::getConvertParam(imu_convert_param_t* param) const
204  {
205  param->accel_res = 8.0f / 32768.0f;
206  param->gyro_res = 2000.0f / 32768.0f;
207  param->temp_res = 1.0f / 333.87f;
208  param->temp_offset = 21.0f;
209  }
210 
211  bool SH200Q_Class::getTempAdc(int16_t *t) const
212  {
213  std::int16_t buf;
214  bool res = readRegister(0x0C, (std::uint8_t*)&buf, 2);
215  if (res) { *t = buf; }
216  return res;
217  }
218 }
219 #endif
virtual ~SH200Q_Class()
SH200Q_Class(std::uint8_t i2c_addr=DEFAULT_ADDRESS, std::uint32_t freq=400000, I2C_Class *i2c=&In_I2C)
Definition: M5Unified.cpp:48