[OoB] 使用 Arduino、C#、JavaScript 和 HTML5 构建声纳
这篇博文标志着“无聊时做的”系列的第一篇。它将围绕使用我最近购买的 Arduino Uno 制作东西展开。让我们暂时放下职业编程的繁杂,纯粹为了好玩而创造一些东西 :) 我的第一个基于 Arduino 的项目是声纳。它利用超声波测距传感器
这篇博文标志着“无聊时做的”系列的第一篇。它将围绕使用我最近购买的 **Arduino Uno** 制作东西展开。让我们暂时放下职业编程的繁杂,纯粹为了 **好玩** 而创造一些东西 :)
我的第一个基于 Arduino 的项目是 **声纳**。它利用超声波测距传感器、舵机、SignalR 和 canvas 来创建声纳图像
我将把描述分为两篇文章。第一篇将侧重于硬件组件和 Arduino 草图,第二篇将介绍 **.NET** 和 **JavaScript** 应用程序。 您可以在 这个 **GitHub 仓库** 中找到完整的代码。您也可以 点击此处 观看整个项目工作的 **短视频**。
以下是使用的 **硬件组件**
元素 | 角色 |
Arduino Uno R3 | 处理 HC-SR04,控制舵机以及与 PC 通信 |
HC-SR04 超声波测距模块 | 测量声音从物体反射回来的时间 |
9g Tower Pro 微型舵机 | 移动传感器以获得 180 度视野 |
红色 LED | 指示就绪状态 |
330 欧姆电阻 | 限制流过二极管的电流 |
面包板和几根跳线 | 无需焊接即可连接组件 |
就是这些,仅仅几个便宜的组件!完成这个项目几乎不需要电子技能。但我假设您具备基本的 Arduino 知识,并且对 C# 和 JavaScript 有所了解。
以下是 **软件栈**
元素 | 角色 |
Arduino 草图(固件) | 测量距离,移动舵机,并通过串口将数据发送到 PC |
.NET/C# 4.5 控制台应用程序(使用 SignalR 库) | 使用 SerialPort 类接收来自 Arduino 的数据,并将角度和距离信息广播给客户端 |
使用 JavaScript SignalR 库的 HTML5 页面 | 接收来自服务器的数据,并使用 canvas 元素创建声纳图像 |
上面听起来可能有点不知所措,但我向您保证,代码很短,并不复杂。
基本思路如下:**HC-SR04** 传感器测量超声波信号从障碍物反射回来的时间,这使我们能够计算出到这些障碍物的距离。传感器位置由 **舵机** 控制。关于物体距离和传感器指向方向的信息被发送到运行着带有 **SignalR** 服务器的控制台应用程序的 PC。PC 接收数据并将其发送给能够使用 HTML5 **canvas** 元素以漂亮的可视方式呈现声纳数据的 JavaScript 客户端...
更多细节!
主要组件(当然,除了 Arduino 本身)是 **HC-SR04 超声波测距模块**。该传感器的工作原理是通过发送 40 kHz 的声波信号(高于人类听觉极限)并检测回声。这就是为什么这个项目被称为“声纳”而不是“雷达”——它使用声波(而不是无线电波)来探测物体。该传感器的工作范围为 2cm 至 400cm,精度为几毫米。但请记住,物体的形状和材料可能会影响性能。我在大约 2 米的最大距离进行了测试,对结果很满意。您可以无需任何库即可使用此传感器。这需要执行诸如将 HIGH
值置于 Trig
引脚上 10uS 以发射超声波信号,测量 Echo
引脚上的 HIGH
脉冲持续时间,并根据声音在空气中的速度约为 340m/s 来计算距离……但有更好的方法:您可以使用 **NewPing
** 库(链接)来获取距离。如果您不知道如何在 Arduino 草图中包含新库,请点击此处。
第二个重要组件是 **舵机**。HC-SR04 传感器的测量角度约为 15 度。但如果我们通过将其安装在舵机的臂上来移动它,我们可以轻松获得 180 度的视野。在这篇文章中,我不会深入探讨舵机的工作原理及其控制方法。我计划在另一篇文章中介绍如何使用 Arduino+笔记本电脑射击彩弹枪,届时我将进行描述。目前您需要知道的是,Arduino 自带 **Servo** 库,这使得将舵机移动到所需位置(角度)非常容易……我在本项目中使用了 **9g Tower Pro 微型舵机**。它的动力足以移动传感器,同时可以直接从 Arduino 的 +5V 引脚供电。
最后一个物理组件是用于指示就绪状态(即 setup
函数已完成)的 LED 及其附带的电阻。让二极管发光是电子学中的“Hello World!”等价物,所以我相信您知道如何处理 LED。即使不知道,您也可以始终使用连接到 Arduino Uno 13 号引脚的微型内置 LED…
此图显示了硬件组件应如何连接
以下是 **应上传到 Arduino 的全部代码**:
#include <NewPing.h>
#include <Servo.h>
const byte setupReadyLedPin = 8;
const byte triggerPin = 10;
const byte echoPin = 11;
const byte servoPin = 12;
const byte maxDistanceInCm = 100;
byte angle;
byte angleStep;
byte angleStepDelayInMs = 50;
NewPing sonar(triggerPin, echoPin, maxDistanceInCm);
Servo servo;
void setup() {
pinMode(setupReadyLedPin, OUTPUT);
angle = 0;
angleStep = 1;
servo.attach(servoPin);
servo.write(angle);
Serial.begin(9600); // Open connection with PC
digitalWrite(setupReadyLedPin, HIGH);
}
void loop() {
alterServoMoveDirection();
measureAndSendDistance();
angle += angleStep;
servo.write(angle); // Move servo
delay(angleStepDelayInMs);
}
void alterServoMoveDirection() {
if (angle == 180) {
angleStep = -1;
} else if (angle == 0) {
angleStep = 1;
}
}
void measureAndSendDistance() {
byte distanceInCm = sonar.ping_cm(); // Use ultrasound to measure distance
byte sonarData[] = {255, angle, distanceInCm};
Serial.write(sonarData, 3); // Send data to PC
}
如前所述,我假设您对 Arduino 编程有所了解,并且诸如 const
、pinMode
、delay
、setup
和 loop
等内容无需解释…
首先吸引您注意的几行是
#include <NewPing.h>
#include <Servo.h>
NewPing sonar(triggerPin, echoPin, maxDistanceInCm);
Servo servo;
以上几行允许我们使用 NewPing
和 Servo
类来测量距离和移动传感器。您还会注意到 setup
函数中有以下几行
servo.attach(servoPin);
servo.write(angle);
这些用于设置用于控制舵机的引脚,并将舵机移动到 0 度的初始位置。
这一行
Serial.begin(9600);
使 Arduino 能够通过 **串行端口** 与 PC(在我这里是运行 Windows 7 的笔记本电脑)通信。是的,尽管 Arduino Uno 通过 USB 线缆连接到计算机,但它实际上使用 COM 端口进行通信。在我的机器上,它被称为“COM3”(下面显示的屏幕截图来自设备管理器——我的 Windows 是波兰语的)
传递给 begin 方法的值决定了波特率(通信速度)。在与 Arduino 通信的软件中使用相同的值很重要。
loop
函数移动舵机并调用 measureAndSendDistance
函数,该函数使用 NewPing
计算距离,并使用 Serial
将数据发送到 PC。借助 NewPing
库,获取厘米距离就是这么简单
byte distanceInCm = sonar.ping_cm()
如果测量距离超过 NewPing
构造函数的最后一个参数指定的 maximum 值,则返回 0。请查看 NewPing
文档 以了解该库的其他有用函数。
最后,这是 Arduino 将数据发送到 PC 的方式
byte sonarData[] = {255, angle, distanceInCm};
Serial.write(sonarData, 3); // Send data to PC
第一个数组元素(255
)用作标记/分隔符,以便轻松区分 **角度-距离值对**。在第二篇介绍 SignalR 服务器和客户端的文章中,它的作用将变得更加清晰……我假设 maxDistanceInCm
常量永远不会设置为超过 200,因此 distanceInCm
永远不会有值 255。由于我们的舵机在 0..180 度范围内移动,因此 angle
也永远不会发送 255。当然,创建一个常量并避免使用 255 这个“魔数”可能是一个好主意。一些验证也很有用……但算了,这个项目只是为了好玩!:)
好的,您已经读完了关于 Arduino/.NET/JS/HTML 声纳的第一篇博文。第二篇博文应该在一周左右准备好。
更新 2014-09-29:这是第二部分: https://codeproject.org.cn/Articles/823304/OoB-Sonar-with-Arduino-Csharp-JavaScript-and-HTM