ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Johnny-Five 实战:Intel Edison 通过 Grove I2C Motor Driver 双路直流电机驱动

Johnny-Five 实战:Intel Edison 通过 Grove I2C Motor Driver 双路直流电机驱动 Johnny-Five 实战Intel Edison 通过 Grove I2C Motor Driver 双路直流电机驱动【免费下载链接】johnny-fiveJavaScript Robotics and IoT programming framework, developed at Bocoup.项目地址: https://gitcode.com/gh_mirrors/jo/johnny-five本指南以 Johnny-Five 仓库中的 Edison 示例文档为核心讲解如何在 Intel Edison Arduino Breakout 平台上通过 Grove I2C Motor Driver 组件驱动双路直流电机。读完本文你将掌握five.MotorGROVE_I2C_MOTOR_DRIVER控制器的完整用法、I2C 底层通信协议以及如何在任意 Arduino 引脚兼容平台上复用这套方案。适用场景与方案概述Grove I2C Motor Driver 是 Seeed Studio Grove 生态中的一款 I2C 接口电机驱动板它把复杂的 H 桥电机控制逻辑封装在板载芯片中主机只需要通过两根 I2C 数据线SDA/SCL发送简单的命令字节即可同时控制A、B 两个通道的直流电机转速与方向。在 Johnny-Five 中这一能力被抽象为five.Motor组件配合GROVE_I2C_MOTOR_DRIVER控制器。示例文档明确说明This shield and component will work with any Arduino pin-out compatible hardware platform.该扩展板和组件适用于任何引脚兼容 Arduino 的硬件平台因此本方案不仅适用于 Intel Edison也可迁移到 Arduino Uno、Leonardo 等标准 Arduino 引脚布局的开发板上。硬件准备运行本示例需要以下硬件对应原文档 Additional Notes 部分的硬件清单Intel Edison Arduino BreakoutEdison 模块的 Arduino 兼容扩展板提供标准 Arduino 引脚布局Grove Base Shield v2或类似的 Grove 扩展板将 Grove 的 4 针接口VCC/GND/SDA/SCL桥接到 Arduino 兼容引脚的中间层让 Grove 组件可以直接插拔使用Grove I2C Motor DriverI2C 电机驱动模块提供 A、B 两个电机输出通道并带有供电接口。提示如果你使用的不是 Grove Base Shield而是其他 Grove 兼容扩展板只要保证 I2C 引脚SDA/SCL正确连通即可代码无需改动。仓库中还存在不依赖 Edison 的通用版本 eg/grove-i2c-motor-driver.js 与配套文档 docs/motor-GROVE_I2C.md接线时请确认 A 通道与 B 通道电机分别接入驱动板的两个输出端子。运行示例原文档提供的运行命令如下node eg/grove-i2c-motor-driver-edison.js从仓库根目录执行该命令后程序会依次执行FORWARD → REVERSE → STOP三个阶段通过串口输出状态日志实际效果为电机先正转 3 秒、再反转 3 秒、最后停止。若你在自己的工程中使用 npm 安装的johnny-five与edison-io则无需eg/前缀直接运行你自己的入口脚本即可。代码逐段解析以下是原文档中的完整示例与仓库 eg/grove-i2c-motor-driver-edison.js 内容一致var five require(johnny-five); var Edison require(edison-io); var board new five.Board({ io: new Edison() }); board.on(ready, function() { var a new five.Motor({ controller: GROVE_I2C_MOTOR_DRIVER, pin: A, }); var b new five.Motor({ controller: GROVE_I2C_MOTOR_DRIVER, pin: B, }); this.wait(3000, function() { console.log(REVERSE); a.rev(127); b.rev(127); // Demonstrate motor stop in 2 seconds this.wait(3000, function() { console.log(STOP); a.stop(); b.stop(); this.wait(1000, function() { process.emit(SIGINT); }); }.bind(this)); }.bind(this)); console.log(FORWARD); a.fwd(127); b.fwd(127); });第一步以 edison-io 作为底层 IO 驱动var five require(johnny-five); var Edison require(edison-io); var board new five.Board({ io: new Edison() });edison-io是 Johnny-Five 面向 Intel Edison 的 IO 插件负责将 Edison 的 GPIO/I2C/PWM 能力映射为 Johnny-Five 标准 IO 接口。通过io: new Edison()注入后Johnny-Five 不再走 Firmata/串口协议而是直接操作 Edison 的板级资源。有关 Edison 平台配置的更多细节可参考仓库文档 docs/edison-io-arduino.md 与 docs/edison-io-miniboard.md。注意board.on(ready)回调中的this指向 board 实例因此后续的this.wait(...)实际上是board.wait(...)这是 Johnny-Five 提供的定时器 API。第二步创建两个 Motor 实例var a new five.Motor({ controller: GROVE_I2C_MOTOR_DRIVER, pin: A, }); var b new five.Motor({ controller: GROVE_I2C_MOTOR_DRIVER, pin: B, });关键配置点controller: GROVE_I2C_MOTOR_DRIVER告诉Motor使用 Grove I2C 电机驱动控制器对应源码 lib/motor.js 中定义的控制器实现pin: A/pin: B指定驱动板上的电机通道。源码在initialize中会执行options.pin.toUpperCase()因此大小写均可接受两个实例共享同一条 I2C 总线、同一个驱动板。驱动板的 I2C 地址默认是0x0F两个实例内部通过共享状态shared state协同工作避免互相覆盖——这正是该控制器设计的核心详见下文源码解析。第三步阶段化电机控制程序启动后立即进入 FORWARD 阶段console.log(FORWARD); a.fwd(127); b.fwd(127);fwd(speed)是forward(speed)的别名rev(speed)是reverse(speed)的别名参数127是 0255 范围内的速度值约等于半速255 为全速0 为停止fwd/rev在底层等价于先设置方向dir、再以给定速度启动start。3 秒后进入 REVERSE 阶段反向以相同速度运行this.wait(3000, function() { console.log(REVERSE); a.rev(127); b.rev(127); ... });再过 3 秒进入 STOP 阶段调用stop()将速度清零this.wait(3000, function() { console.log(STOP); a.stop(); b.stop(); ... });最后等待 1 秒后通过process.emit(SIGINT)优雅退出进程。原文档代码注释 Demonstrate motor stop in 2 seconds 与实际 3 秒的等待时长存在出入请以代码实际执行时序为准正向 3s → 反向 3s → 停止 → 1s 后退出。底层原理GROVE_I2C_MOTOR_DRIVER 控制器源码解析要想理解这套方案为何只需pin: A就能驱动电机需要深入 lib/motor.js 中该控制器的实现。I2C 地址与命令寄存器GROVE_I2C_MOTOR_DRIVER: { REGISTER: { value: { ADDRESS: 0x0F, } }, COMMANDS: { value: { SET_SPEED: 0x82, SET_PWM_FREQUENCY: 0x84, SET_DIRECTION: 0xAA, NOOP: 0x01, } }, ... }驱动板的默认 I2C 从机地址为0x0F可通过options.address覆盖见下方配置项说明SET_SPEED (0x82)设置转速命令SET_DIRECTION (0xAA)设置方向命令SET_PWM_FREQUENCY (0x84)设置 PWM 频率命令Johnny-Five 控制器内部未直接调用由硬件默认配置NOOP (0x01)空操作填充字节用于凑足命令帧长度。initialize共享状态与 I2C 初始化initialize: { value(options) { const state priv.get(this); let shared priv.get(GROVE_I2C_MOTOR_DRIVER); if (!shared) { shared { direction: { A: 0x01, B: 0x01 }, speed: { A: 0, B: 0 } }; priv.set(GROVE_I2C_MOTOR_DRIVER, shared); } state.shared shared; state.pin options.pin.toUpperCase(); this.settings.pins { pwm: options.pin, dir: options.pin, }; this.address options.address || this.REGISTER.ADDRESS; options.address this.address; this.io.i2cConfig(options); } },核心设计共享状态shared state。无论创建多少个Motor实例示例中是 A、B 两个它们都指向同一个驱动板因此转速和方向状态被统一存放在以控制器名称为键的共享对象中方向初始值0x01对应顺时针 CW转速初始值0每个实例的pins被设置为{ pwm: pin, dir: pin }即虚拟引脚直接对应通道名 A/B随后调用io.i2cConfig(options)完成 I2C 总线配置。setPWM一次 I2C 写操作同时刷新两路转速setPWM: { value(pin, value) { const state priv.get(this); const speed Board.constrain(value, 0, 255) | 0; state.shared.speed[state.pin] speed; this.io.i2cWrite(this.address, [ this.COMMANDS.SET_SPEED, state.shared.speed.A, state.shared.speed.B, ]); } },先通过Board.constrain(value, 0, 255)将速度钳制在 0255 合法区间更新共享状态中对应通道的速度向驱动板写入[SET_SPEED, speed.A, speed.B]——一条命令同时更新 A、B 两路转速这正是两个实例必须共享状态的原因单独控制某一路时不能破坏另一路的值。setPin打包方向字节setPin: { value(pin, value) { const state priv.get(this); // DIR_CCW 0x02 // DIR_CW 0x01 state.shared.direction[state.pin] value ? 0x01 : 0x02; const a state.shared.direction.A 0x03; const b state.shared.direction.B 0x03; const direction (b 2) | a; this.io.i2cWrite(this.address, [ this.COMMANDS.SET_DIRECTION, direction, this.COMMANDS.NOOP, ]); } },每个通道的方向值0x01表示顺时针DIR_CW0x02表示逆时针DIR_CCW由于驱动板一条 SET_DIRECTION 命令需要同时携带 A、B 两路方向源码将 B 通道方向左移 2 位再与 A 通道方向做按位或打包成一个字节(B 2) | A以 A、B 均为顺时针为例打包结果为0x01 2 | 0x01 0x05与测试用例中forward(128)断言写出的[SET_DIRECTION, 5, 1]完全吻合见下文测试章节。fwd/rev 的调用链在 lib/motor.js 中forward/fwd/reverse/rev由同一个工厂函数生成{ name: forward, abbr: fwd, value: 1 }, { name: reverse, abbr: rev, value: 0 } ].forEach(dir { Motor.prototype[dir.name] Motor.prototype[dir.abbr] function(speed) { this.dir(dir); this.start(speed); return this; }; });因此a.fwd(127)实际执行两步dir(dir)调用控制器的setPin将共享方向状态更新为0x01CW并打包发送start(127)调用speed({ speed: 127 })经过 0255 钳制与阈值判断后通过控制器的setPWM发送 SET_SPEED 命令。同理rev对应方向值0setPin内部将其映射为0x02CCW。此外Motor构造器在 lib/motor.js 中会将GROVE_I2C*前缀的控制器强制归为DIRECTIONAL设备类型从而启用方向控制语义。速度、阈值与默认值lib/motor.js 中定义了与速度相关的关键参数默认currentSpeed为128未显式传speed时默认threshold为30speed()中任何低于阈值的速度都会被钳为 0避免电机在过低 PWM 下嗡嗡作响却不转speed参数范围 0255fwd(127)表示约半速正向运转。测试用例验证仓库在 test/motor.js 中为GROVE_I2C_MOTOR_DRIVER提供了完整的单元测试套件通过 mock 的i2cConfig/i2cWrite断言了实际发送到 I2C 总线上的字节序列是理解协议行为的权威参考测试用例断言内容说明fwdOptionsToi2cConfigi2cConfig收到address: 0xff、bus: i2c-1options.address、options.bus会被透传给 I2C 配置pinListpins.pwm A、pins.dir A通道名即虚拟引脚start写入[SET_SPEED, 128, 0]默认速度 128 启动 A 通道stop写入[SET_SPEED, 0, 0]两路速度清零forward(128)依次写入[SET_DIRECTION, 5, 1]、[SET_SPEED, 128, 0]方向字节 0x05 (B:CW)2 | (A:CW)reverse(128)依次写入[SET_DIRECTION, 6, 1]、[SET_SPEED, 128, 0]方向字节 0x06 (B:CW)2 | (A:CCW)其中forwardControlBoth与reverseControlBoth两个用例还验证了 A、B 两路先后控制时互不干扰每次对单路操作setPWM都会将两路当前共享速度一并写入这正是共享状态机制正确性的直接证据。可配置参数一览基于源码与测试用例GROVE_I2C_MOTOR_DRIVER控制器支持以下配置项配置项默认值说明controller—必填固定为字符串GROVE_I2C_MOTOR_DRIVERpin—必填电机通道A或B缺失时validatePins抛出Pin must be definedaddress0x0F驱动板 I2C 从机地址多板场景下可配置为其他地址bus平台默认指定 I2C 总线如i2c-1透传给i2cConfigspeed128启动时的初始速度0255threshold30低于该值的速度被钳为 0平台适配与注意事项Intel Edison 专属接线Edison Arduino Breakout 的 I2C 引脚SDA/SCL经 Grove Base Shield 引出电机驱动板的 A、B 输出端子分别连接两路直流电机并为驱动板提供独立电机电源跨平台迁移由于整个控制链路只依赖 I2C 与标准MotorAPI把new Edison()替换为默认 IO即 eg/grove-i2c-motor-driver.js 中直接new five.Board()的写法即可在普通 Arduino 上运行相关说明见 docs/motor-GROVE_I2C.md多驱动板扩展若需驱动 4 路以上电机可为每块驱动板配置不同的address创建多个共享状态组即可电机供电Grove I2C Motor Driver 需要额外供电端子为电机提供电流逻辑电路由 5V I2C 供电接线时务必区分逻辑地与电机电源地速度语义fwd/rev中的速度参数是 PWM 占空比映射值0255并非实际转速实际转速还受电机额定电压、负载影响调试时建议从较低速度起步。总结通过 Johnny-Five 的GROVE_I2C_MOTOR_DRIVER控制器Intel Edison 只需两路 I2C 信号即可驱动双路直流电机且代码层面对 A/B 通道的控制是彼此隔离的——这得益于 lib/motor.js 中共享状态 整包刷新的设计。无论你是搭建小型机器人平台还是验证 Grove 电机驱动硬件node eg/grove-i2c-motor-driver-edison.js都是一个开箱即用的起点其完整的协议实现与测试用例也为你在此基础上做二次开发提供了可靠的参考。【免费下载链接】johnny-fiveJavaScript Robotics and IoT programming framework, developed at Bocoup.项目地址: https://gitcode.com/gh_mirrors/jo/johnny-five创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表