Blockly 与硬件交互:通过 WebUSB 控制 Arduino 实例教程
你是否曾想过用可视化编程控制真实世界的硬件?本文将带你通过 Blockly 和 WebUSB 技术,实现无需安装驱动即可在浏览器中控制 Arduino 开发板的完整流程。完成后你将掌握:WebUSB API 基础应用、Blockly 自定义硬件控制模块、Arduino 固件编写与通信协议设计。
准备工作
硬件需求
- Arduino Leonardo 或 Micro(需支持 WebUSB 协议)
- USB 数据线(A to Micro-B)
- LED 灯与 220Ω 限流电阻
- 面包板及杜邦线
软件环境
- Blockly 开发库
- Arduino IDE(用于烧录固件)
- 现代浏览器(Chrome 61+ 或 Edge 79+)
- 项目示例代码
THE 0TH POSITION OF THE ORIGINAL IMAGE
Blockly 主界面展示:通过拖拽积木块即可构建程序逻辑
Arduino 固件准备
安装 WebUSB 库
- 打开 Arduino IDE,导航至「工具 > 管理库」
- 搜索并安装
WebUSB库(版本 1.0.0+)
编写基础通信固件
创建新的 Arduino 项目,复制以下代码并上传至开发板:
#include <WebUSB.h>
WebUSB WebUSBSerial(1, "https://blockly-demo.glitch.me");
#define Serial WebUSBSerial
void setup() {
pinMode(13, OUTPUT); // 板载LED引脚
Serial.begin(9600);
// WebUSB 授权请求
while (!Serial) {}
Serial.write("WebUSB Arduino Ready\n");
}
void loop() {
if (Serial.available()) {
char cmd = Serial.read();
switch(cmd) {
case '1': digitalWrite(13, HIGH); break;
case '0': digitalWrite(13, LOW); break;
default: Serial.write("Unknown command\n");
}
}
delay(10);
}
固件核心逻辑位于 Arduino WebUSB 示例,本项目简化了通信协议,仅处理 LED 开关指令
Blockly 自定义硬件模块
引入 WebUSB 支持
在 Blockly 项目中创建 hardware/webusb.js 文件,实现 USB 设备连接管理:
class WebUSBDevice {
constructor() {
this.device = null;
this.encoder = new TextEncoder();
this.decoder = new TextDecoder();
}
async connect() {
this.device = await navigator.usb.requestDevice({
filters: [{ vendorId: 0x2341 }] // Arduino 厂商ID
});
await this.device.open();
await this.device.selectConfiguration(1);
await this.device.claimInterface(2);
return true;
}
async sendCommand(cmd) {
if (!this.device) throw new Error("未连接设备");
await this.device.transferOut(5, this.encoder.encode(cmd));
const result = await this.device.transferIn(4, 64);
return this.decoder.decode(result.data);
}
}
创建硬件控制积木块
修改 blocks/hardware.ts 文件,添加 LED 控制积木定义:
Blockly.Blocks['arduino_led'] = {
init: function() {
this.appendDummyInput()
.appendField("设置LED引脚")
.appendField(new Blockly.FieldDropdown([["13","13"],["12","12"],["11","11"]]), "PIN");
this.appendValueInput("STATE")
.setCheck("Boolean")
.appendField("状态");
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(230);
this.setTooltip("控制指定引脚的LED灯开关");
}
};
生成器代码实现
在 generators/javascript.ts 中添加代码生成逻辑:
Blockly.JavaScript['arduino_led'] = function(block) {
const pin = block.getFieldValue('PIN');
const state = Blockly.JavaScript.valueToCode(block, 'STATE', Blockly.JavaScript.ORDER_ATOMIC);
return `usb.sendCommand(${state ? "'1'" : "'0'"});\n`;
};
通信协议设计
数据格式定义
采用简单文本协议实现双向通信:
- 主机发送:单字符命令('1'=开,'0'=关)
- 设备响应:ASCII 字符串("OK"表示成功,"ERR"表示错误)
通信时序图:展示浏览器与Arduino之间的命令交互流程
错误处理机制
在 WebUSBDevice 类中添加异常处理:
async sendCommand(cmd) {
if (!this.device) throw new Error("设备未连接");
try {
await this.device.transferOut(5, this.encoder.encode(cmd));
const result = await this.device.transferIn(4, 64);
return this.decoder.decode(result.data);
} catch (e) {
console.error("通信错误:", e);
throw new Error("与设备通信失败,请重试");
}
}
完整应用示例
连接设备界面
创建 demos/webusb/index.html 文件,实现设备连接控制界面:
<!DOCTYPE html>
<html>
<head>
<title>Blockly WebUSB 控制中心</title>
<script src="../../blockly_compressed.js"></script>
<script src="../../blocks_compressed.js"></script>
<script src="../../hardware/webusb.js"></script>
</head>
<body>
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
<button onclick="connectDevice()">连接Arduino</button>
<button onclick="runCode()">运行程序</button>
<xml id="toolbox" style="display: none;">
<category name="硬件">
<block type="arduino_led"></block>
</category>
<category name="逻辑" ref="LOGIC"></category>
</xml>
<script>
const usb = new WebUSBDevice();
const workspace = Blockly.inject('blocklyDiv', {
toolbox: document.getElementById('toolbox')
});
async function connectDevice() {
try {
await usb.connect();
alert("设备连接成功!");
} catch (e) {
alert("连接失败: " + e.message);
}
}
function runCode() {
const code = Blockly.JavaScript.workspaceToCode(workspace);
eval(code);
}
</script>
</body>
</html>
电路连接示意图
按照以下方式连接硬件:
- LED 长脚(正极) → 220Ω电阻 → Arduino D13
- LED 短脚(负极) → Arduino GND
- 通过 USB 线连接 Arduino 到电脑
Arduino LED 连接示意图
典型的LED与Arduino连接电路,电阻用于限制电流保护元件
运行与调试
操作流程
- 将 Arduino 连接到电脑
- 打开 WebUSB 演示页面
- 点击"连接Arduino",在弹出的设备选择器中选择你的开发板
- 拖拽积木块创建程序(例如:循环切换LED状态)
- 点击"运行程序"执行代码
常见问题解决
- 设备无响应:检查 Arduino 固件是否正确烧录,确认使用支持 WebUSB 的开发板
- 连接失败:确保使用 HTTPS 环境或 localhost,WebUSB 在普通 HTTP 下受限
- 命令延迟:尝试增加 core/utils/delay.ts 中的延迟参数
扩展与进阶
支持更多传感器
通过扩展本文档的通信协议,可以轻松添加对其他硬件的支持:
- 模拟输入:添加读取光敏电阻、温度传感器的积木块
- 舵机控制:实现 PWM 信号输出模块 core/blocks/servo.ts
- I2C 设备:添加 I2C 通信库支持 OLED 显示屏等外设
数据可视化
结合 demos/code/ 中的图表组件,可实现传感器数据的实时可视化:
// 添加数据记录积木
Blockly.Blocks['log_data'] = {
init: function() {
this.appendValueInput("VALUE")
.setCheck("Number")
.appendField("记录数据");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
}
};
总结与展望
本文展示了如何通过 Blockly 和 WebUSB 技术构建浏览器与硬件的桥梁。关键收获包括:
- WebUSB API 提供了浏览器直接访问硬件的能力
- Blockly 自定义积木系统可快速扩展硬件控制功能
- 简单的文本通信协议能满足大多数基础控制需求
未来可以探索更复杂的应用场景,如物联网设备控制、机器人编程教育等。完整项目代码和更多示例可在 Blockly 官方仓库 中找到。
本教程基于 Blockly v9.1.0 版本开发,不同版本可能需要调整部分代码。建议定期查看 CHANGELOG.md 了解API变更。
希望本文能帮助你开启可视化编程控制硬件的旅程!如有问题或创意,欢迎在项目 issues 中交流讨论。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



