

G2 (SDA)、G1 (SCL)。M5UnitEncoderMotor 类,构造时传入产品选择器 M5Unit_EncoderMotor_Driver(默认地址 0x2F,单通道);驱动库通过 #include <M5Unit-EncoderMotor-Driver.h> 引入,显示功能还需使用上述 M5Unified 和 M5GFX 库。#include <M5Unified.h>
#include <M5Unit-EncoderMotor-Driver.h>
// Product selector sets the default address and channel count:
// U232 = 0x2F (1 channel), U233 = 0x24 (4 channels)
M5UnitEncoderMotor motor(M5Unit_EncoderMotor_Driver);
// Draw into an offscreen canvas so a full screen refresh does not flicker
M5Canvas canvas(&M5.Display);
constexpr int8_t I2C_SDA_PIN = 2; // CoreS3 PORT.A
constexpr int8_t I2C_SCL_PIN = 1;
constexpr uint32_t I2C_FREQUENCY = 400000;
constexpr int8_t PWM_DUTY = 100; // -127 ~ 127
constexpr uint32_t RUN_MS = 3000; // Duration of each segment
constexpr uint32_t STEP_MS = 200; // Sampling interval
void halt(const char *message)
{
Serial.println(message);
while (true) {
delay(1000);
}
}
// Center the status screen and mix three font sizes so the key value stands out.
void showScreen(const char *title, const char *value, const char *detail1, const char *detail2)
{
canvas.fillScreen(TFT_BLACK);
canvas.setTextDatum(middle_center);
canvas.setFont(&fonts::DejaVu18);
canvas.setTextColor(TFT_LIGHTGREY);
canvas.drawString(title, canvas.width() / 2, 32);
canvas.setFont(&fonts::DejaVu40);
canvas.setTextColor(TFT_WHITE);
canvas.drawString(value, canvas.width() / 2, 112);
canvas.setFont(&fonts::DejaVu12);
canvas.setTextColor(TFT_LIGHTGREY);
if (detail1 && detail1[0]) {
canvas.drawString(detail1, canvas.width() / 2, 176);
}
if (detail2 && detail2[0]) {
canvas.drawString(detail2, canvas.width() / 2, 204);
}
canvas.pushSprite(0, 0);
}
void drawStatus(const char *state, int8_t duty)
{
int8_t speed = 0;
int32_t encoder = 0;
motor.getSpeed(speed);
motor.getEncoder(encoder);
char value[16];
char detail1[48];
char detail2[48];
snprintf(value, sizeof(value), "%+d", speed);
snprintf(detail1, sizeof(detail1), "%s duty %+d", state, duty);
snprintf(detail2, sizeof(detail2), "encoder %ld", static_cast<long>(encoder));
showScreen("PWM", value, detail1, detail2);
}
// Apply the duty cycle and keep reporting speed and encoder counts
void holdDuty(const char *state, int8_t duty, uint32_t duration_ms)
{
if (!motor.setPWMDuty(duty)) {
halt("Failed to set PWM duty.");
}
for (uint32_t elapsed = 0; elapsed < duration_ms; elapsed += STEP_MS) {
int8_t speed = 0;
int32_t encoder = 0;
motor.getSpeed(speed);
motor.getEncoder(encoder);
drawStatus(state, duty);
Serial.printf("%s duty=%+d speed=%+d encoder=%ld\n", state, duty, speed,
static_cast<long>(encoder));
delay(STEP_MS);
}
}
void setup()
{
auto cfg = M5.config();
cfg.output_power = true;
M5.begin(cfg);
canvas.createSprite(M5.Display.width(), M5.Display.height());
Serial.begin(115200);
// Address 0 selects the default address of the selected product
while (!motor.begin(&Wire, 0, I2C_SDA_PIN, I2C_SCL_PIN, I2C_FREQUENCY)) {
Serial.println("Unit EncoderMotor Driver not found");
delay(1000);
}
delay(100); // give the unit time to finish the previous write
// Soft start is saved in the unit flash; turn it off so this demo runs without a ramp
if (!motor.setSoftStartStop(false)) {
halt("Failed to disable soft start / stop.");
}
if (!motor.setMotorRun(true) || !motor.setMotorMode(M5_UNIT_ENCODER_MOTOR_MODE_NORMAL) || !motor.setPWMDuty(0)) {
halt("Failed to initialise PWM mode.");
}
Serial.println("Unit EncoderMotor Driver ready");
}
void loop()
{
holdDuty("forward", PWM_DUTY, RUN_MS);
holdDuty("coast", 0, 1000);
holdDuty("reverse", -PWM_DUTY, RUN_MS);
holdDuty("coast", 0, 1000);
}程序用产品选择器 M5Unit_EncoderMotor_Driver 构造 M5UnitEncoderMotor 对象,begin() 时地址传 0 表示使用默认地址 0x2F;随后 setMotorRun(true) 使能驱动、setMotorMode(M5_UNIT_ENCODER_MOTOR_MODE_NORMAL) 进入 PWM 开环模式、setPWMDuty(0) 先把占空比清零。循环中先以占空比 100 正转 3 秒,再归零滑行 1 秒,然后以 -100 反转 3 秒,如此往复。PWM 模式下占空比直接作用到 H 桥,转速不受闭环调节,占空比与转速的对应关系随供电电压和负载变化;每 200 ms 通过 getSpeed() 与 getEncoder() 打印实测转速(编码器计数 / 20 ms)和编码器计数。
串口返回信息示例如下:
Unit EncoderMotor Driver ready
forward duty=+100 speed=+0 encoder=0
forward duty=+100 speed=+8 encoder=92
forward duty=+100 speed=+12 encoder=221
forward duty=+100 speed=+17 encoder=404
forward duty=+100 speed=+17 encoder=1008
forward duty=+100 speed=+16 encoder=2226
coast duty=+0 speed=+15 encoder=2622
coast duty=+0 speed=+7 encoder=2875
coast duty=+0 speed=+0 encoder=3021
reverse duty=-100 speed=+0 encoder=3021
reverse duty=-100 speed=-6 encoder=2960
reverse duty=-100 speed=-16 encoder=2712 #include <M5Unified.h>
#include <M5Unit-EncoderMotor-Driver.h>
// Product selector sets the default address and channel count:
// U232 = 0x2F (1 channel), U233 = 0x24 (4 channels)
M5UnitEncoderMotor motor(M5Unit_EncoderMotor_Driver);
// Draw into an offscreen canvas so a full screen refresh does not flicker
M5Canvas canvas(&M5.Display);
constexpr int8_t I2C_SDA_PIN = 2; // CoreS3 PORT.A
constexpr int8_t I2C_SCL_PIN = 1;
constexpr uint32_t I2C_FREQUENCY = 400000;
constexpr int8_t TARGET_SPEED = 15; // Encoder counts per 20 ms
constexpr M5UnitEncoderMotorPID SPEED_PID = {10, 1, 15}; // Default speed loop P / I / D
constexpr uint32_t RUN_MS = 5000;
constexpr uint32_t STEP_MS = 200;
void halt(const char *message)
{
Serial.println(message);
while (true) {
delay(1000);
}
}
// Center the status screen and mix three font sizes so the key value stands out.
void showScreen(const char *title, const char *value, const char *detail1, const char *detail2)
{
canvas.fillScreen(TFT_BLACK);
canvas.setTextDatum(middle_center);
canvas.setFont(&fonts::DejaVu18);
canvas.setTextColor(TFT_LIGHTGREY);
canvas.drawString(title, canvas.width() / 2, 32);
canvas.setFont(&fonts::DejaVu40);
canvas.setTextColor(TFT_WHITE);
canvas.drawString(value, canvas.width() / 2, 112);
canvas.setFont(&fonts::DejaVu12);
canvas.setTextColor(TFT_LIGHTGREY);
if (detail1 && detail1[0]) {
canvas.drawString(detail1, canvas.width() / 2, 176);
}
if (detail2 && detail2[0]) {
canvas.drawString(detail2, canvas.width() / 2, 204);
}
canvas.pushSprite(0, 0);
}
void drawStatus(const char *state, int8_t target)
{
int8_t speed = 0;
int8_t duty = 0;
motor.getSpeed(speed);
motor.getPWMDuty(duty);
char value[16];
char detail1[48];
char detail2[48];
snprintf(value, sizeof(value), "%+d", speed);
snprintf(detail1, sizeof(detail1), "%s target %+d", state, target);
snprintf(detail2, sizeof(detail2), "duty %+d", duty);
showScreen("SPEED", value, detail1, detail2);
}
// Hold a target speed and print the closed loop response
void holdSpeed(const char *state, int8_t target, uint32_t duration_ms)
{
if (!motor.runSpeed(target, SPEED_PID)) {
halt("Failed to run in Speed mode.");
}
for (uint32_t elapsed = 0; elapsed < duration_ms; elapsed += STEP_MS) {
int8_t speed = 0;
int8_t duty = 0;
motor.getSpeed(speed);
motor.getPWMDuty(duty);
drawStatus(state, target);
Serial.printf("%s target=%+d measured=%+d duty=%+d\n", state, target, speed, duty);
delay(STEP_MS);
}
}
void setup()
{
auto cfg = M5.config();
cfg.output_power = true;
M5.begin(cfg);
canvas.createSprite(M5.Display.width(), M5.Display.height());
Serial.begin(115200);
while (!motor.begin(&Wire, 0, I2C_SDA_PIN, I2C_SCL_PIN, I2C_FREQUENCY)) {
Serial.println("Unit EncoderMotor Driver not found");
delay(1000);
}
delay(100); // give the unit time to finish the previous write
// Soft start is saved in the unit flash; turn it off so this demo runs without a ramp
if (!motor.setSoftStartStop(false)) {
halt("Failed to disable soft start / stop.");
}
if (!motor.setMotorRun(true) || !motor.setMotorMode(M5_UNIT_ENCODER_MOTOR_MODE_NORMAL) || !motor.setPWMDuty(0)) {
halt("Failed to initialise Speed mode.");
}
Serial.println("Unit EncoderMotor Driver ready");
}
void loop()
{
holdSpeed("run", TARGET_SPEED, RUN_MS);
holdSpeed("stop", 0, 2000);
}程序以默认速度环参数 {10, 1, 15} 调用 runSpeed(15, SPEED_PID),单元进入速度闭环模式,目标值为 15,单位是 20 ms 内的编码器计数增量,不是 RPM,范围 -127 ~ 127,正负表示方向。运行 5 秒后把目标改成 0 观察减速过程。循环中每 200 ms 打印目标值、实测值和当前 PWM 占空比。
串口返回信息示例如下:
Unit EncoderMotor Driver ready
run target=+15 measured=+15 duty=+0
run target=+15 measured=+15 duty=+107
run target=+15 measured=+15 duty=+80
run target=+15 measured=+14 duty=+92
run target=+15 measured=+15 duty=+91
run target=+15 measured=+15 duty=+89
run target=+15 measured=+15 duty=+88
stop target=+0 measured=+14 duty=+0
stop target=+0 measured=+6 duty=+0
stop target=+0 measured=+0 duty=+0 #include <M5Unified.h>
#include <M5Unit-EncoderMotor-Driver.h>
// Product selector sets the default address and channel count:
// U232 = 0x2F (1 channel), U233 = 0x24 (4 channels)
M5UnitEncoderMotor motor(M5Unit_EncoderMotor_Driver);
// Draw into an offscreen canvas so a full screen refresh does not flicker
M5Canvas canvas(&M5.Display);
constexpr int8_t I2C_SDA_PIN = 2; // CoreS3 PORT.A
constexpr int8_t I2C_SCL_PIN = 1;
constexpr uint32_t I2C_FREQUENCY = 400000;
constexpr int32_t TARGET_POSITION = 1320; // One output revolution: 11 PPR x 4 edges x 30 gear ratio = 1320 counts
constexpr int8_t MAX_SPEED = 60; // Position loop output limit, the firmware uses the absolute value
constexpr M5UnitEncoderMotorPID POSITION_PID = {1, 1, 17}; // Default position loop P / I / D
constexpr uint32_t TIMEOUT_MS = 8000;
constexpr uint32_t STEP_MS = 200;
void halt(const char *message)
{
Serial.println(message);
while (true) {
delay(1000);
}
}
// Center the status screen and mix three font sizes so the key value stands out.
void showScreen(const char *title, const char *value, const char *detail1, const char *detail2)
{
canvas.fillScreen(TFT_BLACK);
canvas.setTextDatum(middle_center);
canvas.setFont(&fonts::DejaVu18);
canvas.setTextColor(TFT_LIGHTGREY);
canvas.drawString(title, canvas.width() / 2, 32);
canvas.setFont(&fonts::DejaVu40);
canvas.setTextColor(TFT_WHITE);
canvas.drawString(value, canvas.width() / 2, 112);
canvas.setFont(&fonts::DejaVu12);
canvas.setTextColor(TFT_LIGHTGREY);
if (detail1 && detail1[0]) {
canvas.drawString(detail1, canvas.width() / 2, 176);
}
if (detail2 && detail2[0]) {
canvas.drawString(detail2, canvas.width() / 2, 204);
}
canvas.pushSprite(0, 0);
}
void drawStatus(int32_t target)
{
int32_t encoder = 0;
int8_t speed = 0;
motor.getEncoder(encoder);
motor.getSpeed(speed);
char value[16];
char detail1[48];
char detail2[48];
snprintf(value, sizeof(value), "%ld", static_cast<long>(encoder));
snprintf(detail1, sizeof(detail1), "target %ld", static_cast<long>(target));
snprintf(detail2, sizeof(detail2), "speed %+d", speed);
showScreen("POSITION", value, detail1, detail2);
}
// Send the target position and wait until it is reached
void moveTo(int32_t target, uint32_t timeout_ms)
{
if (!motor.runPosition(target, MAX_SPEED, POSITION_PID)) {
halt("Failed to run in Position mode.");
}
for (uint32_t elapsed = 0; elapsed < timeout_ms; elapsed += STEP_MS) {
int32_t encoder = 0;
motor.getEncoder(encoder);
drawStatus(target);
Serial.printf("target=%ld encoder=%ld\n", static_cast<long>(target), static_cast<long>(encoder));
if (abs(target - encoder) <= 10) {
Serial.println("position reached");
return;
}
delay(STEP_MS);
}
Serial.println("position timeout");
}
void setup()
{
auto cfg = M5.config();
cfg.output_power = true;
M5.begin(cfg);
canvas.createSprite(M5.Display.width(), M5.Display.height());
Serial.begin(115200);
while (!motor.begin(&Wire, 0, I2C_SDA_PIN, I2C_SCL_PIN, I2C_FREQUENCY)) {
Serial.println("Unit EncoderMotor Driver not found");
delay(1000);
}
delay(100); // give the unit time to finish the previous write
// Soft start is saved in the unit flash; turn it off so this demo runs without a ramp
if (!motor.setSoftStartStop(false)) {
halt("Failed to disable soft start / stop.");
}
if (!motor.setMotorRun(true) || !motor.setMotorMode(M5_UNIT_ENCODER_MOTOR_MODE_NORMAL) || !motor.setPWMDuty(0) ||
!motor.clearEncoder()) {
halt("Failed to initialise Position mode.");
}
Serial.println("Unit EncoderMotor Driver ready");
}
void loop()
{
moveTo(TARGET_POSITION, TIMEOUT_MS);
delay(1000);
moveTo(0, TIMEOUT_MS);
delay(1000);
}程序先用 clearEncoder() 把编码器计数清零,再调用 runPosition(1320, 60, POSITION_PID) 进入位置闭环模式:1320 为目标位置,对应输出轴转一圈(11 PPR × 4 倍频 × 30 减速比 = 1320 计数);60 为位置环输出限幅,固件取绝对值作为最大速度,POSITION_PID = {1, 1, 17} 为固件默认位置环参数。移动过程中每 200 ms 打印目标位置与当前编码器计数,到位后打印 position reached,随后再回到 0 位置。
串口返回信息示例如下:
Unit EncoderMotor Driver ready
target=1320 encoder=0
target=1320 encoder=184
target=1320 encoder=536
target=1320 encoder=884
target=1320 encoder=1286
target=1320 encoder=1323
position reached
target=0 encoder=1323
target=0 encoder=1146
target=0 encoder=520
target=0 encoder=4
position reached #include <M5Unified.h>
#include <M5Unit-EncoderMotor-Driver.h>
// Product selector sets the default address and channel count:
// U232 = 0x2F (1 channel), U233 = 0x24 (4 channels)
M5UnitEncoderMotor motor(M5Unit_EncoderMotor_Driver);
// Draw into an offscreen canvas so a full screen refresh does not flicker
M5Canvas canvas(&M5.Display);
constexpr int8_t I2C_SDA_PIN = 2; // CoreS3 PORT.A
constexpr int8_t I2C_SCL_PIN = 1;
constexpr uint32_t I2C_FREQUENCY = 400000;
constexpr int8_t TARGET_SPEED = 20; // Encoder counts per 20 ms
constexpr M5UnitEncoderMotorPID SPEED_PID = {10, 1, 15}; // Default speed loop P / I / D
constexpr uint32_t RUN_MS = 4000;
constexpr uint32_t STEP_MS = 50;
void halt(const char *message)
{
Serial.println(message);
while (true) {
delay(1000);
}
}
// Center the status screen and mix three font sizes so the key value stands out.
void showScreen(const char *title, const char *value, const char *detail1, const char *detail2)
{
canvas.fillScreen(TFT_BLACK);
canvas.setTextDatum(middle_center);
canvas.setFont(&fonts::DejaVu18);
canvas.setTextColor(TFT_LIGHTGREY);
canvas.drawString(title, canvas.width() / 2, 32);
canvas.setFont(&fonts::DejaVu40);
canvas.setTextColor(TFT_WHITE);
canvas.drawString(value, canvas.width() / 2, 112);
canvas.setFont(&fonts::DejaVu12);
canvas.setTextColor(TFT_LIGHTGREY);
if (detail1 && detail1[0]) {
canvas.drawString(detail1, canvas.width() / 2, 176);
}
if (detail2 && detail2[0]) {
canvas.drawString(detail2, canvas.width() / 2, 204);
}
canvas.pushSprite(0, 0);
}
void drawStatus(const char *state, int8_t target, int8_t speed)
{
char value[16];
char detail1[48];
char detail2[48];
snprintf(value, sizeof(value), "%+d", speed);
snprintf(detail1, sizeof(detail1), "%s target %+d", state, target);
snprintf(detail2, sizeof(detail2), "soft start on");
showScreen("SOFT START", value, detail1, detail2);
}
// Drive the target speed and sample it to show the ramp.
void holdSpeed(const char *state, int8_t target, uint32_t duration_ms)
{
motor.runSpeed(target, SPEED_PID);
for (uint32_t elapsed = 0; elapsed < duration_ms; elapsed += STEP_MS) {
int8_t speed = 0;
int32_t encoder = 0;
motor.getSpeed(speed);
motor.getEncoder(encoder);
drawStatus(state, target, speed);
Serial.printf("%s t=%4lums target=%+d measured=%+d encoder=%ld\n", state, static_cast<long>(elapsed),
target, speed, static_cast<long>(encoder));
delay(STEP_MS);
}
}
void setup()
{
auto cfg = M5.config();
cfg.output_power = true;
M5.begin(cfg);
canvas.createSprite(M5.Display.width(), M5.Display.height());
Serial.begin(115200);
while (!motor.begin(&Wire, 0, I2C_SDA_PIN, I2C_SCL_PIN, I2C_FREQUENCY)) {
Serial.println("Unit EncoderMotor Driver not found");
delay(1000);
}
delay(100); // give the unit time to finish the previous write
if (!motor.setMotorRun(true) || !motor.setMotorMode(M5_UNIT_ENCODER_MOTOR_MODE_SPEED) || !motor.setPWMDuty(0)) {
halt("Failed to initialise speed mode.");
}
// The soft start / stop bit is saved in the unit flash, so set it once in setup()
if (!motor.setSoftStartStop(true)) {
halt("Failed to enable soft start / stop.");
}
Serial.println("Soft start / stop enabled");
Serial.println("Unit EncoderMotor Driver ready");
}
void loop()
{
holdSpeed("run", TARGET_SPEED, RUN_MS);
holdSpeed("stop", 0, RUN_MS);
}软启动 / 软停止由单元固件实现(寄存器 0xD1),setSoftStartStop(true) 打开后,速度给定的变化会按固件内部的斜坡渐变,而不是直接阶跃。该位写入后保存在单元 Flash,掉电不丢,因此在 setup() 里设置一次即可。
例程用速度模式演示:runSpeed(20, SPEED_PID) 起转,4 秒后 runSpeed(0, SPEED_PID) 停止,每 50 ms 采样一次实测转速。速度环会自己把占空比尽快拉满,所以转速爬升比 PWM 模式快;想看到更明显的占空比斜坡,可以改用 PWM 模式(见 3.1)。
5V Grove 供电时从静止直接给速度环阶跃,瞬时电流较大,建议外接 DC 供电。
串口返回信息示例如下:
Soft start / stop enabled
Unit EncoderMotor Driver ready
run t= 0ms target=+20 measured=+0
run t= 50ms target=+20 measured=+4
run t= 100ms target=+20 measured=+13
run t= 150ms target=+20 measured=+19
run t= 200ms target=+20 measured=+21
run t= 400ms target=+20 measured=+20
run t=1000ms target=+20 measured=+21
stop t= 0ms target=+0 measured=+20
stop t= 50ms target=+0 measured=+7
stop t= 100ms target=+0 measured=+0 #include <M5Unified.h>
#include <M5Unit-EncoderMotor-Driver.h>
// Product selector sets the default address and channel count:
// U232 = 0x2F (1 channel), U233 = 0x24 (4 channels)
M5UnitEncoderMotor motor(M5Unit_EncoderMotor_Driver);
// Draw into an offscreen canvas so a full screen refresh does not flicker
M5Canvas canvas(&M5.Display);
constexpr int8_t I2C_SDA_PIN = 2; // CoreS3 PORT.A
constexpr int8_t I2C_SCL_PIN = 1;
constexpr uint32_t I2C_FREQUENCY = 400000;
struct ColorStep {
const char *name;
uint8_t red;
uint8_t green;
uint8_t blue;
};
constexpr ColorStep STEPS[] = {
{"red", 255, 0, 0}, {"green", 0, 255, 0}, {"blue", 0, 0, 255}, {"yellow", 255, 255, 0},
{"cyan", 0, 255, 255}, {"magenta", 255, 0, 255}, {"off", 0, 0, 0},
};
constexpr uint8_t BRIGHTNESS = 80; // 0 ~ 255
constexpr uint32_t STEP_MS = 800;
void halt(const char *message)
{
Serial.println(message);
while (true) {
delay(1000);
}
}
// Center the status screen and mix three font sizes so the key value stands out.
void showScreen(const char *title, const char *value, const char *detail1, const char *detail2)
{
canvas.fillScreen(TFT_BLACK);
canvas.setTextDatum(middle_center);
canvas.setFont(&fonts::DejaVu18);
canvas.setTextColor(TFT_LIGHTGREY);
canvas.drawString(title, canvas.width() / 2, 32);
canvas.setFont(&fonts::DejaVu40);
canvas.setTextColor(TFT_WHITE);
canvas.drawString(value, canvas.width() / 2, 112);
canvas.setFont(&fonts::DejaVu12);
canvas.setTextColor(TFT_LIGHTGREY);
if (detail1 && detail1[0]) {
canvas.drawString(detail1, canvas.width() / 2, 176);
}
if (detail2 && detail2[0]) {
canvas.drawString(detail2, canvas.width() / 2, 204);
}
canvas.pushSprite(0, 0);
}
void setup()
{
auto cfg = M5.config();
cfg.output_power = true;
M5.begin(cfg);
canvas.createSprite(M5.Display.width(), M5.Display.height());
Serial.begin(115200);
while (!motor.begin(&Wire, 0, I2C_SDA_PIN, I2C_SCL_PIN, I2C_FREQUENCY)) {
Serial.println("Unit EncoderMotor Driver not found");
delay(1000);
}
if (!motor.setRGBBrightness(BRIGHTNESS)) {
halt("Failed to set RGB brightness.");
}
Serial.println("RGB demo ready");
}
void loop()
{
for (const auto &step : STEPS) {
const bool ok = motor.setRGBColor(step.red, step.green, step.blue);
delay(100);
uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;
uint8_t brightness = 0;
const bool read_ok = motor.getRGBColor(red, green, blue) && motor.getRGBBrightness(brightness);
char value[16];
char detail1[48];
char detail2[48];
snprintf(value, sizeof(value), "%s", step.name);
snprintf(detail1, sizeof(detail1), "R%3u G%3u B%3u", red, green, blue);
snprintf(detail2, sizeof(detail2), "brightness %u", brightness);
showScreen("RGB", value, detail1, detail2);
Serial.printf("set=%s rgb=(%u,%u,%u) brightness=%u result=%s read=(%u,%u,%u)/%u read_result=%s\n",
step.name, step.red, step.green, step.blue, BRIGHTNESS, ok ? "OK" : "FAIL", red, green,
blue, brightness, read_ok ? "OK" : "FAIL");
delay(STEP_MS);
}
}setRGBBrightness(80) 设置亮度(0 ~ 255),随后依次下发红、绿、蓝、黄、青、品红、熄灭七种颜色,每一步都通过 getRGBColor() 与 getRGBBrightness() 回读颜色和亮度。屏幕显示颜色名称及回读值,串口同时打印下发值、回读值和读写结果。
串口返回信息示例如下:
RGB demo ready
set=red rgb=(255,0,0) brightness=80 result=OK read=(255,0,0)/80 read_result=OK
set=green rgb=(0,255,0) brightness=80 result=OK read=(0,255,0)/80 read_result=OK
set=blue rgb=(0,0,255) brightness=80 result=OK read=(0,0,255)/80 read_result=OK
set=yellow rgb=(255,255,0) brightness=80 result=OK read=(255,255,0)/80 read_result=OK
set=cyan rgb=(0,255,255) brightness=80 result=OK read=(0,255,255)/80 read_result=OK
set=magenta rgb=(255,0,255) brightness=80 result=OK read=(255,0,255)/80 read_result=OK
set=off rgb=(0,0,0) brightness=80 result=OK read=(0,0,0)/80 read_result=OK 将上述任一例程的代码复制粘贴到 Arduino IDE 的代码编辑区,选中设备端口(详情请参考 程序编译与烧录),点击 Arduino IDE 左上角编译上传按钮,等待程序完成编译并上传至设备。