md-llama-com 发表于 2024-10-6 22:27

【Follow me第二季第2期】学习Arduino UNO R4 WiFi 之任务汇总

本帖最后由 md-llama-com 于 2024-10-20 22:28 编辑

# 学习Arduino UNO R4 WiFi任务汇总

Follow me 第二季第二期来了,又又又可以白嫖技术白嫖板子了 ~ 闲话少说 ~开启今日份任务汇总,这次是一份Arduino UNO R4 WiFi的板子,用的是日本瑞萨电子的RA4M1芯片,wifi用的是乐鑫ESP32,非常值得学习的方案。

# 汇总视频链接

bf33d481ab30092d6d1ba4513cc03fc2<br/>

# 全部物料清单(含物料名称、实物图片)

1.最主要的控制板
Arduino UNO R4 WiFi


2.LTR-329 环境光传感器与SHT40温湿度传感器


3.跳线


4.示波器


# 入门任务(必做):搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
搭配器件: Arduino UNO R4 WiFi

这就是今天的主角,这个项目一是为了确定板子的好坏,二是为了测试与电脑是否可以通讯。

## 搭建环境:
在arduino官网下载Arduino IDE



点击微软下载或者MAC下载



仅下载 JUST DOWNLOAD

下载好后点击安装包安装







同意,下一步,安装,三步走,尽量装在D盘

完成安装后在打开arduino IDE并授权一大堆权限后,我们进入了界面,开始获取Arduino UNO R4 WiFi 包



注意这里arduino IDE会要求安装一堆东西



安装这块板子的支持包后即可完成环境搭建

整个步骤就是:上官网->下载软件->安装arduino->配置Arduino UNO R4 WiFi板子扩展包

## Blink

写程序的第一句话是打印hello world
而玩儿开发板的第一步是点灯

在打开IDE后找到文件file->示例Exmples->基础Basics->BLink



用Type-C线连好板子与电脑

点击编译即可

效果如下:



代码如下:
```
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH);// turn the LED on (HIGH is the voltage level)
delay(1000);                      // wait for a second
digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
delay(1000);                      // wait for a second
}
```

## 串口打印Hello EEWorld!

串口打印是很多交互的基础

我们在刚刚的点灯程序下加入这一行:波特率设定为9600,波特率是电脑与单片机之间的通讯频率

```
Serial.println("Hello EEWorld!");
```

打开串口调试器,下载程序

效果如下:



代码如下:
```
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
}

// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH);// turn the LED on (HIGH is the voltage level)
delay(1000);                      // wait for a second
Serial.println("Hello EEWorld!");
digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
delay(1000);                      // wait for a second
}
```
## 程序流程图



# 基础任务(必做):驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
搭配器件: Arduino UNO R4 WiFi
## 驱动12x8点阵LED
12X8点阵LED这是之前没遇到过的,通过查看原理图,原理图如下


至于怎么驱动这块LED屏幕,我们可以在示例里找到LED_Matrix,打开DisplaySingleFrame示例查看

代码如下
```
#include "Arduino_LED_Matrix.h"   // Include the LED_Matrix library
#include "frames.h"               // Include a header file containing some custom icons

ArduinoLEDMatrix matrix;          // Create an instance of the ArduinoLEDMatrix class

void setup() {
Serial.begin(115200);         // Initialize serial communication at a baud rate of 115200
matrix.begin();               // Initialize the LED matrix
}

void loop() {
// Load and display the "chip" frame on the LED matrix
matrix.loadFrame(chip);
delay(500);// Pause for 500 milliseconds (half a second)

// Load and display the "danger" frame on the LED matrix
matrix.loadFrame(danger);
delay(500);

// Load and display the "happy" frame on the LED matrix
matrix.loadFrame(happy);
delay(500);

// Load and display the "big heart" frame provided by the library
matrix.loadFrame(LEDMATRIX_HEART_BIG);
delay(500);

// Turn off the display
matrix.clear();
delay(1000);

// Print the current value of millis() to the serial monitor
Serial.println(millis());
}
```
效果如下:



## 程序流程图如下:



## 用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口
这三个任务可以一起做
### 用DAC生成正弦波
打开案例库SineWave

其代码如下:
```
#include "analogWave.h" // Include the library for analog waveform generation
analogWave wave(DAC);   // Create an instance of the analogWave class, using the DAC pin

int freq = 10;// in hertz, change accordingly

void setup(){
Serial.begin(115200);
wave.sine(freq);
wave.amplitude(0.5);//幅值倍数
}
void loop(){
Serial.println(analogRead(A5));
delay(10);
}
```



### 用OPAMP放大DAC信号
使用运算放大器(OP-AMP)放大数字到模拟转换器(DAC)的信号是一种常见的电子电路设计实践。这种配置可以增加信号的幅度,以满足特定的应用需求,例如驱动更大的负载或提供足够的信号强度以进行测量。

以下是电路图


代码如下:
```
#include "analogWave.h" // Include the library for analog waveform generation
#include "OPAMP.h"
analogWave wave(DAC);   // Create an instance of the analogWave class, using the DAC pin

int freq = 200;// in hertz, change accordingly

void setup() {
Serial.begin(2000000);// Initialize serial communication at a baud rate of 115200
analogReadResolution(14);
wave.sine(freq);       // Generate a sine wave with the initial frequency
wave.amplitude(0.5);//幅值倍数
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
}

void loop() {
delayMicroseconds(100);
}
```
### 用ADC采集并且打印数据到串口

只需要将输出分别导入A4,A5端口即可,循环loop如下
```
void loop() {
Serial.print(analogRead(A4));
Serial.print(",");
Serial.println(analogRead(A5));
delayMicroseconds(100);
}
```

用示波器显示如下



## 流程图



# 进阶任务(必做):通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
搭配器件: Arduino UNO R4 WiFi

要接入到平台HA(HomeAssistant)平台,首先要有一个HA平台,常规做法是搭建一个服务器,在服务器中用docker容器安装HA,我们作为初学者,自己用的电脑直接安装HA

pip3 install homeassistant

在powershell中输入命令下载安装HA,时间会比较久

打开 127.0.0.1:8123 注册HA

接下来要搭建MQTT服务器,这里用的是Docker容器下的EMQX镜像

众所周知Docker安装是真的烦,我这里就遇到了Docker Engine stopped

**我是怎么解决的呢**

### 1.首先检查一下CPU是否开启虚拟化


如果虚拟化是禁用的,要进入BIOS打开虚拟化。我这里是没有问题的。

### 2.启动Docker Desktop Service服务

在windows powershell中(管理员运行),输入 **net start com.docker.service** 启动Docker Desktop Service服务



### 3.wsl安装

在windows powershell中输入**wsl --update**,开始安装wsl或者更新版本。

### 4.启动docker daemon

在windows powershell中输入 ** cd "C:\Program Files\Docker\Docker" ** 跳转到Docker Desktop安装路径

运行命令 **.\DockerCli.exe -SwitchDaemon** 把docker daemon启动

### 5.重启电脑

重启电脑非常重要,网上的步骤都没写这步,导致我一直失败,重启电脑后再运行docker desktop,就可以正常进入了。

正常进入docker后找到Docker Engine

将其中内容改为

```
{
"builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
},
   "debug": true,
   "experimental": false,
   "insecure-registries":[],
   "registry-mirrors":[
   "https://docker.m.daocloud.io"
   ]
}
```

重启docker。

## 然后就可以在docker中拉取emqx

### 1.在windows命令行中输入以下命令搜索镜像,

```c
docker search emqx
```


### 2.回车后可以看到排名第一的 emqx 并且是official; 输入以下命令拉取最新版本镜像

```c
docker pull emqx
```



## 然后创建EMQX容器
```
docker run -d --name="EMQX_container" -v D:/HassWP_2024.4.3/EMQX -p 1883:1883 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqx
```
-v 后面接着的是容器保存路径



## 启动emqx

回到docker点击图示网址即可启动



http://localhost:18083/
默认账号:admin 默认密码:public

## EMQX的一些设置
进入EMQX后会让我们重新设置密码

访问控制 -> 客户端认证 -> 选 **创建** -> 选择 **Password-Based** ->**内置数据库** -> **下一步** -> 3个都默认 -> 点 **创建**

点击 **用户管理** -> 点 +(右侧)-> 填入新的用户名和密码

## EMQX 与 HA相连接

首先要找到EMQX服务器在docker内的地址,按照图片所示寻找即可



在HA中打开设置如下图



设备与服务



添加新设备



输入刚刚的地址与EMQX上新增的用户名与密码

完成后回到EMQX界面可以看到设备连接数加一



这样EMQXHA 之间就打通了

接下来要将咱们的主角与EMQX之间的连接打通。

## Arduino UNO R4 WiFi与EMQX连接

程序如下:
参数定义如下
```c
#define MQTT_SERVER "192.168.3.28"// 电脑无线网卡IP地址"xxx.xxx.xxx.xxX
#define MQTT_PORT 1883 //定义MQTT服务器的端口
#define MQTT_CLIENT_ID "arduino"// 定义客户端的ID'arduino'
#define MQTT_USERNAME "sdfa"   // 定义用户名,EMQX定义"admin'
#define MQTT_PASSWORD "sdfda"      // 定义密码,EMQX定义"admin"
#define TOPIC_SUBSCRIBE "UNO/arduino/switch/cmd_t"//定义订阅的主题
#define SECRET_SSID "dsdfai"    // 路由器WiFi名称 也可使用win移动热点"xxXXX
#define SECRET_PASS "sfdfsf"      // 路由器WiFi密码”xxxXX
```
主程序是HA网站上设定按钮,然后控制Arduino UNO R4 WiFi上14号引脚小灯亮灭。
主程序如下
```c
#include "ArduinoHA.h"
#include "OPAMP.h"
#include "Wire.h"
#include "WiFiS3.h"
#include "arduino_secrets.h"
#include "analogWave.h"

analogWave wave(DAC);

int status= WL_IDLE_STATUS;
unsigned long lastUpdateAt=0;
int freg=1;//max200 Hz limit by serial print

WiFiClient client;
HADevice device(MQTT_CLIENT_ID);//HADevice device (mac, sizeof(mac));
HAMqtt mqtt(client,device);
HAButton buttonON("myButtonON");
HAButton buttonOFF("myButtonOFF");
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);

Serial.begin(115200);
wifi_and_mqtt_init();
analogReadResolution(14);//change to 14-bit resolution
wave.sine(freg);//wave.saw(freg);
wave.amplitude(0.5);
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);

device.setName("Arduino");
device.setSoftwareVersion("1.0.0");
buttonON.setIcon("mdi:fire");
buttonON.setName("Click me ON");
buttonOFF.setIcon("mdi:home");
buttonOFF.setName("click me OFF");
buttonON.onCommand(onButtonCommand);//press callbacks
buttonOFF.onCommand(onButtonCommand);

}

void loop()
{
mqtt.loop();
if((millis() - lastUpdateAt) > 1000)
{//update in 1s interval
    unsigned long uptimeValue=millis()/1000;
    lastUpdateAt =millis();
}
}

void onMqttMessage(const char* topic, const uint8_t* payload, uint16_t length)
{
char message;
memcpy(message,payload,length);
message= '\0';

Serial.print("dbglNew message on topic:");
Serial.println(topic);
Serial.print("Data:");
Serial.println((const char*)message);

if(strstr(message,"on")!=NULL)
{

    int dutyCycle=0;
    if (sscanf(message,"on#%d",&dutyCycle)==1)
   {

   }

}
else if(strstr(message,"off")!=NULL)
         {

      }
   else
   {
   Serial.println("Unrecognized message");
   }
memset(message,0, length);
}



void onMqttConnected()
{
Serial.println("Connected to the broker!");
//You can subscribe to custom topic if you need
mqtt.subscribe(TOPIC_SUBSCRIBE);//command
//mqtt.subscribe(TOPIC SUBSCRIBE2)://status
Serial.println("subscribed to topic:" TOPIC_SUBSCRIBE);
mqtt.publish(TOPIC_SUBSCRIBE,"Hi EMOX I'mArdinO UNO R4 WIFI^^");

}

void onMqttDisconnected()
{
Serial.println("Disconnected from the broker!");
}

void onMqttStateChanged(HAMqtt::ConnectionState state)
{
Serial.print("MoTT state changed to:");
Serial.println(static_cast<int8_t>(state));
}

void onButtonCommand(HAButton* sender)
{
if(sender ==&buttonON)
{
    Serial.print("buttonON");// button A was clicked, do your logic hereelse
    digitalWrite(LED_BUILTIN, HIGH);
   }
   else if(sender==&buttonOFF)
   {
    Serial.print("buttonOFF");// button B was clicked, do your logic here
    digitalWrite(LED_BUILTIN, LOW);
   }
}

void wifi_and_mqtt_init()
{
//check for the WiFi module:
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");
}

//attempt to connect to wiFi network;
while(status!=WL_CONNECTED)
{
Serial.print("Attempting to connect to SSID:");
Serial.println(SECRET_SSID);
//Connect to WPA/WPA2 network, Change this line if using open or WEP network;
status=WiFi.begin(SECRET_SSID,SECRET_PASS);
delay(10000);
}

Serial.println("\nStarting connection to MoTT server...");
mqtt.onMessage(onMqttMessage);
mqtt.onConnected(onMqttConnected);
mqtt.onDisconnected(onMqttDisconnected);
mqtt.onStateChanged(onMqttStateChanged);

//If you want to change prefix only for non-discovery prefix:
mqtt.setDataPrefix("UNO");

if(!mqtt.begin(MQTT_SERVER,MQTT_PORT,MQTT_USERNAME,MQTT_PASSWORD))
{
   Serial.print("Failed, rC=");
   Serial.print(mqtt.getState());//0btaining state of the MoTr connection:
   Serial.println("tryagain in 5 seconds");
   delay(5000);
   }

}

```
效果如下


## 流程图




# 扩展任务(必做,二选一,或根据自己的兴趣,自定义类似难度或更高难度的任务并完成)我选择两个都做

## ■扩展任务一:通过外部LTR-329 环境光传感器,上传光照度到HA,通过HA面板显示数据

搭配器件: Arduino UNO R4 WiFi、5591(LTR-329光传感器扩展板)、跳线

首先要处理一下接线问题,因为没有购买官方的跳线,我们需要自己把插针焊上
如下图



然后按照IIC的要求把时钟线 数据线接上,注意电源线要接3.3V的。





安装Adafruit LTR329 and LTR303 库

打开示例,将没用的语句简化,先测试一下模块是否正常使用,然后再与HA连接:
```
#include "Adafruit_LTR329_LTR303.h"

Adafruit_LTR303 ltr = Adafruit_LTR303();

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

if ( ! ltr.begin() ) {
    Serial.println("Couldn't find LTR sensor!");
    while (1) delay(10);
}
//初始化传感器,如果没找到持续刷新,直到找到
Serial.println("Found LTR sensor!");

ltr.setGain(LTR3XX_GAIN_96);//设置传感器灵敏度
ltr.setIntegrationTime(LTR3XX_INTEGTIME_100);//设置传感器的积分时间ms
ltr.setMeasurementRate(LTR3XX_MEASRATE_200);//设置测量速率ms

// The LTR-303 has interrupt output support, we can enable the pin output!
ltr.enableInterrupt(true);
// The INT pin also has a polarity setting. For active LOW set to 'false',
// for active HIGH set to 'true'
ltr.setInterruptPolarity(false);

//设置低阈值和高阈值
// Then set the low threshold (values BELOW this trigger an interrupt)
ltr.setLowThreshold(2000);
// and set the high threshold (values ABOVE this trigger an interrupt)
ltr.setHighThreshold(30000);


Serial.print("Thresholds: ");Serial.print(ltr.getLowThreshold());
Serial.print(" & ");Serial.println(ltr.getHighThreshold());

// Finally, default is an interrupt on every value that is under/over the
// threshold ranges. However, you're more likely to get spurious IRQs, so
// we can set it to require "N counts in a row" before an IRQ. 1 count is
// IRQ for each reading, 2 count means we need two outside readings in a row, etc
// up to 16.

//设置中断的持续计数,连续4次超出阈值则中断
ltr.setIntPersistance(4);
Serial.print("Consecutive counts for IRQ: ");Serial.println(ltr.getIntPersistance());
}

void loop() {
bool valid;
uint16_t visible_plus_ir, infrared;

//检查是否有新的数据可用
if (ltr.newDataAvailable()) {
    valid = ltr.readBothChannels(visible_plus_ir, infrared);
    //如果数据有效,将可见光+红外和红外的光强度值打印到串行监视器。
    if (valid) {
      Serial.print("CH0 Visible + IR: ");
      Serial.print(visible_plus_ir);
      Serial.print("\t\tCH1 Infrared: ");
      Serial.println(infrared);
    }
}

delay(100);
}
```
运行效果如下



与HA结合程序如下
```
#include "ArduinoHA.h"
#include "OPAMP.h"
#include "Wire.h"
#include "WiFiS3.h"
#include "arduino_secrets.h"
#include "analogWave.h"
#include "Adafruit_LTR329_LTR303.h"

analogWave wave(DAC);
Adafruit_LTR303 ltr = Adafruit_LTR303();

int status= WL_IDLE_STATUS;
unsigned long lastUpdateAt=0;
int freg=1;//max200 Hz limit by serial print

WiFiClient client;
HADevice device(MQTT_CLIENT_ID);//HADevice device (mac, sizeof(mac));
HAMqtt mqtt(client,device);

HASensorNumber analogSensor("myAnalogInput", HASensorNumber::PrecisionP1);
HASensorNumber uptimeSensor("myUptime");

HAButton buttonON("myButtonON");
HAButton buttonOFF("myButtonOFF");
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);

Serial.begin(115200);
wifi_and_mqtt_init();
analogReadResolution(14);//change to 14-bit resolution
wave.sine(freg);//wave.saw(freg);
wave.amplitude(0.5);
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);

device.setName("Arduino");
device.setSoftwareVersion("1.0.0");
buttonON.setIcon("mdi:fire");
buttonON.setName("Click me ON");
buttonOFF.setIcon("mdi:home");
buttonOFF.setName("click me OFF");
buttonON.onCommand(onButtonCommand);//press callbacks
buttonOFF.onCommand(onButtonCommand);

if ( ! ltr.begin() ) {
    Serial.println("Couldn't find LTR sensor!");
    while (1) delay(10);
}
//初始化传感器,如果没找到持续刷新,直到找到
Serial.println("Found LTR sensor!");

ltr.setGain(LTR3XX_GAIN_96);//设置传感器灵敏度
ltr.setIntegrationTime(LTR3XX_INTEGTIME_100);//设置传感器的积分时间ms
ltr.setMeasurementRate(LTR3XX_MEASRATE_200);//设置测量速率ms

// The LTR-303 has interrupt output support, we can enable the pin output!
ltr.enableInterrupt(true);
// The INT pin also has a polarity setting. For active LOW set to 'false',
// for active HIGH set to 'true'
ltr.setInterruptPolarity(false);

//设置低阈值和高阈值
// Then set the low threshold (values BELOW this trigger an interrupt)
ltr.setLowThreshold(2000);
// and set the high threshold (values ABOVE this trigger an interrupt)
ltr.setHighThreshold(30000);
}
void loop()
{

bool valid;
uint16_t visible_plus_ir, infrared;

mqtt.loop();
//检查是否有新的数据可用
if (ltr.newDataAvailable()) {
    valid = ltr.readBothChannels(visible_plus_ir, infrared);
    //如果数据有效,将可见光+红外和红外的光强度值打印到串行监视器。
    if (valid) {
      if((millis() - lastUpdateAt) > 1000)
   {//update in 1s interval
      Serial.print("CH0 Visible + IR: ");
      Serial.print(visible_plus_ir);
      uptimeSensor.setValue(visible_plus_ir);
      Serial.print("\t\tCH1 Infrared: ");
      Serial.println(infrared);
      analogSensor.setValue(infrared);
      lastUpdateAt =millis();
   }
    }
}
}

void onMqttMessage(const char* topic, const uint8_t* payload, uint16_t length)
{
char message;
memcpy(message,payload,length);
message= '\0';

Serial.print("dbglNew message on topic:");
Serial.println(topic);
Serial.print("Data:");
Serial.println((const char*)message);

void onMqttConnected()
{
Serial.println("Connected to the broker!");
//You can subscribe to custom topic if you need
mqtt.subscribe(TOPIC_SUBSCRIBE);//command
//mqtt.subscribe(TOPIC SUBSCRIBE2)://status
Serial.println("subscribed to topic:" TOPIC_SUBSCRIBE);
mqtt.publish(TOPIC_SUBSCRIBE,"Hi EMOX I'mArdinO UNO R4 WIFI^^");

}

void onMqttDisconnected()
{
Serial.println("Disconnected from the broker!");
}

void onMqttStateChanged(HAMqtt::ConnectionState state)
{
Serial.print("MoTT state changed to:");
Serial.println(static_cast<int8_t>(state));
}

void onButtonCommand(HAButton* sender)
{
if(sender ==&buttonON)
{
    Serial.print("buttonON");// button A was clicked, do your logic hereelse
    digitalWrite(LED_BUILTIN, HIGH);
   }
   else if(sender==&buttonOFF)
   {
    Serial.print("buttonOFF");// button B was clicked, do your logic here
    digitalWrite(LED_BUILTIN, LOW);
   }
}

void wifi_and_mqtt_init()
{
//check for the WiFi module:
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");
}

//attempt to connect to wiFi network;
while(status!=WL_CONNECTED)
{
Serial.print("Attempting to connect to SSID:");
Serial.println(SECRET_SSID);
//Connect to WPA/WPA2 network, Change this line if using open or WEP network;
status=WiFi.begin(SECRET_SSID,SECRET_PASS);
delay(10000);
}

Serial.println("\nStarting connection to MoTT server...");
mqtt.onMessage(onMqttMessage);
mqtt.onConnected(onMqttConnected);
mqtt.onDisconnected(onMqttDisconnected);
mqtt.onStateChanged(onMqttStateChanged);

//If you want to change prefix only for non-discovery prefix:
mqtt.setDataPrefix("UNO");

if(!mqtt.begin(MQTT_SERVER,MQTT_PORT,MQTT_USERNAME,MQTT_PASSWORD))
{
   Serial.print("Failed, rC=");
   Serial.print(mqtt.getState());//0btaining state of the MoTr connection:
   Serial.println("tryagain in 5 seconds");
   delay(5000);
   }
}
```
运行效果如下



### 流程图





## ■扩展任务二:通过外部SHT40温湿度传感器,上传温湿度到HA,通过HA面板显示数据

搭配器件: Arduino UNO R4 WiFi、4885(SHT40温湿度传感器扩展板)、跳线



安装Adafruit SHT4X库
与光照传感器一样,焊接引脚,用例程测试温湿度传感器好坏

与HA结合程序如下
```
#include "ArduinoHA.h"
#include "OPAMP.h"
#include "Wire.h"
#include "WiFiS3.h"
#include "arduino_secrets.h"
#include "analogWave.h"
#include "Adafruit_LTR329_LTR303.h"
#include "Adafruit_SHT4x.h"

Adafruit_SHT4x sht4 = Adafruit_SHT4x();

analogWave wave(DAC);
Adafruit_LTR303 ltr = Adafruit_LTR303();

int status= WL_IDLE_STATUS;
unsigned long lastUpdateAt=0;
int freg=1;//max200 Hz limit by serial print

WiFiClient client;
HADevice device(MQTT_CLIENT_ID);//HADevice device (mac, sizeof(mac));
HAMqtt mqtt(client,device);

HASensorNumberhumidity2("myhumidity");
HASensorNumberTemperature2("Temperature");

HAButton buttonON("myButtonON");
HAButton buttonOFF("myButtonOFF");
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
wifi_and_mqtt_init();
analogReadResolution(14);//change to 14-bit resolution
wave.sine(freg);//wave.saw(freg);
wave.amplitude(0.5);
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);

device.setName("Arduino");
device.setSoftwareVersion("1.0.0");
buttonON.setIcon("mdi:fire");
buttonON.setName("Click me ON");
buttonOFF.setIcon("mdi:home");
buttonOFF.setName("click me OFF");
buttonON.onCommand(onButtonCommand);//press callbacks
buttonOFF.onCommand(onButtonCommand);

while (!Serial)
    delay(10);   // will pause Zero, Leonardo, etc until serial console opens

if (! sht4.begin()) {
    Serial.println("Couldn't find SHT4x");
    while (1) delay(1);
}

Serial.println(sht4.readSerial(), HEX);

// You can have 3 different precisions, higher precision takes longer
sht4.setPrecision(SHT4X_HIGH_PRECISION); //精度


// You can have 6 different heater settings
// higher heat and longer times uses more power
// and reads will take longer too!
sht4.setHeater(SHT4X_NO_HEATER);//加热传感器

}

void loop()
{

bool valid;
uint16_t visible_plus_ir, infrared;
sensors_event_t humidity, temp;

sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data

Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");

mqtt.loop();
//检查是否有新的数据可用
if (sht4.getEvent(&humidity, &temp)) {
   
      if((millis() - lastUpdateAt) > 1000)
   {//update in 1s interval

      Temperature2.setValue(temp.temperature);
      humidity2.setValue(humidity.relative_humidity);
      lastUpdateAt =millis();
   }
   
}
}
void onMqttMessage(const char* topic, const uint8_t* payload, uint16_t length)
{
char message;
memcpy(message,payload,length);
message= '\0';

Serial.print("dbglNew message on topic:");
Serial.println(topic);
Serial.print("Data:");
Serial.println((const char*)message);

if(strstr(message,"on")!=NULL)
{
    int dutyCycle=0;
    if (sscanf(message,"on#%d",&dutyCycle)==1)   {   }
}
else if(strstr(message,"off")!=NULL)         {      }
   else
   {
   Serial.println("Unrecognized message");
   }
memset(message,0, length);
}
void onMqttConnected()
{
Serial.println("Connected to the broker!");
//You can subscribe to custom topic if you need
mqtt.subscribe(TOPIC_SUBSCRIBE);//command
//mqtt.subscribe(TOPIC SUBSCRIBE2)://status
Serial.println("subscribed to topic:" TOPIC_SUBSCRIBE);
mqtt.publish(TOPIC_SUBSCRIBE,"Hi EMOX I'mArdinO UNO R4 WIFI^^");
}
void onMqttDisconnected()
{
Serial.println("Disconnected from the broker!");
}

void onMqttStateChanged(HAMqtt::ConnectionState state)
{
Serial.print("MoTT state changed to:");
Serial.println(static_cast<int8_t>(state));
}
void onButtonCommand(HAButton* sender)
{
if(sender ==&buttonON)
{
    Serial.print("buttonON");// button A was clicked, do your logic hereelse
    digitalWrite(LED_BUILTIN, HIGH);
   }
   else if(sender==&buttonOFF)
   {
    Serial.print("buttonOFF");// button B was clicked, do your logic here
    digitalWrite(LED_BUILTIN, LOW);
   }
}

void wifi_and_mqtt_init()
{
//check for the WiFi module:
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");
}

//attempt to connect to wiFi network;
while(status!=WL_CONNECTED)
{
Serial.print("Attempting to connect to SSID:");
Serial.println(SECRET_SSID);
//Connect to WPA/WPA2 network, Change this line if using open or WEP network;
status=WiFi.begin(SECRET_SSID,SECRET_PASS);
delay(10000);
}

Serial.println("\nStarting connection to MoTT server...");
mqtt.onMessage(onMqttMessage);
mqtt.onConnected(onMqttConnected);
mqtt.onDisconnected(onMqttDisconnected);
mqtt.onStateChanged(onMqttStateChanged);

//If you want to change prefix only for non-discovery prefix:
mqtt.setDataPrefix("UNO");

if(!mqtt.begin(MQTT_SERVER,MQTT_PORT,MQTT_USERNAME,MQTT_PASSWORD))
{
   Serial.print("Failed, rC=");
   Serial.print(mqtt.getState());//0btaining state of the MoTr connection:
   Serial.println("tryagain in 5 seconds");
   delay(5000);
   }
}
```

运行效果如下



对着传感器哈气后温度湿度都有所上升,温度从30度上升至35度。湿度由60%上升到90%

### 流程图




# 项目总结

在这个精彩纷呈的“Follow me”第二季项目中,我有幸深入探索了Arduino UNO R4 WiF这一功能强大的开发板,并从中获得了许多宝贵的知识和技能。通过这个项目,我掌握了如何自己搭建物联网服务器,花了我具多时间,一度想要放弃,感谢小助手从中的鼓励。同时也掌握了本地传感器数据上传。

在温度和光照传感器的学习过程中,我了解到了环境监测的重要性,并且学会了如何通过编程来收集和分析这些数据。这些技能在物联网(IoT)和智能家居项目中尤为重要,为我打开了一扇通往未来技术的大门。

这些项目的实践操作不仅锻炼了我的动手能力,更重要的是,它们加深了我对硬件编程的理解。我学会了如何将抽象的编程概念应用到具体的硬件设备上,并且能够解决实际问题。

我非常感激EEWorld和Digi-Key提供的这次学习机会。这次经历不仅丰富了我的技术储备,也为我未来的电子项目和职业生涯打下了坚实的基础。我期待着将这些新学到的技能应用到更多的创新项目中,并且希望能够继续在电子和编程领域不断探索和成长。

# 项目程序


<br/><br/>


# End

秦天qintian0303 发表于 2024-10-22 08:59

<p>恭喜顺利完成&nbsp; &nbsp;</p>
页: [1]
查看完整版本: 【Follow me第二季第2期】学习Arduino UNO R4 WiFi 之任务汇总