0x01 前言

我家里有一套在停电情况下给服务器供电的锂电池组,为监控电池组的健康状态,我特意购买了温湿度传感地和电压传感器,还有火焰传感器用于检测危险情况。

0x02 基本情况

据我了解,树莓派的GPIO接口需要接收数字信号,但我没找到可以直接测量电压并输出数字信号的模块,只找到一款需要串联在电路中的检测模块,可以检测电压与电流,这款模块是:INA219 GY-219,外观如下:

相关的电路图如下:

图片来源:https://www.rototron.info/raspberry-pi-ina219-tutorial/

如果直接将正负极连接在电池上,则会短路,电流无限大,这将会损坏电池,甚至使电池发生爆炸。

因为我需要监测电池电压,所以这种方案是行不通的,然后找到一种模块:

该模块的电路图如下:

该模块可以检测25v以下的电压,但这个模块只能输出模拟信号,如果想通过树莓派读取数据,有两种解决办法:一种是接一个模拟/数字信号转换芯片;另一种是通过arduino读取。

因为我需要连接多个传感器,所以选择连接arduino的解决方式。

上面的电路图中,VCC接电池的正极、GND接电池的负极,S接arduino的信号pin,-接arduino的负极。

连接方式大致如下:

图片来源:http://henrysbench.capnfatz.com/henrys-bench/arduino-voltage-measurements/arduino-25v-voltage-sensor-module-user-manual/

0x03 arduino

据我的了解,arduino是一款单片机,可以将程序通过IDE写到芯片里,与各类传感器通讯并返还数据的一款自由度很高的平台。

可是我完全没接触过arduino相关的知识,经过一周的学习了解后发现,想arduino与树莓派相互通讯并不难,只需要通过USB连接两者:

然后在树莓派中安装IDE即可完成程序在arduino中的烧录:

0x04 UUGear

解决连接的问题后,还需要解决以下问题:

arduino上有许多针脚,我想通过python脚本去读取,可我完全不知道从何处入手。在一番了解之后,发现已经有人做出了相关的库:

  • GitHub:https://github.com/shawnu/UUGear
  • 详细说明:http://www.uugear.com/uugear-rpi-arduino-solution/

通过USB连接上arduino与树莓派之后,在树莓派一侧只会以以下格式呈现:

/dev/ttyUSB*
/dev/ttyACM*

这就带来一个问题,如果USB插拔或有多个USB设备连接在树莓派上的时候,就不知道arduino究竟在哪个接口上。

而这个库也解决了这个问题,在arduino一侧的程序中会生成一个UUGear-Arduino为前缀的设备ID,例如我的arduino:

root@raspberrypi:~/UUGear/RaspberryPi/bin# ./lsuu 
--------------------------------------------------
UUGear-Arduino-1029-9288	(/dev/ttyACM0)
--------------------------------------------------
1 device(s) found.

然后使用python脚本调用该库的API并带上该设备ID即可通过serial协议与arduino通讯。

更多信息请浏览上面的地址。

0x05 IDE

将程序写入arduino的流程也很简单,先通过vnc登入树莓派并打开终端,然后clone该项目的代码:

#进入桌面目录
pi@raspberrypi:~ $ cd Desktop/

#clone项目
pi@raspberrypi:~/Desktop $ git clone https://github.com/uugear/UUGear.git

然后安装IDE:

pi@raspberrypi:~ $ sudo apt-get install arduino

安装完成后,在开始菜单中打开IDE:

在开始编译烧录等操作之前需要先确认USB端口与设备型号:

然后导入一个程序,清理寄存器中的数据:

再然后点击upload,IDE会编译并上传到arduino中:

完成上面步骤后,在IDE中导入UUGear.ino,该文件在刚才clone的文件夹中:

root@raspberrypi:/home/pi/Desktop# tree ./UUGear/
./UUGear/
├── Arduino
│   └── UUGear
│       └── UUGear.ino

导入完成后同样地点击upload,即可完成编译和烧录。

0x06 应用

至此,arduino的部分已经完成,接下来需要在树莓派上编译相关文件,首先进入相关文件夹:

pi@raspberrypi:~/Desktop $ cd ./UUGear/RaspberryPi/
pi@raspberrypi:~/Desktop/UUGear/RaspberryPi $ ls -l
总用量 12
-rw-r--r-- 1 pi pi 1394 7月   8 19:04 build.sh
drwxr-xr-x 4 pi pi 4096 7月   8 19:04 example
drwxr-xr-x 2 pi pi 4096 7月   8 19:04 src

然后执行build.sh这个文件:

编译过程中虽然有告警,但并没有错误,可以忽略告警。然后进入bin目录,执行lsuu这个可执行文件,如果一切正常,即可列出所有arduino的设备ID:

pi@raspberrypi:~/Desktop/UUGear/RaspberryPi $ cd ./bin/
pi@raspberrypi:~/Desktop/UUGear/RaspberryPi/bin $ ls -l
总用量 212
-rwxr-xr-x 1 pi pi  8520 7月   8 19:41 AnalogWrite
-rwxr-xr-x 1 pi pi  8584 7月   8 19:41 ControlServo
-rw-r--r-- 1 pi pi   442 7月   8 19:41 ControlServos.py
-rwxr-xr-x 1 pi pi  8724 7月   8 19:41 DigitalReadWrite
-rw-r--r-- 1 pi pi   446 7月   8 19:41 DigitalReadWrite.py
-rwxr-xr-x 1 pi pi 18104 7月   8 19:41 libUUGear.so
-rwxr-xr-x 1 pi pi 13504 7月   8 19:41 lsuu
-rwxr-xr-x 1 pi pi  8608 7月   8 19:41 ReadDHT
-rw-r--r-- 1 pi pi   660 7月   8 19:41 ReadDHT.py
-rwxr-xr-x 1 pi pi  8692 7月   8 19:41 ReadSpeed
-rwxr-xr-x 1 pi pi  8552 7月   8 19:41 ReadSR04
-rw-r--r-- 1 pi pi   374 7月   8 19:41 ReadSR04.py
-rwxr-xr-x 1 pi pi 23500 7月   8 19:41 SocketBroker
-rw-r--r-- 1 pi pi   433 7月   8 19:41 TwoDevices.py
-rwxr-xr-x 1 pi pi 23600 7月   8 19:41 UUGearDaemon
-rw-r--r-- 1 pi pi 10580 7月   8 19:41 UUGear.o
-rw-r--r-- 1 pi pi  5495 7月   8 19:41 UUGear.py
-rwxr-xr-x 1 pi pi  8564 7月   8 19:41 VoltageMeasurement
-rw-r--r-- 1 pi pi   343 7月   8 19:41 VoltageMeasurement.py
pi@raspberrypi:~/Desktop/UUGear/RaspberryPi/bin $ ./lsuu 
--------------------------------------------------
UUGear-Arduino-4608-5541	(/dev/ttyACM0)
--------------------------------------------------
1 device(s) found.

确认设备工作正常后,再将传感器接入arduino:

然后到以下目录修改python脚本:

#进入目录
root@raspberrypi:/home/pi/Desktop# cd UUGear/RaspberryPi/bin/

#修改文件:
root@raspberrypi:/home/pi/Desktop/UUGear/RaspberryPi/bin# vim VoltageMeasurement.py

将device中的设备ID修改为通过lsuu检索到的设备ID,然后确认第10行中的接口编号:

device.analogRead(3)

脚本中预设的是A3接口。

另外,该脚本中的数值换算并不适用于该模块,在这里需要做一些修改,根据电路图,公式如下:

v=读取到的数值
n=实际数值

R1=30000
R2=7500

公式:
n=(( n * 5.0 ) / 1024.0 ) / ( R2 / ( R1 + R2 ))

然后修改脚本中的第10行为:

print "%0.2f" % ((float(device.analogRead(3)) * 5.0 / 1024.0 ) / ( 7500.0 / (30000.0 + 7500.0))), "V"

最终整个脚本如下:

root@raspberrypi:~/UUGear/RaspberryPi/bin# cat VoltageMeasurement.py 
from time import sleep
from UUGear import *

UUGearDevice.setShowLogs(0)

device = UUGearDevice('UUGear-Arduino-1029-9288')

if device.isValid():
  for i in range(10):
    print "%0.2f" % ((float(device.analogRead(3)) * 5.0 / 1024.0 ) / ( 7500.0 / (30000.0 + 7500.0))), "V"
    sleep(0.2)
  
  device.detach()
  device.stopDaemon()
else:
  print 'UUGear device is not correctly initialized.'

然后在检测模块上接上1.5V的AA电池,并启动脚本,输出如下:

root@raspberrypi:~/UUGear/RaspberryPi/bin# python VoltageMeasurement.py 
1.68 V
1.68 V
1.68 V
1.68 V
1.66 V
1.66 V
1.68 V
1.68 V
1.66 V
1.68 V

用万能表再次检查该电池的电压后发现,arduino检测的结果比万能表检测的高了0.1v。

接下来接上一块24v的电池组,再运行脚本:

root@raspberrypi:~/UUGear/RaspberryPi/bin# python VoltageMeasurement.py 
24.98 V
24.98 V
24.98 V
24.98 V
24.98 V
24.98 V
24.98 V
24.98 V
24.98 V
24.98 V

而万能表检测的数值为26v,比arduino检测到的结果高了1v。

0x07 结语

接下来我需要编写脚本以适配所有传感器,经过测试后再部署到机柜里。

虽然arduino的电压传感器检测到的数值有小许误差,但还在可以接受的范围之内。