Skip to content

Commit 404bbcf

Browse files
committed
Fixed current offset fault bug, added support for multiple IMUs and ICM-20948
1 parent 490d44d commit 404bbcf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+369
-66
lines changed

CHANGELOG

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
=== FW 3.56 ===
2+
* Fixed current offset fault bug in non-FOC mode.
3+
* Multiple IMU support.
4+
* Added support for the ICM-20948 IMU.
5+
* Decreased ERPM cut in open loop flux linkage measurement.
6+
17
=== FW 3.55 ===
28
* Initial sin/cos encoder support.
39
* New ADC control mode.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
Binary file not shown.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

build_all/46_o_47/VESC_0005ohm.bin

0 Bytes
Binary file not shown.

build_all/46_o_47/VESC_33k.bin

0 Bytes
Binary file not shown.

build_all/46_o_47/VESC_default.bin

0 Bytes
Binary file not shown.

build_all/46_o_47/VESC_servoout.bin

0 Bytes
Binary file not shown.

build_all/46_o_47/VESC_ws2811.bin

0 Bytes
Binary file not shown.

build_all/46_o_47/VESC_ws2811_33k.bin

0 Bytes
Binary file not shown.

build_all/48/VESC_0005ohm.bin

0 Bytes
Binary file not shown.

build_all/48/VESC_default.bin

0 Bytes
Binary file not shown.

build_all/48/VESC_servoout.bin

0 Bytes
Binary file not shown.

build_all/48/VESC_ws2811.bin

0 Bytes
Binary file not shown.

build_all/60/VESC_default.bin

0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

build_all/60/VESC_servoout.bin

0 Bytes
Binary file not shown.

build_all/60/VESC_ws2811.bin

0 Bytes
Binary file not shown.

build_all/75_300/VESC_default.bin

0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

build_all/75_300/VESC_servoout.bin

0 Bytes
Binary file not shown.

build_all/75_300/VESC_ws2811.bin

0 Bytes
Binary file not shown.

build_all/75_300_R2/VESC_default.bin

0 Bytes
Binary file not shown.
Binary file not shown.

build_all/75_300_R2/VESC_servoout.bin

0 Bytes
Binary file not shown.

build_all/75_300_R2/VESC_ws2811.bin

0 Bytes
Binary file not shown.

build_all/DAS_RS/VESC_default.bin

0 Bytes
Binary file not shown.

build_all/PALTA/VESC_default.bin

0 Bytes
Binary file not shown.

conf_general.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ bool conf_general_measure_flux_linkage_openloop(float current, float duty,
829829
break;
830830
}
831831

832-
if (rpm_now >= 20000) {
832+
if (rpm_now >= 12000) {
833833
break;
834834
}
835835
}

conf_general.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
// Firmware version
2424
#define FW_VERSION_MAJOR 3
25-
#define FW_VERSION_MINOR 55
25+
#define FW_VERSION_MINOR 56
2626

2727
#include "datatypes.h"
2828

hwconf/hw_60.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@
221221
#define MPU9X50_SDA_PIN 2
222222
#define MPU9X50_SCL_GPIO GPIOA
223223
#define MPU9X50_SCL_PIN 15
224-
#define MPU9x50_FLIP
224+
#define IMU_FLIP
225225

226226
// Measurement macros
227227
#define ADC_V_L1 ADC_Value[ADC_IND_SENS1]

hwconf/hw_binar_v1.c

+6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ void hw_init_gpio(void) {
5353
PAL_MODE_OUTPUT_PUSHPULL |
5454
PAL_STM32_OSPEED_HIGHEST);
5555

56+
// Switch on second 3.3v net (TODO: Expose this functionality?)
57+
palSetPadMode(GPIOB, 2,
58+
PAL_MODE_OUTPUT_PUSHPULL |
59+
PAL_STM32_OSPEED_HIGHEST);
60+
palSetPad(GPIOB, 2);
61+
5662
ENABLE_GATE();
5763

5864
// GPIOA Configuration: Channel 1 to 3 as alternate function push-pull

hwconf/hw_binar_v1.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,12 @@
188188
#define DRV8301_CS_GPIO GPIOC
189189
#define DRV8301_CS_PIN 9
190190

191-
// MPU9250
192-
#define MPU9X50_SDA_GPIO GPIOB
193-
#define MPU9X50_SDA_PIN 7
194-
#define MPU9X50_SCL_GPIO GPIOB
195-
#define MPU9X50_SCL_PIN 6
196-
#define MPU9x50_FLIP
191+
// ICM20948
192+
#define ICM20948_SDA_GPIO GPIOB
193+
#define ICM20948_SDA_PIN 7
194+
#define ICM20948_SCL_GPIO GPIOB
195+
#define ICM20948_SCL_PIN 6
196+
#define ICM20948_AD0_VAL 0
197197

198198
// Measurement macros
199199
#define ADC_V_L1 ADC_Value[ADC_IND_SENS1]

i2c_bb.c

+9
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,16 @@ static bool clock_stretch_timeout(i2c_bb_state *s);
4141
static void i2c_delay(void);
4242

4343
void i2c_bb_init(i2c_bb_state *s) {
44+
chMtxObjectInit(&s->mutex);
4445
palSetPadMode(s->sda_gpio, s->sda_pin, PAL_MODE_OUTPUT_OPENDRAIN);
4546
palSetPadMode(s->scl_gpio, s->scl_pin, PAL_MODE_OUTPUT_OPENDRAIN);
4647
s->has_started = false;
4748
s->has_error = false;
4849
}
4950

5051
void i2c_bb_restore_bus(i2c_bb_state *s) {
52+
chMtxLock(&s->mutex);
53+
5154
SCL_HIGH();
5255
SDA_HIGH();
5356

@@ -66,9 +69,13 @@ void i2c_bb_restore_bus(i2c_bb_state *s) {
6669
i2c_stop_cond(s);
6770

6871
s->has_error = false;
72+
73+
chMtxUnlock(&s->mutex);
6974
}
7075

7176
bool i2c_bb_tx_rx(i2c_bb_state *s, uint16_t addr, uint8_t *txbuf, size_t txbytes, uint8_t *rxbuf, size_t rxbytes) {
77+
chMtxLock(&s->mutex);
78+
7279
i2c_write_byte(s, true, false, addr << 1);
7380

7481
for (unsigned int i = 0;i < txbytes;i++) {
@@ -85,6 +92,8 @@ bool i2c_bb_tx_rx(i2c_bb_state *s, uint16_t addr, uint8_t *txbuf, size_t txbytes
8592

8693
i2c_stop_cond(s);
8794

95+
chMtxUnlock(&s->mutex);
96+
8897
return !s->has_error;
8998
}
9099

i2c_bb.h

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ typedef struct {
3232
int scl_pin;
3333
bool has_started;
3434
bool has_error;
35+
mutex_t mutex;
3536
} i2c_bb_state;
3637

3738
void i2c_bb_init(i2c_bb_state *s);

imu/icm20948.c

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
Copyright 2019 Benjamin Vedder [email protected]
3+
4+
This file is part of the VESC firmware.
5+
6+
The VESC firmware is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
The VESC firmware is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "icm20948.h"
21+
#include "terminal.h"
22+
#include "commands.h"
23+
#include "utils.h"
24+
25+
#include <stdio.h>
26+
#include <string.h>
27+
28+
// Threads
29+
static THD_FUNCTION(icm_thread, arg);
30+
31+
// Private functions
32+
static bool reset_init_icm(ICM20948_STATE *s);
33+
static void terminal_read_reg(int argc, const char **argv);
34+
static uint8_t read_single_reg(ICM20948_STATE *s, uint8_t reg);
35+
static bool write_single_reg(ICM20948_STATE *s, uint8_t reg, uint8_t value);
36+
37+
// Function pointers
38+
static void(*m_read_callback)(float *accel, float *gyro, float *mag) = 0;
39+
40+
// Private variables
41+
static ICM20948_STATE *m_terminal_state = 0;
42+
43+
void icm20948_init(ICM20948_STATE *s, i2c_bb_state *i2c_state, int ad0_val,
44+
stkalign_t *work_area, size_t work_area_size) {
45+
46+
s->i2cs = i2c_state;
47+
s->i2c_address = ad0_val ? 0x69 : 0x68;
48+
49+
if (reset_init_icm(s)) {
50+
chThdCreateStatic(work_area, work_area_size, NORMALPRIO, icm_thread, s);
51+
}
52+
53+
// Only register terminal command for the first instance of this driver.
54+
if (m_terminal_state == 0) {
55+
m_terminal_state = s;
56+
terminal_register_command_callback(
57+
"icm_read_reg",
58+
"Read register of the ICM-20948",
59+
"[bank] [reg]",
60+
terminal_read_reg);
61+
}
62+
}
63+
64+
void icm20948_set_read_callback(void(*func)(float *accel, float *gyro, float *mag)) {
65+
m_read_callback = func;
66+
}
67+
68+
static void terminal_read_reg(int argc, const char **argv) {
69+
if (argc == 3) {
70+
int bank = -1;
71+
int reg = -1;
72+
sscanf(argv[1], "%d", &bank);
73+
sscanf(argv[2], "%d", &reg);
74+
75+
if (reg >= 0 && (bank == 0 || bank == 1 || bank == 2)) {
76+
write_single_reg(m_terminal_state, ICM20948_BANK_SEL, bank << 4);
77+
unsigned int res = read_single_reg(m_terminal_state, reg);
78+
char bl[9];
79+
80+
write_single_reg(m_terminal_state, ICM20948_BANK_SEL, 0 << 4);
81+
82+
utils_byte_to_binary(res & 0xFF, bl);
83+
84+
commands_printf("Reg 0x%02x: %s (0x%02x)\n", reg, bl, res);
85+
} else {
86+
commands_printf("Invalid argument(s).\n");
87+
}
88+
} else {
89+
commands_printf("This command requires one argument.\n");
90+
}
91+
}
92+
93+
static bool write_single_reg(ICM20948_STATE *s, uint8_t reg, uint8_t value) {
94+
uint8_t txb[2];
95+
96+
txb[0] = reg;
97+
txb[1] = value;
98+
99+
bool res = i2c_bb_tx_rx(s->i2cs, s->i2c_address, txb, 2, 0, 0);
100+
return res;
101+
}
102+
103+
static uint8_t read_single_reg(ICM20948_STATE *s, uint8_t reg) {
104+
uint8_t rxb[1];
105+
uint8_t txb[1];
106+
107+
txb[0] = reg;
108+
bool res = i2c_bb_tx_rx(s->i2cs, s->i2c_address, txb, 1, rxb, 1);
109+
110+
if (res) {
111+
return rxb[0];
112+
} else {
113+
return 0;
114+
}
115+
}
116+
117+
static bool reset_init_icm(ICM20948_STATE *s) {
118+
i2c_bb_restore_bus(s->i2cs);
119+
120+
chThdSleep(1);
121+
122+
// TODO: Check for errors
123+
124+
// Set clock source to auto
125+
write_single_reg(s, ICM20948_BANK_SEL, 0 << 4);
126+
write_single_reg(s, ICM20948_PWR_MGMT_1, 1);
127+
128+
// Set accelerometer to +-16 G and disable lp filter
129+
write_single_reg(s, ICM20948_BANK_SEL, 2 << 4);
130+
write_single_reg(s, ICM20948_ACCEL_CONFIG, 0b00000110);
131+
132+
// Set gyro to +-2000 dps and disable lp filter
133+
write_single_reg(s, ICM20948_BANK_SEL, 2 << 4);
134+
write_single_reg(s, ICM20948_GYRO_CONFIG_1, 0b00000110);
135+
136+
// I2C bypass to access magnetometer directly
137+
// write_single_reg(s, ICM20948_BANK_SEL, 0);
138+
// write_single_reg(s, ICM20948_PIN_CFG, 2);
139+
140+
// Select bank0 so that data can be polled.
141+
write_single_reg(s, ICM20948_BANK_SEL, 0 << 4);
142+
143+
return true;
144+
}
145+
146+
static THD_FUNCTION(icm_thread, arg) {
147+
ICM20948_STATE *s = (ICM20948_STATE*)arg;
148+
149+
chRegSetThreadName("ICM Sampling");
150+
151+
for(;;) {
152+
uint8_t txb[1];
153+
uint8_t rxb[12];
154+
txb[0] = ICM20948_ACCEL_XOUT_H;
155+
156+
bool res = i2c_bb_tx_rx(s->i2cs, s->i2c_address, txb, 1, rxb, 12);
157+
158+
if (res) {
159+
float accel[3], gyro[3], mag[3];
160+
161+
accel[0] = (float)((int16_t)((int16_t)rxb[0] << 8 | (int16_t)rxb[1])) * 16.0 / 32768.0;
162+
accel[1] = (float)((int16_t)((int16_t)rxb[2] << 8 | (int16_t)rxb[3])) * 16.0 / 32768.0;
163+
accel[2] = (float)((int16_t)((int16_t)rxb[4] << 8 | (int16_t)rxb[5])) * 16.0 / 32768.0;
164+
165+
gyro[0] = (float)((int16_t)((int16_t)rxb[6] << 8 | (int16_t)rxb[7])) * 2000.0 / 32768.0 ;
166+
gyro[1] = (float)((int16_t)((int16_t)rxb[8] << 8 | (int16_t)rxb[9])) * 2000.0 / 32768.0;
167+
gyro[2] = (float)((int16_t)((int16_t)rxb[10] << 8 | (int16_t)rxb[11])) * 2000.0 / 32768.0;
168+
169+
// TODO: Read magnetometer as well
170+
memset(mag, 0, sizeof(mag));
171+
172+
if (m_read_callback) {
173+
m_read_callback(accel, gyro, mag);
174+
}
175+
} else {
176+
reset_init_icm(s);
177+
chThdSleepMilliseconds(10);
178+
}
179+
180+
chThdSleepMilliseconds(5);
181+
}
182+
}

imu/icm20948.h

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
Copyright 2019 Benjamin Vedder [email protected]
3+
4+
This file is part of the VESC firmware.
5+
6+
The VESC firmware is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
The VESC firmware is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#ifndef IMU_ICM20948_H_
21+
#define IMU_ICM20948_H_
22+
23+
#include "ch.h"
24+
#include "hal.h"
25+
26+
#include <stdint.h>
27+
#include <stdbool.h>
28+
29+
#include "i2c_bb.h"
30+
31+
typedef struct {
32+
i2c_bb_state *i2cs;
33+
uint8_t i2c_address;
34+
} ICM20948_STATE;
35+
36+
void icm20948_init(ICM20948_STATE *s, i2c_bb_state *i2c_state, int ad0_val,
37+
stkalign_t *work_area, size_t work_area_size);
38+
void icm20948_set_read_callback(void(*func)(float *accel, float *gyro, float *mag));
39+
40+
// All banks
41+
#define ICM20948_BANK_SEL 0x7F
42+
43+
// Bank 0 registers
44+
#define ICM20948_PWR_MGMT_1 0x06
45+
#define ICM20948_PIN_CFG 0x0F
46+
#define ICM20948_ACCEL_XOUT_H 0x2D
47+
48+
// Bank 2 registers
49+
#define ICM20948_ACCEL_CONFIG 0x14
50+
#define ICM20948_GYRO_CONFIG_1 0x01
51+
52+
#endif /* IMU_ICM20948_H_ */

0 commit comments

Comments
 (0)