第三阶段:带 Arduino 和 ThingSpeak 的实时气象站






4.97/5 (18投票s)
本文是为初学者准备的教程,介绍如何使用 ThingSpeak 服务,在没有以太网/WiFi 模块的情况下,为 Arduino 开发物联网框架,并搭建一个实时在线天气站。
目录
5. 使用 Arduino 数据更新 ThingSpeak 频道
- 下载 WeatherStationArduinoSketch.zip - 882 B
- 下载 ArduinoThingSpeakIntegration-noexe.zip - 247.7 KB
- 下载 ArduinoThingSpeakIntegration.zip - 247.7 KB
1. 背景
图 1.1:使用 ThingSpeak 的物联网框架架构
ThingSpeak 是一家物联网云服务提供商。Arduino、Raspberry Pi 等嵌入式物联网设备可以连接到互联网。然后,这些板卡可以使用 API 从 ThingSpeak 存储中获取或上传数据。设备存储的数据可以通过其他客户端实体(如连接到互联网的手机、平板电脑、笔记本电脑)使用 ThingSpeak API 访问。简而言之,ThingSpeak 是一家物联网服务提供商,它提供 API 以通过云上传、检索和可视化物联网设备的数据。
了解了 ThingSpeak 是什么之后,让我们更详细地了解一下。基本上,当 Arduino Yun、Intel Edison、Intel Galileo、Raspberry Pi 等设备连接到互联网时,它们可以访问互联网上的其他节点(如 Google、Facebook 或任何其他网站)。但要将这些设备专门用作其他互联网客户端可以从中获取数据的 Master 或服务器,则需要大量的网络设置,包括为节点分配唯一的 IP 地址、设置服务器等。解决此问题的简单替代方法是部署一个可以处理通信的中间件。它充当设备之间的全局消息空间。设备从服务器接收命令,将数据发送到服务器。像移动设备这样的其他节点可以从服务器获取设备的数据。因此,它不需要任何专用的网络协议。
这时,物联网服务提供商就派上用场了。它们为设备提供了简单而安全的 API,以便访问云中的数据。ThingSpeak 是一个很棒的物联网解决方案,它不仅提供了简单的基于时间戳的云端数据访问机制,同时还集成了社交网络服务。因此,基于某个事件(如燃气泄漏、洪水、过温或计时器事件)生成社交通知(如更新 Facebook 状态消息、发送电子邮件、发布推文)变得更加容易。
图 1.2 ThingSpeak 的简单服务架构
图 1.2 是 ThingSpeak 服务的简单示意图,如图 1.1 所示。简单来说,连接到互联网的设备可以使用 ThingSpeak 服务将数据上传到 Web 数据库。其他客户端可以通过 ThingSpeak 服务获取数据。
除了数据存储和获取服务外,ThingSpeak 还提供了“服务连接”接口,可以轻松地让 Arduino 设备在其 Sketch 中访问服务,而无需使用任何高级客户端。
现在的问题是,这些数据是如何提供的?ThingSpeak 允许用户创建自己的 **频道**。用户可以选择将频道设置为公开或私有。简单来说,您可以将频道视为一个数据库表。每个频道最多可以有 8 个属性,可以将其视为数据库字段。每个频道都提供一组 API:用于读取数据和写入数据。公开频道的数据可以被所有其他用户读取,无需任何密钥,但要写入数据,您需要一个特定于该频道的 API 密钥。
因此,数据可以安全地从一个节点存储,并可以被多个其他节点使用。ThingSpeak 还提供数据可视化服务,可以轻松地将数据以图表和图形的形式可视化。ThingSpeak 服务还扩展到分析服务,提供对数据的统计操作。
有许多公开频道允许您从手机实时获取数据。因此,您可以创建访问这些公开频道的移动应用程序。有关一些公开频道,请参阅下图 1.3。
图 1.3:ThingSpeak 的一些特色公开频道
因此,任何人都可以使用频道并使用 JSON 获取数据。开发人员现在可以开发用于实时天气监测、灾害管理、地震警报系统等的应用程序。
那么,本教程是关于什么的?请查看图 1.1。您可以看到“硬件”接口,它是设备连接到 ThingSpeak 云的互联网网关。ThingSpeak 还为 Arduino 提供连接服务,可以直接从其 Sketch 使用 ThingSpeak API。然而,仍然有许多优秀的微控制器,包括没有以太网 Shield 的 Arduino 板以及非 Yun 型号,无法直接连接到云。但是,大多数现代微控制器设备可以通过串行接口与 PC/Laptop 通信。因此,通过在串行通信客户端中开发一个可以接口这些设备的框架,我们可以将 ThingSpeak 提供的物联网云服务通过 API 扩展到所有这些基本设备。
本文的目的是帮助您开发自己的 ThingSpeak C# 客户端,该客户端将通过串行通信将 ThingSpeak 服务绑定到您的 Arduino 板。本教程还将抽象出硬件通信逻辑与云服务。
更棒的是什么?与我们之前的教程不同,我们将在这里做一些实际的事情。我们将构建一个 ThingSpeak 频道,该频道提供温度和光强度值。我们将传感器连接到 Arduino,开发代码以定期获取传感器值,通过串行通信将传感器值发送到我们的 C# 客户端。我们将创建一个 ThingSpeak 频道来存储这些值。我们将 C# 客户端与 ThingSpeak 集成,使其能够将获取的传感器数据传输到 ThingSpeak 云。我们还将设计一个 Android 客户端,使用户能够通过手机可视化数据。
2. 硬件设置
我们还需要一些基本硬件。我选择一些基本传感器来做这个教程的原因是,不仅要演示 ThingSpeak 集成,同时我也想演示它的实际应用。因此,我选择了光和温度传感器,因为它们用途广泛,价格便宜,易于连接和编码。
表 1 列出了本教程所需的组件。
零件 |
规格 |
图片 |
预估单价 |
数量 |
---|---|---|---|---|
Arduino Duemilanove |
|
|
$12 |
1 |
温度传感器 |
LM35 |
|
$1.5 |
1 |
LDR 传感器 |
|
|
$4 |
1 |
电阻器 |
470 欧姆 |
|
$.01 |
1 |
|
4.7k 欧姆 |
|
$.01 |
1 |
连接线 |
|
|
$0.02 |
6 |
表 1:本教程所需的零件清单
我们的目标是测量温度和光强度值,并通过 Thingspeak 不断更新它们,以便任何其他应用程序都可以在互联网上获取这些信息。
2.1 LM 35 与 Arduino 的配置
我们将从配置我们的硬件并进行测试开始。然后,我们将它集成到物联网中。
我们将从温度传感器 LM 35 开始。这可能是最便宜、最有效的传感器之一,适合开始您的 Arduino DIY 项目。它是一个三引脚传感器,工作电压在 0-5V 范围内,用于测量 0-92'c 的温度。
如果您是硬件初学者,刚刚开始学习硬件,那么在操作组件之前研究其数据手册总是一个好主意。它为您提供了操作这些设备所需的电气和逻辑理解。
LM35 有三个引脚,分别连接到 Arduino 的接地、Vcc 和模拟引脚。您可以直接从 Arduino 的 5V 引脚为其供电,并将输出引脚连接到任何模拟引脚。我将其连接到了引脚 5。请参见图 2.1 了解电路。
图 2.1:LM 35 连接 Arduino
您可能想知道如何连接这三个引脚到 Arduino。许多教程会建议您使用面包板。所以您可以使用面包板或三引脚连接器。我更喜欢如图 2.2 所示的短三引脚连接器。将 LM35 引脚插入连接器的三个插槽,并将导线插入相应的 Arduino 插槽。
图 2.2:使用 3 引脚连接器将 LM 35 连接到 Arduino
现在,在我们编写 LM 35 的代码之前,了解一些概念很重要。
LM35 将温度转换为 1V 的电压范围。这意味着当温度约为 90'c 时,LM35 的输出电压约为 1V。那么 Arduino 如何读取这个温度呢?
正如您所注意到的,LM35 的输出电压连接到 Arduino 的模拟引脚 5,Arduino 将读取模拟电压,该电压将通过内部 10 位 ADC 转换为数字值。10 位 ADC 意味着当电压为 5 伏时,Arduino 读取 1024 (2^10)。但由于 LM35 的输出永远不会超过 1V,所以丢失了 4Vs 或约 10% 的精度。这可以通过简单地将参考电压从 5V 更改为 1.1V 来克服。这可以使用以下简单代码实现。
analogReference(INTERNAL);
但是,如果您使用 1.1V 作为参考电压,则方程将完全改变。如果您将 1.1V 除以 1024,模拟读数每增加一步,电压变化约为 0.001074V = 1.0742 mV。如果 10mV 等于 1 摄氏度,则 10 / 1.0742 = ~9.31。因此,每改变 9.31 的模拟读数,温度变化就为一摄氏度。
因此,
温度值 = Value_Read_By_Pin_5/9.31,参考电压为 1.1V。让我们编写一个简单的程序,每秒探测一次温度。
现在我们将使用 ArdOS 来构建我们简单的 Arduino Sketch,以便每秒读取一次温度。在这里,我使用了我们服务教程中的 Arduino 代码,并修改了 task1,使其能够读取模拟电压、计算温度并将其打印到串行端口。
#include <kernel.h>
#include <queue.h>
#include <sema.h>
#define NUM_TASKS 2
void taskSerialRead(void *p)
{
int n2=0;
while(1)
{
if(Serial.available())
{
n2=Serial.read() ;
////////////// Switching Logic///////////
if(n2>0)
{
if(n2==1)
{
digitalWrite(13,HIGH);
}
if(n2==2)
{
digitalWrite(13,LOW);
}
/////////////////////////
/*
/////////// Uncomment following lines while testing Serial Data
Serial.print(" DATA RECEIVED AS SERIAL INPUT COMMAND IS :");
Serial.println(n2);
*/
}
OSSleep(100);
}
}
}
void taskTemperature(void * p)
{
int n1=0;
float tempC;
while(1)
{
n1=analogRead(5);
tempC= (float)n1 / 9.31;
Serial.println(tempC);
OSSleep(1000);
}
}
void setup()
{
OSInit(NUM_TASKS);
// Print a message to the LCD.
analogReference(INTERNAL);
Serial.begin(19200);
pinMode(13, OUTPUT);
digitalWrite(13,LOW);
OSCreateTask(0, taskSerialRead, NULL);
OSCreateTask(1, taskTemperature, NULL);
OSRun();
}
void loop()
{
// Empty
}
所以,taskTemperature
是我们读取和打印温度的方法。
以下是读取温度的截图!
图 2.3:Arduino 温度传感器输出
当我在传感器附近点燃一根熏香时,您可以看到温度升高。
2.2 LDR 与 Arduino 的配置
LDR 代表光敏电阻。当 LDR 表面上的光线增加时,其电阻会增加,从而导致其两端的电压降低。当光线减少时,电阻也会减小,导致其两端的输出电压升高。因此,如果我们作为电压分压电路中的一个电阻来连接 LDR,那么分压器的电压将随着光照强度的变化而变化。图 2.4 显示了 LDR 与 Arduino 的连接以及分压电路的原理。
2.4:LDR 连接 Arduino 并解释分压原理。
由于 R2=1K/4.7k 是常数,如果 R1 减小(即光照强度低),Vout 将减小;如果 R1 增大(即光照强度高),Vout 将增大。
因此,Arduino 中的逻辑应遵循模拟引脚值与光强度值成正比的原理。我们可以将光强度表示为最大强度的百分比,如下所示:
光强度百分比 = (模拟值)*100/1024
让我们创建一个任务来测试以百分比形式通过 LDR 电路检测光强度变化。
void taskLight(void * p)
{
int n2=0;
float lightPc;
while(1)
{
n2=analogRead(4);
lightPc= (float)(n2)*100 / 1024.0;
Serial.println(lightPc);
OSSleep(1000);
}
}
准备好任务后,让我们使用此任务来检查光强度变化。下图 2.5 显示了光强度变化时的串行端口读数。
图 2.5:使用 LDR 检测光强度变化
现在观察,温度和光强度值都在同一范围内(0-100)。因此,当设备返回的传感器结果超过一个时,任何其他客户端应用程序都无法知道它从哪个传感器获取结果。
因此,我们将使用某些标记来让客户端应用程序知道哪个值属于哪个传感器。因此,我们将使用 sprintf 将两个值写入字符串,格式为 **"T=25,L=61"**。ArdOS 的主要问题之一是,当您尝试从多个任务使用 Serial.println() 时,事情会变得非常棘手,需要非常精确地计算时间。因此,我们将把从单个函数读取温度和光强度结合起来,将两个值写入一个字符串并打印该字符串。这是我们的 taskTemperatureLight
组合方法。
void taskTemperatureLight(void * p)
{
int n1=0;
float tempC;
char s[32];
int n2=0;
float lightPc;
char s1[16];
while(1)
{
n1=analogRead(5);
n2=analogRead(4);
tempC= (float)n1 / 9.31;
lightPc= (float)(n2)*100 / 1024.0;
// dtostrf(tempC,5,2,s);
sprintf(s,"T=%02d,L=%02d\0",(int)tempC,(int)lightPc);
Serial.println(s);
OSSleep(1000);
}
}
现在,当您测试您的应用程序时,您将看到类似图 2.6 的结果。
图 2.6:监控和打印 LDR 和 LM 35 的组合任务结果
硬件准备就绪,我们现在可以开始使用 ThingSpeak 了。
3. ThingSpeak 入门
3.1 创建频道
本教程的主要重点是展示如何将 ThingSpeak 与我们的硬件结合使用,为我们的设备提供与互联网的无缝连接。因此,让我们开始在 ThingSpeak.com 上创建一个帐户。
成功创建帐户后,单击“Channels”并选择“My Channels”,如图 3.1 所示。
图 3.1:开始创建 ThingSpeak 频道
如上所述,ThingSpeak 频道就像一个数据库字段,它附带自定义 API,可用于远程存储和检索数据。那些对定义有具体要求的人
引用频道是您发送数据存储的地方。每个频道包含 8 个用于任何类型数据的字段,3 个位置字段和 1 个状态字段。创建 ThingSpeak 频道后,您将数据发布到该频道,让 ThingSpeak 处理数据,然后让您的应用程序检索数据。
进入频道创建页面后,为频道命名。尽量为您的频道指定一个有意义的名称。因为这将是公开的,其他人可以自由使用它(除非您希望将频道保持为私有)。一个好的有意义的名称会吸引更多开发人员使用您的频道。
图 3.2:在 ThingSpeak 中创建新频道
创建频道时,您会在底部看到八个字段。您可以输入任意数量的字段。由于我们有两个记录,即温度和光强度,因此我们使用了两个字段。指定位置字段(纬度和经度)是可选的。但最好还是指定它们。如果您不知道您所在区域的纬度和经度,您可以随时寻求 Google 地图或 Bing 地图的帮助。
另外,请确保选中“Make Public?”复选框,这将使该频道对所有人开放。
Description 字段用于向可能正在寻找使用您的频道的公众提供描述。Metadata 有助于轻松识别您的频道并帮助其正确分类。完成表单后,单击“Save channel”保存信息并创建频道。
频道创建后,您将在频道列表中看到该频道,并附有频道编号以及频道提供的所有数据,如图 3.3 所示。
图 3.3:ThingSpeak 频道创建成功
3.2 频道中的数据读写操作
现在转到“Data Import/Export”(数据导入/导出)选项卡。您将看到两个选项:Sending data(发送数据)和 Viewing data(查看数据)。在“Sending data”选项中,指定了一个 URL 示例 field1。您可以使用以下模式形成您的 URL。
http://api.thingspeak.com/update?key=C606GJW98AWMN9P9&field1=10&field2=20
如果您的应用程序有多个字段,您可以通过简单地使用字段编号(如 field1,field2,field3,field4 等)与 URL 以“&”连接来添加更多字段。
key=C606GJW98AWMN9P9 应替换为您自己的 API 密钥。由于我创建的 ThingSpeak 频道是公开的,您可以直接使用我的频道来开始您的 ThingSpeak 教程。
因此,我们可以通过更改 URL 中的参数来更新数据。
为了测试数据,复制“Viewing Data”URL 到浏览器地址栏并按 Enter。它将以 JSON 对象形式返回结果。
对于 GulbargaWeather,Read URL 是
http://api.thingspeak.com/channels/18828/feed.json?key=C606GJW98AWMN9P9
图 3.4:ThingSpeak 频道数据查看结果
但最棒的是,ThingSpeak 为普通大众提供了现成的数据查看 URL。因此,一旦您的频道创建并公开,任何人都可以通过在 ThingSpeak 频道中使用您的频道编号来查看数据,如下所示。
https://thingspeak.com/channels/18828
图 3.5 显示了频道的公开视图截图。
图 3.6:GulbargaWeather 频道的公开视图
这不是很棒吗?所以,您无需太多软件基础设施,只需通过 ThingSpeak 服务将您的嵌入式设备连接到云,就可以创建一个全球天气站、地震监测系统或污染跟踪系统。
ThingSpeak 为 Arduino Yun 及以上型号提供了现成的 API。这些设备可以直接连接到互联网。我使用的是 Arduino Duemilanove,它既没有以太网也没有 WiFi 模块。因此,我需要通过 **串行通信 C# 客户端(如本教程中所述)** 将设备连接到互联网。
因此,我们的下一个任务是通过 C# 客户端将 ThingSpeak 服务集成到我们的客户端中,通过该客户端我们的设备将更新频道数据。
4. 使用 C# 配置 ThingSpeak
4.1 更新数据
调用特定频道的 ThingSpeak 更新方法的逻辑非常简单。每个频道都有独立的更新方法 API 密钥。我们只需要从我们的程序中构造一个以下格式的 URL:
http://api.thingspeak.com/update?
现在,附加 **key=YOUR_KEY_VALUE&field1=FIELD1_VALUE&FIELD2_VALUE**
一旦 URL 准备就绪,我们就可以使用 HttpWebRequest
请求该 URL 并使用 HttpWebResponse
获取结果。
为了使方法可重用且更通用,我创建了一个名为 UpdateThingSpeakData
的方法,该方法接受字符串数组作为参数和 API 密钥,并返回字符串形式的结果。
这是我们的 UpdateThingSpeakData
方法。
string UpdateThingSpeakData( string []fields,string APIKey)
{
string url = "http://api.thingspeak.com/";
StringBuilder sb = new StringBuilder();
if (fields.Length > 8)
{
throw (new Exception("Can't Handle More than 8 Parameters"));
}
sb.Append(url + "update?key=" + APIKey);
for (int i = 0; i < fields.Length; i++)
{
sb.Append("&field"+(i+1)+"=" + HttpUtility.UrlEncode(fields[i]));
}
string QueryString = sb.ToString();
StringBuilder sbResponse = new StringBuilder();
byte[] buf = new byte[8192];
// Hit the URL with the querystring and put the response in webResponse
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(QueryString);
HttpWebResponse webResponse = (HttpWebResponse)myRequest.GetResponse();
try
{
Stream myResponse = webResponse.GetResponseStream();
int count = 0;
// Read the response buffer and return
do
{
count = myResponse.Read(buf, 0, buf.Length);
if (count != 0)
{
sbResponse.Append(Encoding.ASCII.GetString(buf, 0, count));
}
}
while (count > 0);
return sbResponse.ToString();
}
catch (WebException ex)
{
return "0";
}
}
这里您必须记住,HttpUtility
使用 **System.Web.dll**,而 .Net framework Client profile 中没有该库。因此,请确保从项目属性中选择了完整框架。然后添加 System.Web 引用。
测试该方法很容易。我添加了一个按钮单击事件来查看它是否有效!
try
{
//string s = UpdateThingSpeakData(new string[] { "40", "40" }, "C606GJW98AWMN9P9");
string s = UpdateThingSpeakData(new string[] { "40", "40}, "C606GJW98AWMN9P9");
}
catch
{
}
如图 4.1 所示,它确实有效。
图 4.1:从 C# 串行客户端成功更新
4.2 检索数据
尽管我们开发的这个特定应用程序在从 ThingSpeak 读取数据方面意义不大,但我还是想涵盖这一部分,以使其成为一个完整的软件包。
看看图 4.1。您绝对会明白,查询读取频道数据后的响应是 JSON 响应。因此,我们的 C# 代码必须能够处理 JSON 响应并反序列化结果,对吧?
JSON 反序列化需要一个类来表示 JSON 的数据定义。那么,如何通过查看 JSON 对象来构建相关的 C# 类呢?
幸运的是,有一个非常棒的在线工具叫做 json2csharp。
http://json2csharp.com/
您所要做的就是从浏览器复制(在这种情况下,我们的 URL 是:http://api.thingspeak.com/channels/18828/feed.json?key=C606GJW98AWMN9P9)JSON 响应或 URL 并粘贴到文本框中,然后单击“**Generate**”(生成)按钮。搞定!您已经获得了 C# 类。您只需要使用这个类进行 JSON 反序列化。请参阅图 4.2 中的 Json2Csharp 工具。
图 4.2:用于获取特定于 JSON 响应的类的 Json2Csharp 工具
我们获取响应的方法如下。
public static ThingSpeak.ChannelData.RootObject FetchThingSpeakData(string ChannelNo, string APIKey)
{
string url = "http://api.thingspeak.com/channels/";
StringBuilder sb = new StringBuilder();
sb.Append(url + ChannelNo + "/feed.json?key=" + APIKey);
string requestUrl = sb.ToString();
try
{
HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.StatusDescription));
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(ThingSpeak.ChannelData.RootObject));
object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
ThingSpeak.ChannelData.RootObject jsonResponse = objResponse as ThingSpeak.ChannelData.RootObject;
return jsonResponse;
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
该方法返回 RootObject
,其中包含频道信息和 feed。Feed 就是数据。ThingSpeak 的优点在于,它最多只能有八个字段,并且频道元数据对所有频道都是相同的。因此,如图 4.2 所示,可以更新 Feed
类以匹配实际字段的数量,从而反序列化任何 JSON 对象。
您可以通过将频道 ID 和 APIKey 字符串传递给方法来测试该方法,如下所示。
var Response = ThingSpeak.Services.Utility.FetchThingSpeakData("18828", "C606GJW98AWMN9P9");
Response
显然是 RootObject
类型。
图 4.3:ThingSpeak 响应测试结果
总而言之,我在表单中做了一个小区域,您可以在其中测试发布和获取 ThingSpeak 数据。
图 4.4:在串行客户端中测试 ThingSpeak C# 集成
我需要您注意的一点是,ThingSpeak 的 API 非常棒。因此,当您尝试更新相同的数据时,它不允许您进行更新,响应是“0”。
5. 使用 Arduino 数据更新 ThingSpeak 频道
请记住,我们每秒从 Arduino 通过串行端口获取数据。这些数据将以“T=20,L=30”的格式提供。我们需要从这些信息中分别提取温度和光强度值,然后创建并以大约每 30 秒的间隔发送一个聚合结果。最好将传感器数据累积和聚合一段时间,因为温度和光强度等实际参数的变化会非常缓慢。
为了从串行数据中提取温度和强度并将其存储在列表中,我们更新显示方法如下。
List<int> tempList = new List<int>();
List<int> lightList = new List<int>();
void Display(string s)
{
listBox1.Items.Add(s);
this.Text = s;
try
{
//////// Put Acquired Data in List////////
string[] parts = s.Split(new char[]{':',',','=','\r'});
int temp = int.Parse(parts[1]);
int light = int.Parse(parts[3]);
tempList.Add(temp);
lightList.Add(light);
/////////////////////////
}
catch
{
}
}
我们使用间隔为 30 秒的计时器。每三十秒,我们将 tempList
和 lightList
(分别是温度和光强度值)中的数据进行聚合。然后使用我们在第 4 节中开发的 Update 方法将平均值发送到 ThingSpeak 频道。
private void timThingSpeakUpdate_Tick(object sender, EventArgs e)
{
timThingSpeakUpdate.Enabled = false;
try
{
double light = Mean(lightList);
double temp = Mean(tempList);
tempList.Clear();
lightList.Clear();
ThingsSpeak.Services.Utility.UpdateThingsSpeakData(new string[] { string.Format("{0:00.0}", temp), string.Format("{0:0.0}", light) }, "C606GJW98AWMN9P9");
}
catch
{
}
timThingSpeakUpdate.Enabled = true;
}
请注意,平均值是使用简单的 Mean 方法计算的双精度数据类型。为了将小数精度保留到小数点后一位,我使用了 String.Format 将聚合的温度和光强度格式化为一位小数。数据更新后,它会清除列表。请参见图 5,这是系统的最终输出。
图 5:通过 Arduino 和 ThingsSpeak 更新天气信息
右下角窗口显示了电路板的数据采集情况。其上方的窗口是正在聚合和更新数据的串行客户端。左侧两个图表是通过其网站实时观察的 ThingSpeak 频道。
6. 结论
ThingSpeak 通过其物联网云服务为嵌入式平台带来了巨大的价值。能够更新真实数据并拥有现成的客户端以实时查看数据,使得该平台极具吸引力。另一方面,Arduino 无疑是硬件原型开发中最受欢迎的选择之一。随着越来越多的应用程序与云集成,并且物联网呈现出明确的新趋势,这两种技术结合在一起提供了巨大的可能性。在本教程中,我试图展示一种使用串行客户端将 Arduino 与 ThingSpeak 服务连接的一种技术,因为这种架构可以很好地抽象底层的硬件平台,并可用于其他可以通过串行端口通信的嵌入式设备和平台。希望您喜欢本教程,就像我写的时候一样享受。