【2024 DigiKey创意大赛】+ 控制模块的使用
本帖最后由 zsy-s 于 2024-10-29 22:29 编辑# 前言
此节实现对 模块 icm20948 9轴传感器的数据读写
# 模块介绍
ICM-20948集成了三轴陀螺仪、三轴加速度计、三轴磁力计以及数字运动处理器(DMP)。这种高度集成的设计简化了系统设计,降低了成本,并提高了系统的可靠性。三轴陀螺仪的可编程满量程范围(FSR)为±250dps、±500dps、±1000dps和±2000dps;三轴加速度计的可编程FSR为±2g、±4g、±8g和±16g;三轴磁力计的量程可达±4900µT。这些高精度的测量参数使得ICM-20948能够准确地进行姿态测量和运动追踪。ICM-20948提供了I2C和7MHz的高速SPI通信接口,方便与主控器进行数据传输。
#硬件支持
开发板提供了1.8v的输出,可惜实际测量有2.1v
通过拍照查看丝印为S5XE,不是1.8v的丝印,可能焊接错误了。
~~输出的电压用于给电压转换器芯片提供电压转换的基准,所以我需要买一个1.8v芯片给这个换下来。~~
开发板的引脚使用, io48(scl),io47(sda)。
iic的地址,通过文档可知默认为:0x69
# 控制模块
通过iic接口与此控制模块通信。
上面的1.8v引脚是输出引脚,可以对外提供1.8v电压。模块内部有电压芯片,用于转换vdd到1.8v。
vdd的电压提供3.3v或者5v都是可以的。
对于9轴数据,位于band0的寄存器区,如下:
3轴惯导(GYRO),3轴加速度(ACCLE),3轴磁罗盘(COMPASS),为 此小应用工具需要的数据。
# 程序讲解
```c
//初始化iic的句柄
static esp_err_t
i2c_bus_init(void)
{
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = 47;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = 48;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
conf.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL;
esp_err_t ret = i2c_param_config(I2C_MASTER_NUM, &conf);
if (ret != ESP_OK)
return ret;
return i2c_driver_install(I2C_MASTER_NUM, conf.mode, 0, 0, 0);
}
保存iic的配置信息
```c
icm20948_handle_t
icm20948_create(i2c_port_t port, const uint16_t dev_addr)
{
icm20948_dev_t *sensor = (icm20948_dev_t *)calloc(1, sizeof(icm20948_dev_t));
sensor->bus = port;
sensor->dev_addr = dev_addr << 1;
sensor->counter = 0;
sensor->dt = 0;
sensor->timer = (struct timeval *)calloc(1, sizeof(struct timeval));
return (icm20948_handle_t)sensor;
}
```
```
创建写寄存器的接口
```c
static esp_err_t
icm20948_write(icm20948_handle_t sensor,
const uint8_t reg_start_addr,
const uint8_t *const data_buf,
const uint8_t data_len)
{
icm20948_dev_t *sens = (icm20948_dev_t *)sensor;
esp_err_t ret;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
ret = i2c_master_start(cmd);
assert(ESP_OK == ret);
ret = i2c_master_write_byte(cmd, sens->dev_addr | I2C_MASTER_WRITE, true);
assert(ESP_OK == ret);
ret = i2c_master_write_byte(cmd, reg_start_addr, true);
assert(ESP_OK == ret);
ret = i2c_master_write(cmd, data_buf, data_len, true);
assert(ESP_OK == ret);
ret = i2c_master_stop(cmd);
assert(ESP_OK == ret);
ret = i2c_master_cmd_begin(sens->bus, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
```
创建读的接口
```c
static esp_err_t
icm20948_read(icm20948_handle_t sensor, const uint8_t reg_start_addr, uint8_t *const data_buf, const uint8_t data_len)
{
icm20948_dev_t *sens = (icm20948_dev_t *)sensor;
esp_err_t ret;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
ret = i2c_master_start(cmd);
assert(ESP_OK == ret);
ret = i2c_master_write_byte(cmd, sens->dev_addr | I2C_MASTER_WRITE, true);
assert(ESP_OK == ret);
ret = i2c_master_write_byte(cmd, reg_start_addr, true);
assert(ESP_OK == ret);
ret = i2c_master_start(cmd);
assert(ESP_OK == ret);
ret = i2c_master_write_byte(cmd, sens->dev_addr | I2C_MASTER_READ, true);
assert(ESP_OK == ret);
ret = i2c_master_read(cmd, data_buf, data_len, I2C_MASTER_LAST_NACK);
assert(ESP_OK == ret);
ret = i2c_master_stop(cmd);
assert(ESP_OK == ret);
ret = i2c_master_cmd_begin(sens->bus, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
```
设置活跃的bank寄存器区
```c
esp_err_t
icm20948_set_bank(icm20948_handle_t sensor, uint8_t bank)
{
esp_err_t ret;
if (bank > 3)
return ESP_FAIL;
bank = (bank << 4) & 0x30;
ret = icm20948_write(sensor, ICM20948_REG_BANK_SEL, &bank, 1);
return ret;
}
```
重启芯片
```c
esp_err_t
icm20948_reset(icm20948_handle_t sensor)
{
esp_err_t ret;
uint8_t tmp;
ret = icm20948_read(sensor, ICM20948_PWR_MGMT_1, &tmp, 1);
if (ret != ESP_OK)
return ret;
tmp |= 0x80;
ret = icm20948_write(sensor, ICM20948_PWR_MGMT_1, &tmp, 1);
if (ret != ESP_OK)
return ret;
return ret;
}
```
唤醒芯片,开始工作
```c
esp_err_t
icm20948_wake_up(icm20948_handle_t sensor)
{
esp_err_t ret;
uint8_t tmp;
ret = icm20948_read(sensor, ICM20948_PWR_MGMT_1, &tmp, 1);
if (ESP_OK != ret) {
return ret;
}
tmp &= (~BIT6);
ret = icm20948_write(sensor, ICM20948_PWR_MGMT_1, &tmp, 1);
return ret;
}
```
获取加速度三轴
```c
esp_err_t
icm20948_get_acce_fs(icm20948_handle_t sensor, icm20948_acce_fs_t *acce_fs)
{
esp_err_t ret;
uint8_t tmp;
ret = icm20948_set_bank(sensor, 2);
if (ret != ESP_OK)
return ret;
ret = icm20948_read(sensor, ICM20948_ACCEL_CONFIG, &tmp, 1);
#if CONFIG_LOG_DEFAULT_LEVEL == 4
printf(BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(tmp));
#endif
tmp &= 0x06;
tmp >>= 1;
*acce_fs = tmp;
return ret;
}
```
获取惯导三轴
```c
esp_err_t
icm20948_get_acce_fs(icm20948_handle_t sensor, icm20948_acce_fs_t *acce_fs)
{
esp_err_t ret;
uint8_t tmp;
ret = icm20948_set_bank(sensor, 2);
if (ret != ESP_OK)
return ret;
ret = icm20948_read(sensor, ICM20948_ACCEL_CONFIG, &tmp, 1);
#if CONFIG_LOG_DEFAULT_LEVEL == 4
printf(BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(tmp));
#endif
tmp &= 0x06;
tmp >>= 1;
*acce_fs = tmp;
return ret;
}
```
<p>1.8v电压供电也够低了</p>
<p>为什么实际测量有2.1v呢</p>
Jacktang 发表于 2024-10-30 07:46
1.8v电压供电也够低了
为什么实际测量有2.1v呢
<p>降压芯片错了吧</p>
<p>不过这不是个问题,模块上有降压芯片,我学习不到位</p>
页:
[1]