Skip to main content

Firmata 教程:如何在 Arduino 兼容开发板上使用 Firmata

什么是 Firmata​

Firmata 是一个连接嵌入式系统与主机计算机的中间协议,协议通道默认使用串口。Arduino 平台是 Firmata 的标准参考实现。Arduino IDE 内置了对 Firmata 的支持。

这可以与 Odyssey-X86 及其板载 Arduino 核心完美配合,这意味着您可以使用 Firmata 协议和不同的编程语言简单地控制 Arduino 核心!本教程基于 Windows 操作系统。

参考:Firmata 协议

通过 Arduino IDE 烧录 Firmata 固件​

Arduino IDE >= 1.6.X 版本内置了 Firmata 固件,因此我们可以使用 Arduino IDE 将 firmata 固件烧录到 Arduino 核心中。

note

您可以从这里下载 Arduino IDE。

  • 打开 Arduino IDE 并导航到 Examples -> Firmata -> StandardFirmata:
  • StandardFirmata.ino 将会出现。选择正确的开发板和端口,然后点击 Upload:
note

如果您还没有为 Odyssey 安装开发板库,请按照这里的说明安装开发板。

  • 上传完成后,应该看起来像这样:

现在,Arduino Firmata 固件已经烧录到 Odyssey-X86 上的 Arduino 核心中!

测试 Firmata 固件​

要测试 Firmata 固件,您可以导航到 Microsoft Store,搜索并下载 Windows Remote Arduino Experience。下载完成后,您可以通过选择 USB 连接、开发板和波特率来连接到 Arduino 核心:

连接后,您可以将 LED 连接到相应的引脚来测试固件:

使用 Python 解析 Firmata​

有一些库实现了 Firmata 协议,以便从计算机、智能手机或平板电脑等设备与运行在微控制器平台上的 Firmata 固件进行通信。

pyFirmata 是 Firmata 协议的 Python 接口,运行在 python3 上。

pyFirmata 安装​

note

需要 Python3。

使用 pip 安装:

pip install pyfirmata

让连接在 D13 上的 LED 闪烁​

注意: 将 COM4 更改为您的 Arduino USB COM 端口。

对于简单的 LED 模块,您可以使用 Grove - LED 模块来测试!

#!/usr/bin/env python3
from pyfirmata import Arduino, util
from time import sleep

board = Arduino('COM4') # 更改为您的端口
print("Start blinking D13")
while True:
board.digital[13].write(1)
sleep(1)
board.digital[13].write(0)
sleep(1)

读取 A0 上的模拟信号​

#!/usr/bin/env python3
from pyfirmata import Arduino,util
import time
import sys

board = Arduino('COM4') # 更改为您的端口
it = util.Iterator(board)
it.start()
board.analog[0].enable_reporting()
print ("Read Start")
for i in range(10):
time.sleep(1)
print(board.analog[0].read())

board.analog[0].disable_reporting()

在 D6 上输出 PWM​

向连接在 D6 上的 LED 输出 PWM 信号。

#!/usr/bin/env python3
from pyfirmata import Arduino, util
from time import sleep

board = Arduino('COM4') # 更改为您的端口
lenPin = board.get_pin('d:6:p') # PWM 引脚
print("Starting to output PWM signal")
while True:
for i in range(0, 101, 4):
lenPin.write(i/100)
sleep(0.05)
sleep(1)
for i in range(100, -1, -4):
lenPin.write(i/100)
sleep(0.05)
sleep(1)

现在您可以使用 python 脚本(甚至其他语言)来控制 Odyssey-X86 上的 Arduino 核心,这在一些对实时性要求不高的情况下非常有用(例如使用 python 构建 Web 服务器,并使用 Arduino 控制继电器)。

注意: 更多 API 参考,请访问 pyFirmata API。

note

对于更高级的 Firmata python 用法,您可以考虑使用 pymata4。

使用 JavaScript 解释 Firmata​

就像使用 Python 通过 Firmata 协议控制 Arduino Core 一样,您也可以选择其他您熟悉的语言进行编程,比如 JavaScript!这是由官方 Firmata 团队实现的,您可以在 firmata.js 找到更多信息。

firmata.js 入门​

note

确保 PC 上已安装 node.js。

  • 创建一个新项目:
mkdir js && cd js
npm init -y
npm install --save firmata # 安装 firmata.js

让连接在 D13 上的 LED 闪烁​

const Board = require("firmata");
const pin = 13;

//初始化
Board.requestPort((error, port) => {
if (error) {
console.log(error);
return;
}

const board = new Board(port.path);
//等待连接
board.on("ready", () => {
console.log("Ready!");
let state = 1;
//设置引脚为输出模式
board.pinMode(pin, board.MODES.OUTPUT);
setInterval(() => {
console.log("State Change");
board.digitalWrite(pin, (state ^= 1));
}, 500);
});
});

读取 A0 上的模拟信号​

要测试模拟信号,您可以简单地使用 Grove - 旋转角度传感器!

const Board = require('firmata');
const Pin = 0;

// 初始化
Board.requestPort(function(error, port) {
if (error) {
console.log(error);
return;
}
var board = new Board(port.path);
// 等待连接
board.on("ready", function() {
console.log("Ready!");
// 读取模拟值
board.analogRead(Pin, function(value) {
console.log("Analog value: ", value);
});
});
});

D6 上的 PWM 输出​

var Board = require('firmata');
const LED = 6;

var brightness = 0;
var fadeAmount = 5;

// 初始化
Board.requestPort(function(error, port) {
if (error) {
console.log(error);
return;
}
const board = new Board(port.path);
// 等待连接
board.on("ready", function() {
console.log("Ready!");
// 设置引脚为 PWM 模式
board.pinMode(LED, board.MODES.PWM);

// LED 的 PWM 信号
function fadeLed() {
brightness += fadeAmount;
if (brightness == 0 || brightness == 255) {
fadeAmount = -fadeAmount;
}
board.analogWrite(LED, brightness);
setTimeout(fadeLed, 30);
}
console.log("Breathing");
fadeLed();
});
});

I2C 信号​

firmata.js 也支持 I2C 和 UART 通信,这里提供一个使用 Grove - 3轴数字加速度计(ADXL345)(±16g) 的示例:

  • 硬件连接:
const Board = require("firmata");

Board.requestPort((error, port) => {
if (error) {
console.log(error);
return;
}

const register = {
POWER: 0x2D,
RANGE: 0x31,
READ: 0xB2,
};

const board = new Board(port.path);

board.on("ready", function() {
console.log("Ready");

const adxl345 = 0x53;
const sensitivity = 0.00390625;

// 启用 I2C
this.i2cConfig();

// 切换电源以重置
this.i2cWrite(adxl345, register.POWER, 0);
this.i2cWrite(adxl345, register.POWER, 8);

// 设置范围(这是 2G 范围)
this.i2cWrite(adxl345, register.RANGE, 8);

// 设置寄存器到读取位置并请求 6 字节
this.i2cRead(adxl345, register.READ, 6, data => {
const x = (data[1] << 8) | data[0];
const y = (data[3] << 8) | data[2];
const z = (data[5] << 8) | data[4];

// 包装并限制 16 位;
const X = (x >> 15 ? ((x ^ 0xFFFF) + 1) * -1 : x) * sensitivity;
const Y = (y >> 15 ? ((y ^ 0xFFFF) + 1) * -1 : y) * sensitivity;
const Z = (z >> 15 ? ((z ^ 0xFFFF) + 1) * -1 : z) * sensitivity;

console.log("X: ", X);
console.log("Y: ", Y);
console.log("Z: ", Z);
});
});
});

注意: 有关更多 API 参考,请访问 firmata.js 并查看示例。

Loading Comments...