LinkIt ONE 板的探索之旅

在本文中,将分享使用LinkIt ONE板作为远程传感器设备的经历。在此之前,强烈建议先阅读之前的文章,因为本文的许多内容都基于之前讨论过的概念。

项目源代码

本项目的源代码托管在GitHub上的仓库中。

LinkIt ONE 板印象

作为一个不喜欢C/C++语言,并且没有相关经验的人,更喜欢快速应用开发环境。即使是基于.NET Micro Framework的Netduino,也依赖于Visual Studio这样的优秀IDE。.NET库和出色的调试器使得Netduino板成为使用过的最好的开发板。

每次面对C/C++程序,都会感到沮丧。对于这个项目,不得不将原始的Netduino C#源代码“翻译”成Arduino/C/C++的“工作”草图。之所以称之为“工作”,是因为目标只是让板子工作,而不是编写一个体面的程序。

为什么“沮丧”?因为认为在超冗长的C/C++项目上浪费时间是没有意义的,还不如简单地编写像C#或Java这样的高级语言。LinkIt ONE板甚至比Netduino Plus 2更快,资源也更丰富。它不仅仅是一个8位AVR。

那么,为什么LinkIt ONE板应该是“了不起”的呢?首先,是因为硬件。对于业余爱好者来说,这块板子是一个小杰作,因为它功能齐全,而且价格也相当合理。

其次,认为Arduino API的方法简化了像这样懒惰的程序员的工作。坦率地说,API覆盖了板子的许多特性,但希望能有更好的覆盖。印象是,它更像是一个薄薄的层,包裹着板子上运行的操作系统。这很遗憾,因为用户可能很早就会感受到一些限制。

一个明显的例子是HTTP支持,这是不存在的。一个明确声称是“用于原型设计可穿戴设备和物联网设备”的板子,至少应该提供典型的物联网项目使用的最常见服务。

个人发现,在互联网上寻找关于非常基本服务的开源项目,如JSON操作、HTTP客户端等,是令人烦恼的。幸运的是,Arduino世界仍然很大,有很多用户贡献他们自己的作品。

软件

正如前面提到的,除了JSON和HTTP库之外,几乎所有的东西都是从原始的C#源代码中“克隆”出来的。这是因为中的许多人,也许是C/C++技能娴熟的人,看到是如何编写移植源代码的,可能会微笑(大笑)。

JSON库来自Benoît Blanchon,他做得非常出色。在看来,这个库写得很好,但应该记住,Benoît的目标是“真正的”Arduino,资源非常有限(以及语言特性)。

也就是说,LinkIt板是一个32位ARM核心,因此内存使用量远远高于库中描述的。此外,Arduino默认平台没有“new”和“delete”,而JSON库添加了它自己的“new”运算符重载。然而,这将与LinkIt SDK发生冲突,SDK是一个C/C++特性平台,这样的运算符是完全支持的。

顺便说一下,这块板子有4MB的RAM。分配一些KB的缓存远不是问题!对于HTTP客户端,选择了这个库。这是一个极简的HTTP组合器和解析器,但对于任何业余项目所需的都足够了。它还带有基本认证。

与Netduino项目的其他差异

首先,TCP连接是通过Wi-Fi建立的,因为LinkIt ONE没有以太网插口。然而,这是一个非常简单的任务,因为API/样本非常清楚地说明了如何设置无线连接。

另一个区别是GPS传感器监控,在Netduino中是缺失的,但在标准的LinkIt ONE包中是包含的。尽管主要出于好玩而使用它,但相信如果需要跟踪设备的移动位置,它会是有用的。

再次,设置起来非常简单。

草图初始化

/* * 硬件输入端口定义 **/ InputPortWrapper* _switch0; InputPortWrapper* _switch1; AnalogInputWrapper* _analog0; AnalogInputWrapper* _analog1; IInput* _inputPorts[16]; int _portCount; #define LED 13 #define WIFINAME "(your wi-fi name)" #define WIFIPWD "(your wi-fi password)" int _wifiStatus; MobileServiceClient* _ms; gpsSentenceInfoStruct _gpsinfo; void setup() { /* * 硬件输入端口定义 **/ _switch0 = new InputPortWrapper("Switch0", 0); _switch1 = new InputPortWrapper("Switch1", 1); _analog0 = new AnalogInputWrapper("Analog0", 0, 100.0, 0.0); _analog1 = new AnalogInputWrapper("Analog1", 1, 100.0, 0.0); _inputPorts[0] = _switch0; _inputPorts[1] = _switch1; _inputPorts[2] = new RampGenerator("Ramp20min", 1200, 100, 0); _inputPorts[3] = new RampGenerator("Ramp30min", 1800, 150, 50); _inputPorts[4] = _analog0; _inputPorts[5] = _analog1; _portCount = 6; pinMode(LED, OUTPUT); LGPS.powerOn(); LWiFi.begin(); _wifiStatus = LWiFi.connectWPA(WIFINAME, WIFIPWD); _ms = new MobileServiceClient("(your service name).azure-mobile.net", "(your application-id)", "(your master key)"); }

“loop”部分

void loop() { if (_wifiStatus >= 0) { bool hasChanged = false; for (int i = 0; i < _portCount; i++) { if (_inputPorts[i]->sample()) { hasChanged = true; } } if (hasChanged) { StaticJsonBuffer<4096> jsonBuffer; LGPS.getData(&_gpsinfo); JsonObject& jobj = jsonBuffer.createObject(); jobj["devId"] = "01234567"; jobj["ver"] = 987654321; jobj["pos"] = (char*)_gpsinfo.GPGGA; JsonArray& jdata = jobj.createNestedArray("data"); for (int i = 0; i < _portCount; i++) { IInput* port; if ((port = _inputPorts[i])->getHasChanged()) { port->serialize(&jdata); } } _ms->apiOperation("myapi", REST_Create, &jobj); } digitalWrite(LED, digitalRead(LED) == 0); delay(1000); } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485