【arduino学习笔记】通过批处理向串口发送数据到arduino的坑

需求

现有编程为需要从串口接收数据进行处理的arduino主板,每次传输内容为3位数字;arduino处理方法为先读取为字符串,再转换为整型变量进行处理。
每次从串口接收到有效数据时,arduino需要打开一个LED灯;若后续5秒内没有接收到串口数据,则关闭LED。

在实际使用时,需要使用批处理先从powershell执行一条命令,将其结果写入文本文件,随后将文件第四行的内容发送到串口上。

初步方法

询问bing chat和网上搜索,开始编写脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@echo off
setlocal EnableDelayedExpansion
:loop
mode COM3 BAUD=96 PARITY=n DATA=8
Powershell -command "Get-WMIObject -Query “SELECT * FROM Win32_PerfFormattedData_Counters_ThermalZoneInformation” -Namespace “root/CIMV2” | Select-object Temperature" >temp.txt
for /f "skip=3 delims=" %%a in (temp.txt) do (
set txt=%%~a
goto :nxt
)
:nxt
echo %txt%
echo %txt% >COM3
:break
del temp.txt
ping localhost -n 5 >nul
goto loop

这里的mode COM3 BAUD=96 PARITY=n DATA=8就是用于设置串口通信参数的命令,而>COM3是将内容发送到COM3串口上。

问题

该方法存在一个缺陷,arduino的串口通信模式与这里设定的可能不同(尤其是与IDE的默认模式),导致LED灯无法正常打开。

这里还有一个奇怪的地方,不知道是不是我代码有问题,每次重新上传烧录代码到arduino之后LED就能正常被批处理打开,但如果断电重连则不行;此外,断电后如果先用IDE通信则LED正常打开,再用批处理发送不能打开,LED保持熄灭;而如果先用批处理发送,则后续再用IDE发送也无法打开LED。

推测与解决方案

由于我没有仔细阅读arduino官方reference文档,不是非常了解Serial.available()函数具体是如何动作的;但我的推测是,这个函数在等待串口数据的时候会暂时阻塞机器,这也是半双工串口通信的一个问题。

至于它如何影响arduino以至于出现这些奇怪的问题?我也不是很清楚,但我找到了解决方案。

微软官方文档:https://learn.microsoft.com/zh-cn/windows-server/administration/windows-commands/mode
在仔细阅读了批处理中mode指令控制串口参数的用法后,我进行了一些尝试,并成功解决了问题。

只需要在mode这一行后面加入DTR=OFF RTS=OFF即可:

1
mode COM3 BAUD=96 PARITY=n DATA=8 DTR=OFF RTS=OFF

这是什么原因呢?我猜测批处理默认情况下会通过DTR和RTS信号来决定何时发送数据。这两个信号是串行通信中的控制信号,前者用于计算机向arduino发出信号,让arduino准备好接收;后者用于arduino向计算机回馈信号,允许计算机发送串口数据。

但这样的过程会浪费很多等待时间,相当于双方要完成握手才能发送数据(类比TCP连接);而整个握手和等待的时间内arduino都处于阻塞状态,LED就处于熄灭状态。

因此,在手动关闭了DTR和RTS信号后,计算机便无需等待arduino响应即可发送数据,arduino也无需等待连接建立,计算机可随时向arduino发送数据(类比UDP包),进而大幅节约了进程时间,使得arduino不再一直处于阻塞状态,LED可以正常点亮。


【arduino学习笔记】通过批处理向串口发送数据到arduino的坑
https://zjxdiu.github.io/blog/arduino_batch_com_comm/
作者
zjxdiu
发布于
2024年1月4日
许可协议