ctrlshift12138 发表于 2024-10-8 02:23

【Follow me第二季第2期】(Arduino Uno R4)作品提交汇总

# 【Follow me第二季第2期】任务提交

## 一、前置准备:

硬件:无
软件:VSCode、科学上网工具

### 1、设置代理

打开VSCode,进入设置



搜索“代理”,在1和2中填写代理服务器的地址和端口,并取消勾选3



### 2、安装PlatformIO IDE扩展

选择扩展,搜索“PlatformIO”,安装扩展插件




### 4、升级WiFi模块固件(非必须步骤,可跳过)

下载下面代码到arduino Uno R4 WiFi开发板,检查的WiFi模块(ESP32-S3)的固件。如果WiFi模块固件不是最新版本,建议升级固件。

```cpp
#include <Arduino.h>
#include <WiFiS3.h>

void setup() {
        Serial.begin(115200);

        BaseType_t xReturn;
        // 检查WiFi模组
        if (WiFi.status() == WL_NO_MODULE)
        {
                Serial.println("Communication with WiFi module failed!");
                while (true);
        }
        String fv = WiFi.firmwareVersion();
        Serial.print("Current WiFi firmware version:");
        Serial.println(fv);
        Serial.print("Laste WiFi firmware version:");
        Serial.println(WIFI_FIRMWARE_LATEST_VERSION);
        if (fv < WIFI_FIRMWARE_LATEST_VERSION)
        {
                Serial.println("Please upgrade the firmware");
        }
}

void loop() {

}
```

[官方更新WiFi模块固件教程和资源链接](https://support.arduino.cc/hc/en-us/articles/9670986058780-Update-the-connectivity-module-firmware-on-UNO-R4-WiFi#espflash)

1、下载并解压官方资源



2、使用跳线帽(或金属镊子)短接图中突出显示的引脚:

!(/data/attachment/forum/202410/08/020439n8seso30j6f2sosn.png.thumb.jpg?rand=7115.516748703152)

3、使用 USB 线将 UNO R4 WiFi 板连接到电脑

4、运行`update.bat`脚本

5、选择正确的串口,并等待固件更新完成



## 二、入门任务

**Blink&串口打印Hello EEWorld!**

硬件:Arduino UNO R4 WiFi、USB-C to A线
软件:VSCode

### 1、操作步骤

打开PlatformIO的“home”主页,选择“New Project”



填写“Name”,“Board”选择“Arduino Uno R4 WiFi”,“Framework”选择“Arduino”,“Location”为项目存放位置,自行设置。



点击“FInish”,等待相关资源下载完成(如果卡在下载资源,请设置代理)。



### 2、代码

```cpp
#include <Arduino.h>
#include <Arduino_FreeRTOS.h>


void blink(void * para);
void printHelloWorld(void * para);

// 任务句柄
TaskHandle_t blink_task_handle = NULL;
TaskHandle_t print_hello_world_task_handle = NULL;

void setup() {
        pinMode(LED_BUILTIN, OUTPUT);                // LED管脚设置为输出模式
        Serial.begin(115200);                                // 串口设置波特率115200

        // 创建Blink任务
        xTaskCreate((TaskFunction_t)blink,
                                (const char*)"blink",
                                100,
                                NULL,
                                1,
                                &blink_task_handle);
        configASSERT( blink_task_handle );

        // 创建串口打印任务
        xTaskCreate((TaskFunction_t)printHelloWorld,
                                (const char *)"printHelloWord",
                                100,
                                NULL,
                                2,
                                &print_hello_world_task_handle);
        configASSERT(print_hello_world_task_handle);

        vTaskStartScheduler();                                // 启动任务调度
}

void blink(void * para)
{
        while (1)
        {
                digitalWrite(LED_BUILTIN, HIGH);                // 点亮LED
                vTaskDelay(500 * portTICK_PERIOD_MS);        // 延时500ms
                digitalWrite(LED_BUILTIN, LOW);                        // 关闭LED
                vTaskDelay(500 * portTICK_PERIOD_MS);        // 延时500ms
        }
}

void printHelloWorld(void * para)
{
        while (1)
        {
                Serial.println("Hello EEWorld !");                // 串口打印
                vTaskDelay(1000 * portTICK_PERIOD_MS);        // 延时1000ms
        }
}

void loop() {

}

```

### 3、说明

软件流程图:


使用FreeRTOS创建了“blink”和“printHelloWord”两个任务,分别实现了LED指示灯每隔0.5秒闪烁一次,串口每隔1秒发送一次“Hello EEWorld!”。

```cpp
pinMode(LED_BUILTIN, OUTPUT);                // LED管脚设置为输出模式
```

`LED_BUILTIN`为板上的黄色LED灯对应的管脚,见下图,`OUTPUT`表示将该管脚设置为输出模式。



### 4、效果展示

LED灯闪烁



串口打印



## 三、基础任务

**驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线**

硬件:Arduino UNO R4 WiFi、USB-C to A线、10K插件电阻、公对公杜邦线

软件:VSCode、Arduino IDE

### 1、代码:驱动12x8点阵LED

```cpp
#include <Arduino.h>
#include <Arduino_FreeRTOS.h>
#include <Arduino_LED_Matrix.h>
#include <animate_data.h>

void blink(void * para);
void ledMatrix(void * para);

// 任务句柄
TaskHandle_t blink_task_handle = NULL;
TaskHandle_t led_matrix_task_handle = NULL;
ArduinoLEDMatrix matrix;

void setup() {
        pinMode(LED_BUILTIN, OUTPUT);
        matrix.begin();

        // 创建Blink任务
        xTaskCreate((TaskFunction_t)blink,
                                (const char*)"blink",
                                100,
                                NULL,
                                1,
                                &blink_task_handle);
        configASSERT( blink_task_handle );

        // 创建点阵LED任务
        xTaskCreate((TaskFunction_t)ledMatrix,
                                (const char *)"ledMatrix",
                                100,
                                NULL,
                                2,
                                &led_matrix_task_handle);
        configASSERT(led_matrix_task_handle);
        vTaskStartScheduler();                                // 启动任务调度
}

void loop() {

}

void blink(void * para)
{
        while (1)
        {
                digitalWrite(LED_BUILTIN, HIGH);                // 点亮LED
                vTaskDelay(500 * portTICK_PERIOD_MS);        // 延时500ms
                digitalWrite(LED_BUILTIN, LOW);                        // 关闭LED
                vTaskDelay(500 * portTICK_PERIOD_MS);        // 延时500ms
        }
}

void ledMatrix(void *para)
{
        while (1)
        {
                uint16_t length = sizeof(frames)/sizeof(frames);
                for ( uint16_t i = 0; i < length; i++)
                {
                        matrix.loadFrame(&frames);
                        vTaskDelay(33 * portTICK_PERIOD_MS);
                }
        }
}

```

### 2、说明

软件流程图:


使用FreeRTOS创建了“blink”和“led_matrix”两个任务,分别实现了LED指示灯每隔0.5秒闪烁一次;使用LED矩阵播放动画。动画的数据在.h文件中,在代码合集中给出。

因为动画的30fps,每帧约33.3ms,所以使用了`vTaskDelay(33 * portTICK_PERIOD_MS);`来设置固定的延时。

关于如何生成动画的文件:

1、使用ffmpeg,将视频中的每一帧输出为12*8大小的bmp文件;

```ba
ffmpeg -i video.m4s -vf scale=12:8 output_frame_%04d.bmp
```

2、将bmp文件转换为hex格式的文件,以下是python转换脚本

```python
from PIL import Image
import os

def convert_image_to_led_matrix(input_image):
    # 打开图片并将其转换为灰度模式
    image = Image.open(input_image).convert('1')# '1'模式表示黑白模式
    # 缩放图片到12x8分辨率
    image = image.resize((12, 8))
   
    # 创建一个96位的数组来存储整个LED矩阵
    led_matrix_full = * 96
   
    # 遍历每个像素,将其转换为1或0并存储到led_matrix_full中
    for y in range(8):
      for x in range(12):
            pixel = image.getpixel((x, y))
            if pixel == 0:# 黑色像素表示LED点亮
                led_matrix_full = 1
   
    # 将96位数据分割成3个32位的uint32数组
    led_matrix_32 =
   
    for i in range(3):
      for bit in range(32):
            led_matrix_32 |= (led_matrix_full << (31 - bit))
   
    return led_matrix_32

def process_image_sequence(input_dir, output_file):
    led_matrices = []# 用于存储所有图片的结果

    # 遍历文件夹中的图片
    files = sorted(os.listdir(input_dir))
    for file in files:
      if file.startswith("output_frame_") and file.endswith(".bmp"):
            print(f"Processing {file}")
            file_path = os.path.join(input_dir, file)
            led_matrix = convert_image_to_led_matrix(file_path)
            # print("uint32_t led_matrix = {")
            # for value in led_matrix:
                # print(f"0x{value:08X},")
            # print("};")
            led_matrices.append(led_matrix)

    # 将结果保存到txt文件
    with open(output_file, "w") as f:
      for matrix in led_matrices:
            f.write("{" + ", ".join(f"0x{value:08X}" for value in matrix) + "},\n")
   
    print(f"LED matrices saved to {output_file}")

if __name__ == "__main__":
    # input_dir = "C://Users//ctrls//Documents//Tencent Files//2114028461//FileRecv//MobileFile//c_3724723//32//1"# 替换为图片序列所在的文件夹路径
    input_dir = os.path.dirname(os.path.abspath(__file__))# 获取当前文件所在的目录
    output_file = "output_led_matrices.txt"# 结果保存为的txt文件名
    process_image_sequence(input_dir, output_file)

```

### 3、效果展示

LED 点阵播放Bad Apple



原视频



### 4、代码:用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线

```cpp
#include <analogWave.h> // 用于模拟波形的生成
#include <OPAMP.h>

analogWave wave(DAC);
uint16_t freq = 100; // DAC生成的正弦波频率, 单位Hz
uint16_t adc_val;       // ADC值

void setup()
{
        Serial.begin(115200);
        OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
        analogReadResolution(14); // 设置 ADC 分辨率为14bit
        wave.sine(freq);                  // 设置生成正弦波并设置频率
        wave.amplitude(0.25);          // 设置幅值比例 0 ~ 1
}

void loop()
{
        adc_val = analogRead(A4);
        Serial.println(adc_val);
}

```

### 5、说明

软件流程图:


搭建的电路如下图所示,DAC输出正弦波,经过同相放大电路,R6和R5都为10K,放大倍数为2倍,输出到A4脚ADC采样。
$$
V_{out} = V_{in} \times \left( 1 + \frac{R_6}{R_5} \right)
$$



根据MCU的数据手册,可知ADC是14位的,ADC值范围是0到16383(0~5V)。



```cpp
wave.amplitude(0.25);          // 设置幅值比例 0 ~ 1
```

设置DAC的幅值比例为0.25,则输出的正弦波的电压范围是0到1.25V,经过同相放大电路,电压范围是0到2.5V,输入到ADC中,ADC值则为0到8191。

### 6、效果展示



波形与预期相符。

## 四、进阶任务

通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)

硬件:Arduino UNO R4 WiFi、USB-C to A线
软件:VSCode

### 1、代码

```cpp
#include <Arduino.h>
#include <WiFiS3.h>
#include <ArduinoHA.h>

// WiFi 设置
const char *ssid = "1708";                       // WiFi名称
const char *password = "tsl199725?"; // WiFi密码

// MQTT 设置
const char *mqtt_server = "192.168.31.46";                                                // MQTT服务器IP
uint16_t mqtt_port = 1883;                                                                                // MQTT端口
const char *mqtt_user = "arduino_uno_r4";                                                // 用户名
const char *mqtt_password = "arduino_uno_r4";                                        // 密码
const char *mqtt_client_id = "arduino";                                                        // 客户id
const char *topic_subscribe = "homeassistant/sensor/arduino";        // 订阅主题

WiFiClient client;
HADevice device(mqtt_client_id); // 创建一个HA设备
HAMqtt mqtt(client, device);

HASwitch led_switch("ledSwitch");                  // 开关实体
uint32_t last_update_time;

void onSwitchCommand(bool state, HASwitch *sender);
void wifiAndMqttInit();
void printWifiStatus();

void setup()
{
        Serial.begin(115200);
        pinMode(LED_BUILTIN, OUTPUT);
        wifiAndMqttInit(); // 初始化

        device.setName("Arduino");                        // 设备名称
        device.setSoftwareVersion("1.0.0"); // 设备软件版本

        led_switch.setIcon("mdi:led-outline");
        led_switch.setName("arduino LED");
        // led_switch.onCommand(onSwitchCommand);
}

void loop()
{
        mqtt.loop();

        if ((millis() - last_update_time) > 1000)
        {
                if (digitalRead(LED_BUILTIN) == HIGH)
                        led_switch.setState(true);
                else
                        led_switch.setState(false);

                last_update_time = millis();
        }
}

/**
* @brief MQTT接收到数据后的回调函数
*
* @param topic
* @param payload
* @param length
*/
void onMqttMessage(const char *topic, const uint8_t *payload, uint16_t length)
{
        char message;
        memcpy(message, payload, length);
        message = '\0';

        // 打印接收的数据
        Serial.print("{dbg}New message on topic: ");
        Serial.println(topic);
        Serial.print("Data: ");
        Serial.println((const char *)message);

        if (strstr(message, "ON") != NULL) // 在字符串中查找另一个子字符串
        {
                // uint8_t dutyCyclt = 0;
                // if (sscanf(message, "on#%d", &dutyCyclt) == 1) // 从一个字符串中读取数据,并按照指定的格式存储到变量中
                // {
                //         /* code */
                // }
                digitalWrite(LED_BUILTIN, HIGH);
                Serial.println("LED ON");
        }
        else if (strstr(message, "OFF") != NULL)
        {
                /* code */
                digitalWrite(LED_BUILTIN, LOW);
                Serial.println("LED OFF");
        }
        else
        {
                Serial.println("Unrecongnized meaasge");
        }
        memset(message, 0, length);
}

/**
* @brief 连接MQTT服务器后的回调函数
*
*/
void onMqttConnected()
{
        Serial.println("Connected to the broker!");

        mqtt.subscribe(topic_subscribe);
        Serial.println("Subscribe to topic: ");
        Serial.print(topic_subscribe);
        // mqtt.publish(topic_subscribe, "Hello, MQTT!");
}

/**
* @brief 断开 MQTT broker后的回调函数
*
*/
void onMqttDisconneted()
{
        Serial.println("Disconnected from the broker!");
}

/**
* @brief MQTT连接状态改变后的回调函数
*
* @param state
*/
void onMqttStateChanged(HAMqtt::ConnectionState state)
{
        Serial.print("MQTT state changed to: ");
        Serial.println(static_cast<uint8_t>(state));
}


/**
* @brief 连接WiFI和MQTT服务器
*
*/
void wifiAndMqttInit()
{
        // 检查WiFi模组
        if (WiFi.status() == WL_NO_MODULE)
        {
                Serial.println("Communication with WiFi module failed!");
                while (true)
                        ;
        }
        String fv = WiFi.firmwareVersion();
        if (fv < WIFI_FIRMWARE_LATEST_VERSION)
        {
                Serial.println("Please upgrade the firmware");
        }

        // 连接WiFi
        WiFi.begin(ssid, password); // Connect to WPA/WPA2 network:
        Serial.print("Attempting to connect to WPA SSID: ");
        Serial.println(ssid);
        while (WiFi.status() != WL_CONNECTED)
        {
                WiFi.begin(ssid, password);
                delay(1000);
        }
        printWifiStatus();

        // 配置MQTT
        Serial.println("Starting connect to MQTT server");
        mqtt.onMessage(onMqttMessage);                       // 当设备接收到 MQTT 消息时调用
        mqtt.onConnected(onMqttConnected);               // 每次获取与 MQTT 代理的连接时调用
        mqtt.onDisconnected(onMqttDisconneted);       // 每次与 MQTT 代理的连接丢失时调用
        mqtt.onStateChanged(onMqttStateChanged); // 每次连接状态改变时调用
        mqtt.setDataPrefix("homeassistant/sensor"); // 设置数据主题的前缀

        // 连接MQTT服务器
        if (!mqtt.begin(mqtt_server, mqtt_port, mqtt_user, mqtt_password))
        {
                Serial.print("Failed, rc = ");
                Serial.print(mqtt.getState());
                Serial.println(", try again in 5 seconds");
                delay(5000);
        }
}

/**
* @brief 打印WiFi信息
*
*/
void printWifiStatus()
{
        // print the SSID of the network you're attached to:
        Serial.print("SSID: ");
        Serial.println(WiFi.SSID());

        // print your board's IP address:
        IPAddress ip = WiFi.localIP();
        Serial.print("IP Address: ");
        Serial.println(ip);

        // print the received signal strength:
        long rssi = WiFi.RSSI();
        Serial.print("signal strength (RSSI):");
        Serial.print(rssi);
        Serial.println(" dBm");
}

```

### 2、说明

软件流程图:


关于Homeassistant的搭建,9月的技术直播中已经详细说明了,可以观看我的[录播回顾](https://www.bilibili.com/video/BV1884seCEAA)。

我的Homeassistant安装在Linux的docker容器中,EMQX没有使用docker,直接安装在Linux上。





**注意:在MQTT集成中,需要勾选“启用自动发现”,发现前缀配置为“homeassistant”,否则无法自动发现arduno开发板。**



调用`dawidchyrzynski/home-assistant-integration`库,实现HA联动功能。

```cpp
HASwitch led_switch("ledSwitch");                  // 开关实体
```

创建了1个HA开关实体,开发板连接到MQTT Broker后,HA自动发现,会在主页面上显示一个LED灯开关,开关可以控制开发板上的LED灯。

```cpp
if (digitalRead(LED_BUILTIN) == HIGH)
    led_switch.setState(true);        // 反馈开关状态到MQTT Broker
else
    led_switch.setState(false);        // 反馈开关状态到MQTT Broker
```

需要调用`led_switch.setState()`来将开关状态反馈到HA,如果HA获取不到开关状态,会默认开关状态是关。

### 3、效果展示

关灯状态



开灯状态



## 五、扩展任务

硬件:Arduino UNO R4 WiFi、USB-C to A线、SHT40温湿度传感器扩展板、Qwiic缆线
软件:VSCode

### 1、代码

```cpp
#include <Arduino.h>
#include <WiFiS3.h>
#include <ArduinoHA.h>
#include <Wire.h>
#include <SensirionI2cSht4x.h>
#include <string.h>

// macro definitions
// make sure that we use the proper definition of NO_ERROR
#ifdef NO_ERROR
#undef NO_ERROR
#endif
#define NO_ERROR 0

// WiFi 设置
const char *ssid = "1708";                       // WiFi名称
const char *password = "tsl199725?"; // WiFi密码

// MQTT 设置
const char *mqtt_server = "192.168.31.46";                                          // MQTT服务器IP
uint16_t mqtt_port = 1883;                                                                          // MQTT端口
const char *mqtt_user = "arduino_uno_r4";                                          // 用户名
const char *mqtt_password = "arduino_uno_r4";                                  // 密码
const char *mqtt_client_id = "arduino";                                                  // 客户id
const char *topic_subscribe = "homeassistant/sensor/arduino"; // 订阅主题

WiFiClient client;
HADevice device(mqtt_client_id); // 创建一个HA设备
HAMqtt mqtt(client, device);

HASensor sht4x_temp_sensor("sht4x_temp"); // 温度传感器实体
HASensor sht4x_humi_sensor("sht4x_humi"); // 湿度传感器实体
HASwitch led_switch("ledSwitch");                  // 开关实体

SensirionI2cSht4x sensor;                                        // SHT40

static char errorMessage;
static int16_t error;
uint32_t last_update_time;

void wifiAndMqttInit();
void printWifiStatus();

void setup()
{
        Serial.begin(115200);
        pinMode(LED_BUILTIN, OUTPUT);

        Wire1.begin();
        sensor.begin(Wire1, SHT40_I2C_ADDR_44);
        sensor.softReset();
        delay(10);

        // 读取SHT40序列号
        uint32_t serial_number;
        error = sensor.serialNumber(serial_number);
        if (NO_ERROR != error)
        {
                Serial.print("Error trying to execute serialNumber(): ");
                errorToString(error, errorMessage, sizeof(errorMessage));
                Serial.println(errorMessage);
                return;
        }
        Serial.print("serialNumber: ");
    Serial.println(serial_number);


        wifiAndMqttInit(); // 初始化

        device.setName("Arduino");                        // 设备名称
        device.setSoftwareVersion("1.0.0"); // 设备软件版本

        led_switch.setIcon("mdi:led-outline");
        led_switch.setName("arduino LED");
        // led_switch.onCommand(onSwitchCommand);

        sht4x_temp_sensor.setIcon("mdi:coolant-temperature");
        sht4x_temp_sensor.setName("温度传感器");
        sht4x_humi_sensor.setIcon("mdi:water-percent");
        sht4x_humi_sensor.setName("湿度传感器");
}

void loop()
{
        mqtt.loop();

        if ((millis() - last_update_time) > 1000)
        {
                if (digitalRead(LED_BUILTIN) == HIGH)
                        led_switch.setState(true);        // 反馈开关状态到MQTT Broker
                else
                        led_switch.setState(false);        // 反馈开关状态到MQTT Broker

                // 读取SHT40温湿度数据
                float a_temperature;
                float a_humidity;
                error = sensor.measureHighPrecision(a_temperature, a_humidity);
                if (NO_ERROR != error)
                {
                        Serial.print("Error trying to execute measureHighPrecision(): ");
                        errorToString(error, errorMessage, sizeof(errorMessage));
                        Serial.println(errorMessage);
                        return;
                }
                Serial.print("aTemperature: ");
                Serial.println(a_temperature);
                Serial.print("aHumidity: ");
                Serial.println(a_humidity);

                // 发送数据到MQTT Broker
                String str = String(a_temperature, 2);
                sht4x_temp_sensor.setValue(str.c_str());
                sht4x_temp_sensor.setUnitOfMeasurement("℃");
                str = String(a_humidity, 2);
                sht4x_humi_sensor.setValue(str.c_str());
                sht4x_humi_sensor.setUnitOfMeasurement("%");
                last_update_time = millis();
        }
}

/**
* @brief MQTT接收到数据后的回调函数
*
* @param topic
* @param payload
* @param length
*/
void onMqttMessage(const char *topic, const uint8_t *payload, uint16_t length)
{
        char message;
        memcpy(message, payload, length);
        message = '\0';

        // 打印接收的数据
        Serial.print("{dbg}New message on topic: ");
        Serial.println(topic);
        Serial.print("Data: ");
        Serial.println((const char *)message);

        if (strstr(message, "ON") != NULL) // strstr()在字符串中查找另一个子字符串
        {
                // uint8_t dutyCyclt = 0;
                // if (sscanf(message, "on#%d", &dutyCyclt) == 1) // 从一个字符串中读取数据,并按照指定的格式存储到变量中
                // {
                //         /* code */
                // }
                digitalWrite(LED_BUILTIN, HIGH);
                Serial.println("LED ON");
        }
        else if (strstr(message, "OFF") != NULL)
        {
                /* code */
                digitalWrite(LED_BUILTIN, LOW);
                Serial.println("LED OFF");
        }
        else
        {
                Serial.println("Unrecongnized meaasge");
        }
        memset(message, 0, length);
}

/**
* @brief 连接MQTT服务器后的回调函数
*
*/
void onMqttConnected()
{
        Serial.println("Connected to the broker!");

        mqtt.subscribe(topic_subscribe);
        Serial.println("Subscribe to topic: ");
        Serial.print(topic_subscribe);
        // mqtt.publish(topic_subscribe, "Hello, MQTT!");
}

/**
* @brief 断开 MQTT broker后的回调函数
*
*/
void onMqttDisconneted()
{
        Serial.println("Disconnected from the broker!");
}

/**
* @brief MQTT连接状态改变后的回调函数
*
* @param state
*/
void onMqttStateChanged(HAMqtt::ConnectionState state)
{
        Serial.print("MQTT state changed to: ");
        Serial.println(static_cast<uint8_t>(state));
}


/**
* @brief 连接WiFI和MQTT服务器
*
*/
void wifiAndMqttInit()
{
        // 检查WiFi模组
        if (WiFi.status() == WL_NO_MODULE)
        {
                Serial.println("Communication with WiFi module failed!");
                while (true)
                        ;
        }
        String fv = WiFi.firmwareVersion();
        if (fv < WIFI_FIRMWARE_LATEST_VERSION)
        {
                Serial.println("Please upgrade the firmware");
        }

        // 连接WiFi
        WiFi.begin(ssid, password); // Connect to WPA/WPA2 network:
        Serial.print("Attempting to connect to WPA SSID: ");
        Serial.println(ssid);
        while (WiFi.status() != WL_CONNECTED)
        {
                WiFi.begin(ssid, password);
                delay(1000);
        }
        printWifiStatus();

        // 配置MQTT
        Serial.println("Starting connect to MQTT server");
        mqtt.onMessage(onMqttMessage);                       // 当设备接收到 MQTT 消息时调用
        mqtt.onConnected(onMqttConnected);               // 每次获取与 MQTT 代理的连接时调用
        mqtt.onDisconnected(onMqttDisconneted);       // 每次与 MQTT 代理的连接丢失时调用
        mqtt.onStateChanged(onMqttStateChanged); // 每次连接状态改变时调用
        mqtt.setDataPrefix("homeassistant/sensor"); // 设置数据主题的前缀

        // 连接MQTT服务器
        if (!mqtt.begin(mqtt_server, mqtt_port, mqtt_user, mqtt_password))
        {
                Serial.print("Failed, rc = ");
                Serial.print(mqtt.getState());
                Serial.println(", try again in 5 seconds");
                delay(5000);
        }
}

/**
* @brief 打印WiFi信息
*
*/
void printWifiStatus()
{
        // print the SSID of the network you're attached to:
        Serial.print("SSID: ");
        Serial.println(WiFi.SSID());

        // print your board's IP address:
        IPAddress ip = WiFi.localIP();
        Serial.print("IP Address: ");
        Serial.println(ip);

        // print the received signal strength:
        long rssi = WiFi.RSSI();
        Serial.print("signal strength (RSSI):");
        Serial.print(rssi);
        Serial.println(" dBm");
}

```

### 2、说明

软件流程图:


调用`sensirion/Sensirion I2C SHT4x`的库,来读取STH40的温湿度数据。

**注意:开发板有2个IIC端口,QWIC接口使用的是WIRE1,所以使用`Wire1.begin();`来使能IIC端口。**



```cpp
HASensor sht4x_temp_sensor("sht4x_temp"); // 温度传感器实体
HASensor sht4x_humi_sensor("sht4x_humi"); // 湿度传感器实体
```

创建了2个HA传感器实体,分别显示温度和湿度。

```cpp
sensor.measureHighPrecision(a_temperature, a_humidity);
```

使用`measureHighPrecision()`函数,来获取温度和湿度数据。

```cpp
sht4x_temp_sensor.setValue();
sht4x_humi_sensor.setValue();
```

通过`setValue()`函数,将温度和湿度数据发送到MQTT Broker。

### 3、效果展示



HA中显示的温湿度数据:



家里的小米温湿度传感器



## 六、源代码



## 七、展示视频

[大学堂视频链接](https://training.eeworld.com.cn/video/41270)

ctrlshift12138 发表于 2024-10-11 01:58

文章最后2张图是显示BUG,我在编辑页面是没有这2张图的,浏览时请大家忽略

ctrlshift12138 发表于 2024-10-11 02:01

文章中嵌入的代码缩进有些问题,大家可以下载源代码自行查看

nmg 发表于 2024-11-2 19:36

ctrlshift12138 发表于 2024-10-11 01:58
文章最后2张图是显示BUG,我在编辑页面是没有这2张图的,浏览时请大家忽略

<p>之所以有这2张图片,是因为你上传了,但是没用,所以它们放在了最后,你在图片里删除,就不会显示了。我这边帮你直接删除了。</p>

<div style="text-align: center;"></div>

<p>&nbsp;</p>

nmg 发表于 2024-11-2 19:36

ctrlshift12138 发表于 2024-10-11 02:01
文章中嵌入的代码缩进有些问题,大家可以下载源代码自行查看

<p>可以具体说说嘛,看我们这边能否改进</p>

ctrlshift12138 发表于 2024-11-8 23:54

nmg 发表于 2024-11-2 19:36
可以具体说说嘛,看我们这边能否改进

<p>在旧版种,代码缩进是正常的;新版界面,代码缩进有问题的。</p>

<div style="text-align: center;"></div>

<div style="text-align: center;">&nbsp;</div>

<div style="text-align: center;">&nbsp;</div>

<div style="text-align: center;">&nbsp;</div>

<div style="text-align: center;">
<div style="text-align: center;"></div>

<p>&nbsp;</p>
</div>

<p>&nbsp;</p>

ctrlshift12138 发表于 2024-11-8 23:56

ctrlshift12138 发表于 2024-11-8 23:54
在旧版种,代码缩进是正常的;新版界面,代码缩进有问题的。



&nbsp;

&nbsp;

&nbsp;



...

<p>好像是 Tab 缩进无法识别</p>

nmg 发表于 2024-11-11 11:34

ctrlshift12138 发表于 2024-11-8 23:56
好像是 Tab 缩进无法识别

<p>收到,我去反馈</p>
页: [1]
查看完整版本: 【Follow me第二季第2期】(Arduino Uno R4)作品提交汇总