如何与JS中的微控制器对话

为什么需要微控制器? 例如,在家中设置一个啤酒厂。 如果您的啤酒厂不够用,那么您可以做更大的事情:建立一个探访室,安排一个演示文稿,一个用滴画图画的交互式喷泉或一家大型公司的展位。 您可以使用微控制器执行任何操作-这完全取决于您的想象力。

有一个误解,要创建自己的压盖,您需要了解汇编程序C / C ++,能够管理内存并深刻理解电。 它曾经是,但是技术正在发展,现在要完全实施其项目,仅JS就足够了!



好的,我们知道JavaScript,但是如何将其连接到硬件? 那里有什么铁,它能做什么? 如何配置整个系统? 在对报告进行解码时, FrontendConf的 Victor Nakoryakova 学习:仅使用JS来控制伺服器,如何将系统与PC物理组合,以及有关JS应用程序的通讯选项。 我们将讨论serialport和Firmata软件包,带有C ++自写固件的serialport,Espruino,以及直接在JS,Raspberry Pi,本地网络上的HTTP和通过云的HTTP和MQTT上对控制器进行编程的方法。



Victor Nakoryakovnailxx )-技术总监,Amperka的共同创始人。 他喜欢先进的开发技术,功能编程和物理计算。 Amperka生产和销售电子模块,因此非专业人士可以用自己的双手,培训工具包和可以添加到其设备中的单个构造块来创建智能设备-电动机,GPS,SMS。

在哪里写JavaScript


Espruino具有带JavaScript的独立微控制器。 Espruino平台允许您直接将JS写入微控制器。 这本身就是一个自治的事物:连接到计算机,闪烁,然后独立工作。

Raspberry Pi是带有GPIO的小型计算机。

在Web应用程序中 ,到前端或后端。

我将以青蛙为例来说明系统的操作。 从手机转到toad.amperka.ru-将出现一个简单的Web界面。



左列控制左眼,右-右。 原理很简单-我按下按钮,伺服电机转眼。



报告期间视频展示的立场与青蛙。

青蛙如何工作


当您打开toad.amperka.ru时,您将获得一个包含使用MQTT.js库的静态JS的静态网页。 该库与云中的MQTT代理联系。



如果您知道Redis,发布/订阅,RabbitMQ或其他消息队列,那么您会立即了解它的含义。 MQTT是机器对机器的消息代理 。 轻巧简单,因此即使是薄弱的腺体也可以使用它。

MQTT需要服务器上的代理。 但是您甚至不必提起它-租用它。 每月只需​​花几美元,您就可以拥有自己的MQTT经纪人。 无需后端。

另一方面,MQTT代理有一个控制器。 有许多不同的设备都具有此角色,例如Wi-Fi Slot 。 这是一个可以连接到Internet的控制器。



它基于流行的ESP8266芯片工作。 增加了通过微型USB供电的能力,并通过三触点连接外围设备以连接到其他设备。

如何用JS编程硬件


没什么特别的,JS常规-几乎是完整的ES6。 用于在低水平上处理电信号的某些功能和对象已添加到标准库中。 例如,用于简单的数字读写的功能。

digitalRead-数字读数 。 对于控制器,这是一个问题:“ 4号插针上有3伏电压吗?” 如果有电压,它将返回TRUE;否则,将返回FALSE。 这实现了简单的二进制传感器的读取:按钮,开关,簧片锁和红外运动传感器。

digitalWrite是一个简单的数字记录 。 我们说digitalWrite TRUE-3V与引脚相连。 我们说的是digitalWrite FALSE-0V。 使用这个简单的原理,您可以点亮/熄灭LED灯带或发射核导弹。 我们向中继传递一个微弱的信号,它将大负载换向,然后火箭飞了起来。

还有一些用于处理介于0至3V之间的中间值的函数:

  • AnalogRead;
  • AnalogWrite;
  • setWatch;
  • digitalPulse。

命令允许您询问各种扭曲并提供模糊记录功能。

接下来是与微控制器世界公认的接口配合使用的对象。 如果在网络上我们理解并熟悉HTTP,WebSocket,TCP,那么对于微控制器,这是:

  • 串口-串口;
  • I2C总线
  • SPI总线
  • OneWire总线。

如何踢伺服电机


例如,我将告诉您如何控制皮下注射的电机。 电机协议很简单。 将0V施加到控制引脚-下限。 每隔20μs必须踢一次,以提供稳定的3V单位,过一会儿-重置为0。



然后,一切再次重复。 根据单元的长度,我们得到不同的转速。 脉冲长度为1,500μs时,电机静止不动。 当朝一个方向或另一个方向偏离时,它会顺时针或逆时针旋转。 偏差的大小会影响旋转速度。

如何编程


在同名的Espruino IDE中完成对Espruino平台的编程。 微控制器板通过微型USB电缆连接到计算机。 唯一的事情是您必须安装驱动程序,这需要1.5分钟。 该驱动程序是为MAC和Windows安装的,在Linux上,一切都可以直接使用。

这是一个只需单击一下即可加载到环境中的程序示例。 它每秒闪烁一次LED:

var on = false; setInterval(function() { on = !on; LED1.write(on); },500); 

在环境的左侧是REPL解释器。 输入“ 1 + 1”。 程序给出答案“ 2”。 奇迹!

奇迹是,当您按下按钮时,数字“ 1”,“ +”号和下一个单元将通过电缆连接到控制器。 当您按ENTER键时,表达式在微控制器而不是计算机内部执行。 微控制器得到结果“ 2”,并通过电缆将其返回给计算机。 显示屏上显示“ 2”。

JavaScript在硬件内部执行。

除了演算娱乐外,您还可以旋转电动机。 您将需要AnalogWrite函数,该函数发送一个方波。 我们说什么叫波。 例如,在我的主板上,它被签名为A7。 然后我们指出持续时间-例如,在20 000μs中的1300μs,我们将服务一个。 还需要一个选项来设置此突跳的频率-每秒50次,即20,000μs。

 >analogWrite(A7, 1300 / 2000, {freq: 50}} =undefined > 

我们将经过1500-我们将强制以更大的速度向另一个方向旋转。

 >analogWrite(A7, 2300 / 2000, {freq: 50}} =undefined > 

或说停下来。

 >digitalWrite(A7, 0) =undefined > 

使用相同的功能,您可以编写一个完整的程序,该程序可以根据外部因素(按按钮,传感器读数)进行所需的操作。

图书馆


回忆协议实现的细节并不总是很方便。 因此,对于各种铁,已经创建了许多图书馆,从小型到大型。 它们包含所有技术功能。 这些库使用清晰的方法:从nfc标签读取数据,读取以ppm为单位的二氧化碳浓度,或向Telegram发送消息。
  • 伺服写;
  • barometer.init;
  • 晴雨表
  • 晴雨表温度
  • nfc.listen;
  • nfc.on('tag',...);
  • nfc.readPage;
  • nfc.writePage;
  • relay.turnOn;
  • relay.turnOff;
  • 气体校准
  • gas.read('CO2');
  • telegram.sendMessage。

理解低级命令很有用,但是不必创建就可以开始创建。

客户代码


因此,当我们在青蛙中单击左列或右列的按钮之一时,我们要在相应的伺服上设置的值将发送到主题蟾蜍/眼睛/左或右。



 <button class="toad__eye__control" data-queue="left" data-payload="1300"> -1 </button> 

1300是脉冲持续时间。 左边的和1300是哪里来的? 我只是将它们作为数据属性添加到HTML中。

在JS中,我们编写了简单的代码。

 import mqtt from 'mqtt'; const client = mqtt.connect(`ws://${location.hostname}:9001`); function onEyeControlClick() { const { queue, payload } = this.dataset; client.publish(`toad/eye/${queue}`, payload); } document.querySelectorAll(".toad__eye__control") .forEach(e => e.addEventListener('click', onEyeControlClick)); 

让我们分部分分析代码。 首先,我们连接到代理,该代理默认情况下在端口9001上工作: const client = mqtt.connect(`ws://${location.hostname}:9001`);

当单击任何按钮时,我们会发布一条带有有效负载的新消息,该消息是从数据属性中获得的: client.publish(`toad/eye/${queue}`, payload);

接下来,我们发布有关主题,该主题也是在数据属性的基础上形成的。 这是浏览器中所有的JS代码。

董事会代码


Wi-fi插槽启动时,它会订阅感兴趣的主题并接收数据。 当它们到达时,插槽会做出反应并使电动机工作。



板上的代码通常分为几部分。 首先,我们正在连接库。 特别是,这只是运行Servo库,以免调用细节。 它们在安培范围内。

 const ssid = "Droidxx"; const password = "****"; const brokerHostname = "toad.amperka.ru"; const leftEye = require("@amperka/servo").connect(A5); const rightEye = require("@amperka/servo").connect(A7). 

每个人都可以创建和发布自己的库。 我们已经为自己的模块和其他流行模块制作了几十个模块。 所有开放源代码- 快来使用吧

然后,我们需要用于与Wi-Fi和MQTT代理一起使用的库

 const wifi = require("Wifi"); const mqtt = require("tinyMQTT").create(brokerHostname); 

没有操作系统,因此即使连接到Wi-Fi也是手动操作。 连接护理是您的事,但并不难。 要连接到网络,我们只需调用“ connect”方法,如果成功或失败,将调用“ callback”并报告操作结果。

 wifi.connect(ssid, { password: password }, function(e) { if (e) { console.log("Error connecting:", e); wifi.disconnect(); } else { console.log("Wi-Fi OK, connecting to broker ..."); mqtt.connect(); } }); 

如果一切正常,请连接到MQTT代理。

连接成功后,我们将订阅有趣的主题,即,所有以蟾蜍/眼睛开头的主题。

 mqtt.on("connected", function() { mqtt.subscribe("toad/eye/*"); console.log("Connected to broker", brokerHostname); }); 

收到消息后,我们便知道消息的来源。 这与简单的URL解析非常相似。 根据主题,我们决定影响哪只眼睛。 如果您有意识,那么用这种眼光我们可以写出“有效载荷”中以微秒为单位的内容。

 mqtt.on("message", function(msg) { const eye = (msg.topic === "toad/eye/left") ? leftEye : (msg.topic === "toad/eye/right") ? rightEye : null; if (eye) { eye.write(Number(msg.message), "us"); } }); 

那就是青蛙的全部魔力。

Espruino JS的局限性


我们浏览了Espruino平台。 扭青蛙不是她唯一的选择。 但是该平台有其自己的暗区,这使我们考虑了其他选择。

“总计” 1-4 Mb RAM 。 RAM有限制。 同时在代码和数据上只给出了几兆字节。 似乎在一个以演出来衡量RAM的时代,这还不够。 但是对于一组小型设备而言,这就足够了。 在2 Mb时,您可以做华丽的事情-足以容纳喷泉。

使用NPM并不是那么简单 。 此问题适用于Espruino IDE。 如果我们写“ require”,Espruino会放在一个地方,而在另一个地方,如果没有,它将对NPM产生后退。 此时,它可能会变慢。 Espruino并不总是能够处理复杂的程序包。 从这个意义上讲,它的功能比同一个Webpack或Parcel的功能低得多。 这很痛苦,但是如果您自己配置工具链,并且了解熨斗内部发生的情况,那么就没有问题。

铁的分类。 并非称为开发平台的所有硬件都会吸引Espruino。 按照微控制器世界的标准,Espruino非常脆弱-它需要500 Kb的RAM。 这样的记忆不会有任何铁。 规范的Arduino Uno或Arduino Nano只有2 Kb的RAM-因此,在那里是不可能的。 我们可以在Espruino的官方硬件上使用Espruino进行硬件工作。



Espruino是一家一人的公司,经常在Kickstarter上推出新产品,并且总是成功收集。 如果您想支持该平台-正式购买。

还有第三种选择-使用功能强大但第三方的开发板。 例如,公司ST产生“ Nuclear”和“ Discovery”。 标有STM32的铁可能会拉动Espruino。

让我们来看两个替代选项。 首先是Raspberry Pi。

树莓派


这是一台成熟的名片大小的Linux计算机。




此外,还有输入/输出引脚。 如果您可以使用Raspberry Pi,请使用以下设备拓扑。



这里的云是可选的-移动设备可以通过主机名,API或自动检测网络上设备的系统直接连接到设备。 我家里有智能电视和备用硬盘。 仅因为它们位于同一LAN上,即可从所有其他设备访问它们。

原理是一样的。 将设备放在网络上的Raspberry Pi上并构建客户端,以使其绕过中介直接通过HTTP或WebSocket连接到它。 云将Raspberry Pi上的应用程序用于其目的:它记录传感器或广播天气预报。

具有完整后端的下一个可能的拓扑。



服务器在云中崛起。 他的客户端与通过HTTP或WebSocket保持连接的移动应用程序相同。 另一方面,已经使用HTTP或相同的MQTT通过Raspberry Pi保持了连接。

用这种方法的好处是可以完全控制:验证,授权,拒绝客户。 同时,在莫斯科,一种全球性的设备已成为一种设备,符拉迪沃斯托克(Vladivostok)可以与它进行通信。

Raspberry Pi的局限性


加载时间长。 Raspberry Pi是一台完整的计算机,需要花费一些时间才能启动。 SD卡用作硬盘驱动器。 即使最快的卡,仍然会丢失常规的HDD,更不用说SSD。 随着时间的推移,负载接近一分钟。

下一个缺点是能耗 。 在能源效率方面,谈论Raspberry Pi作为移动设备。 电池不会持续很长时间-账单会一直计时。 为了使该设备工作六个月或一年,需要一个合格的微控制器程序和一组电池。

不良的GPIO是通用输入/输出 。 在Raspberry Pi上,波形馈送,波形读取以及与模拟信号一起使用的功能比微控制器要弱得多,这是微控制器的主要任务。 例如,在Raspberry Pi上开箱即用,将无法在硬件模式下控制伺服器。



限制是有条件的,因为扩展可以绕开它。 例如, Troyka帽 ,可对所有信号进行低级控制。 Raspberry Pi通过高级软件包与她进行通信。 发出命令以扭转伺服器并起作用。 使用这些扩展卡,您可以连接任何所需的设备。

Arduino的


您可以选择普通的Arduino ,每个人都已经厌倦了。 但是必须将JavaScript移到可以打开Node JS的位置-旧计算机或同一台Raspberry Pi。



我们通过USB电缆将不需要的旧计算机连接到Arduino。 在Arduino中, 一次填充标准Firmata固件。 她将Arduino变成了一个僵尸,他遵循主人-一台旧计算机的指示。 主人说要向某某引脚发送某某信号,然后Arduino进行传输。

为了进行通信,使用带有NPM的库-带有清晰API的SerialPort和Firmata。 因此,您又回到了JS世界,编写了发送到服务器的高级程序。 您相信Arduino可以处理信号,并且她可以执行信号。

并非总是与Firmata一起设法管理一切。 它能够与所需的硬件进行交互:伺服器,LED灯带,媒体控制器。 但是,如果不具备读取非常特殊的陀螺仪或加速度计的功能,它将无法正常工作。 然后,您必须在常规的Arduino上用C编写程序。

但这还不是全部-如果您不想用C编写,请使用开源工具XOD.io。



这是一个可视化的编程环境,您在其中构建的图将变成代码,并且您已经可以对其进行编译和填充。 XOD.io允许不熟悉微控制器编程的复杂性和细微差别的人快速创建简单的程序。 如果您是从Firmata成长的,但仍然不觉得低强度的写作能力,请使用XOD.io。

下一次FrontendConf会议将于10月举行。 您了解大多数前端开发人员所不了解的JavaScript,开发了易于使用的界面或发现了性能瓶颈,并准备告诉它它的位置,我们正在等待应用程序提供报告。

我们会在程序中收集有趣的报告,会议新闻,视频和文章到常规新闻通讯中- 注册

Source: https://habr.com/ru/post/zh-CN450826/


All Articles