在创建应用程序时,我们面临许多选择,问题等等,我们将在本文中与您进行熟悉。 事实证明,您可以与汽车进行对话,而且效率很高。 自然,为了组织与汽车的通信,您需要“建立联系”,“询问正确的问题”并正确理解从汽车收到的“答案”。 因此,本文旨在以一种易于使用的语言来解释对话的组织,并告诉您一路上可能遇到的错误以及如何处理这些错误。
连接选择
最初,有必要弄清楚将使用ELM327适配器连接汽车。 ELM327是微电路,可让您将汽车诊断轮胎中使用的协议转换为RS232协议,我们将向该协议传输数据。 由于通过RS232协议连续进行数据传输,因此出现了第一个问题-数据传输速度,我们将在以下段落之一中尝试规避。
ELM327适配器有多种变体,按数据传输方法分类-蓝牙,WIFI,USB。 基于开发目标是运行Android的移动设备这一事实,您可以选择两个最合适的ELM327版本,例如蓝牙和WIFI。 由于只有一种接收和处理数据的方法,并且它们的区别仅在于适配器的连接选项,因此您只能选择一种,与之组织对话,然后添加其余的连接选项。
ELM327 1.5和ELM327 2.1

可能遇到的第一个问题是选择适配器本身的问题,在我们的例子中是蓝牙。 事实证明,如果您需要支持所有(至少大多数)汽车,则需要选择版本v1.5而不是版本v2.1,实际上在购买适配器时需要多次澄清,因为卖家尝试提供的适配器版本不适合于实际上,因为 它们并没有特别的不同。 实际上,在v2.1版本中,不支持J1850 PWM和J1850 VPW协议,这意味着您将无法连接到使用这些协议的汽车。
连接方式
连接到适配器的过程分为以下几个阶段:
- 连接到适配器(蓝牙,WIFI)
- 发送初始化命令(初始化字符串)
连接的组织是否一切正常。 操作原理与任何蓝牙/ WIFI聊天相同。 为了理解如何发送初始化字符串,有必要研究存在哪些命令以及它们执行什么功能。
AT Z [全部重设]
将适配器设置重置为出厂默认值。
在L1-0启用/禁用换行。
在E1-0回声开-关
在H1-0标题打开-关闭
在AT0-1-2自适应定时关闭-自适应定时自动1-自适应定时自动2
在ST FF将超时设置为最大。
AT D [全部设置为默认]
将设置重置为初始用户配置状态。
AT DP [描述当前协议]
扫描仪能够独立确定其所连接的车辆的协议。
AT IB10 [将ISO波特率设置为10400]
该命令设置ISO 9141-2的波特率,
ISO 14230-4 10400
AT IB96 [将ISO波特率设置为9600]
该命令设置ISO 9141-2的波特率,
符合协议3、4、5的ISO 14230-4 9600。
AT SP h [设置协议h]
协议选择命令h,其中h:
0-自动;
1-SAE J1850 PWM(41.6 Kbaud);
2-SAE J1850 VPW(10.4 Kbaud);
3-ISO 9141-2(5波特init,10.4 Kbaud);
4-ISO 14230-4 KWP(5波特init,10.4 Kbaud);
5-ISO 14230-4 KWP(快速初始化,10.4 Kbaud);
6-ISO 15765-4 CAN(11位ID,500 Kbaud);
7-ISO 15765-4 CAN(29位ID,500 Kbaud);
8-ISO 15765-4 CAN(11位ID,250 Kbaud);
9-ISO 15765-4 CAN(29位ID,250 Kbaud);
AT SP Ah [使用自动设置协议h]
该命令设置默认协议h,如果使用协议h的连接失败,则适配器开始自动选择协议。
基于上述命令,我们形成初始化字符串。
initializeCommands = Arrays.asList("ATZ", "ATL0", "ATE1", "ATH1", "ATAT1", "ATSTFF", "ATDP", "ATSP0");
建议使用户能够更改初始化命令,因为为了选择某些汽车的“钥匙”,必须选择更合适的适配器设置。 在我们的情况下,所使用的设置适用于大多数标准协议。
还建议注意APSP0命令,因此我们设置了默认的自动协议选择,这可能需要一些时间。
因此,如果用户知道他的自动协议是什么,则使用更改连接协议的能力,他可以将0更改为其协议号。
读取诊断数据
PID的特殊命令用于读取诊断数据。
PID(参数ID-车载诊断参数标识符)-用于查询特定车辆传感器性能的代码。
主要pid可以在Wikipedia上找到,所有汽车都应支持一整套基本命令。 对于某些品牌和类型的汽车,还有一些命令集,这些命令集是有偿提供的。 在我们的案例中,该应用程序分别专注于汽车的基本诊断,我们使用基本的命令集。
也可以从汽车接收当前数据,而从汽车接收数据的命令的开头将以
01开头,表明我们要获取真实数据。 如果要获取保存的汽车数据,则在命令开头必须指定
02 。 例如,获取汽车当前速度的命令为
010D ,并获取保存的速度
-020D 。
如果仔细查看开放资源提供的命令数量,您可能会注意到我一开始就提到的问题,即适配器响应速度的问题。 由于发送和接收命令是顺序的,因此为了在当前时间接收传感器读数,必须等待所有先前命令的答案。 因此,如果您请求接收所有命令,则很有可能实际数据的更新将非常缓慢地发生。 但是,如果使用仅显示汽车中存在的团队的命令,则可以解决此问题。 例如:
0100-支持的PID [01-20]
0120-支持的PID [21-40]
0140-支持的PID [41-60]
0160-支持的PID [61-80]
0180-支持的PID [81-A0]
01A0-支持的PID [A1-C0]
我将演示如何使用PID之一确定汽车中存在哪些传感器。 例如:
- 0100 \\请求
- BB1E3211 \\来自车内的答案
我们将汽车的答案转换为二进制数字系统
BB1E3211(16) > 10111011000111100011001000010001(2)
使用以下铭牌,我们可以确定从01到20的汽车支持的pid:

根据获得的数据,我们可以确定我们的汽车支持以下pid:
01, 03, 04, 05, 07, 08, 0C, 0D, 0E, 0F, 13, 14, 17, 1C, 20
现在,尽管可能会缺席一些团队,但我们将只使用15个团队,而不是发送所有32个团队并等待他们的答复。 但这不是所谓的优化的限制。 为了更快地更新数据,我建议您仅请求有关屏幕上显示的那些传感器的数据。 尽管这限制了应用程序的某些功能。 例如,历史记录。
读取和解码汽车错误
汽车错误也可以不同,并且针对它们也存在单独的命令。 例如:
- 03-显示已保存的错误代码
- 0A-显示持续的错误代码。
与其他命令一样,汽车错误分别以编码形式出现,就像在其他命令中一样,需要对其进行解码以获得必要的信息。 让我举一个例子说明错误解码的工作原理。 代码:
private final static char[] dtcLetters = {'P', 'C', 'B', 'U'}; private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); private void performCalculations(String fault) { final String result = fault; String workingData = ""; int startIndex = 0; troubleCodesArray.clear(); try { if (result.contains("43")) { workingData = result.replaceAll("^43|[\r\n]43|[\r\n]", ""); } else if (result.contains("47")) { workingData = result.replaceAll("^47|[\r\n]47|[\r\n]", ""); } for(int begin=startIndex; begin < workingData.length(); begin += 4) { String dtc = ""; byte b1 = Utility.hexStringToByteArray(workingData.charAt(begin)); int ch1 = ((b1 & 0xC0) >> 6); int ch2 = ((b1 & 0x30) >> 4); dtc += dtcLetters[ch1]; dtc += hexArray[ch2]; dtc += workingData.substring(begin + 1, begin + 4); if (dtc.equals("P0000")) { continue; } troubleCodesArray.add(dtc); } } catch (Exception e) { Log.e(TAG, "Error: " + e.getMessage()); } }
现在进行解释。
根据收到的响应,我们可以得到一个错误代码,为此,我们使用以下代码对收到的消息进行解码。
第一个字符:

第二个字符:

根据此表形成3、4、5个字符:

基于此,我们可以尝试解析以下答案0001000000111110

错误代码:P103E
结语
在此阶段,我们想出了如何组织与适配器的对话,向其发送命令,接收和解密其答案的方法。 如果您考虑学习材料需要多少时间,这是工作的很大一部分,但同时却很有趣。 本文之外,还有许多与可视界面相关的问题,以及许多其他功能,例如从文件添加新的pid,连接到适配器和创建图形的标准和高级方式。
马特维年科·亚历山大(Matvienko Alexander),侯赛因·法赫(Hossein Fakhr)。