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

[OoB] 使用 Arduino、C#、JavaScript 和 HTML5 构建声纳

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (18投票s)

2014 年 9 月 19 日

CPOL

6分钟阅读

viewsIcon

62623

这篇博文标志着“无聊时做的”系列的第一篇。它将围绕使用我最近购买的 Arduino Uno 制作东西展开。让我们暂时放下职业编程的繁杂,纯粹为了好玩而创造一些东西 :) 我的第一个基于 Arduino 的项目是声纳。它利用超声波测距传感器

这篇博文标志着“无聊时做的”系列的第一篇。它将围绕使用我最近购买的 **Arduino Uno** 制作东西展开。让我们暂时放下职业编程的繁杂,纯粹为了 **好玩** 而创造一些东西 :)

我的第一个基于 Arduino 的项目是 **声纳**。它利用超声波测距传感器、舵机、SignalR 和 canvas 来创建声纳图像

Sonar at work... Click to enlarge...

我将把描述分为两篇文章。第一篇将侧重于硬件组件和 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…

此图显示了硬件组件应如何连接

Fritzing breadboard diagram

以下是 **应上传到 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 编程有所了解,并且诸如 constpinModedelaysetuploop 等内容无需解释…

首先吸引您注意的几行是

#include <NewPing.h>
#include <Servo.h>  

NewPing sonar(triggerPin, echoPin, maxDistanceInCm); 
Servo servo;

以上几行允许我们使用 NewPingServo 类来测量距离和移动传感器。您还会注意到 setup 函数中有以下几行

servo.attach(servoPin);   
servo.write(angle);

这些用于设置用于控制舵机的引脚,并将舵机移动到 0 度的初始位置。

这一行

Serial.begin(9600);

使 Arduino 能够通过 **串行端口** 与 PC(在我这里是运行 Windows 7 的笔记本电脑)通信。是的,尽管 Arduino Uno 通过 USB 线缆连接到计算机,但它实际上使用 COM 端口进行通信。在我的机器上,它被称为“COM3”(下面显示的屏幕截图来自设备管理器——我的 Windows 是波兰语的)

COM port for Arduino... Click to enlarge...

传递给 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

© . All rights reserved.