我知道,这是一个很长的问题,但你真的会帮我解决这个问题。经过3天的反复试验和研究,我没有主意了。也许你会发现我错过的一些明显的东西,或者你比我更清楚。
该项目
我目前正在建造一辆使用以下材料的小型汽车:
- DShot600 ESC(通过RMT外围设备进行传输)
- DShot Telemetry(Serial2 上的基本 UART),最重要的是:我需要轮子 RPM
- 通过应用程序进行控制的WebSockets
- 定时器中断触发每1ms发送一次数据的功能
- 每 1ms 记录一次采集的数据
- MPU6050用于加速度测量(每 1ms)。
是的,没有转向,它只需要直行 - 但它必须快速完成。“汽车”有点夸大其词
什么有效
除了 MPU 部分,我已经让所有这些都可靠地工作。我使用 Jeff Rowberg 的I2CDevLib进行获取(我只需要 x 轴加速度和原始值,没有花哨的 DMP 东西,也没有陀螺仪功能)。
什么不
问题是,每当我尝试从 MPU 获取任何数据时,都会出现[...]esp-idf/components/freertos/queue.c:1446 (xQueueGenericReceive)- assert failed!
错误。我不知道这是什么以及如何解决它。
CPU 核心分配
我在核心 1 循环上有所有对时间敏感的东西(遥测处理、MPU 处理和油门计算),而对时间不太敏感的东西(WebSockets、与 PC 的串行通信)在核心 0 上完成。
- 核心 0
- 环形
- 网络套接字
- 与 PC 的串行通信
- 中断
- 每 1ms:通过 RMT 发送 ESC 值
- 环形
- 核心 1
- 环形
- MPU数据获取(根据
millis()
功能每1ms) - 获取遥测数据
- 油门计算
- MPU数据获取(根据
- 环形
澄清一下:定时器中断和节流发送是在核心 0 上完成的。我这样做是为了让定时器中断不会干扰 MPU 数据获取(大约需要 300µs)。
我试过的
在核心 1 上处理它并不能解决它。
我读过有一个portENTER_CRITICAL
和portEXIT_CRITICAL
函数对可以暂时禁用中断。用这个包装 MPU 数据获取解决了这个问题,但在退出函数中引入了 50 毫秒的延迟。这 50ms 使 ESC 进入故障保护状态(即关闭)。
在中断函数中手动获取 MPU 数据没有帮助。这给了我Guru Meditation error
。在中断服务程序中设置一个标志并在主循环中获取它也会产生错误。
当我禁用 ESC 中断时,不会发生此错误,即使此中断是在另一个内核上处理的。
其他信息
对于 ESC 传输功能,我需要使用计时器,因为 ESC 油门值必须每 1ms 精确传输一次,最多相差 50µs。问题是遥测(ESC在我发送完整的油门数据包后立即发回)需要> 800μs(由UART外围设备异步接收)。然后另一个函数必须处理遥测轮速并将新的油门值调整为发送该值之前的值。这一切都有效。我只是想提一下,所以没有人建议我将该函数放在主循环中。
我很乐意提供更多调试信息,我只是不知道什么有用。我已经尝试了比我在这里解释的更多的东西(这会导致更长的问题)。通常,在单独的项目(仅 MPU)中获取数据可以完美地工作。所以没有损坏的电缆,没有死机或类似的东西。
提前致谢。
软件:带 Arduino 内核的 PlatformIO、Windows 10 和 Manjaro Linux(相同的错误)
硬件:Ryzen 1700、16GB RAM、Radeon Vega 56、ESP32 WROOM