使用声纳接近传感器进行原型设计
此示例展示了如何使用连接 Wi-Fi 的 Arduino® 开发板通过 ThingSpeak™ 进行原型设计。
您可以使用 ThingSpeak 通信库读取和写入通道数据。在此示例中,从 ThingSpeak 读取可调阈值来创建接近检测器。硬件包括一个带有声纳传感器的 Arduino MKR100 和一个指示 LED,用于显示物体的存在。
传感器项目原型设计可能需要多次刷新代码以微调校准参数,例如温度传感器的校准参数。硬件调整会增加复杂性,降低可靠性,并且在部署项目时可能难以实现。相反,您可以从 ThingSpeak 读取校准参数并实时更改参数。当您调整存储在 ThingSpeak 上的调整参数时,您可以提高测量的质量。
支持的硬件
Arduino MKR1000
具有无线网络或以太网连接的 Arduino Uno、Mega、Due 或 Leonardo
粒子光子(带有一些代码和原理图调整)
在此示例中,声纳传感器监测订书机并将测量结果发布到您的通道。声纳传感器的工作原理是发送声音脉冲并测量脉冲从物体返回所需的时间。系统使用从 ThingSpeak 读取的距离阈值,并将该阈值与测量的距离进行比较。当订书机存在时,LED 亮起。
完成此示例后,您将在通道中看到接近度数据和设置。ThingSpeak 通道视图显示以下接近数据和设置:
阈值设置为 15 厘米
每个平均值进行十次测量
设置读取标志,强制读取校准参数
数据显示,有人在上午 11 点“借”了订书机,后来又将其放回了新位置
所需硬件
Arduino MKR1000 或其他具有以太网或无线网络连接的 Arduino
HC-SR04 声纳传感器
跳线(至少 4 根)
LED
小电阻(100 Ω – 1 kΩ)
USB 电缆
通道设置
1) 创建一个 ThingSpeak 通道,如在新通道中收集数据所示。将数据存储在第一个字段中,并将设备设置存储在连续的字段中。设备设置包括距离阈值、平均测量次数以及控制设备是否在每个循环上更新设置的标志。
2) 启用 Channel Settings 视图中的字段 1、2、3 和 4。为了区分字段,请为每个字段提供一个描述性名称。该图显示了配置为在第一个字段中收集数据并在字段 2、3 和 4 中存储校准参数的通道。
3) 从 Channel Settings 视图中的 API Keys 选项卡中注意适当的读写 API 密钥(图中圈出部分)。
4) 使用浏览器窗口填充校准字段。您可以从 API Keys 选项卡复制文本,也可以使用您的写入 API 密钥修改此文本。将每个 URL 直接输入到浏览器的地址栏中,将“YOUR WRITE API KEY”更改为您通道的写入 API 密钥。
a.设置检测物体的阈值(50 厘米是一个很好的起点):
https://api.thingspeak.com/update?api_key=YOUR WRITE API KEY&field2=THRESHOLD
b.设置要平均的测量次数:
https://api.thingspeak.com/update?api_key=YOUR WRITE API KEY&field3=NUMTOAVERAGE
c.设置控制标志,以便设备定期检查新设置:
https://api.thingspeak.com/update?api_key=YOUR WRITE API KEY&field4=1
浏览器返回通道中的条目数。如果您刚刚创建了通道,则在填充三个必需的校准字段时,您会看到 1、2 和 3。
原理图和连接
1) 将 VCC 连接到 MKR-1000 上的 5 V。
2) 将传感器地线连接至 Arduino 地线。
3) 将 Trig 引脚连接到 Arduino 引脚 8。
4) 将 Echo 引脚连接到 Arduino 引脚 12。
5) 将电阻连接到 Arduino 引脚 5,然后将电阻连接到指示灯 LED。将 LED 的阳极连接到地面。
编程您的 Arduino
1) 下载最新的 Arduino IDE。
2) 将 Arduino 和 ESP8266 的 ThingSpeak 库添加到库管理器。选择 Sketch
> Include Library
> Manage Libraries
。选择 ThingSpeak
将其添加到您的草图中。
3) 在库管理器中添加 WiFi101
库。注意: 确保安装该库的 0.13 版本。0.14 版本中有一个错误,导致帖子发布失败。选择 Sketch
> Include Library
> Manage Libraries
。选择 WiFi101
将其添加到您的草图中。
4) 创建应用程序。在 Arduino IDE 中打开一个新窗口并保存文件。添加代码部分提供的代码。确保编辑无线网络信息、通道 ID 和 API 密钥。
5) 成功上传程序后,您可以使用串行监视器监视输出。如果物体的距离比设定的阈值更近,那么您的设备会将距离发布到您的通道。尝试对测量次数进行平均,看看测量的波动如何变化。设置参数后,您可以将读取标志的值从 1
更改为 0
。一旦您的设备将此标志读为 0,它就会停止检查 ThingSpeak 的参数,从而节省电量和带宽。
代码
1) 包含库并初始化控制引脚。
#include <ThingSpeak.h> #include<WiFi101.h> #define triggerPin 8 #define echoPin 12 #define LEDpin 6
2) 定义并初始化变量。确保编辑无线网络信息、通道 ID 和 API 密钥。在通道主页顶部找到您的通道 ID。
// Network information const char* ssid = "SSID"; const char* password = "xxxxxxxxxx"; // ThingSpeak information char* writeAPIKey = "XXXXXXXXXXXXXXXX"; char* readAPIKey = "YYYYYYYYYYYYYYYY"; const long channelID = 000000; const unsigned int firstReadFieldNumber = 2; const unsigned int secondReadFieldNumber = 3; const unsigned int switchField = 4; // Field number (1-8) to use to change status of device. Determines if data is read from ThingSpeak. // Other constants const unsigned long postingInterval = 60L * 1000L; // Post data every 60 seconds // Global variables unsigned long lastConnectionTime = 0; long lastUpdateTime = 0; float distanceThreshold = 0; bool getInfo = 1; // Set this to zero if you don’t want to read data from ThingSpeak anymore (i.e. calibration complete) int points = 7; WiFiClient client;
3) 初始化输入和输出引脚,并在 setup
例程中第一次读取校准参数。
void setup() { Serial.begin (9600); pinMode(triggerPin, OUTPUT); pinMode(LEDpin, OUTPUT); pinMode(echoPin, INPUT); connectWifi(); Serial.println("Start"); // Get the initial parameters from ThingSpeak. distanceThreshold = readTSData(channelID,firstReadFieldNumber,readAPIKey); points = readTSData(channelID,secondReadFieldNumber,readAPIKey); }
4) 主循环每次执行时,进行多次测量。如果一段时间内数据还没有写入 ThingSpeak,则将数据写入输出通道。此外,如果读取标志最后一次读取为真,则检查每个周期中的校准数据和标志。
void loop() { float distance=0; // Make sure there is an Internet connection. if(WiFi.status() != WL_CONNECTED){ connectWifi(); } for (uint16_t loops = 0; loops < points; loops++){ distance += getDistance(triggerPin,echoPin); //make a measurement, store the sum of all measurements delay(5); } distance = distance/points; if (distance < distanceThreshold){ digitalWrite(LEDpin,HIGH); } else{ digitalWrite(LEDpin,LOW); } Serial.println("Ave: "+ String(distance)+ " cm"); if (millis() - lastUpdateTime >= postingInterval) { lastUpdateTime = millis(); if (!(getInfo==0)){ distanceThreshold = readTSData(channelID,firstReadFieldNumber,readAPIKey); points = readTSData(channelID,secondReadFieldNumber,readAPIKey); getInfo = (bool)readTSData(channelID,switchField,readAPIKey); } if (distance < distanceThreshold){ // Write data to ThingSpeak channel. writeTSData(channelID, 1, distance, writeAPIKey); } } delay(500); // Provide some delay between measurements. }
5) 使用这些函数从 ThingSpeak 读取和写入数据。
int writeTSData(long TSChannel,unsigned int TSField,float data,char* ReadAPIKey){ int writeSuccess = ThingSpeak.writeField(TSChannel, TSField, data, writeAPIKey); //write the data to the channel return writeSuccess; } // Use this function if you want multiple fields simultaneously. /* int writeTDData(long TSChannel,unsigned int TSField1,float data1,unsigned int TSField2,data2,char* ReadAPIKey){ ThingSpeak.setField(TSField1,data1); ThingSpeak.setField(TSField1,data2); writeSuccess = ThingSpeak.writeFields(TSChannel, writeAPIKey); return writeSuccess; } */ float readTSData(long TSChannel,unsigned int TSField,char* ReadAPIKey){ float data = 0; data = ThingSpeak.readFloatField(TSChannel,TSField,ReadAPIKey); Serial.println(" Data read from ThingSpeak "+String(data)); return data; }
6) 使用 getDistance
从传感器获取单次测量值。
float getDistance(int tPin,int ePin){ long duration, distance; digitalWrite(tPin, LOW); // Reset the trigger pin. delayMicroseconds(2); digitalWrite(tPin, HIGH); // Start a measurement. delayMicroseconds(10); // digitalWrite(tPin, LOW); // Complete the pulse. duration = pulseIn(ePin, HIGH); // Wait for a reflection pulse. distance = (duration/2) / 29.1; // Calculate the appropriate distance using the estimated speed of sound. // This section is useful when debugging the sensor. /* if (distance >= 200 || distance <= 0){ Serial.println("Out of range"); } else { Serial.print(distance); Serial.println(" cm"); } */ return distance; }
7) 使用 connectWiFi
功能将您的设备连接到无线网络。
int connectWifi(){ while (WiFi.status() != WL_CONNECTED) { WiFi.begin(ssid, password); delay(2500); Serial.println("Connecting to WiFi"); } Serial.println("Connected"); ThingSpeak.begin(client); }