By Toradex Leonardo Graboski Veiga
1). 简介
这是关于 IoT 应用开发系列文章中的第二篇。本文继续关注传感器读取以及向云端发送收集到的数据。Toradex Colibri VF61 模块 + Iris 底板继续作为本次演示的嵌入式系统。图 1 展示了本系列文章所介绍应用整体框图。
图1:应用框图
2). 添加传感器模块到 Iris 底板
项目中使用的传感器产生数据,模块通过 Wi-Fi 联网:
./ MPU-6050 陀螺仪 + 加速度和温度
./ HC-SR04 超声波模块
./ IKeyes GPS shield v1.2
./ WL250N USB Wi-Fi
MPU-6050 已经提供了内核驱动模块,能够同 Linux 应用通信(适用于 Toradex Vybrid 的
4.4.0 Linux 内核版本 )。
该文档 说明了使用模块硬件接口的 device
tree 配置。该模块驱动不能直接添加到内核中,需要编译的时候包含进来。 这篇
文章 详细说明了如何配置、编译和更新内核。如果 MPU-6050 的 I²C 地址和板载RTC(0x68)冲突,最简单的解决方法是将 MPU-6050 的 AD0 接至高电平,这可以将其地址变为 0x69。
HC-SR04 在 Github 上有
驱动模块 ,其中的一个分支可以针对 Colibri VF61 的 4.4.0 内核进行编译。针对Toradex 模块的源码以及编译好的驱动模块可以从
这里下载。
GPS 模块通过 UART 通信,其与 GPSD 服务连接。更多关于 GPSD 的信息请查看
这里. 。如果你想要
编译自己的镜像,GPSD 也提供了
OpenEmbedded
recipe。
依次配置 GPSD、加载 HC-SR04 驱动以及向云端发送数据。无论是重启还是开机,init 服务都会被调用。如果本文使用的
Github repository 已经复制到目标板上,你会发现服务文件(car.service)和 init 脚本(init.sh)在主文件夹中。为了使其工作,还需要其他一些步骤。首先,Github repository 需要复制到 /home/root 目录,这是默认的路径。然后 car.service 需要放在 /lib/systemd/system 中,启用相应的服务。下面的步骤描述了操作步骤:
---------------------------
root@colibri-vf:~# git clone https://github.com/leograba/azure-iot-car.git
root@colibri-vf:~# cd azure-iot-car
root@colibri-vf:~# cp car.service /lib/systemd/system
root@colibri-vf:~# systemctl enable car.service
---------------------------
如果想要在启动时停止该服务,例如停止向 IoT Hub 发送数据,那么可以通过下面命令停止:
---------------------------
root@colibri-vf:~# systemctl stop car.service
---------------------------
USB Wi-Fi 模块 WL250N 可以直接使用,但是仍旧需要配置才能连接网络。如何配置连接的说明可以参考
这里。
关于模块和 Iris 底板之间的连接,只能使用 X16 排针引脚。Iris
技术手册 提供了关于接口、连接器等的信息,如果需要可以参阅 Colibri VF61 CoM
技术手册。表 1 描述了 Iris 和模块之间的引脚连接。图 2 是 MPU-6050和 HC-SR04 在早期研发阶段的连接。
---------------------------
表 1:传感器和 Iris 底板连接
Iris pin header (x16) Iris pin description Module Pin
5 I²C SDA MPU 6050 SDA
6 I²C SCL MPU 6050 SCL
7 GND MPU 6050 / HC-SR04 / GPS GND / GND / GND
12 +5V MPU 6050 / HC-SR04 / GPS VCC / VCC / 5V
17 GPIO HC-SR04 Trig
18 GPIO HC-SR04 Echo
31 UART_B Rx GPS Tx
32 UART_B Tx GPS Rx
33 +3.3V HC-SR04 AD0
---------------------------
图 2:MPU-6050 以及 HC-SR04 和 Iris 连接
3). IoT 车辆
在所有的模块连接到 Toradex 嵌入式系统后,接下来就需要把它嵌入到遥控车里,如图 3 所示。这是简单的步骤,但仍旧需要在一些地方引起注意。
图 3:IoT 原型
因为 GPS 模块有主动天线,模块放置在 Toradex 系统下,天线接到车顶外面。为了安装超声波测距模块,如图 3 所示在保险杆位置开了两个孔。加速器传感器则被固定在电路板上,PCB 板与地面平行,这可以直接使用模块的数据而不需要修正(在实际应用中这往往是需要的)。
嵌入式系统的电源选用两芯(2S – 7.4V)1200mAh 可充电锂电池。考虑到目前系统耗电为 200mA,锂电池 实际放电 不应该超过容量的 80% 的规律,系统能够工作 4.8 个小时。图 4 为最终的原型。
图 4:IoT 车辆最终原型
4). 读取传感器并向云端发送数据
MPU-6050 和 HC-SR04 可以通过访问文件系统读取数据,读取 GPS 数据需要使用 Bancroft 同 GPSD 通信,获取解析的数据。
从 HC-SR04 由内核模块返回的值为发送一个脉冲至其返回的时间,单位毫秒。该值需要乘以声音的速度并除以2E6,因为一半的时间用于超声波的发送,另一半是反射:
distance = (value*sound_speed)/2000000
MPU-6050 的数据具有一个比例,一旦获取精度配置。同样,每一个温度传感器都已不同的偏移。在本文中,MPU-6050 会采用默认的配置,一般的方法就可以换算读取的数据:
value = (raw_value+offset)*scale
换算后各个值的单位:加速度 - m/s²; 陀螺仪 - °/s ;温度 - °C.
GPS 模块返回如下的数据:
---------------------------
{
timestamp: 1311296682000,
latitude: 45.456445,
longitude: -73.569651667,
altitude: 28.9,
speed: 11,
track: 10.3788,
geometries: { type: 'Point', coordinates: [ -73.569651667, 45.456445, 28.9 ] }
}
---------------------------
读取和向 IoT Hub 发送数据的应用是由第一部分博文中修改该而来的 send_data.js。对应目前应用的文件是send_data_from_sensors.js,这个可以在先前复制到目标板上的 Github repository 中找到。修改后的主要需要注意的是无论什么时候读取到新的数据,Bancroft 模块都会触发事件。对于访问传感器的路径, MPU-6050 是/sys/bus/iio/devices/iio:device2/,HC-SR04 是 /sys/class/hcsr04/。下面是部分代码的说明。
首先,MPU-6050 的偏移和比例变量可以同步读取,防止代码在偏移和比例变量确定之前读取数值并计算。同样,保存需要发送到云端的数据的变量也需要申明:
---------------------------
//Read some offset and scale constants from the MPU-6050 and convert to number
var temp_offset = +fs.readFileSync('/sys/bus/iio/devices/iio:device2/in_temp_offset');
var temp_scale = +fs.readFileSync('/sys/bus/iio/devices/iio:device2/in_temp_scale');
var accel_scale = +fs.readFileSync('/sys/bus/iio/devices/iio:device2/in_accel_scale');
var anglvel_scale = +fs.readFileSync('/sys/bus/iio/devices/iio:device2/in_anglvel_scale');
var gps_coordinates ;//variable to hold the gps coordinates
// Data to be sent to the cloud
var timenow, temperature, Distance, Acceleration = {}, Gyroscope = {};
---------------------------
然后处理对应用至关重要的 GPS 数据。无论什么时候坐标被更新,其都会保存在变量中,一旦与模块之间连接丢失,它都会尝试重新连接:
---------------------------
// gps events
bancroft.on('location', function (location) {//updates the gps coordinates variable
location.geometries = "point";
gps_coordinates = location;
console.log('got new location', gps_coordinates);
});
bancroft.on('disconnect', function (err) {//if gps is disconnected
bancroft = new Bancroft();//tries to reconnect once
console.log('trying to reconnect gps...');
});
---------------------------
最后一部分代码是循环调用函数读取传感器并将数据发送至 IoT Hub。每一个函数采用独立的循环,使得代码更加灵活,例如,读取传感器数据并保存到备份文件需要比发送到云端更加频繁:
---------------------------
// Loops that call the functions to read sensors and send to the cloud
sendInterval.handlerGet = setInterval(getAllSensors, sendInterval.timerGet);
sendInterval.handlerSend = setInterval(sendToIotHub, sendInterval.timerSend);
---------------------------
上面调用的 getAllSensors 函数尽管很简单,但是也会被删除:其更新嵌入式系统保存的当前时间,针对每次测量调用 readSensor() 函数 - 距离、温度、3 轴加速度、3 轴陀螺仪。 readSensor() 仅仅读取文件并打印错误到终端。否者它和 readFile() 函数非常类似。
---------------------------
//Function that reads data from sensor
function readSensor(path, callback) {
fs.readFile(path, function (err, data) {
if(err){//if data could not be read
console.log("Error reading sensor: " + err);
callback(err, null);//pass the error to the callback
return;
}
callback(null, data);//callback without error
});
}
---------------------------
sendToIotHub() 函数将最新的数据转换成 JSON 编码字符串、封装成消息、在终端输出反馈并将其发送至 IoT Hub。这也是本文解释最后一部分代码,所示如下:
---------------------------
function sendToIotHub() {
// Add the data to a JSON encoded string
var data = JSON.stringify({
ObjectName: 'toradex2',
ObjectType: 'SensorTagEvent',
temp: temperature,
acceleration: Acceleration,
gyroscope: Gyroscope,
gps: gps_coordinates,
distance: Distance,
boardTime: timenow
});
var message = new Message(data);// Encapsulate the message to be sent
message.properties.add('myproperty', 'myvalue');
console.log('sending message to the IoT Hub: ');// Feedback message to the console
console.log(data);
client.sendEvent(message, printResultFor('send'));// Send message to the IoT Hub
}
---------------------------
5). 总结
到现在为止,在本系列的第一篇文章中介绍了项目目标和 IoT 总体情况。然后配置 Azure IoT Hub,接收来自Toradex 嵌入式系统的消息(并发送消息,在该项目中没有过多说明),提出了一些关于从嵌入式系统发送数据的思考,最后,演示了从云端获取数据的方法,用以验证系统正常工作。
然后,本文主要关注于嵌入式系统的项目。从如何连接传感器/模块到 Colibri VF61 + Iris 载板的步骤开始到Node 应用的具体细节。
基于以上内容,接下来的内容是为了减轻挖掘有用的分析并生成 BI 工作,介绍使用 Azure Stream Analytics 和 Microsoft Power BI 过滤数据并显示易于理解的结果。希望这是一篇有用的文章,我也想要感谢来自巴西的
Grupo Viceri 团队在 Azure 和 Business Intelligence 丰富的经验,促成了我们的合作,并最终实现了 IoT 项目。期待在第三部分文章中再见!