初始提交卡包 USB 工程
纳入固件源码、屏幕组件、nand_xfer 工具和文档。忽略本机构建产物、sdkconfig,以及含本机路径的依赖锁。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,989 @@
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "../config.h"
|
||||
|
||||
#if !EXAMPLE_USE_TOUCH
|
||||
#error "SC7U22 requires EXAMPLE_USE_TOUCH (IMU shares the touch I2C bus)."
|
||||
#endif
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include <math.h>
|
||||
#include "esp_timer.h"
|
||||
#include "../ui/generated/gui_guider.h" // 包含GUI引导器头文件
|
||||
#include "lvgl.h" // 包含LVGL头文件
|
||||
#include "LVGL/lvgl_init.h"
|
||||
#include "ui_cmd.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
static bool event_cooldown_active = false; // 是否处于冷却屏蔽中
|
||||
static int64_t cooldown_end_time = 0; // 冷却结束时间戳
|
||||
static const char *TAG_IMU = "SCU722";
|
||||
i2c_master_dev_handle_t SC7U22_handle;
|
||||
/** 与触摸共用的 I2C 总线句柄(SC7U22_init 写入,供扫描/查询) */
|
||||
i2c_master_bus_handle_t s_i2c_bus;
|
||||
sensor_data_t data_buffer[DATA_BUFFER_SIZE];
|
||||
SC7U22_DataType sensor_data = {0};
|
||||
static int buffer_index = 0;
|
||||
static int buffer_count = 0;
|
||||
|
||||
struct acc_offset offset_data = {0};
|
||||
noise_datatype noise_data = {0};
|
||||
|
||||
float ax=0,ay=0,az=0,gx=0,gy=0,gz=0;
|
||||
//float acc_pre_x=0,acc_pre_y=0,acc_pre_z=0;
|
||||
|
||||
float acc_sum = 0;
|
||||
float acc_sign_sum = 0;
|
||||
|
||||
float acc_hp = 0;
|
||||
uint32_t bum_energy = 0;
|
||||
float iir_state = 0;
|
||||
|
||||
uint16_t start_stop_cnt = 0;
|
||||
uint16_t stop_cnt = 0;
|
||||
|
||||
|
||||
uint8_t sharp_turn_flag = 0,pre_st_flag = 0;
|
||||
bool sharpturn_ret_L = false,sharpturn_ret_R = false;
|
||||
|
||||
|
||||
uint8_t rapid_acc_flag = 0,pre_ra_flag = 0,rapid_acc_ret = 0;
|
||||
uint8_t rapid_dec_flag = 0,pre_rd_flag = 0,rapid_dec_ret = 0;
|
||||
bool brake_fir_flag = false, rapid_fir_flag = false;
|
||||
|
||||
const char* MYTAG = "SC7U22";
|
||||
|
||||
extern int lottie_id;
|
||||
extern int current_page_idx;
|
||||
extern lv_ui guider_ui; // 外部声明GUI引导器
|
||||
|
||||
/*
|
||||
* @brief This function converts lsb to meter per second squared for 16 bit accelerometer at
|
||||
* range 2G, 4G, 8G or 16G.
|
||||
*/
|
||||
float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width)
|
||||
{
|
||||
double power = 2;
|
||||
|
||||
float half_scale = (float)((pow((double)power, (double)bit_width) / 2.0f));
|
||||
|
||||
return (GRAVITY_EARTH * val * g_range) / half_scale;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* @brief This function converts lsb to degree per second for 16 bit gyro at
|
||||
* range 125, 250, 500, 1000 or 2000dps.
|
||||
*/
|
||||
float lsb_to_dps(int16_t val, float dps, uint8_t bit_width)
|
||||
{
|
||||
double power = 2;
|
||||
|
||||
float half_scale = (float)((pow((double)power, (double)bit_width) / 2.0f));
|
||||
|
||||
return (dps / (half_scale)) * (val);
|
||||
}
|
||||
|
||||
void i2c_scan_devices(void)
|
||||
{
|
||||
if (s_i2c_bus == NULL) {
|
||||
ESP_LOGW(MYTAG, "i2c_scan: bus not ready (call SC7U22_init first)");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t address;
|
||||
esp_err_t ret;
|
||||
bool found = false;
|
||||
|
||||
ESP_LOGI(MYTAG, "Scanning I2C devices on shared bus...");
|
||||
|
||||
for (address = 1; address < 127; address++) {
|
||||
ret = i2c_master_probe(s_i2c_bus, (uint16_t)address, 100);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(MYTAG, "Device found at address: 0x%02X", address);
|
||||
found = true;
|
||||
}
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
ESP_LOGI(MYTAG, "No I2C devices found");
|
||||
}
|
||||
}
|
||||
|
||||
void SC7U22_init(i2c_master_bus_handle_t i2c_bus)
|
||||
{
|
||||
|
||||
if (i2c_bus == NULL) {
|
||||
ESP_LOGE(MYTAG, "SC7U22_init: I2C bus handle is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
s_i2c_bus = i2c_bus;
|
||||
ESP_LOGI(MYTAG, "SC7U22 on shared I2C bus: %p", (void *)s_i2c_bus);
|
||||
|
||||
i2c_device_config_t dev_cfg = {
|
||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||
.device_address = SC7U22_I2C_ADDR,
|
||||
.scl_speed_hz = I2C_MASTER_FREQ_HZ,
|
||||
};
|
||||
|
||||
esp_err_t ret = i2c_master_bus_add_device(s_i2c_bus, &dev_cfg, &SC7U22_handle);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(MYTAG, "添加设备失败,错误码: %s", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
SC7U22_Sensor_enable();
|
||||
|
||||
ESP_LOGI(MYTAG, "SC7U22 初始化完成(硬件就绪,校准将在后台进行)");
|
||||
}
|
||||
esp_err_t SC7U22_Reg_W(uint8_t reg_addr, uint8_t data)
|
||||
{
|
||||
uint8_t write_buf[2] = {reg_addr, data};
|
||||
return i2c_master_transmit(SC7U22_handle, write_buf, sizeof(write_buf), 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
esp_err_t SC7U22_Reg_R(uint8_t reg_addr, uint8_t *data)
|
||||
{
|
||||
return i2c_master_transmit_receive(SC7U22_handle, ®_addr, 1, data, 1, 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
void SC7U22_Sensor_enable(void)
|
||||
{
|
||||
SC7U22_Reg_W(0x7F, 0x00); // Bank / page(如需要)
|
||||
vTaskDelay(pdMS_TO_TICKS(2));
|
||||
SC7U22_Reg_W(0x7D, 0x0E); // PWR_CTRL enable acc + gyro
|
||||
vTaskDelay(pdMS_TO_TICKS(5));
|
||||
|
||||
// 加速度
|
||||
SC7U22_Reg_W(0x40, 0xA8); // ACC_CONF(用缺省)
|
||||
SC7U22_Reg_W(0x41, 0x02); // ±4g
|
||||
|
||||
// 陀螺仪(关键)
|
||||
SC7U22_Reg_W(0x42, 0xA9); // GYR_CONF(缺省、安全)
|
||||
SC7U22_Reg_W(0x43, 0x00); // ±2000 dps
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SC7U22_DaMYTAGet(SC7U22_DataType* SC7U22_DataStucture)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint8_t raw_acc[6]; // 用于存放 AX_L, AX_H, AY_L, AY_H, AZ_L, AZ_H
|
||||
uint8_t raw_gyr[6]; // 用于存放 GX_L, GX_H, GY_L, GY_H, GZ_L, GZ_H
|
||||
|
||||
// ================= 加速度计读取 (一次读6字节) =================
|
||||
// 假设 XOUT_L 是起始地址。如果你的宏定义 XOUT_H 比 XOUT_L 小,请改用 XOUT_H
|
||||
uint8_t acc_reg_addr = SC7U22_ACCEL_XOUT_H;
|
||||
|
||||
ret = i2c_master_transmit_receive(SC7U22_handle, &acc_reg_addr, 1, raw_acc, 6, 1000 / portTICK_PERIOD_MS);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
// 拼接数据。注意:通常 I2C 传感器先发低位(L),后发高位(H)。
|
||||
// 具体的 buffer 顺序取决于寄存器地址顺序。
|
||||
// 假设地址顺序是: X_L(0), X_H(1), Y_L(2), Y_H(3), Z_L(4), Z_H(5)
|
||||
SC7U22_DataStucture->Ax = (int16_t)((raw_acc[0] << 8) | raw_acc[1]);
|
||||
SC7U22_DataStucture->Ay = (int16_t)((raw_acc[2] << 8) | raw_acc[3]);
|
||||
SC7U22_DataStucture->Az = (int16_t)((raw_acc[4] << 8) | raw_acc[5]);
|
||||
|
||||
} else {
|
||||
ESP_LOGE(MYTAG, "Accel read failed: %s", esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
// ================= 陀螺仪读取 (一次读6字节) =================
|
||||
// 假设 XOUT_L 是起始地址
|
||||
uint8_t gyr_reg_addr = SC7U22_GYRO_XOUT_H;
|
||||
//暂时注释掉
|
||||
ret = i2c_master_transmit_receive(SC7U22_handle, &gyr_reg_addr, 1, raw_gyr, 6, 1000 / portTICK_PERIOD_MS);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
SC7U22_DataStucture->Gx = (int16_t)((raw_gyr[0] << 8) | raw_gyr[1]);
|
||||
SC7U22_DataStucture->Gy = (int16_t)((raw_gyr[2] << 8) | raw_gyr[3]);
|
||||
SC7U22_DataStucture->Gz = (int16_t)((raw_gyr[4] << 8) | raw_gyr[5]);
|
||||
} else {
|
||||
ESP_LOGE(MYTAG, "Gyro read failed");
|
||||
}
|
||||
}
|
||||
|
||||
void baseline_remove(void)
|
||||
{
|
||||
// 加速度计去偏
|
||||
ax = lsb_to_mps2(sensor_data.Ax, (float)4, 16) - offset_data.acc_x_offset;
|
||||
ay = lsb_to_mps2(sensor_data.Ay, (float)4, 16) - offset_data.acc_y_offset;
|
||||
az = lsb_to_mps2(sensor_data.Az, (float)4, 16) - offset_data.acc_z_offset;
|
||||
|
||||
// 陀螺仪去偏 (新增)
|
||||
gx = lsb_to_dps(sensor_data.Gx, (float)2000, 16) - offset_data.gyr_x_offset;
|
||||
gy = lsb_to_dps(sensor_data.Gy, (float)2000, 16) - offset_data.gyr_y_offset;
|
||||
gz = lsb_to_dps(sensor_data.Gz, (float)2000, 16) - offset_data.gyr_z_offset;
|
||||
}
|
||||
|
||||
void noise_threshold_get(void)
|
||||
{
|
||||
uint8_t ax_cnt = 0,ay_cnt = 0,az_cnt = 0,gx_cnt = 0,gy_cnt = 0,gz_cnt = 0;
|
||||
SC7U22_DaMYTAGet(&sensor_data);
|
||||
baseline_remove();
|
||||
for(int i = 0;i<50;i++)
|
||||
{
|
||||
if(ax!=0) {noise_data.accx_noise+=fabs(ax); ax_cnt++;}
|
||||
if(ay!=0) {noise_data.accy_noise+=fabs(ay); ay_cnt++;}
|
||||
if(az!=0) {noise_data.accz_noise+=fabs(az); az_cnt++;}
|
||||
if(gx!=0) {noise_data.gyrx_noise+=fabs(gx); gx_cnt++;}
|
||||
if(gy!=0) {noise_data.gyry_noise+=fabs(gy); gy_cnt++;}
|
||||
if(gz!=0) {noise_data.gyrz_noise+=fabs(gz); gz_cnt++;}
|
||||
vTaskDelay(pdMS_TO_TICKS(5));
|
||||
}
|
||||
noise_data.accx_noise/=(float)ax_cnt;
|
||||
noise_data.accy_noise/=(float)ay_cnt;
|
||||
noise_data.accz_noise/=(float)az_cnt;
|
||||
noise_data.gyrx_noise/=(float)gx_cnt;
|
||||
noise_data.gyry_noise/=(float)gy_cnt;
|
||||
noise_data.gyrz_noise/=(float)gz_cnt;
|
||||
}
|
||||
|
||||
void data_deal_with_noise(void)
|
||||
{
|
||||
if(fabs(ax)<fabs(noise_data.accx_noise)*1.5f+0.05) ax = 0;
|
||||
if(fabs(ay)<fabs(noise_data.accy_noise)*1.5f+0.05) ay = 0;
|
||||
if(fabs(az)<fabs(noise_data.accz_noise)*1.5f+0.05) az = 0;
|
||||
if(fabs(gx)<fabs(noise_data.gyrx_noise)*1.5f+1) gx = 0;
|
||||
if(fabs(gy)<fabs(noise_data.gyry_noise)*1.5f+1) gy = 0;
|
||||
if(fabs(gz)<fabs(noise_data.gyrz_noise)*1.5f+1) gz = 0;
|
||||
}
|
||||
|
||||
void mySC7_getdata(void)
|
||||
{
|
||||
|
||||
SC7U22_DaMYTAGet(&sensor_data);
|
||||
baseline_remove(); //去零偏处理
|
||||
data_deal_with_noise();//去噪声处理
|
||||
|
||||
|
||||
data_buffer[buffer_index].accel_x = ax;
|
||||
data_buffer[buffer_index].accel_y = ay;
|
||||
data_buffer[buffer_index].accel_z = az;
|
||||
data_buffer[buffer_index].timestamp = esp_timer_get_time();
|
||||
|
||||
buffer_index = (buffer_index + 1) % DATA_BUFFER_SIZE;
|
||||
if (buffer_count < DATA_BUFFER_SIZE) {
|
||||
buffer_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void accel_Getoffset(void)
|
||||
{
|
||||
float ax_sum=0, ay_sum=0, az_sum=0;
|
||||
float gx_sum=0, gy_sum=0, gz_sum=0; // 新增
|
||||
|
||||
ESP_LOGI(MYTAG, "正在校准传感器,请保持静止...");
|
||||
|
||||
for(int i = 0; i < 100; i++) // 采样100次
|
||||
{
|
||||
SC7U22_DaMYTAGet(&sensor_data);
|
||||
|
||||
// 累加加速度
|
||||
ax_sum += lsb_to_mps2(sensor_data.Ax, (float)4, 16);
|
||||
ay_sum += lsb_to_mps2(sensor_data.Ay, (float)4, 16);
|
||||
az_sum += lsb_to_mps2(sensor_data.Az, (float)4, 16);
|
||||
|
||||
// 累加陀螺仪 (注意:这里使用 2000dps 量程)
|
||||
gx_sum += lsb_to_dps(sensor_data.Gx, (float)2000, 16);
|
||||
gy_sum += lsb_to_dps(sensor_data.Gy, (float)2000, 16);
|
||||
gz_sum += lsb_to_dps(sensor_data.Gz, (float)2000, 16);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
// 计算平均值
|
||||
offset_data.acc_x_offset = ax_sum / 100.0f;
|
||||
offset_data.acc_y_offset = ay_sum / 100.0f;
|
||||
offset_data.acc_z_offset = (az_sum / 100.0f) - GRAVITY_EARTH; // Z轴要扣除重力
|
||||
|
||||
// 计算陀螺仪偏移 (理论上静止时全是0,所以读数即为偏移)
|
||||
offset_data.gyr_x_offset = gx_sum / 100.0f;
|
||||
offset_data.gyr_y_offset = gy_sum / 100.0f;
|
||||
offset_data.gyr_z_offset = gz_sum / 100.0f;
|
||||
|
||||
int gz_milli = (int)(offset_data.gyr_z_offset * 1000.0f);
|
||||
ESP_LOGI(MYTAG, "校准完成! Gz Offset: %d.%03d", gz_milli / 1000, abs(gz_milli % 1000));
|
||||
}
|
||||
void bum_energy_get(void)
|
||||
{
|
||||
acc_sum += fabs(az);
|
||||
acc_sign_sum += az;
|
||||
iir_state = ALPHA * iir_state + (1 - ALPHA) * acc_sum;
|
||||
acc_hp = acc_sum -iir_state; //高通滤波
|
||||
bum_energy += (uint32_t)(acc_hp*acc_hp*1000); //处理颠簸能量
|
||||
}
|
||||
|
||||
bool is_bump(void)
|
||||
{
|
||||
uint32_t temp = bum_energy;
|
||||
static bool wasbump = false;
|
||||
float variance = 0;
|
||||
bum_energy = 0;
|
||||
acc_sum = 0;
|
||||
acc_sign_sum /= DATA_BUFFER_SIZE;
|
||||
for(int i = 0;i<DATA_BUFFER_SIZE;i++)
|
||||
{
|
||||
variance += fabs(data_buffer[i].accel_z - acc_sign_sum); //平均绝对值误差
|
||||
}
|
||||
acc_sign_sum = 0;
|
||||
bool isbump = (temp>=BUM_THRESHOLD&&variance>=400);
|
||||
if(isbump&&!wasbump)
|
||||
{
|
||||
wasbump = isbump;
|
||||
return true;
|
||||
}
|
||||
wasbump = isbump;
|
||||
return false;
|
||||
}
|
||||
|
||||
void sharp_turn_detect(void)
|
||||
{
|
||||
if(fabs(gz) > turn_gyro_threshold && fabs(ay) > turn_accel_threshold)
|
||||
{
|
||||
sharp_turn_flag++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sharp_turn_flag = 0;
|
||||
}
|
||||
|
||||
if(sharp_turn_flag == 0 && pre_st_flag >= 5) // 连续触发次数稍微减少一点,灵敏些
|
||||
{
|
||||
pre_st_flag = 0;
|
||||
// 左转通常 gyrz > 0 (逆时针),右转 gyrz < 0 (顺时针)
|
||||
// 具体正负取决于芯片安装面,你测试时如果不准,互换一下即可
|
||||
if(gz > 0) sharpturn_ret_L = true;
|
||||
else if(gz < 0) sharpturn_ret_R = true;
|
||||
}
|
||||
pre_st_flag = sharp_turn_flag;
|
||||
}
|
||||
|
||||
driving_event_t is_sharp_turn(void)
|
||||
{
|
||||
if(sharpturn_ret_L)
|
||||
{
|
||||
sharpturn_ret_L = 0;
|
||||
return EVENT_SHARP_LTURN;
|
||||
}
|
||||
else if(sharpturn_ret_R)
|
||||
{
|
||||
sharpturn_ret_R = 0;
|
||||
return EVENT_SHARP_RTURN;
|
||||
}
|
||||
return EVENT_NONE;
|
||||
}
|
||||
|
||||
static float calculate_acceleration_magnitude(void)
|
||||
{
|
||||
return sqrtf(ax * ax + ay * ay + az * az);
|
||||
}
|
||||
|
||||
void start_stop_state(void)
|
||||
{
|
||||
static uint8_t st_cnt = 0;
|
||||
static uint8_t sp_cnt = 0;
|
||||
static bool stop_flag = false;
|
||||
bool is_stop = calculate_acceleration_magnitude()<= is_stop_magnitude;
|
||||
if(is_stop&&!stop_flag) sp_cnt++;
|
||||
if(sp_cnt>=3)
|
||||
{
|
||||
stop_flag = true;
|
||||
sp_cnt = 0;
|
||||
}
|
||||
if(is_stop&&stop_flag)
|
||||
{
|
||||
stop_cnt++;
|
||||
}
|
||||
|
||||
if(stop_flag&&!is_stop)
|
||||
{
|
||||
st_cnt++;
|
||||
}
|
||||
else{
|
||||
st_cnt = 0;
|
||||
}
|
||||
if(st_cnt>=3)
|
||||
{
|
||||
start_stop_cnt++;
|
||||
st_cnt = 0;
|
||||
stop_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 判断急停急加速
|
||||
void detect_driving_events(void)
|
||||
{
|
||||
//获取数据
|
||||
mySC7_getdata();
|
||||
//颠簸能量累加
|
||||
bum_energy_get();
|
||||
//急转弯检测
|
||||
sharp_turn_detect();
|
||||
//急加速检测 急刹车检测
|
||||
|
||||
if (buffer_count < 2) return ;
|
||||
|
||||
int current_idx = (buffer_index - 1 + DATA_BUFFER_SIZE) % DATA_BUFFER_SIZE;
|
||||
int prev_idx = (buffer_index - 2 + DATA_BUFFER_SIZE) % DATA_BUFFER_SIZE;
|
||||
|
||||
// 计算时间差(秒)
|
||||
float time_diff = (data_buffer[current_idx].timestamp -
|
||||
data_buffer[prev_idx].timestamp) / 1000000.0f;
|
||||
|
||||
if (time_diff <= 0) return ;
|
||||
|
||||
|
||||
float accel_diff_x = data_buffer[current_idx].accel_x - data_buffer[prev_idx].accel_x;
|
||||
float jerk_x = accel_diff_x / time_diff; // 急动度
|
||||
|
||||
// 急刹车/减速检测
|
||||
// 逻辑:当前有一个很大的负向加速度(刹车),且变化率很大
|
||||
// 注意:如果是“前倾 accx 变大”,说明 +X 是车头向下或向前。
|
||||
// 假设 +X 是向前加速,那么 -X 就是刹车。
|
||||
if ((jerk_x < -rapid_accel_threshold/0.02) && (data_buffer[current_idx].accel_x < -rapid_accel_threshold))
|
||||
rapid_dec_flag = 1;
|
||||
|
||||
if ((data_buffer[current_idx].accel_x < -rapid_accel_threshold) && rapid_dec_flag)
|
||||
rapid_dec_flag++;
|
||||
else
|
||||
rapid_dec_flag = 0;
|
||||
|
||||
if (rapid_dec_flag == 0 && pre_rd_flag >= 4) rapid_dec_ret = 1; // 阈值改小一点容易触发
|
||||
pre_rd_flag = rapid_dec_flag;
|
||||
|
||||
// 急加速检测
|
||||
// 逻辑:当前有一个很大的正向加速度
|
||||
if ((jerk_x > rapid_accel_threshold/0.02) && (data_buffer[current_idx].accel_x > rapid_accel_threshold))
|
||||
rapid_acc_flag = 1;
|
||||
|
||||
if ((data_buffer[current_idx].accel_x > rapid_accel_threshold) && rapid_acc_flag)
|
||||
rapid_acc_flag++;
|
||||
else
|
||||
rapid_acc_flag = 0;
|
||||
|
||||
if (rapid_acc_flag == 0 && pre_ra_flag >= 4) rapid_acc_ret = 1;
|
||||
pre_ra_flag = rapid_acc_flag;
|
||||
|
||||
}
|
||||
driving_event_t is_rapid_acc_or_dec(void)
|
||||
{
|
||||
if(rapid_acc_ret)
|
||||
{
|
||||
rapid_acc_ret = 0;
|
||||
return EVENT_SUDDEN_ACCEL;
|
||||
}
|
||||
if(rapid_dec_ret)
|
||||
{
|
||||
rapid_dec_ret = 0;
|
||||
return EVENT_SUDDEN_BRAKE;
|
||||
}
|
||||
return EVENT_NONE;
|
||||
}
|
||||
|
||||
bool is_jam(void)
|
||||
{
|
||||
|
||||
float stop_proportion = (float)stop_cnt/600.0;
|
||||
uint16_t temp_cnt = start_stop_cnt;
|
||||
stop_cnt = 0;
|
||||
start_stop_cnt = 0;
|
||||
if((stop_proportion>=stop_proportion_threshold&&temp_cnt>=start_stop_threshold)||stop_proportion>=0.8f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// 在IMU任务函数外定义(全局区),避免栈溢出,同时供回调函数访问
|
||||
// 驾驶事件冷却检查:冷却中返回true,允许触发返回false
|
||||
bool is_event_in_cooldown(void)
|
||||
{
|
||||
if (!event_cooldown_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 当前时间 < 结束时间 = 还在冷却
|
||||
if (esp_timer_get_time() < cooldown_end_time) {
|
||||
return true;
|
||||
} else {
|
||||
// 冷却结束,复位
|
||||
event_cooldown_active = false;
|
||||
ESP_LOGI(MYTAG, "冷却时间已结束,可以再次触发驾驶事件");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 触发一次事件后,启动50秒冷却
|
||||
void start_event_cooldown(void)
|
||||
{
|
||||
event_cooldown_active = true;
|
||||
cooldown_end_time = esp_timer_get_time() + (EVENT_COOLDOWN_MS * 1000); // 转微秒
|
||||
ESP_LOGI(MYTAG, "已启动冷却,%d 毫秒内不再触发", EVENT_COOLDOWN_MS);
|
||||
}
|
||||
|
||||
/** 诊断:因 g_ble_play_sticker_active 抑制幸运表情时打印(节流,避免刷屏) */
|
||||
#define BLE_GUARD_LOG_THROTTLE_MS 3000
|
||||
static uint32_t s_ble_guard_last_log_tick;
|
||||
static void ble_guard_log_lucky_suppressed(const char *reason)
|
||||
{
|
||||
uint32_t t = lv_tick_get();
|
||||
if (s_ble_guard_last_log_tick != 0 && (t - s_ble_guard_last_log_tick) < BLE_GUARD_LOG_THROTTLE_MS)
|
||||
return;
|
||||
s_ble_guard_last_log_tick = t;
|
||||
ESP_LOGW("BLE_STICKER_GUARD",
|
||||
"Lucky suppressed: %s (g_ble_play_sticker_active still true)",
|
||||
reason);
|
||||
}
|
||||
|
||||
void imu_task(void *param)
|
||||
{
|
||||
ESP_LOGI(MYTAG, "Starting IMU task");
|
||||
driving_event_t drive_even = EVENT_NONE;
|
||||
uint16_t i = 0;
|
||||
|
||||
/* 保持原校准逻辑不变,只调整执行时机:由主初始化路径改为后台任务执行。 */
|
||||
uint32_t calib_start_ms = (uint32_t)(esp_timer_get_time() / 1000ULL);
|
||||
ESP_LOGI(MYTAG, "IMU 后台校准开始");
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
accel_Getoffset();
|
||||
noise_threshold_get();
|
||||
uint32_t calib_elapsed_ms = (uint32_t)(esp_timer_get_time() / 1000ULL) - calib_start_ms;
|
||||
ESP_LOGI(MYTAG, "IMU 后台校准完成,耗时: %" PRIu32 " ms", calib_elapsed_ms);
|
||||
|
||||
while(1)
|
||||
{
|
||||
// ========== 原有逻辑保持不变 ==========
|
||||
mySC7_getdata(); // 永远读取传感器数据
|
||||
ESP_LOGW(MYTAG,"正在读取IMU数据...");
|
||||
if (current_page_idx == 0)
|
||||
{
|
||||
detect_driving_events();
|
||||
drive_even = is_sharp_turn();
|
||||
if(drive_even == EVENT_SHARP_LTURN) //急转弯判断 结束一个急转弯后判定
|
||||
{
|
||||
if (is_event_in_cooldown()) continue; // 冷却中直接跳过
|
||||
if (g_ble_play_sticker_active)
|
||||
{
|
||||
ble_guard_log_lucky_suppressed("left sharp turn");
|
||||
continue; /* BLE 正在播表情时不插播 IMU 幸运 */
|
||||
}
|
||||
start_event_cooldown(); // 启动50秒冷却
|
||||
|
||||
|
||||
/*左急转弯反馈入口*/
|
||||
lottie_id = 29;
|
||||
ESP_LOGE(MYTAG,"左急转!");
|
||||
/*左急转弯反馈结束*/
|
||||
}else if(drive_even == EVENT_SHARP_RTURN)
|
||||
{
|
||||
|
||||
if (is_event_in_cooldown()) continue; // 冷却中直接跳过
|
||||
if (g_ble_play_sticker_active)
|
||||
{
|
||||
ble_guard_log_lucky_suppressed("right sharp turn");
|
||||
continue;
|
||||
}
|
||||
start_event_cooldown(); // 启动50秒冷却
|
||||
|
||||
|
||||
/*右急转弯反馈入口*/
|
||||
lottie_id = 29;
|
||||
ESP_LOGE(MYTAG,"右急转!");
|
||||
/*右急转弯反馈入口*/
|
||||
}
|
||||
|
||||
drive_even = is_rapid_acc_or_dec();
|
||||
if(drive_even==EVENT_SUDDEN_ACCEL)
|
||||
{
|
||||
if (is_event_in_cooldown()) continue; // 冷却中直接跳过
|
||||
if (g_ble_play_sticker_active)
|
||||
{
|
||||
ble_guard_log_lucky_suppressed("sudden accel");
|
||||
continue;
|
||||
}
|
||||
start_event_cooldown(); // 启动50秒冷却
|
||||
|
||||
|
||||
/*急加速反馈入口*/
|
||||
lottie_id = 29;
|
||||
ESP_LOGE(MYTAG,"急加速!");
|
||||
/*急加速反馈结束*/
|
||||
}
|
||||
else if(drive_even==EVENT_SUDDEN_BRAKE)
|
||||
{
|
||||
if (is_event_in_cooldown()) continue; // 冷却中直接跳过
|
||||
if (g_ble_play_sticker_active)
|
||||
{
|
||||
ble_guard_log_lucky_suppressed("sudden brake");
|
||||
continue;
|
||||
}
|
||||
start_event_cooldown(); // 启动50秒冷却
|
||||
|
||||
|
||||
/*急刹车反馈入口*/
|
||||
lottie_id = 29;
|
||||
ESP_LOGE(MYTAG,"急刹车!");
|
||||
/*急刹车反馈结束*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ========== 4. 通用逻辑(堵车/颠簸检测) ==========
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
i++;
|
||||
|
||||
if(i%25==0 && current_page_idx == 0)
|
||||
{
|
||||
//堵车数据检测
|
||||
start_stop_state();
|
||||
// printf("accx:%4.2f, accy:%4.2f, accz:%4.2f, gyrx:%4.2f, gyry:%4.2f, gyrz:%4.2f\n",
|
||||
// ax,ay,az,gx,gy,gz);
|
||||
}
|
||||
|
||||
if(i%200==0 && current_page_idx == 0) //2秒累加检测 反馈程序入口
|
||||
{
|
||||
if(is_bump()) //判断路面颠簸
|
||||
{
|
||||
ESP_LOGE(MYTAG,"路面颠簸!");
|
||||
}
|
||||
}
|
||||
|
||||
if(i>=15000 && current_page_idx == 0) //5分钟判定一次堵车
|
||||
{
|
||||
if(is_jam())
|
||||
{
|
||||
ESP_LOGE(MYTAG,"堵车!");
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(30));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
i2c_master_bus_handle_t get_i2c_master_bus_handle(void)
|
||||
{
|
||||
return s_i2c_bus;
|
||||
}
|
||||
i2c_master_bus_handle_t touch_bus_handle_BMI;
|
||||
i2c_master_bus_handle_t touch_bus_handle_NST112;
|
||||
i2c_master_bus_handle_t touch_bus_handle_MS523;
|
||||
i2c_master_bus_handle_t n_i2c_bus;
|
||||
//i2c_master_bus_config_t i2c_bus_config = {0};
|
||||
esp_err_t BMI_init(void)
|
||||
{
|
||||
ESP_LOGI(TAG_IMU, "开始初始化 SC7U22...");
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
#if !EXAMPLE_USE_TOUCH
|
||||
#error "BMI_init requires EXAMPLE_USE_TOUCH (SC7U22 shares touch I2C bus)."
|
||||
#endif
|
||||
|
||||
//extern i2c_master_bus_handle_t touch_bus_handle; I2C主总线
|
||||
i2c_master_bus_config_t i2c_bus_config = {0};
|
||||
i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
|
||||
i2c_bus_config.i2c_port = 0;
|
||||
i2c_bus_config.scl_io_num = TEST_BOARD_I2C_SCL_PIN;
|
||||
i2c_bus_config.sda_io_num = TEST_BOARD_I2C_SDA_PIN;
|
||||
i2c_bus_config.glitch_ignore_cnt = 7;
|
||||
i2c_bus_config.flags.enable_internal_pullup = true;
|
||||
//i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
|
||||
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &touch_bus_handle_BMI));
|
||||
s_i2c_bus = touch_bus_handle_BMI;
|
||||
i2c_scan_devices();
|
||||
SC7U22_init(touch_bus_handle_BMI);
|
||||
bmi_task_stack = heap_caps_malloc(BMI_TASK_STACK_SIZE, MALLOC_CAP_SPIRAM);
|
||||
if (bmi_task_stack == NULL)
|
||||
{
|
||||
ESP_LOGE("LVGL", "Failed to allocate BMI task stack");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
TaskHandle_t task_handle = xTaskCreateStaticPinnedToCore(imu_task, "BMI", BMI_TASK_STACK_SIZE, NULL, BMI_TASK_PRIORITY, bmi_task_stack, &bmi_task_tcb, 0);
|
||||
if (task_handle == NULL)
|
||||
{
|
||||
ESP_LOGE("LVGL", "Failed to create BMI task");
|
||||
heap_caps_free(bmi_task_stack);
|
||||
bmi_task_stack = NULL;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_LOGI("LVGL", "BMI task created successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
i2c_master_dev_handle_t NST112_handle;
|
||||
uint8_t temp_data[2] ={0};
|
||||
uint8_t config_data[2] = {0};
|
||||
uint8_t H_tmp_data[2] = {0};
|
||||
uint8_t L_tmp_data[2] = {0};
|
||||
esp_err_t NST112_Reg_W(uint8_t reg_addr, uint8_t data)
|
||||
{
|
||||
uint8_t write_buf[] = {reg_addr, data};
|
||||
return i2c_master_transmit(NST112_handle, write_buf, sizeof(write_buf), 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
esp_err_t NST112_Reg_R(uint8_t reg_addr)
|
||||
{
|
||||
esp_err_t ret = i2c_master_transmit_receive(NST112_handle,®_addr,1,temp_data,2,1000 / portTICK_PERIOD_MS);
|
||||
if(ret != ESP_OK){
|
||||
ESP_LOGE("NST112", "读取 NST112 寄存器失败,错误码: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
else{
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
extern StaticTask_t nst112_task_tcb;
|
||||
extern StackType_t *nst112_task_stack;
|
||||
void nst112_task(void *param)
|
||||
{
|
||||
ESP_LOGI("NST112", "Starting NST112 task");
|
||||
uint8_t read_addr = 0x00;
|
||||
float temp_c = 0;
|
||||
while(1)
|
||||
{
|
||||
i2c_master_transmit_receive(NST112_handle, &read_addr, 1, temp_data, 2, 1000 / portTICK_PERIOD_MS);
|
||||
int16_t raw = (int16_t)((temp_data[0] << 8) | temp_data[1]);
|
||||
temp_c = raw / 256.0f;
|
||||
ESP_LOGI("NST112", "TEMP: %02X %02X", temp_data[0], temp_data[1]);
|
||||
ESP_LOGI("NST112", "TEMP (C): %f", temp_c);
|
||||
if(temp_c > 70){
|
||||
ESP_LOGI("NST112", "TEMP: WARNING");
|
||||
}
|
||||
if(temp_c < (-20)){
|
||||
ESP_LOGI("NST112", "TEMP: WARNING");
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t NST112_init(void)
|
||||
{
|
||||
|
||||
//extern i2c_master_bus_handle_t touch_bus_handle_touch;
|
||||
|
||||
i2c_master_bus_config_t i2c_bus_config = {0};
|
||||
i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
|
||||
i2c_bus_config.i2c_port = 1;
|
||||
i2c_bus_config.scl_io_num = NST112_I2C_SCL_PIN;
|
||||
i2c_bus_config.sda_io_num = NST112_I2C_SDA_PIN;
|
||||
i2c_bus_config.glitch_ignore_cnt = 7;
|
||||
i2c_bus_config.flags.enable_internal_pullup = true;
|
||||
//i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
|
||||
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &touch_bus_handle_NST112)); //此处单传感器调试用,正式使用时改为传入共享总线句柄
|
||||
|
||||
n_i2c_bus = touch_bus_handle_NST112;//touch_bus_handle_touch
|
||||
s_i2c_bus = touch_bus_handle_NST112;
|
||||
i2c_scan_devices();
|
||||
ESP_LOGI("NST112", "NST112 on shared I2C bus: %p", (void *)n_i2c_bus);
|
||||
|
||||
i2c_device_config_t dev_cfg = {
|
||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||
.device_address = NST112_I2C_ADDR,
|
||||
.scl_speed_hz = I2C_MASTER_FREQ_HZ,
|
||||
};
|
||||
esp_err_t ret = i2c_master_bus_add_device(n_i2c_bus, &dev_cfg, &NST112_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE("NST112", "添加 NST112 设备失败");
|
||||
return ret;
|
||||
}
|
||||
uint8_t write_buf[] = {0x01,0x60,0xA0}; // 0x01 寄存器地址,0x60 和 0xA0 是要写入的数据
|
||||
uint8_t high_temp_config_reg[] = {0x03,0x05,0x50};
|
||||
uint8_t low_temp_config_reg[] = {0x02,0x00,0xA0};
|
||||
uint8_t read_config_addr = 0x01;
|
||||
uint8_t read_H_TMP_addr = 0x02;
|
||||
uint8_t read_L_TMP_addr = 0x03;
|
||||
i2c_master_transmit(NST112_handle, write_buf, sizeof(write_buf), 1000 / portTICK_PERIOD_MS);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
ret = i2c_master_transmit_receive(NST112_handle,&read_config_addr,1 ,config_data,2,pdMS_TO_TICKS(100));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
ret = i2c_master_transmit_receive(NST112_handle,&read_L_TMP_addr,1 ,H_tmp_data,2,pdMS_TO_TICKS(100));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
ret = i2c_master_transmit_receive(NST112_handle,&read_H_TMP_addr,1 ,L_tmp_data,2,pdMS_TO_TICKS(100));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
ESP_LOGI("NST112", "TEMP: %02X %02X L:%02X %02X H:%02X %02X ", config_data[0], config_data[1],L_tmp_data[0],L_tmp_data[1],H_tmp_data[0],L_tmp_data[1]);
|
||||
|
||||
//i2c_master_transmit(NST112_handle, high_temp_config_reg, sizeof(high_temp_config_reg), 1000 / portTICK_PERIOD_MS);
|
||||
//i2c_master_transmit(NST112_handle, low_temp_config_reg, sizeof(low_temp_config_reg), 1000 / portTICK_PERIOD_MS);
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
uint8_t read_addr = 0x00;
|
||||
//i2c_master_transmit_receive(NST112_handle, &read_addr, 1, temp_data, 2, 1000 / portTICK_PERIOD_MS);
|
||||
nst112_task_stack = heap_caps_malloc(NST112_TASK_STACK_SIZE, MALLOC_CAP_SPIRAM);
|
||||
if (nst112_task_stack == NULL)
|
||||
{
|
||||
ESP_LOGE("LVGL", "Failed to allocate NST112 task stack");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
xTaskCreateStaticPinnedToCore(nst112_task, "NST112", NST112_TASK_STACK_SIZE, NULL, NST112_TASK_PRIORITY, nst112_task_stack, &nst112_task_tcb,0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#define MS523_CTRL_GPIO GPIO_NUM_48
|
||||
i2c_master_dev_handle_t MS523_handle;
|
||||
extern StaticTask_t MS523_task_tcb;
|
||||
extern StackType_t *MS523_task_stack;
|
||||
esp_err_t ms523_write_byte(uint8_t reg_addr, uint8_t data) {
|
||||
uint8_t write_buf[2] = {reg_addr, data};
|
||||
esp_err_t ret = i2c_master_transmit(MS523_handle, write_buf, sizeof(write_buf), pdMS_TO_TICKS(100));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE("MS523", "Write reg 0x%02X failed: %s", reg_addr, esp_err_to_name(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t ms523_read_byte(uint8_t reg_addr, uint8_t *data) {
|
||||
esp_err_t ret = i2c_master_transmit_receive(MS523_handle, ®_addr, 1, data, 1, pdMS_TO_TICKS(100));
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI("MS523", "Read reg 0x%02X = 0x%02X", reg_addr, *data);
|
||||
} else {
|
||||
ESP_LOGE("MS523", "Read reg 0x%02X failed: %s", reg_addr, esp_err_to_name(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define GPIO_OUTPUT_PIN GPIO_NUM_48 // 以GPIO2为例
|
||||
void MS523_ctrl_init(void){
|
||||
|
||||
gpio_config_t io_conf = {
|
||||
.pin_bit_mask = (1ULL << GPIO_OUTPUT_PIN), // 选择要配置的引脚[reference:5]
|
||||
.mode = GPIO_MODE_OUTPUT, // 设置为输出模式[reference:6]
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE, // 禁用内部上拉电阻[reference:7]
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE, // 禁用内部下拉电阻[reference:8]
|
||||
.intr_type = GPIO_INTR_DISABLE // 禁用中断[reference:9]
|
||||
};
|
||||
|
||||
gpio_config(&io_conf); // 应用配置[reference:10]
|
||||
|
||||
|
||||
// 2. 设置GPIO输出高电平
|
||||
gpio_set_level(GPIO_OUTPUT_PIN, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
ESP_LOGI("MS523", "当前输出高电平");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ms523_detect_card(void) {
|
||||
// 1-4:发送寻卡指令
|
||||
ms523_write_byte(0x0A, 0x80);
|
||||
ms523_write_byte(0x09, 0x52);
|
||||
ms523_write_byte(0x0D, 0x87);
|
||||
ms523_write_byte(0x01, 0x0C);
|
||||
|
||||
// 5:轮询等待 RxIRq(超时 50ms)
|
||||
uint8_t irq = 0;
|
||||
int timeout_ms = 50;
|
||||
TickType_t start = xTaskGetTickCount();
|
||||
while ((xTaskGetTickCount() - start) < pdMS_TO_TICKS(timeout_ms)) {
|
||||
ms523_read_byte(0x04, &irq);
|
||||
if (irq & 0x20) {
|
||||
ESP_LOGI("MS523", "✅ Card detected!");
|
||||
return; // 检测到卡,退出函数
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
}
|
||||
|
||||
// 检查碰撞
|
||||
uint8_t err;
|
||||
ms523_read_byte(0x06, &err);
|
||||
if (err & 0x08) {
|
||||
ESP_LOGI("MS523", "✅ Card detected (Collision)!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 无卡
|
||||
ESP_LOGW("MS523", "No card detected.");
|
||||
}
|
||||
|
||||
void MS523_task(void *param){
|
||||
while (1)
|
||||
{
|
||||
ms523_detect_card();
|
||||
ESP_LOGW("MS523", "运行中");
|
||||
vTaskDelay(500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
esp_err_t MS523_init(void)
|
||||
{
|
||||
MS523_ctrl_init();
|
||||
ESP_LOGI(TAG_IMU, "开始初始化 MS523");
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
#if !EXAMPLE_USE_TOUCH
|
||||
#error "BMI_init requires EXAMPLE_USE_TOUCH (SC7U22 shares touch I2C bus)."
|
||||
#endif
|
||||
|
||||
//extern i2c_master_bus_handle_t touch_bus_handle; I2C主总线
|
||||
i2c_master_bus_config_t i2c_bus_config = {0};
|
||||
i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
|
||||
i2c_bus_config.i2c_port = 0;
|
||||
i2c_bus_config.scl_io_num = TEST_BOARD_I2C_SCL_PIN;
|
||||
i2c_bus_config.sda_io_num = TEST_BOARD_I2C_SDA_PIN;
|
||||
i2c_bus_config.glitch_ignore_cnt = 7;
|
||||
i2c_bus_config.flags.enable_internal_pullup = true;
|
||||
//i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
|
||||
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &touch_bus_handle_MS523));
|
||||
s_i2c_bus = touch_bus_handle_MS523;
|
||||
//i2c_scan_devices();
|
||||
|
||||
i2c_device_config_t dev_cfg = {
|
||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||
.device_address = MS523_I2C_ADDR,
|
||||
.scl_speed_hz = I2C_MASTER_FREQ_HZ,
|
||||
};
|
||||
esp_err_t ret = i2c_master_bus_add_device(s_i2c_bus, &dev_cfg, &MS523_handle);
|
||||
uint8_t reg_addr = 0x37;
|
||||
uint8_t version = 0;
|
||||
uint8_t data = 0;
|
||||
ms523_read_byte(reg_addr,&version);
|
||||
ms523_write_byte(0x14, 0x83); // 开启 TX1/TX2 天线驱动
|
||||
|
||||
ms523_write_byte(0x12, 0x00); // 发送速率 106k
|
||||
ms523_write_byte(0x13, 0x08); // 接收速率 106k
|
||||
ms523_write_byte(0x26, 0x48); // 接收增益 48dB
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI("MS523", "NFC version:0x%02X", version);
|
||||
} else {
|
||||
ESP_LOGE("MS523", "Read version failed: %s", esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
|
||||
MS523_task_stack = heap_caps_malloc(MS523_TASK_STACK_SIZE, MALLOC_CAP_SPIRAM);
|
||||
if (MS523_task_stack == NULL)
|
||||
{
|
||||
ESP_LOGE("LVGL", "Failed to allocate NST112 task stack");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
//ms523_write_byte(0x0A, 0x80);
|
||||
//ms523_read_byte(0x0A,&data);
|
||||
//ms523_write_byte(0x09, 0x52);
|
||||
//ms523_read_byte(0x09,&data);
|
||||
//ms523_write_byte(0x0D, 0x87);
|
||||
//ms523_read_byte(0x0D,&data);
|
||||
//ms523_write_byte(0x01, 0x0C);
|
||||
//ms523_read_byte(0x01,&data);
|
||||
xTaskCreateStaticPinnedToCore(MS523_task, "MS523", MS523_TASK_STACK_SIZE, NULL, MS523_TASK_PRIORITY, MS523_task_stack, &MS523_task_tcb,1);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
#include "driver/i2c_master.h"
|
||||
|
||||
#ifndef __SC7U22_H_
|
||||
#define __SC7U22_H_
|
||||
|
||||
|
||||
#define SC7U22_CONFIG 0x1A
|
||||
#define SC7U22_GYRO_CONFIG 0x42
|
||||
#define SC7U22_ACCEL_CONFIG 0x40
|
||||
|
||||
#define SC7U22_ACCEL_XOUT_H 0x0C
|
||||
#define SC7U22_ACCEL_XOUT_L 0x0D
|
||||
#define SC7U22_ACCEL_YOUT_H 0x0E
|
||||
#define SC7U22_ACCEL_YOUT_L 0x0F
|
||||
#define SC7U22_ACCEL_ZOUT_H 0x10
|
||||
#define SC7U22_ACCEL_ZOUT_L 0x11
|
||||
#define SC7U22_GYRO_XOUT_H 0x12
|
||||
#define SC7U22_GYRO_XOUT_L 0x13
|
||||
#define SC7U22_GYRO_YOUT_H 0x14
|
||||
#define SC7U22_GYRO_YOUT_L 0x15
|
||||
#define SC7U22_GYRO_ZOUT_H 0x16
|
||||
#define SC7U22_GYRO_ZOUT_L 0x17
|
||||
|
||||
#define SC7U22_WHO_AM_I 0x01
|
||||
|
||||
#define SC7U22_I2C_ADDR 0x18
|
||||
#define NST112_I2C_ADDR 0x48
|
||||
#define MS523_I2C_ADDR 0x28
|
||||
#define I2C_MASTER_FREQ_HZ 800000 // kHz 800000
|
||||
#define I2C_MASTER_FREQ_TEMP_HZ 100000 // kHz 800000
|
||||
#define GRAVITY_EARTH (9.80665f)
|
||||
#define ALPHA 0.90f // 高通系数
|
||||
#define BUM_THRESHOLD 4.0e8f // 颠簸能量阈值(暂定)
|
||||
#define turn_gyro_threshold 30.0f //急转弯角速度阈值
|
||||
#define turn_accel_threshold 2.0f //急转弯向心加速度阈值
|
||||
#define rapid_accel_threshold 3.0f //急加速阈值
|
||||
#define rapid_decel_threshold -3.0f //急刹车阈值
|
||||
#define DATA_BUFFER_SIZE 200
|
||||
#define is_stop_magnitude 0.35f //启动
|
||||
#define stop_proportion_threshold 0.5f //停止时间比例阈值
|
||||
#define start_stop_threshold 15 //启停次数阈值
|
||||
|
||||
// 驾驶事件冷却屏蔽(10秒内不再触发表情)
|
||||
#define EVENT_COOLDOWN_MS 10000 // 冷却时间 10 秒
|
||||
|
||||
|
||||
|
||||
|
||||
extern float ax,ay,az,gx,gy,gz;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16_t Ax;
|
||||
int16_t Ay;
|
||||
int16_t Az;
|
||||
int16_t Gx;
|
||||
int16_t Gy;
|
||||
int16_t Gz;
|
||||
}SC7U22_DataType;
|
||||
|
||||
struct acc_offset
|
||||
{
|
||||
float acc_x_offset;
|
||||
float acc_y_offset;
|
||||
float acc_z_offset;
|
||||
|
||||
float gyr_x_offset;
|
||||
float gyr_y_offset;
|
||||
float gyr_z_offset;
|
||||
};
|
||||
|
||||
typedef struct{
|
||||
float accx_noise;
|
||||
float accy_noise;
|
||||
float accz_noise;
|
||||
float gyrx_noise;
|
||||
float gyry_noise;
|
||||
float gyrz_noise;
|
||||
}noise_datatype;
|
||||
|
||||
typedef struct {
|
||||
float accel_x;
|
||||
float accel_y;
|
||||
float accel_z;
|
||||
float gyro_x;
|
||||
float gyro_y;
|
||||
float gyro_z;
|
||||
int64_t timestamp;
|
||||
} sensor_data_t;
|
||||
|
||||
typedef enum {
|
||||
EVENT_NONE = 0,
|
||||
EVENT_SUDDEN_ACCEL, // 急加速
|
||||
EVENT_SUDDEN_BRAKE, // 急刹车
|
||||
EVENT_SHARP_LTURN, //急左转弯
|
||||
EVENT_SHARP_RTURN, //急右转弯
|
||||
} driving_event_t;
|
||||
|
||||
void SC7U22_init(i2c_master_bus_handle_t i2c_bus);
|
||||
esp_err_t SC7U22_Reg_W(uint8_t reg_addr, uint8_t data);
|
||||
esp_err_t SC7U22_Reg_R(uint8_t reg_addr, uint8_t *data);
|
||||
// void SC7U22_DataGet(SC7U22_DataType* SC7U22_DataStucture);
|
||||
|
||||
void mySC7_getdata(void); //获得处理后的数据
|
||||
void SC7U22_Sensor_enable(void);
|
||||
void noise_threshold_get(void);
|
||||
void accel_Getoffset(void);
|
||||
float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width);
|
||||
float lsb_to_dps(int16_t val, float dps, uint8_t bit_width);
|
||||
|
||||
void bum_energy_get(void);
|
||||
bool is_bump(void);
|
||||
void sharp_turn_detect(void);
|
||||
driving_event_t is_sharp_turn(void);
|
||||
void start_stop_state(void);
|
||||
void detect_driving_events(void);
|
||||
driving_event_t is_rapid_acc_or_dec(void);
|
||||
bool is_jam(void);
|
||||
void imu_task(void *param);
|
||||
i2c_master_bus_handle_t get_i2c_master_bus_handle(void);
|
||||
|
||||
esp_err_t BMI_init(void);
|
||||
esp_err_t NST112_init(void);
|
||||
esp_err_t MS523_init(void);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user