不要心血来潮做硬件仿真,会变得不幸。
前言 如果你学的不是软工而是计算机,那么你的遇到大作业可以变得多种多样!
我在开学前看这个硬件课设的大纲时,里面有一些软硬结合的项目,看上去都是以软件系统的形式作为最终呈现,所以我一个软件人早早地就看准了大纲中的一个偏软件的选题,但是新冠疫情完美诠释了什么叫做『天不遂人愿』——像上半年的操作系统课设一样——题目又被改了:4个Arduino编程,1个纯软件编码查看器,还有一个明确了不给高分的加法器模拟,直接把家里蹲的我从万事俱备整成不知所措,不过想到队友都在校,主动权必然是队友掌握,我也就不管选什么题了。
不得不说队友真是非常amazing啊,过了几天领到Arduino UNO开发板直接开始研究,两天之后硬件功能已经实现了,我当然不好意思腆着脸坐等项目完成,想着能否参与一下软件功能的实现,想不到有个大坑正等着我。
仿真环境搭建
我们需要下载安装Proteus和Arduino IDE。
然后根据网上收集到的一些教程[1] [2] [3] 逐步搭建仿真环境。
坑:
问题出在测试虚拟串口连接时,无论如何都搜不到两个串口,自然也无法看到串口助手中显示出信息了。
一开始我还以为是代码的问题或者是配置的问题,但不管怎么尝试就是读不到串口,就差重启电脑了。
巧了。
搜到一个VMware的串口问题[4] ,里面说虚拟机不支持热插拔,要重启电脑 ,事到如今也顾不得浏览器开着几十个窗口了,反正之后可以恢复,重启就重启吧。然后
好了。
可以读到串口了。
挺好。
随后根据课设的要求模拟了测试体温的程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <LiquidCrystal.h> LiquidCrystal lcd (13 , 12 , 11 , 10 , 9 , 8 ) ; void setup () { Serial.begin(9600 ); lcd.begin(16 , 2 ); }void loop () { long rand = random(359 , 420 ); float output = rand / 10.0 ; lcd.setCursor(0 , 0 ); lcd.println(output); Serial.println(output); delay(1000 ); }
软件与串口通信 秉持着『非必要不学新语言』的一贯原则,C#上位机必然不是我的首选,机缘巧合下发现了Node.js下有一个SerialPort[5] ,加之我正好在学前端,遂大喜,这样就可以基于Node.js搭建一个简陋的前后端来提供友好的交互。
SerialPort的文档写得其实一般,所以在借助另寻的文档[6] 后比较顺利地写了一个能够读取串口数据并进行判断体温的逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import { SerialPort } from 'serialport' ;import { log } from 'console' ;const SERIAL_PATH = 'COM2' ; const TEMPERATURE_THRESHOLD = 37.3 ; const serialPort = new SerialPort ({ path : SERIAL_PATH , baudRate : 9600 , autoOpen : true , });let serialInputList = []; serialPort.on ("readable" , () => { let serialInput = serialPort.read (); if (serialInput.toString ('hex' ) !== '0a' ) { if (serialInput.toString ('hex' ) !== '0d' ) { serialInputList.push (serialInput); } } else { let serialBuffer = Buffer .concat (serialInputList); let temperature = parseFloat (serialBuffer.toString ()); if (isTemperatureSafe (temperature)) { log (temperature.toFixed (1 ), '°C' ); } else { log ('\t\t' , temperature.toFixed (1 ), '°C, WARNING!' ); } serialInputList = []; } });function isTemperatureSafe (temperature ) { if (temperature <= TEMPERATURE_THRESHOLD ) { return true ; } else { return false ; } }
串口发送来的数据被Node.js接收后实际上是十六进制的Buffer类型,而在每一行数据的的行尾也都包含了换行符“0A 0D”,所以在读取数据的过程中需要对Buffer收到的每一位数据都做好检查。
参考资料 [1].Arduino UNO Library for Proteus V2.0
[2].【教程】Proteus仿真Arduino,串口打印hello
[3].Arduino与Protues串口通信
[4].vmware虚拟机检测不到vspd虚拟串口问题
[5].SerialPort Usage
[6].JS知识点归纳 : serialport.js串口使用