Funpack3-5:基于Arduino UNO R4 WiFi的远程云端LED矩阵控制与传感器数据读取
该项目使用了Arduino IDE、C语言,实现了Arduino UNO R4 WiFi物联网的设计,它的主要功能为:通过Arduino UNO R4 WiFi上的ESP32S3连接到Arduino IoT Cloud,可以通过网页与Arduino IoT Cloud的dashboard来控制LED矩阵与实时读取温湿度传感器的数据。
标签
嵌入式系统
Funpack活动
显示
开发板
陈子均
更新2025-01-15
上海工程技术大学
8

项目总结报告

 

项目介绍

本项目选择了板卡三:Arduino UNO R4WiFi的任务一、二综合实现,可以在远程云端控制LED矩阵与读取传感器数据

 

项目的具体功能如下:

1. 通过局域网连接到Arduino IoT Cloud

2. 可以在网页与Arduino IoT Cloud中控制LED矩阵

3. 可以在网页与Arduino IoT Cloud中读取温湿度传感器数据

 

设计思路

1、 通过板载的ESP32S3连接到网络

2、 使用Arduino IoT Cloud实时读写数据

3、 联动NUCLEO-G0B1RE读取X-NUCLEO-IKS4A1上的传感器数据,从串口发送到Arduino UNO R4WiFi

4、 根据选择的LED矩阵显示模式设定亮度


本期开发硬件介绍

Arduino UNO R4 WiFi 是一款基于 Renesas RA4M1 微控制器的开发板,专为物联网 (IoT) 和无线连接应用设计。以下是其主要硬件特点:

1、核心处理器:采用 48 MHz 的 Arm® Cortex®-M4 核心,性能相比传统 Arduino UNO R3 显著提升。

2、无线连接:集成了 ESP32-S3 模块,支持 Wi-Fi 和 Bluetooth® LE,方便进行无线通信和 IoT 应用。

3、接口与引脚

兼容 Arduino UNO R3 的引脚布局。

提供多种通信接口,包括 UART、SPI 和 I2C。

4、电源管理:支持多种供电方式,包括 USB-C 接口和外部电源输入,具备更高效的电源管理能力。

5、板载功能

内置 RGB LED,便于状态指示。

板载 12 位 DAC(数字模拟转换器),支持生成模拟信号。

5、开发支持:与 Arduino IDE 无缝兼容,同时支持多种编程语言和库,便于快速开发。

7、应用场景:适用于物联网、无线控制、环境监测和智能家居等领域。

软件流程图及主要代码片段

1.、初始化:包括硬件初始化、通信接口初始化、网络连接初始化

void setup() {
  brightness = 50;
  wat=0;
  temperature=0;
  hand=50;
  mode = 0;


  Serial.begin(9600);
  Serial1.begin(9600);
  matrix.begin();


  delay(1500);
  while (status != WL_CONNECTED) {  
    Serial.print("正在尝试连接到 SSID: ");  
    Serial1.print("正在尝试连接到 SSID: ");
    Serial.println(ssid);  
    status = WiFi.begin(ssid, pass);  
    delay(10000);  
  }


  initProperties();


  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  setDebugMessageLevel(4);  
  ArduinoCloud.printDebugInfo();


  server.begin();  
  printWifiStatus();
 
}


2、主函数

1、处理客户端请求

2、读取串口数据

3、模式判别与控制灯光

4、更新云端数据

void loop() {  
  WiFiClient client = server.available();  // 监听客户端连接  


  if (client) {                            // 如果有客户端连接  
    boolean currentLineIsBlank = true;  
    String currentLine = "";  


    while (client.connected()) {  
      if (client.available()) {  
        char c = client.read();  
       
        if (c == '\n' && currentLineIsBlank) {  
          sendResponse(client);
          break;  
        }  


        if (c == '\n') {  // 当前行结束  
          currentLineIsBlank = true;  
         
          //Serial.println("Received request: " + currentLine);  // Debug output  


          if (currentLine.startsWith("GET /on")) {  
            // setLight(brightness);  
            mode=HAND;
          } else if (currentLine.startsWith("GET /off")) {  
            setLight(0);
            mode=-1;  
          } else if (currentLine.startsWith("GET /brightness?value=")) {  
            int valueIndex = currentLine.indexOf('=');  
            int spaceIndex = currentLine.indexOf(' ', valueIndex);  
            String valueStr = currentLine.substring(valueIndex + 1, spaceIndex);  
            hand = valueStr.toInt();  
            // setLight(hand);
            // mode=HAND;
          }
          else if (currentLine.startsWith("GET /temperature")){
            mode = TEM;
            Serial.print("切换到: 温度查询\n");
          } else if (currentLine.startsWith("GET /humidity")){
            mode = WAT;
            Serial.print("切换到: 湿度查询\n");
          }  
          currentLine = "";  
        } else if (c != '\r') {  
          currentLineIsBlank = false;  
          currentLine += c;  
        }  
      }  
    }  
   
    delay(1);  
    client.flush();
    client.stop();  // Ensure client connection is closed  
  }
 
  if (Serial1.available() > 0) {                   //传感器数据读取
    String input = Serial1.readStringUntil('\n');
    input.trim();  


    // 解析串口数据值
    if (input.startsWith("Wat:")) {
      wat = input.substring(4).toFloat();  // 接收湿度值
      // Serial.print("wat = ");           //串口输出测试
      // Serial.println(wat);
     
    }
    if (input.startsWith("Temperature: ")) {
      temperature = input.substring(12).toFloat();  // 接收温度值
      if (temperature < 0) temperature = 0;
      if (temperature > 100) temperature = 100;
     
      // Serial.print("temperature= ");             //串口输出测试
      // Serial.println(temperature);  
    }
  }
  //判别mode
  if(mode==HAND){
    brightness = hand;
    setLight(brightness);  
  } else if(mode==TEM){
    brightness = temperature;
    setLight(brightness);
  }else if(mode==WAT){
    brightness = wat;
    setLight(brightness);
  }else if(mode==OFF){
    brightness=0;
    setLight(brightness);
  }
  ArduinoCloud.update();
}


3、前端网页:包含一个亮度控制滑块与四个模式切换按钮

void sendResponse(WiFiClient client) {
  client.println("HTTP/1.1 200 OK");
  client.println("Content-type:text/html");
  client.println("Connection: close");
  client.println();


  client.println("<!DOCTYPE HTML>");
  client.println("<html lang='zh-CN'>");
  client.println("<head>");
  client.println("<meta charset='UTF-8'>");
  client.println("<meta name='viewport' content='width=device-width, initial-scale=1.0'>");
  client.println("<title>LED 控制</title>");
  client.println("<style>");
  client.println("body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }");
  client.println("h1 { color: #333; }");
  client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 15px 32px; text-align: center; font-size: 16px; margin: 4px 2px; cursor: pointer; }");
  client.println("input[type=range] { width: 300px; }");
  client.println("</style>");
  client.println("</head>");
  client.println("<body>");
  client.println("<h1>LED 矩阵控制</h1>");
 
  // 动态嵌入亮度值
  client.println("<p>亮度: <span id='brightnessValue'>" + String(brightness) + "</span>%</p>");
 
  // 第一排:亮度滑块和开关按钮
  client.println("<input type='range' min='0' max='100' value='" + String(brightness) + "' id='brightnessSlider'>");
  client.println("<p>");
  client.println("<button class='button' onclick=\"fetch('/on').then(() => location.reload());\">\手动</button>");
  client.println("<button class='button' onclick=\"fetch('/off').then(() => location.reload());\">\关灯</button>");
  client.println("</p>");
 
  // 第二排:查询温湿度按钮
  client.println("<p>");
  client.println("<button class='button' onclick=\"fetch('/temperature').then(() => location.reload());\">\温度查询</button>");
  client.println("<button class='button' onclick=\"fetch('/humidity').then(() => location.reload());\">\湿度查询</button>");
  client.println("</p>");
 
  client.println("<script>");
  client.println("var slider = document.getElementById('brightnessSlider');");
  client.println("var output = document.getElementById('brightnessValue');");
  client.println("slider.oninput = function() {");
  client.println("  output.innerHTML = this.value;");
  client.println("}");
  client.println("slider.onchange = function() {");
  client.println("  fetch('/brightness?value=' + this.value);");
  client.println("}");
  client.println("</script>");
 
  client.println("</body></html>");
}


4、百分比亮度函数:实现LED矩阵逐渐从中心向外亮起

void setBrightnessLevel(int brightness) {
    // 限制亮度百分比在 0 到 100 之间
    if (brightness < 0) {
        brightness = 0;
    } else if (brightness > 100) {
        brightness = 100;
    }
   
    // 计算总的 LED 数量
    int totalLEDs = ROWS * COLUMNS;
   
    // 计算需要亮起的 LED 数量
    int ledsToTurnOn = (brightness * totalLEDs) / 100;
   
    // 将 frame 数组所有元素设为 0 (表示关闭)
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLUMNS; j++) {
            frame[i][j] = 0;
        }
    }
   
    // 中心点坐标
    int centerRow1 = ROWS / 2 - 1;
    int centerRow2 = ROWS / 2;
    int centerCol1 = COLUMNS / 2 - 1;
    int centerCol2 = COLUMNS / 2;
   
    // 创建一个二维数组保存每个 LED 的欧几里得距离
    float distances[ROWS][COLUMNS] = {0};
   
    // 计算每个 LED 到两个中心点的欧几里得距离
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLUMNS; j++) {
            // 选择距离两个中心点中较小的那个作为最终距离
            distances[i][j] = fmin(euclideanDistance(i, j, centerRow1, centerCol1),
                                   euclideanDistance(i, j, centerRow2, centerCol2));
        }
    }
   
    // 按照距离从小到大的顺序点亮 LED
    for (float d = 0; d <= ROWS + COLUMNS; d += 0.1) {  // 逐步增加半径,步长 0.1
        for (int i = 0; i < ROWS; i++) {
            for (int j = 0; j < COLUMNS; j++) {
                if (distances[i][j] <= d && frame[i][j] == 0) {  // 确保该 LED 尚未亮起
                    frame[i][j] = 1;  // 点亮 LED
                    ledsToTurnOn--;   // 计数器减 1
                    if (ledsToTurnOn == 0) {
                        return;  // 已经点亮所需数量的 LED
                    }
                }
            }
        }
    }
}


功能展示

网页控制

云端控制


活动心得体会
在本次使用Arduino UNO R4 WiFi开发项目的过程中,我收获了许多宝贵的经验。从硬件搭建到软件编写,再到与云端的集成,每一个环节都让我对物联网技术有了更深入的理解。

1、硬件方面

Arduino UNO R4 WiFi的强大功能让我快速实现了WiFi通信和传感器数据采集。通过学习和实践,我熟悉了设备的模块化设计和串口通信机制,感受到硬件调试和优化的重要性。

2、软件方面

在软件开发中,我深入了解了HTTP请求的实现及客户端与服务器的交互原理。通过分模块开发和调试,我提升了逻辑分析能力和代码组织能力,同时也积累了处理复杂问题的经验。

附件下载
R4_LED_control_dec21a.zip
Arduino UNO R4 WiFi代码
团队介绍
陈子均
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号