Blockly 与硬件交互:通过 WebUSB 控制 Arduino 实例教程

Blockly 与硬件交互:通过 WebUSB 控制 Arduino 实例教程

【免费下载链接】blockly The web-based visual programming editor. 【免费下载链接】blockly 项目地址: https://gitcode.com/gh_mirrors/bl/blockly

你是否曾想过用可视化编程控制真实世界的硬件?本文将带你通过 Blockly 和 WebUSB 技术,实现无需安装驱动即可在浏览器中控制 Arduino 开发板的完整流程。完成后你将掌握:WebUSB API 基础应用、Blockly 自定义硬件控制模块、Arduino 固件编写与通信协议设计。

准备工作

硬件需求

  • Arduino Leonardo 或 Micro(需支持 WebUSB 协议)
  • USB 数据线(A to Micro-B)
  • LED 灯与 220Ω 限流电阻
  • 面包板及杜邦线

软件环境

THE 0TH POSITION OF THE ORIGINAL IMAGE

Blockly 主界面展示:通过拖拽积木块即可构建程序逻辑

Arduino 固件准备

安装 WebUSB 库

  1. 打开 Arduino IDE,导航至「工具 > 管理库」
  2. 搜索并安装 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"表示错误)

mermaid

通信时序图:展示浏览器与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>

电路连接示意图

按照以下方式连接硬件:

  1. LED 长脚(正极) → 220Ω电阻 → Arduino D13
  2. LED 短脚(负极) → Arduino GND
  3. 通过 USB 线连接 Arduino 到电脑

Arduino LED 连接示意图

典型的LED与Arduino连接电路,电阻用于限制电流保护元件

运行与调试

操作流程

  1. 将 Arduino 连接到电脑
  2. 打开 WebUSB 演示页面
  3. 点击"连接Arduino",在弹出的设备选择器中选择你的开发板
  4. 拖拽积木块创建程序(例如:循环切换LED状态)
  5. 点击"运行程序"执行代码

常见问题解决

  • 设备无响应:检查 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 中交流讨论。

【免费下载链接】blockly The web-based visual programming editor. 【免费下载链接】blockly 项目地址: https://gitcode.com/gh_mirrors/bl/blockly

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值