【发布时间】:2021-01-09 17:30:00
【问题描述】:
我对 Arduino 很陌生,这是我在这里的第一个主题。我目前正在研究汽车的 CAN BUS (500,000bps) 通信,以便实时读取和翻译 CAN 消息。 UNO 与 MCP2515 一起连接到汽车 OBD2 端口,以便嗅探所有支持的 PID 数据,现在打印出可用的输出,看起来很有希望(附图)。然而,我经历了频繁的数据丢失,即使有 5 秒的延迟来读取下一个循环的数据。我确实尝试过搜索,但从未接近正确的解决方案。这种情况称为竞争条件还是数据溢出?或者我必须看看传输数据的缓冲区大小?
所有源文件和草图都参考https://github.com/sandeepmistry/arduino-OBD2。
这是我使用的草图(libraries\OBD2-0.0.1\examples\OBD2_01_SupportedPIDs); 打印结果见附件。
[#include <CAN.h> // the OBD2 library depends on the CAN library
#include <OBD2.h>
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println(F("OBD2 data printer"));
while (true) {
Serial.print(F("Attempting to connect to OBD2 CAN bus ... "));
if (!OBD2.begin()) {
Serial.println(F("failed!"));
delay(1000);
} else {
Serial.println(F("success"));
break;
}
}
Serial.println();
Serial.print("VIN = ");
Serial.println(OBD2.vinRead());
Serial.print("ECU Name = ");
Serial.println(OBD2.ecuNameRead());
Serial.println();
}
void loop() {
// loop through PIDs 0 to 95, reading and printing the values
for (int pid = 0; pid < 96; pid++) {
processPid(pid);
}
Serial.println();
// wait 5 seconds before next run
delay(5000);
}
void processPid(int pid) {
if (!OBD2.pidSupported(pid)) {
// PID not supported, continue to next one ...
return;
}
// print PID name
Serial.print(OBD2.pidName(pid));
Serial.print(F(" = "));
if (OBD2.pidValueRaw(pid)) {
// read the raw PID value
unsigned long pidRawValue = OBD2.pidReadRaw(pid);
Serial.print(F("0x"));
Serial.print(pidRawValue, HEX);
} else {
// read the PID value
float pidValue = OBD2.pidRead(pid);
if (isnan(pidValue)) {
Serial.print("error");
} else {
// print value with units
Serial.print(pidValue);
Serial.print(F(" "));
Serial.print(OBD2.pidUnits(pid));
}
}
Serial.println();
}][1]
【问题讨论】:
-
不知道这些 ODB 库做了什么,但它们是中断还是内部驱动的 DMA?如果它们基于轮询,那么您显然不能在读取之间有一堆 printf 和 icky 忙延迟,否则您将立即获得缓冲区溢出。一个 11 位标识符和 500kbps 的 CAN 包最多需要 222us 才能接收。
标签: arduino arduino-uno can-bus