65.9K
CodeProject 正在变化。 阅读更多。
Home

Arduino 和 Web: 使用 NodeJS 和 SerialPort2

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.65/5 (22投票s)

2012年5月22日

CPOL

6分钟阅读

viewsIcon

194121

downloadIcon

3190

本文重点介绍如何使用 SerialPort2 Node.JS 模块监听 Arduino 通过串行端口(Linux、Mac)或 Windows 的 COM 端口发送的信号,并使用 Socket.IO 将信号数据实时提供给 Web。

引言

本文介绍了允许您的 Arduino 板使用每个人都可以使用的、新颖但开源的技术与 Web 连接的必要步骤。这早已可用,但使用其他替代方法,如使用 Arduino 的 LAN 或 Zigbee 模块/扩展板,可能会非常昂贵。但是,根据用途,这个简单的解决方案可能已经足够了。

您可以通过观看这个简单的视频来简单演示使用 Arduino 和 Web 可以做什么。

背景

通过 USB,Arduino 板串行连接到 PC 的某个 COM 端口,该端口由操作系统分配。Node.JS,异步服务器端 JavaScript 引擎,然后使用一个名为 SerialPort2 的 Node.JS 模块监听该端口。当收到信号时,使用 Node.JS Socket.IO 模块,数据也以异步方式提供给 Web,从而提供 Arduino 信号的实时馈送。

以下是用于展示此方法对特定问题可行性的关键技术:

  • Arduino - 一个小型电子原型板。有多种版本,但在本文中使用的版本是 Arduino Mega 2560 Version 1。只要 Arduino 有串行输出数据的方式,就可以将相同的方法应用于其他版本的 Arduino。
  • NodeJS - 服务器端 JavaScript 解释器。
  • NodeJS SerialPort2 - 一个用于监听 COM 端口的 Node.JS 模块。
  • NodeJS Socket.IO - 一个用于使用 WebSockets 等技术向 Web 提供异步数据的 Node.JS 模块。
  • NPM - 一个 Node.JS 包管理器,已包含在 Node.JS 的官方安装程序中。
  • jQuery - 一个便于编写脚本的 JavaScript 库。
  • Flot - Flot 是一个纯 JavaScript 的、用于 jQuery 的绘图库。
  • Apache - 本项目用于提供静态内容。建议使用WAMP 套件以方便安装。用户也可以使用WAMP 套件来托管 PHP 和 MySQL。

对于 Windows 用户,SerialPort2 需要以下组件才能成功构建:

  • Python 2.7.3
  • Visual Studio 2010
  • Windows SDK 7.1

解决方案

假设用户已经具备 Arduino 的工作知识。在本文中,我们将创建一个特定场景并为其创建解决方案。将一个电位器连接到 Arduino 板的模拟引脚 0(以下简称 A0)。我们希望将模拟信号电平流式传输到 Web,并使用 Google Chrome、Firefox 或 Internet Explorer 等 Web 浏览器进行查看。信号电平必须随着电位器的旋转实时更新。

准备 Arduino 板

您可以使用以下原理图来设置电位器和 Arduino 板。

编写 Arduino 程序

您可以使用以下代码来编写 Arduino 程序。代码已充分注释。建议读者了解代码如何与 Arduino 一起工作,以便完全理解后续步骤。

const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to

int sensorValue = 0;        // value read from the pot
int prevsensorValue = 0;

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 
}

void loop() {
  // read the analog in value:
  sensorValue = analogRead(analogInPin);
  
  // If the previous value is the same as the new one, the do not send to save
  // communication link between the Arduino and the PC. 
  if (prevsensorValue != sensorValue) {
    // print the results to the serial monitor:
    Serial.print("A"); // Print the letter A to signal the beginning of an Input
    Serial.print(sensorValue); // Send the sensor Value (this is an integer)
    Serial.print("B"); // Print the letter B to signal the end of an Input
    prevsensorValue = sensorValue; // Change the previous sensor value
  }
  // wait 100 milliseconds before the next loop
  // for the analog-to-digital converter to settle
  // after the last reading. If you are sending too fast
  // there is also a tendency to flood the communication line.
  delay(100);                     
}

准备 Node.JS

您可以从 Node.JS 官方网站下载官方安装程序。推荐版本是 Node.JS v0.7.8。此外,为了在 Windows 上成功构建 SerialPort2,您需要安装 Python 2.7.3 和 Microsoft Visual Studio 2010 以及 Microsoft Windows SDK 7.1。NPM 模块(已包含在 Node.JS v0.7.8 中)将负责构建过程。但是,为了简化操作,您可能需要将 *python.exe* 的目录路径添加到 PATH 环境变量。

要使用命令提示符安装所需的 Node.JS 模块,请进入您的工作目录。以下命令将下载、构建和安装必要的 Node.JS 模块。

npm install serialport2 socket.io

您应该会看到类似如下的输出。

准备服务器端

在工作目录中创建一个名为 *server.js* 的文件。

以下代码行准备了 Node.JS 和端口所需的连接。接收到的数据是全局变量

var SerialPort  = require('serialport2').SerialPort;
var portName = 'COM3';
...

然后以下代码打开串行端口连接

...
var sp = new SerialPort(); // instantiate the serial port.
sp.open(portName, { // portName is instatiated to be COM3, replace as necessary
   baudRate: 9600, // this is synced to what was set for the Arduino Code
   dataBits: 8, // this is the default for Arduino serial communication
   parity: 'none', // this is the default for Arduino serial communication
   stopBits: 1, // this is the default for Arduino serial communication
   flowControl: false // this is the default for Arduino serial communication
});
...

以下代码仅在串行端口接收到指定端口的消息时触发。

...
var cleanData = ''; // this stores the clean data
var readData = '';  // this stores the buffer
sp.on('data', function (data) { // call back when data is received
    readData += data.toString(); // append data to buffer
    // if the letters 'A' and 'B' are found on the buffer then isolate what's in the middle
    // as clean data. Then clear the buffer. 
    if (readData.indexOf('B') >= 0 && readData.indexOf('A') >= 0) {
        cleanData = readData.substring(readData.indexOf('A') + 1, readData.indexOf('B'));
        readData = '';
        /*
            More code here later...
        */
    }
});
...

现在我们可以将清理后的数据发送到 Web 了。为此,我们必须先设置 Socket.IO 模块。在文件的顶部,插入 Socket.IO 模块的实例化。

var SerialPort  = require('serialport2').SerialPort;
var portName = 'COM3';

var io = require('socket.io').listen(8000); // server listens for socket.io communication at port 8000
io.set('log level', 1); // disables debugging. this is optional. you may remove it if desired.
...

下一步是启动 Socket.IO。

io.sockets.on('connection', function (socket) {
    // If socket.io receives message from the client browser then 
    // this call back will be executed.
    socket.on('message', function (msg) {
        console.log(msg);
    });
    // If a web browser disconnects from Socket.IO then this callback is called.
    socket.on('disconnect', function () {
        console.log('disconnected');
    });
});

最后一步是允许服务器端 Socket.IO 在有新的传感器数据时向所有正在监听的客户端发出消息。为此,请将以下行插入到 `sp.on('data')` 中。

...
io.sockets.emit('message', cleanData);
...

更新代码后,`sp.on('data')` 将如下所示:

...
var cleanData = ''; // this stores the clean data
var readData = '';  // this stores the buffer
sp.on('data', function (data) { // call back when data is received
    readData += data.toString(); // append data to buffer
    // if the letters 'A' and 'B' are found on the buffer then isolate what's in the middle
    // as clean data. Then clear the buffer. 
    if (readData.indexOf('B') >= 0 && readData.indexOf('A') >= 0) {
        cleanData = readData.substring(readData.indexOf('A') + 1, readData.indexOf('B'));
        readData = '';
        io.sockets.emit('message', cleanData);
    }
});
...

您的整个服务器端源代码 *server.js* 将如下所示:

var SerialPort  = require('serialport2').SerialPort;
var portName = 'COM3';

var io = require('socket.io').listen(8000); // server listens for socket.io communication at port 8000
io.set('log level', 1); // disables debugging. this is optional. you may remove it if desired.

var sp = new SerialPort(); // instantiate the serial port.
sp.open(portName, { // portName is instatiated to be COM3, replace as necessary
   baudRate: 9600, // this is synced to what was set for the Arduino Code
   dataBits: 8, // this is the default for Arduino serial communication
   parity: 'none', // this is the default for Arduino serial communication
   stopBits: 1, // this is the default for Arduino serial communication
   flowControl: false // this is the default for Arduino serial communication
});

io.sockets.on('connection', function (socket) {
    // If socket.io receives message from the client browser then 
    // this call back will be executed.
    socket.on('message', function (msg) {
        console.log(msg);
    });
    // If a web browser disconnects from Socket.IO then this callback is called.
    socket.on('disconnect', function () {
        console.log('disconnected');
    });
});

var cleanData = ''; // this stores the clean data
var readData = '';  // this stores the buffer
sp.on('data', function (data) { // call back when data is received
    readData += data.toString(); // append data to buffer
    // if the letters 'A' and 'B' are found on the buffer then isolate what's in the middle
    // as clean data. Then clear the buffer. 
    if (readData.indexOf('B') >= 0 && readData.indexOf('A') >= 0) {
        cleanData = readData.substring(readData.indexOf('A') + 1, readData.indexOf('B'));
        readData = '';
        io.sockets.emit('message', cleanData);
    }
});

准备客户端

这就是我们希望客户端看起来的样子:

进度条由 jQuery 提供支持。图表输出由 Flot 提供支持。值、进度条和图表会像此视频中所示那样实时更新。

为了使此功能正常工作,您的工作目录中必须包含 jQuery 库和适当的 jQuery UI 库。此外,还需要 Flot 库来使图表正常工作。

有关 index.html 的确切代码,请参阅源代码部分。

最后一步

使用 USB 将 Arduino 连接到 PC,并确定它被分配到的正确端口。您通常可以通过使用 Arduino 编程器软件并检查可用端口来轻松做到这一点。对于 Windows,它通常高于 COM 端口 1。

设置 Apache 配置,使其指向您的工作目录,并让它为客户端提供 *index.html*。

在命令提示符下进入您的工作目录,您可以执行以下命令来运行 *server.js*:

node server.js 

然后您可以旋转电位器,看到电位器值、条形图和折线图实时响应变化。

最新更新

NodeJS SerialPort2 目前似乎已合并到原始的 SerialPort 项目中。您可以在此处查看项目,并在此处阅读这些优秀模块的作者的消息。

关注点

当然,如果您想要一个更简单的解决方案,可以购买以太网盾或 ZigBee 盾,以实现更复杂的实现。

历史

  • 2012 年 8 月 19 日 上午 1:03 PHT - 已编辑链接并添加了一些信息。
  • 2012 年 5 月 22 日 上午 7:02 PHT - 已提交发布。
© . All rights reserved.