资料介绍
描述
根据研究公司IHS Markit的数据,“今年美国轻型车辆的平均运行车龄 (VIO) 已上升至 12.1 年,比 2020 年增加了近 2 个月”。如果您关注我的项目,您就会知道我开的是一辆旧卡车(可能是弯道的那辆)。
你最近看到车价了吗?现在比以往任何时候都更需要让这辆卡车继续运转。我需要为我的检查引擎灯亮起做好准备。正如 Andreas Spiess 所说,“它也可能发生在你身上”。唯一的问题是OBD-II CAN-BUS 开发套件缺货。
经过进一步研究,我们发现了具有蓝牙连接功能的ELM 327 V1.5。这里的想法是将 Wio Terminal 无线连接到 ELM 327,这将允许我们连接到发动机控制单元 (ECU)。我们对五个参数感兴趣:
- 电池电压
- 发动机每分钟转数 (RPM)
- 车辆速度
- 进气温度
- 发动机冷却液温度
第一个可以通过仅连接到 ELM 327 来获得,但其余参数需要连接到 ECU,这只能在我的卡车上发生,当点火开关打开时。
这个项目将比其他类似项目更侧重于解释代码。开始前要注意两句话:
- 在您了解汽车的反应之前,请勿在驾驶时使用此项目。我的卡车不介意在 OBD2 端口插入一些东西,但其他汽车可能会。
- 我不得不通过替换 'm_semaphoreRegForNotifyEvt.wait("registerForNotify");' 来修改 BLERemoteCharacteristic.cpp 使用 'm_semaphoreRegForNotifyEvt.timedWait("registerForNotify", 1000);'。可能有更好的方法来避免卡在图书馆的这一行。
因此,请确保您首先访问该页面。
我们通过准备好按钮来开始设置。
pinMode(WIO_KEY_A, INPUT_PULLUP);
pinMode(WIO_KEY_B, INPUT_PULLUP);
pinMode(WIO_KEY_C, INPUT_PULLUP);
接下来,我们设置显示。
tft.init();
tft.setTextWrap(false);
tft.setTextSize(7);
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_BLUE);
tft.setCursor(40, 100);
tft.print("OBD2");
然后在开始时播放音调。
for (int i = 1000; i <= 3000; i += 500)
{
tone(WIO_BUZZER, i);
delay(50);
noTone(WIO_BUZZER);
delay(50);
}
在这里,我们开始扫描蓝牙设备。我们引用一个回调函数来接收来自所选设备的数据。所选设备必须具有此处定义的通用唯一标识符 (UUID) 的服务、读取特性和写入特性。
BLEDevice::init("");
BLEScan *ThisBLEScan = BLEDevice::getScan();
ThisBLEScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCB());
ThisBLEScan->setActiveScan(true);
ThisBLEScan->start(20);
BLEClient *ThisClient = BLEDevice::createClient();
ThisClient->connect(OBD2Device);
ThisService = ThisClient->getService((BLEUUID)0xfff0);
NotifyCharacteristic = ThisService->getCharacteristic((BLEUUID)0xfff1);
NotifyCharacteristic->registerForNotify(NotifyCB);
WriteCharacteristic = ThisService->getCharacteristic((BLEUUID)0xfff2);
现在我们连接到 ELM 327。我们使用AT 命令重置设备、关闭回声和自动选择协议。接下来,我们发送参数 ID (PID)以确保我们已连接到 ECU。
WriteCharacteristic->writeValue("AT Z\r");
WriteCharacteristic->writeValue("AT E0\r");
WriteCharacteristic->writeValue("AT SP 0\r");
WriteCharacteristic->writeValue("01 00\r");
while (NewString.substring(0, 12) != "SEARCHING...")
yield();
while (NewString.length() > 0)
{
if (NewString.substring(0, 17) == "UNABLE TO CONNECT")
{
ItemsInArray = 1;
NewString = "";
}
tft.fillScreen(TFT_BLACK);
tft.setCursor(40, 100);
tft.print("OBD2");
delay(10);
}
NewScreen = ItemsInArray;
WriteCharacteristic->writeValue("AT I\r");
while (NewString == "")
yield();
tft.fillScreen(TFT_BLACK);
在设置中我们需要做的最后一件事是将中断附加到按钮上。
attachInterrupt(digitalPinToInterrupt(WIO_KEY_A), ScreenUp, FALLING);
attachInterrupt(digitalPinToInterrupt(WIO_KEY_B), ScreenHome, FALLING);
attachInterrupt(digitalPinToInterrupt(WIO_KEY_C), ScreenDown, FALLING);
我们必须在循环中确定是显示所有参数还是仅显示一个。
tft.setCursor(10, -30);
for (I = 0; I < ItemsInArray; I++)
{
if (OldScreen != NewScreen)
{
tft.fillScreen(TFT_BLACK);
OldScreen = NewScreen;
break;
}
if (NewScreen != ItemsInArray && NewScreen != I)
continue;
NewString = "";
WriteCharacteristic->writeValue(CommandArray[I]);
while (NewString == "")
yield();
}
在每个屏幕的底部,我们将以秒为单位显示自开始以来的时间。
tft.setTextSize(3);
tft.fillRect(0, 280, 240, 40, TFT_BLACK);
tft.setCursor(10, 280);
tft.setTextColor(TFT_BLUE);
tft.printf("%d", int(millis() / 1000));
为了使这段代码正常工作,我们需要为每个按钮定义一个函数。
void ScreenUp(void)
{
NewScreen--;
NewScreen = constrain(NewScreen, 0, ItemsInArray);
tone(WIO_BUZZER, 2500, 100);
}
void ScreenHome(void)
{
NewScreen = ItemsInArray;
tone(WIO_BUZZER, 2500, 100);
}
void ScreenDown(void)
{
NewScreen++;
NewScreen = constrain(NewScreen, 0, ItemsInArray);
tone(WIO_BUZZER, 2500, 100);
}
之前我们扫描了蓝牙设备。类似的项目使用设备 MAC 地址来选择一个特定的 ELM 327,但我们希望我们的 Wio 终端无需硬编码任何设备特定值即可工作。由于获取设备名称并不容易,我们使用了所有 ELM 327 应该通用的其他设备属性。
class AdvertisedDeviceCB : public BLEAdvertisedDeviceCallbacks
{
void onResult(BLEAdvertisedDevice advertisedDevice)
{
if (advertisedDevice.haveServiceUUID() && !advertisedDevice.getAddressType() && advertisedDevice.getAppearance() == 576 && advertisedDevice.getServiceUUID().length() == 2)
{
BLEDevice::getScan()->stop();
OBD2Device = new BLEAdvertisedDevice(advertisedDevice);
}
}
};
最后但并非最不重要的一点是,在收到响应时显示值的函数。
static void NotifyCB(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify)
{
NewString = (char *)pData;
NewString = NewString.substring(0, max(NewString.indexOf(">"), 0));
NewString.trim();
if (!NewString.length() || I == ItemsInArray)
return;
else
{
if (NewString.substring(0, 2) == "41")
{
unsigned long UnsignedLong = strtoul(NewString.substring(3, 5).c_str(), NULL, 16);
NewString = NewString.substring(6, NewString.length());
NewString.replace(" ", "");
switch (UnsignedLong)
{
case 0x0C:
UnsignedLong = strtoul(NewString.c_str(), NULL, 16) / 4;
break;
case 0x0D:
UnsignedLong = strtoul(NewString.c_str(), NULL, 16) * 0.621371;
break;
case 0x05:
case 0x0F:
UnsignedLong = (strtoul(NewString.c_str(), NULL, 16) - 40) * 9 / 5 + 32;
break;
default:
UnsignedLong = strtoul(NewString.c_str(), NULL, 16);
break;
}
NewString = String(UnsignedLong);
}
if (NewScreen == ItemsInArray)
{
tft.setTextSize(3);
tft.fillRect(0, tft.getCursorY() + 40, 240, 40, TFT_BLACK);
tft.setCursor(10, tft.getCursorY() + 40);
tft.setTextColor(TFT_GREEN);
tft.print(LabelArray[I]);
tft.setTextColor(TFT_RED);
tft.printf(" %s", NewString.c_str());
}
else
{
tft.setTextSize(7);
tft.setCursor(10, 10);
tft.setTextColor(TFT_GREEN);
tft.print(LabelArray[I]);
tft.fillRect(0, 100, 240, 50, TFT_BLACK);
tft.setCursor(10, 100);
tft.setTextColor(TFT_RED);
tft.printf("%s", NewString.c_str());
OldString = NewString;
}
delay(10);
}
}
- Seeed Wio终端开源分享
- Lyapunov分形与Seeeduino Wio终端开源
- 基于OBD2的仪表板
- 使用Seeeduino Wio终端模拟Dadiplus掷骰子
- ISO15765 OBD2 PID故障码读取 5次下载
- 在Wio终端上显示精确的分贝计 0次下载
- 使用Wio终端扩展Arduboy
- 用于维修ECU(Webasto等)的OBD2测试板
- 用于维修ECU的OBD2测试板
- OBD_CAN的读取代码程序下载 3次下载
- "PIC18F25K80芯片烧录方案(汽车诊断仪OBD-II,OBD2,ELM327 V1.5)"
- OBD故障码读取和清除方法 85次下载
- OBD2输出信息的9种诊断模式 106次下载
- 自我诊断OBD2的工作原理 97次下载
- OBD_CAN读取代码 68次下载
- 示波器如何读取电压值 2783次阅读
- 汽车OBD是什么?OBD的应用场景 643次阅读
- 车辆OBD是什么?全面了解OBD系统 1660次阅读
- 无法读取I2C地址的调试案例 1648次阅读
- 带你全面了解OBD系统 1343次阅读
- 如何利用TinyML实现语音识别机器人车的设计 2110次阅读
- 内存是怎么读取数据的 5102次阅读
- 如何使用SFC1读取PLC时间 5780次阅读
- dfrobotDB9 OBD II连接线简介 2514次阅读
- 中控智慧科技终端xFace500介绍 4298次阅读
- 中控智慧科技BioFace600识别终端简介 2434次阅读
- 三菱plc读取时钟程序_三菱plc怎么读取程序 3w次阅读
- mpu6050对应i2c地址是什么_如何读取数据 2.4w次阅读
- 分解OBD接口能到采集哪些具体的车辆数据 2.3w次阅读
- 浅谈汽车故障诊断OBD接口功用和引脚定义 10.2w次阅读
下载排行
本周
- 1山景DSP芯片AP8248A2数据手册
- 1.06 MB | 532次下载 | 免费
- 2RK3399完整板原理图(支持平板,盒子VR)
- 3.28 MB | 339次下载 | 免费
- 3TC358743XBG评估板参考手册
- 1.36 MB | 330次下载 | 免费
- 4DFM软件使用教程
- 0.84 MB | 295次下载 | 免费
- 5元宇宙深度解析—未来的未来-风口还是泡沫
- 6.40 MB | 227次下载 | 免费
- 6迪文DGUS开发指南
- 31.67 MB | 194次下载 | 免费
- 7元宇宙底层硬件系列报告
- 13.42 MB | 182次下载 | 免费
- 8FP5207XR-G1中文应用手册
- 1.09 MB | 178次下载 | 免费
本月
- 1OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 2555集成电路应用800例(新编版)
- 0.00 MB | 33566次下载 | 免费
- 3接口电路图大全
- 未知 | 30323次下载 | 免费
- 4开关电源设计实例指南
- 未知 | 21549次下载 | 免费
- 5电气工程师手册免费下载(新编第二版pdf电子书)
- 0.00 MB | 15349次下载 | 免费
- 6数字电路基础pdf(下载)
- 未知 | 13750次下载 | 免费
- 7电子制作实例集锦 下载
- 未知 | 8113次下载 | 免费
- 8《LED驱动电路设计》 温德尔著
- 0.00 MB | 6656次下载 | 免费
总榜
- 1matlab软件下载入口
- 未知 | 935054次下载 | 免费
- 2protel99se软件下载(可英文版转中文版)
- 78.1 MB | 537798次下载 | 免费
- 3MATLAB 7.1 下载 (含软件介绍)
- 未知 | 420027次下载 | 免费
- 4OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 5Altium DXP2002下载入口
- 未知 | 233046次下载 | 免费
- 6电路仿真软件multisim 10.0免费下载
- 340992 | 191187次下载 | 免费
- 7十天学会AVR单片机与C语言视频教程 下载
- 158M | 183279次下载 | 免费
- 8proe5.0野火版下载(中文版免费下载)
- 未知 | 138040次下载 | 免费
评论
查看更多