Skip to content

Commit 2c038fc

Browse files
committed
Add M5.IMU support
1 parent c7f7c0d commit 2c038fc

File tree

8 files changed

+1011
-5
lines changed

8 files changed

+1011
-5
lines changed

examples/Basics/IMU/IMU.ino

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// define must ahead #include <M5Stack.h>
2+
#define M5STACK_MPU6886
3+
// #define M5STACK_MPU9250
4+
// #define M5STACK_MPU6050
5+
// #define M5STACK_200Q
6+
7+
#include <M5Stack.h>
8+
9+
float accX = 0.0F;
10+
float accY = 0.0F;
11+
float accZ = 0.0F;
12+
13+
float gyroX = 0.0F;
14+
float gyroY = 0.0F;
15+
float gyroZ = 0.0F;
16+
17+
float pitch = 0.0F;
18+
float roll = 0.0F;
19+
float yaw = 0.0F;
20+
21+
float temp = 0.0F;
22+
23+
// the setup routine runs once when M5Stack starts up
24+
void setup(){
25+
26+
// Initialize the M5Stack object
27+
M5.begin();
28+
/*
29+
Power chip connected to gpio21, gpio22, I2C device
30+
Set battery charging voltage and current
31+
If used battery, please call this function in your project
32+
*/
33+
M5.Power.begin();
34+
35+
M5.IMU.Init();
36+
37+
M5.Lcd.fillScreen(BLACK);
38+
M5.Lcd.setTextColor(GREEN , BLACK);
39+
M5.Lcd.setTextSize(2);
40+
}
41+
42+
// the loop routine runs over and over again forever
43+
void loop() {
44+
// put your main code here, to run repeatedly:
45+
M5.IMU.getGyroData(&gyroX,&gyroY,&gyroZ);
46+
M5.IMU.getAccelData(&accX,&accY,&accZ);
47+
M5.IMU.getAhrsData(&pitch,&roll,&yaw);
48+
M5.IMU.getTempData(&temp);
49+
50+
M5.Lcd.setCursor(0, 20);
51+
M5.Lcd.printf("%6.2f %6.2f %6.2f ", gyroX, gyroY, gyroZ);
52+
M5.Lcd.setCursor(220, 42);
53+
M5.Lcd.print(" o/s");
54+
M5.Lcd.setCursor(0, 65);
55+
M5.Lcd.printf(" %5.2f %5.2f %5.2f ", accX, accY, accZ);
56+
M5.Lcd.setCursor(220, 87);
57+
M5.Lcd.print(" G");
58+
M5.Lcd.setCursor(0, 110);
59+
M5.Lcd.printf(" %5.2f %5.2f %5.2f ", pitch, roll, yaw);
60+
M5.Lcd.setCursor(220, 132);
61+
M5.Lcd.print(" degree");
62+
M5.Lcd.setCursor(0, 155);
63+
M5.Lcd.printf("Temperature : %.2f C", temp);
64+
65+
delay(1);
66+
}

src/M5Stack.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,13 @@
9191
* </pre>
9292
*
9393
*/
94+
// #define ESP32
9495

9596
#ifndef _M5STACK_H_
9697
#define _M5STACK_H_
9798

9899
#if defined(ESP32)
99100

100-
// #define MPU9250_INSDE
101101
#include "gitTagVersion.h"
102102
#include <Arduino.h>
103103
#include <Wire.h>
@@ -112,6 +112,12 @@
112112
#include "utility/Power.h"
113113
#include "utility/CommUtil.h"
114114

115+
#if defined(M5STACK_MPU6886) || defined(M5STACK_MPU9250) || defined(M5STACK_MPU6050)
116+
#include "utility/MPU6886.h"
117+
#elif defined M5STACK_200Q
118+
#include "utility/SH200Q.h"
119+
#endif
120+
115121
class M5Stack
116122
{
117123
public:
@@ -138,11 +144,12 @@
138144
// HardwareSerial Serial0 = HardwareSerial(0);
139145
// HardwareSerial Serial2 = HardwareSerial(2);
140146

141-
// MPU9250
142-
#ifdef MPU9250_INSDE
143-
MPU9250 IMU = MPU9250();
147+
#if defined(M5STACK_MPU6886) || defined(M5STACK_MPU9250) || defined(M5STACK_MPU6050)
148+
MPU6886 IMU = MPU6886();
149+
#elif defined M5STACK_200Q
150+
SH200Q IMU = SH200Q();
144151
#endif
145-
152+
146153
// I2C
147154
CommUtil I2C = CommUtil();
148155

src/utility/MPU6886.cpp

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#include "MPU6886.h"
2+
#include <math.h>
3+
#include <Arduino.h>
4+
#include "../M5Stack.h"
5+
#include "MahonyAHRS.h"
6+
7+
MPU6886::MPU6886(){
8+
9+
}
10+
11+
void MPU6886::I2C_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer){
12+
M5.I2C.readBytes(driver_Addr, start_Addr, number_Bytes, read_Buffer);
13+
}
14+
15+
void MPU6886::I2C_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer) {
16+
M5.I2C.writeBytes(driver_Addr, start_Addr, write_Buffer, number_Bytes);
17+
}
18+
19+
int MPU6886::Init(void) {
20+
unsigned char tempdata[1];
21+
unsigned char regdata;
22+
23+
Gyscale = GFS_2000DPS;
24+
Acscale = AFS_8G;
25+
26+
Wire1.begin(21,22);
27+
28+
I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_WHOAMI, 1, tempdata);
29+
imuId = tempdata[0];
30+
delay(1);
31+
32+
regdata = 0x00;
33+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, &regdata);
34+
delay(10);
35+
36+
regdata = (0x01<<7);
37+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, &regdata);
38+
delay(10);
39+
40+
regdata = (0x01<<0);
41+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, &regdata);
42+
delay(10);
43+
44+
regdata = 0x10;
45+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, &regdata);
46+
delay(1);
47+
48+
regdata = 0x18;
49+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, &regdata);
50+
delay(1);
51+
52+
regdata = 0x01;
53+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_CONFIG, 1, &regdata);
54+
delay(1);
55+
56+
regdata = 0x05;
57+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_SMPLRT_DIV, 1,&regdata);
58+
delay(1);
59+
60+
regdata = 0x00;
61+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, &regdata);
62+
delay(1);
63+
64+
regdata = 0x00;
65+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG2, 1, &regdata);
66+
delay(1);
67+
68+
regdata = 0x00;
69+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_USER_CTRL, 1, &regdata);
70+
delay(1);
71+
72+
regdata = 0x00;
73+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_FIFO_EN, 1, &regdata);
74+
delay(1);
75+
76+
regdata = 0x22;
77+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_PIN_CFG, 1, &regdata);
78+
delay(1);
79+
80+
regdata = 0x01;
81+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, &regdata);
82+
83+
delay(10);
84+
85+
setGyroFsr(Gyscale);
86+
setAccelFsr(Acscale);
87+
return 0;
88+
}
89+
90+
void MPU6886::getAccelAdc(int16_t* ax, int16_t* ay, int16_t* az) {
91+
uint8_t buf[6];
92+
I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_XOUT_H, 6, buf);
93+
94+
*ax=((int16_t)buf[0]<<8)|buf[1];
95+
*ay=((int16_t)buf[2]<<8)|buf[3];
96+
*az=((int16_t)buf[4]<<8)|buf[5];
97+
}
98+
99+
void MPU6886::getGyroAdc(int16_t* gx, int16_t* gy, int16_t* gz) {
100+
uint8_t buf[6];
101+
I2C_Read_NBytes(MPU6886_ADDRESS,MPU6886_GYRO_XOUT_H, 6, buf);
102+
103+
*gx=((uint16_t)buf[0]<<8)|buf[1];
104+
*gy=((uint16_t)buf[2]<<8)|buf[3];
105+
*gz=((uint16_t)buf[4]<<8)|buf[5];
106+
}
107+
108+
void MPU6886::getTempAdc(int16_t *t) {
109+
uint8_t buf[2];
110+
I2C_Read_NBytes(MPU6886_ADDRESS,MPU6886_TEMP_OUT_H,2,buf);
111+
112+
*t=((uint16_t)buf[0]<<8)|buf[1];
113+
}
114+
115+
//!俯仰,航向,横滚:pitch,yaw,roll,指三维空间中飞行器的旋转状态。
116+
void MPU6886::getAhrsData(float *pitch, float *roll, float *yaw) {
117+
118+
float accX = 0;
119+
float accY = 0;
120+
float accZ = 0;
121+
122+
float gyroX = 0;
123+
float gyroY = 0;
124+
float gyroZ = 0;
125+
126+
127+
getGyroData(&gyroX, &gyroY, &gyroZ);
128+
getAccelData(&accX, &accY, &accZ);
129+
130+
MahonyAHRSupdateIMU(gyroX * DEG_TO_RAD, gyroY * DEG_TO_RAD, gyroZ * DEG_TO_RAD, accX, accY, accZ, pitch, roll, yaw);
131+
}
132+
133+
// Possible gyro scales (and their register bit settings)
134+
void MPU6886::updateGres() {
135+
switch (Gyscale) {
136+
case GFS_250DPS:
137+
gRes = 250.0/32768.0;
138+
break;
139+
case GFS_500DPS:
140+
gRes = 500.0/32768.0;
141+
break;
142+
case GFS_1000DPS:
143+
gRes = 1000.0/32768.0;
144+
break;
145+
case GFS_2000DPS:
146+
gRes = 2000.0/32768.0;
147+
break;
148+
}
149+
150+
}
151+
152+
// Possible accelerometer scales (and their register bit settings) are:
153+
// 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs (11).
154+
// Here's a bit of an algorith to calculate DPS/(ADC tick) based on that 2-bit value:
155+
void MPU6886::updateAres() {
156+
switch (Acscale) {
157+
case AFS_2G:
158+
aRes = 2.0/32768.0;
159+
break;
160+
case AFS_4G:
161+
aRes = 4.0/32768.0;
162+
break;
163+
case AFS_8G:
164+
aRes = 8.0/32768.0;
165+
break;
166+
case AFS_16G:
167+
aRes = 16.0/32768.0;
168+
break;
169+
}
170+
}
171+
172+
void MPU6886::setGyroFsr(Gscale scale) {
173+
unsigned char regdata;
174+
regdata = (scale<<3);
175+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, &regdata);
176+
delay(10);
177+
Gyscale = scale;
178+
updateGres();
179+
}
180+
181+
void MPU6886::setAccelFsr(Ascale scale) {
182+
unsigned char regdata;
183+
regdata = (scale<<3);
184+
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, &regdata);
185+
delay(10);
186+
Acscale = scale;
187+
updateAres();
188+
}
189+
190+
void MPU6886::getAccelData(float* ax, float* ay, float* az) {
191+
int16_t accX = 0;
192+
int16_t accY = 0;
193+
int16_t accZ = 0;
194+
getAccelAdc(&accX,&accY,&accZ);
195+
196+
*ax = (float)accX * aRes;
197+
*ay = (float)accY * aRes;
198+
*az = (float)accZ * aRes;
199+
}
200+
201+
void MPU6886::getGyroData(float* gx, float* gy, float* gz) {
202+
int16_t gyroX = 0;
203+
int16_t gyroY = 0;
204+
int16_t gyroZ = 0;
205+
getGyroAdc(&gyroX,&gyroY,&gyroZ);
206+
207+
*gx = (float)gyroX * gRes;
208+
*gy = (float)gyroY * gRes;
209+
*gz = (float)gyroZ * gRes;
210+
}
211+
212+
void MPU6886::getTempData(float *t) {
213+
int16_t temp = 0;
214+
getTempAdc(&temp);
215+
216+
*t = (float)temp / 326.8 + 25.0;
217+
}

0 commit comments

Comments
 (0)