【Funpack3-5】基于Arduino UNO R4 WiFi的远程灯光控制和联网时钟设计
该项目使用了Arduino UNO R4 WiFi,实现了远程灯光控制的设计,它的主要功能为:通过网络连接到智能云端,尝试将设备模拟成可以控制的灯,远程端发送指令,将灯光开启关闭,0到90%时,矩阵亮起逐渐变大的范围,90%以上时,灯板显示出太阳的图标。 该项目使用了Arduino UNO R4 WiFi,实现了联网时钟的设计,它的主要功能为:通过LED矩阵显示从NTP服务器获取到的时间信息,包括年、月、日、时、分、秒,同时约每12分钟会自动校时一次。
标签
Funpack活动
FunPack3-5
Arduino UNO R4 WiFi
QuaX
更新2025-01-14
12

大家好,我是Zhou


这次Funpack3-5活动给大家带来的是,基于Arduino UNO R4 WiFi的远程灯光控制和联网时钟设计。


Arduino UNO R4 WiFi 将瑞萨电子的 RA4M1 微处理器与乐鑫的 ESP32-S3 相结合,为创客打造了一款一体化工具,具有增强的处理能力和多样化的全新外设。凭借其内置的 Wi-Fi® 和蓝牙®功能,UNO R4 WiFi 使制造商能够探索无限的创意可能性。此外,这款多功能板拥有方便的板载 12x8 LED 矩阵和 Qwiic 连接器,为各个级别的创客提供了无与伦比的灵活性和可能性。


电路板上的 MCU 是高性能的 Renesas RA4M1(Arm® Cortex®-M4),具有 48 MHz 时钟速度、32 kB SRAM 和 256 kB 闪存。 UNO R4 WiFi 还配备了用于连接 Wi-Fi®/Bluetooth® 的 ESP32-S3,也可通过特定的接头对其进行单独编程。


本次活动我选择完成的是任务一,同时自由发挥完成了可视化联网时钟的设计


所连接的WiFi应为2.4G频段


任务1:点灯!通过网络连接到智能云端,尝试将设备模拟成可以控制的灯,远程端发送指令,将灯光开启关闭,或调整灯光的亮度,0到90%时,矩阵亮起逐渐变大的范围,90%以上时,灯板显示出太阳的图标


想要实现这个设计,我们需要将任务进行拆分:

  • 智能云端
  • 矩阵显示


矩阵显示又可以细化为:

  1. 点亮不同数量LED
  2. 太阳图案显示



我们需要声明以下头文件:

#include "WiFiS3.h"
#include "arduino_secrets.h"
#include "array.h"
#include "Arduino_LED_Matrix.h"

其中 "WiFiS3.h" 和 "Arduino_LED_Matrix.h" 是官方库的头文件


"array.h"是我定义的一个头文件,用于存储LED数组,如显示太阳图标:

uint8_t frame1[8][12]={
  {0,0,1,0,0,1,1,0,0,1,0,0},
  {1,0,0,1,0,0,0,0,1,0,0,1},
  {0,0,0,0,0,1,1,0,0,0,0,0},
  {0,0,1,0,1,0,0,1,0,1,0,0},
  {0,0,1,0,1,0,0,1,0,1,0,0},
  {0,0,0,0,0,1,1,0,0,0,0,0},
  {1,0,0,1,0,0,0,0,1,0,0,1},
  {0,0,1,0,0,1,1,0,0,1,0,0},
  };


"arduino_secrets.h"是官方例程中用到的一个统一SSID和密码的头文件,方便用户测试不同例程,免去了删除例程头文件声明和添加SSID、密码的步骤。因为程序参考例程设计,这里我进行了保留:

//arduino_secrets.h header file
#define SECRET_SSID "yournetwork"
#define SECRET_PASS "yourpassword"


接下来声明一个 ArduinoLEDMatrix 类:

ArduinoLEDMatrix matrix;


存储 arduino_secrets.h 中的SSID和密码,声明网络密钥索引号(仅WEP需要),声明两个标志位用于存储矩阵数组的行列信息:

char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;        
int keyIndex = 0; // 网络密钥索引号(仅WEP需要)
int num1;
int num2;


声明单颗LED引脚、WiFi模块的状态,同时在端口80上创建一个服务器:

int led = LED_BUILTIN;             // 连接LED的引脚
int status = WL_IDLE_STATUS;
WiFiServer server(80);             // 在端口80上创建一个服务器


处理客户端发送的HTTP请求,并根据请求内容生成相应的HTML响应

实现在网页创建一个调节亮度的滑块:

        if (c == '\n') {
          if (currentLine.length() == 0) {
// 发送响应:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();

            client.print("<p style=\"font-size:5vw;\">Num Choose</p>");
            client.print("<input type='range' min='0' max='100' value='50' class='slider' id='myRange' 'updateSliderValue()'>");
            client.print("");
            client.print("<br><br>Current Value: <span id='demo'></span>");
            client.print("");
            client.println();
            // 退出while循环:
            break;
          } else {      // 如果收到换行符,则清除currentLine:
            currentLine = "";
          }


再是根据不同情况判断LED矩阵应该如何显示:

        if (currentLine.endsWith("GET /B?val=100")) {
          digitalWrite(led, HIGH);               // GET /B?val=100打开LED
          matrix.renderBitmap(frame1, 8, 12);
        } else if (currentLine.endsWith("GET /B?val=0")) {
          digitalWrite(led, LOW);                // GET /B?val=0关闭LED
          matrix.renderBitmap(frame0, 8, 12);
        } else if (currentLine.startsWith("GET /B?val=")) {
          int val = currentLine.substring(11).toInt(); // 提取val后面的值
          analogWrite(led, map(val, 0, 100, 0, 255)); // 将值映射到PWM范围并设置LED亮度
         
          if(val >= 90){matrix.renderBitmap(frame1, 8, 12);}
          else {
            for(int m = 0; m < 8; m++){
              for(int n = 0; n < 12; n++){
                frame2[m][n] = 0;
              }  
            }
            num1 = val / 12;
            num2 = val % 12;
            for(int m = 0; m <= num1; m++){
              for(int n = 0; n <= 11; n++){
                if(m == num1 & n == num2) {break;}
                frame2[m][n] = 1;
              }  
            }
            matrix.renderBitmap(frame2, 8, 12);
          }


以上即是主要代码段的讲解,使用时先连接开发板创建的热点,浏览器访问192.48.56.2,即可通过滑块控制LED矩阵了:



实际效果如下:





自由发挥:通过LED矩阵显示从NTP服务器获取到的时间信息,包括年、月、日、时、分、秒,同时约每12分钟会自动校时一次



想要实现这个设计,我们需要将任务进行拆分:

  • NTP校时
  • 矩阵显示


参考NTP例程,我们需要声明以下头文件:

// Include the RTC library
#include "RTC.h"


//Include the NTP library
#include <NTPClient.h>
#if defined(ARDUINO_PORTENTA_C33)
#include <WiFiC3.h>
#elif defined(ARDUINO_UNOWIFIR4)
#include <WiFiS3.h>
#endif
#include <WiFiUdp.h>


矩阵显示使用了官方提供的滚动显示例程,声明以下头文件

// To use ArduinoGraphics APIs, please include BEFORE Arduino_LED_Matrix
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"


添加自己WiFi的SSID和密码:

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = "";        // your network SSID (name)
char pass[] = "";    // your network password (use for WPA, or use as key for WEP)


setup()函数中我们需要进行以下操作:


初始化串口通信,波特率为9600

Serial.begin(9600);
while (!Serial);


连接到WiFi和RTC模块。调用自定义函数连接到WiFi网络初始化RTC模块初始化NTP客户端​,更新NTP客户端的时间

connectToWiFi();
RTC.begin();
Serial.println("\nStarting connection to server...");
timeClient.begin();
timeClient.update();


获取并设置时间。

因为我们使用北京时间,所以定义时区偏移量为8。打印调整后的Unix时间戳到串口、将Unix时间转换为RTC时间对象并设置

auto timeZoneOffsetHours = 8;
auto unixTime = timeClient.getEpochTime() + (timeZoneOffsetHours * 3600);
Serial.print("Unix time = ");
Serial.println(unixTime);
RTCTime timeToSet = RTCTime(unixTime);
RTC.setTime(timeToSet);


从读取RTC并串口打印时间

	RTCTime currentTime;
RTC.getTime(currentTime);
Serial.println("The RTC was just set to: " + String(currentTime));


初始化LED矩阵显示屏,设置绘图颜色为白色、文本字体、起始位置,并显示文本:

matrix.begin();

matrix.beginDraw();
matrix.stroke(0xFFFFFFFF);
// add some static text
// will only show "UNO" (not enough space on the display)
const char text[] = "UNO r4";
matrix.textFont(Font_4x6);
matrix.beginText(0, 1, 0xFFFFFF);
matrix.println(text);
matrix.endText();

matrix.endDraw();
}


loop()函数中我们需要进行以下操作:


同上获取当前时间并设置RTC模块,计数到一定值时才校准时间:

RTC.getTime(currentTime);

if (i == 100)
{
RTCTime timeToSet = RTCTime(unixTime);
RTC.setTime(timeToSet);

// Retrieve the date and time from the RTC and print them
Serial.println("The RTC was just set to: " + String(currentTime));
i = 0;
}


开始绘制操作并设置文本滚动速度:

matrix.beginDraw();

matrix.stroke(0xFFFFFFFF);
matrix.textScrollSpeed(40);


添加并显示滚动文本:

const char* text = ("    " + String(currentTime) + " ").c_str();
matrix.textFont(Font_5x7);
matrix.beginText(0, 1, 0xFFFFFF);
matrix.println(text);
matrix.endText(SCROLL_LEFT);


结束绘制操作并增加计数器:

matrix.endDraw();
i++;
delay(2000);



以上即是主要代码段的讲解,实际效果如下:



感谢阅读


(~ ̄▽ ̄)~



对本活动的心得体会

任务难度适中,板卡资源丰富,活动体验良好


(但还是建议返现金捏



2024/12/28

附件下载
mission.rar
任务工程
NTP.rar
团队介绍
NULL
团队成员
QuaX
github.com/Amanitaphalloides/
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号