Funpack3-5 基于Arduino UNO R4 WiFi的LED矩阵花式点灯
一、项目介绍
本项目旨在利用 Arduino UNO R4 WiFi 开发板的强大功能,结合其内置的 Wi-Fi能,通过网络连接到智能云端,实现远程对模拟灯的控制操作。用户可以在远程端发送指令,不仅能够开启和关闭灯光,还可以精确调整灯光的亮度。当亮度在 0 到 90% 之间变化时,开发板上的 12x8 LED 矩阵会亮起逐渐变大的范围,直观地展示亮度变化效果;而当亮度达到 90% 以上时,灯板会显示出太阳的图标,为用户提供一种独特且有趣的交互体验。
该项目可应用于智能家居照明控制、远程灯光场景设置等领域,具有较高的实用价值和拓展性。
二、硬件介绍
1.Arduino UNO R4 WiFi 开发板
Arduino UNO R4 WiFi采用高性能的 Renesas RA4M1(Arm® Cortex®-M4),具有 48 MHz 时钟速度、32 kB SRAM 和 256 kB 闪存, 还配备了用于连接 Wi-Fi®/Bluetooth® 的 ESP32-S3。
- 与 UNO R3的硬件兼容性:保持有相同的外形尺寸、引脚排列和 5 V 工作电压,可实现现有扩展板和项目的无缝过渡。
- WiFi和蓝牙:配备 ESP32-S3 ,可使用Wi-Fi和蓝牙进行连接。
- LED 矩阵:12x8 红色 LED 矩阵,非常适合带有动画或绘制传感器数据的创意项目。
- 内置的 HID支持:通过 USB 连接到计算机时可以轻松模拟鼠标或键盘。
三、设计思路
1.网络连接层
采用 WiFiS3.h
库实现设备与 WiFi 网络的连接,获取网络访问权限。在此基础上,利用 ArduinoMqttClient.h
库构建 MQTT 客户端,连接到指定的 MQTT 代理服务器,以实现设备与外部控制系统(如手机应用、服务器端程序等)之间的消息传递。
2.消息处理层
在主循环中不断检查 MQTT 连接状态,若断开则尝试重新连接。当接收到 MQTT 消息时,首先解析消息主题,根据主题判断是开关控制消息还是亮度控制消息。对于开关控制消息,直接更新 LED 矩阵的开关状态变量,并相应地执行打开或关闭矩阵的操作;对于亮度控制消息,将接收到的亮度值转换并限制在合理范围后,存储为全局变量以供后续显示更新使用。
3.显示控制层
根据 LED 矩阵的开关状态和亮度值来更新显示内容。当处于关闭状态时,直接清除矩阵显示。当处于打开状态时,依据亮度值进行不同的显示处理。亮度较高时,选择预定义的太阳图标数据并复制到显示缓冲区;亮度较低时,通过映射函数根据亮度计算出要点亮的行数和列数,构建相应的矩形点亮图案数据,最后将构建好的显示数据通过 Arduino_LED_Matrix.h
库提供的函数渲染到 LED 矩阵上,完成显示更新。
四、流程图
五、主要代码片段及说明
1.引入必要的库
#include <WiFiS3.h>
#include <ArduinoMqttClient.h>
#include "Arduino_LED_Matrix.h"
说明:
#include <WiFiS3.h>
:用于处理 WiFi 相关的功能,可能是针对特定硬件(如某些 ESP32 芯片等带有 WiFi 功能的开发板)的 WiFi 库。#include <ArduinoMqttClient.h>
:用于实现 MQTT 客户端相关的操作,方便连接到 MQTT 代理服务器、发送和接收消息等。#include "Arduino_LED_Matrix.h"
:应该是自定义或者特定的用于控制 LED 矩阵的库,包含了对 LED 矩阵初始化、显示等操作的函数声明。
2.定义相关常量和变量
// WiFi 凭证
const char* ssid = "ssid";
const char* password = "password";
// MQTT 代理服务器详情
const char* mqtt_server = "192.168.123.16";
const int mqtt_port = 1883;
const char* mqtt_username = "siot";
const char* mqtt_password = "dfrobot";
const char* mqtt_topic_onoff = "siot/led_matrix/onoff";
const char* mqtt_topic_brightness = "siot/led_matrix/brightness";
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
ArduinoLEDMatrix matrix;
bool isOn = false;
int brightness = 50; // 默认亮度设置为中等
说明:
const char* ssid
和const char* password
:定义了要连接的 WiFi 网络的名称(SSID)和密码。const char* mqtt_server
、const int mqtt_port
、const char* mqtt_username
、const char* mqtt_password
等:分别定义了 MQTT 代理服务器的地址、端口、登录用户名和密码,以及用于控制 LED 矩阵开关和亮度的 MQTT 主题名称。WiFiClient wifiClient
和MqttClient mqttClient(wifiClient)
:创建 WiFi 客户端对象和基于该 WiFi 客户端的 MQTT 客户端对象,用于后续的网络连接和消息收发。ArduinoLEDMatrix matrix
:用于操作 LED 矩阵的对象实例。bool isOn
:用于记录 LED 矩阵的开关状态,初始化为false
,表示关闭状态。int brightness
:用于记录 LED 矩阵的亮度值,初始化为 50,表示中等亮度。
3.初始化函数
- 功能概述:该函数在程序启动时执行一次,用于完成一系列的初始化操作,为后续的主循环运行做准备。
void setup() {
Serial.begin(9600);
while (!Serial);
// 初始化 LED 矩阵
matrix.begin();
Serial.println("LED 矩阵已初始化");
// 连接到 WiFi
connectToWiFi();
// 连接到 MQTT 代理服务器
connectToMQTT();
// 初始状态下关闭 LED 矩阵
matrix.clear();
Serial.println("LED 矩阵初始状态已清除");
}
说明:
- 串口初始化:
Serial.begin(9600);
开启串口通信,波特率设置为 9600,方便后续输出调试信息等,并且通过while (!Serial);
等待串口初始化完成。
- LED 矩阵初始化:
matrix.begin();
调用Arduino_LED_Matrix.h
库中的函数对 LED 矩阵进行初始化,之后输出提示信息表明初始化完成。
- 网络连接操作:
- 调用
connectToWiFi
函数尝试连接到指定的 WiFi 网络,连接成功后会输出相应提示信息以及获取到的 IP 地址。 - 调用
connectToMQTT
函数连接到指定的 MQTT 代理服务器,若连接成功,会进行主题订阅操作,并输出订阅的主题名称等信息;若连接失败,会输出相应的错误提示和错误代码。
- 调用
- 初始状态设置:
matrix.clear();
将 LED 矩阵初始化为关闭(清除显示内容)状态,并输出相应提示信息。
4.loop函数
- 功能概述:该函数是程序的主循环部分,会不断地重复执行,用于实时处理各种任务,例如检查 MQTT 连接状态、接收和处理 MQTT 消息以及更新 LED 矩阵显示等。
void loop() {
if (!mqttClient.connected()) {
Serial.println("MQTT 连接已断开,尝试重新连接...");
connectToMQTT();
}
int messageSize = mqttClient.parseMessage();
if (messageSize) {
String topic = mqttClient.messageTopic();
String message = "";
while (mqttClient.available()) {
message += (char)mqttClient.read();
}
Serial.print("收到消息: ");
Serial.print(topic);
Serial.print(" ");
Serial.println(message);
if (topic == mqtt_topic_onoff) {
if (message == "ON") {
isOn = true;
Serial.println("收到 ON 命令,打开 LED 矩阵");
} else if (message == "OFF") {
isOn = false;
matrix.clear();
Serial.println("收到 OFF 命令,关闭 LED 矩阵");
}
} else if (topic == mqtt_topic_brightness) {
brightness = message.toInt();
if (brightness < 0) brightness = 0;
if (brightness > 100) brightness = 100;
Serial.print("设置亮度为: ");
Serial.println(brightness);
}
updateMatrix();
}
mqttClient.poll();
}
说明:
- MQTT 连接检查与重连:
- 通过
if (!mqttClient.connected())
判断 MQTT 连接是否断开,如果断开,则调用connectToMQTT
函数尝试重新连接,并输出相应提示信息。
- 通过
- 消息处理:
- 通过int messageSize = mqttClient.parseMessage()判断是否接收到新的 MQTT 消息,若有消(messageSize大于 0):
- 先获取消息的主题
topic
和内容message
,并输出接收到的消息详情(主题和内容)到串口。 - 根据消息主题进行不同的操作:
- 若主题是开关控制主题(
mqtt_topic_onoff
):当消息内容为 “ON” 时,将isOn
设置为true
,表示打开 LED 矩阵;当消息内容为 “OFF” 时,将isOn
设置为false
,并清除 LED 矩阵显示内容。 - 若主题是亮度控制主题(
mqtt_topic_brightness
):将接收到的消息内容转换为整数赋值给brightness
,并对亮度值进行范围限制(0 - 100),然后输出设置的亮度值。
- 若主题是开关控制主题(
- 最后调用
updateMatrix
函数根据最新的开关状态和亮度值更新 LED 矩阵的显示内容。
- 先获取消息的主题
- MQTT 客户端轮询:
mqttClient.poll();
用于保持 MQTT 客户端的正常运行,处理一些底层的网络通信、消息收发等相关任务。
5.connectToWiFi函数
- 功能概述:此函数专门用于建立设备与指定 WiFi 网络的连接,通过不断尝试直到成功连接或者超时为止。
void connectToWiFi() {
// 设置LED引脚为输出模式
pinMode(LED_BUILTIN, OUTPUT);
// 先将LED设置为表示未连接的状态(熄灭)
digitalWrite(LED_BUILTIN, LOW);
Serial.print("正在连接到 WiFi");
WiFi.begin(ssid, password);
while (WiFi.status()!= WL_CONNECTED) {
delay(500);
Serial.print(".");
// 在连接未成功时,LED保持熄灭状态
digitalWrite(LED_BUILTIN, LOW);
}
// 连接成功后,将LED设置为表示连接成功的状态(点亮)
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("\n已连接到 WiFi");
Serial.print("IP 地址: ");
Serial.println(WiFi.localIP());
}
说明:
- 联网状态LED指示:
将 LED_BUILTIN
引脚设置为输出模式,并将 LED 初始化为熄灭状态,表示网络未连接。当成功连接到 WiFi 网络后,将 LED 点亮,以指示网络连接成功的状态。
- 连接WiFi网络:
通过 WiFi.begin(ssid, password)启动连接到指定 WiFi 网络,然后在 while (WiFi.status()!= WL_CONNECTED)
循环中不断检查连接状态,每隔 500 毫秒输出一个.,作为连接等待的提示,当网络连接成功,输出提示信息以及获取到的本地 IP 地址。··
6.connectToMQTT函数
- 功能概述:该函数旨在让设备与指定的 MQTT 代理服务器建立连接,并在连接成功后订阅相关的 MQTT 主题,若连接失败则输出相应的错误提示和错误代码。
void connectToMQTT() {
Serial.println("正在连接到 MQTT 代理服务器...");
// 设置 MQTT 用户名和密码
mqttClient.setUsernamePassword(mqtt_username, mqtt_password);
int retries = 0;
while (!mqttClient.connect(mqtt_server, mqtt_port) && retries < 5) {
Serial.print(".");
delay(1000);
retries++;
}
if (mqttClient.connected()) {
Serial.println("\n已成功连接到 MQTT 代理服务器");
// 订阅 MQTT 主题
mqttClient.subscribe(mqtt_topic_onoff);
mqttClient.subscribe(mqtt_topic_brightness);
Serial.println("已订阅主题:");
Serial.println(mqtt_topic_onoff);
Serial.println(mqtt_topic_brightness);
} else {
Serial.println("\nMQTT 连接失败");
Serial.print("错误代码: ");
Serial.println(mqttClient.connectError());
}
}
说明:
通过 WiFi.begin(ssid, password);
启动连接到指定 WiFi 网络的过程,然后在 while (WiFi.status()!= WL_CONNECTED)
循环中不断检查连接状态,每隔 500 毫秒输出一个 .
作为连接等待的提示,直到成功连接上 WiFi 网络,此时输出连接成功的提示信息以及获取到的本地 IP 地址。
7.updateMatrix函数
- 功能概述:该函数依据 LED 矩阵当前的开关状态(由
isOn
变量表示)以及亮度值(由brightness
变量表示)来更新 LED 矩阵的显示内容。
void updateMatrix() {
if (!isOn) {
matrix.clear();
Serial.println("LED 矩阵已关闭");
return;
}
uint8_t frame[8][12] = {0};
if (brightness >= 90) {
// 显示太阳图标
uint8_t sun[8][12] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}
};
memcpy(frame, sun, sizeof(frame));
Serial.println("显示太阳图标");
} else {
// 根据亮度显示逐渐变大的矩形
int lit_rows = map(brightness, 0, 89, 1, 8);
int lit_cols = map(brightness, 0, 89, 1, 12);
for (int i = 0; i < lit_rows; i++) {
for (int j = 0; j < lit_cols; j++) {
frame[i][j] = 1;
}
}
Serial.print("显示亮度范围,点亮的行数: ");
Serial.print(lit_rows);
Serial.print(", 列数: ");
Serial.println(lit_cols);
}
matrix.renderBitmap(frame, 8, 12);
Serial.println("LED 矩阵已更新");
}
说明:
- 开关状态处理:
- 首先通过
if (!isOn)
判断如果 LED 矩阵处于关闭状态,则调用matrix.clear();
清除显示内容,并输出相应提示信息,然后直接返回,不再进行后续显示更新操作。
- 首先通过
- 亮度显示处理:
- 定义了一个
uint8_t
类型的二维数组frame[8][12]
用于构建要显示在 LED 矩阵上的位图数据。 - 根据亮度值进行不同显示逻辑:
- 当亮度值大于等于 90 时,定义了一个表示太阳图标的二维数组
sun[8][12]
,通过memcpy(frame, sun, sizeof(frame));
将太阳图标数据复制到frame
数组中,然后输出显示太阳图标的提示信息。 - 当亮度值小于 90 时,通过
map
函数根据亮度值(0 - 89)将其映射到点亮的行数(1 - 8)和列数(1 - 12),然后使用双重循环将对应的frame
数组元素设置为 1,表示点亮,之后输出点亮的行数和列数提示信息。
- 当亮度值大于等于 90 时,定义了一个表示太阳图标的二维数组
- 最后通过
matrix.renderBitmap(frame, 8, 12);
将构建好的位图数据显示到 LED 矩阵上,并输出 LED 矩阵已更新的提示信息。
- 定义了一个
六、功能展示及说明
1.连接到WiFi
已连接到WiFi,并成功打印出Arduino UNO R4 WiFi 的IP地址。
2.连接到MQTT服务器
已成功连接到MQTT服务器,并成功订阅主题。
3.远程点亮LED矩阵
远程发布MQTT 消息“ON”到主题"siot/led_matrix/onoff"。
Arduino UNO R4 WiFi 收到来自"siot/led_matrix/onoff"主题的消息“ON”,以默认亮度50点亮 LED矩阵。
4.远程熄灭LED矩阵
远程发布MQTT 消息“OFF”到主题"siot/led_matrix/onoff"。
Arduino UNO R4 WiFi 收到来自"siot/led_matrix/onoff"主题的消息“OFF”,关闭 LED矩阵。
5.调整LED矩阵点亮范围
远程发布MQTT 消息“80”到主题"siot/led_matrix/brightness"。
Arduino UNO R4 WiFi 收到来自"siot/led_matrix/brightness"主题的消息“80”,更新 LED矩阵点亮范围。
6.LED矩阵显示太阳
远程发布MQTT 消息“95”到主题"siot/led_matrix/brightness"。
Arduino UNO R4 WiFi 收到来自"siot/led_matrix/brightness"主题的消息“95”, LED矩阵显示太阳。
七、心得体会
首次我很高兴参加了此次Funpack 活动,感谢电子森林、捷得电子为我们提供的这次项目式学习机会和交流平台。通过此项目,我也深感 Arduino UNO R4 WiFi 功能强大,以及通过Arduino IDE开发项目的便捷性。