项目演示视频
物料展示
清单
Arduino UNO R4 WiFi
Qwiic缆线-50mm
SHT40温湿度传感器扩展板
10K电阻 * 2
6PIN 排针
1.Arduino UNO R4 WiFi 分析与介绍
UNO R4 WiFi采用了强大且非常稳健的瑞萨微控制器,该控制器也用于UNO R4 Minima上。瑞萨的微控制器以其高性能和稳健性而闻名,包括其内置的外设。这些外设包括模数转换器、定时器、脉冲宽度调制(PWM)单元、通信接口(例如UART、SPI和I2C)等。
1.1、核心规格
- 处理器:采用Renesas RA4M1(Arm Cortex®-M4)微控制器,运行速度为48MHz,相比UNO R3快3倍。
- 存储:SRAM从R3的2kB增加到32kB,闪存从32kB增加到256kB,以适应更复杂的项目需求。
- 工作电压:标准5V,但输入电压支持6V至24V,提供了更大的灵活性。
- 编程端口:USB-C接口,方便现代设备的连接。
1.2、特色功能
- WiFi与蓝牙:内置Espressif S3 WiFi模块,支持WiFi和蓝牙连接,便于开发者创建物联网项目。
- LED矩阵:板载一个12x8的红色LED矩阵(总共96个点),非常适合用于创意项目中的动画或数据可视化。
- Qwiic连接器:提供一个行业标准的Qwiic I2C连接器,便于快速连接各种兼容模块,扩展开发板的功能。
- 新外设:包括12位模拟DAC、CAN总线、运算放大器和SWD端口等,增强了开发板的功能和灵活性。
1.3硬件探索
供电电路
主要有3种供电方式
- 开发板可以通过VIN引脚供电,支持6-24V的范围。
- VIN引脚也连接到直流插孔(圆柱插头连接器)。
- USB C口供电。
使用ISL8541102 降压型DC-DC芯片 将VIN的电压转换成5V电源,ISL8541102是瑞萨的一个宽输入,能提供1.2A电流能力的同步整流的降压芯片,封装很小,使用圣邦微SGM2205(线性稳压器)提供3.3V电源
USB CONNECTOR 电路
NLASB3157 是一个模拟开关用于切换USB C 是跟ESP32S3连接,还是R7FA4M1AB3CFM。
综合来看这个板子,应该是用ESP32给瑞萨MCU下载的。
2.基本任务
2.1入门任务(必做):搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
2.1.1 Blink LED闪灯
使用物料及外设:GPIO,一个板载LED
// the setup function runs once when you press reset or power the board
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
}
2.1.2 串口打印Hello EEWorld!
使用物料及外设:GPIO,一个板载LED
void setup()
{
Serial.begin(9600);//设置波特率
Serial.println("Hello EEWorld!\r\n");//提示字符
}
void loop()
{
delay(5000);
Serial.println("Hello EEWorld!\r\n");
}
2.2 基础任务(必做):驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据曲线
2.2.1驱动12x8点阵LED
使用物料及外设:使用板载LED矩阵
UNO R4 WiFi 板载了一个12*8的红色LED矩阵,可以通过编程来控制这个矩阵以显示不同的图案、文字或动画。
该矩阵使用Charlieplexing将 96 个 LED 连接到仅 11 个 GPIO 端口(Arduino 表示法中的 D28 到 D38)。这种方式使用了很少的gpio端口就点亮了很多的LED灯, 因为像素由两个反并联连接的 LED 组成,并且像素共享端口。然而,由于人眼速度较慢,快速时间复用可以欺骗大脑看到完整的图像。
Arduino官方开发了一种工具,可以在浏览器中的 LED 矩阵上渲染的帧和动画。制作完动画之后,可以从工具中导出LED点阵数据。
单击此处转到 LED 矩阵工具。
制作完动画之后,你可以按照前面讨论过的格式,从工具中导出它们。
这里可以导出.h 文件
#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;
byte frame[8][12] = {
{ 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
uint32_t animation[] = {
0x400e015,
0x400400,
0x40040000
};
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
matrix.begin();
matrix.renderBitmap(frame, 8, 12);
delay(1000);
delay(1000);
frame[0][0] = 1;
matrix.renderBitmap(frame, 8, 12);
delay(1000);
delay(1000);
matrix.loadFrame(animation);
}
void loop() {
// put your main code here, to run repeatedly:
}
2.2.2用DAC生成正弦波
使用物料及外设:使用板载ADC DAC
Arduino R4可以直接使用wave生成正弦波
void setup() {
Serial.begin(500000);//设置波特率
Serial.println("Hello EEWorld!\r\n");//提示字符
wave.sine(freq);
wave.amplitude(0.5);
}
void loop() {
sensorValue = analogRead(A4);
Serial.println(sensorValue);
}
2.2.3用OPAMP放大DAC信号
使用物料及外设:2个10K电阻,板载放大器,ADC
#include "analogWave.h"
#include <OPAMP.h>
analogWave wave(DAC); // 使用DAC引脚实例化模拟曲线对象wave
float freq = 1; // 设置曲线初始频率
void setup() {
Serial.begin(2000000); // 串口波特率
OPAMP.begin(OPAMP_SPEED_HIGHSPEED); //设置OPAMP
wave.sine(freq); // 使用模拟曲线对象wave按照初始频率生成正弦波
wave.amplitude(0.5); //设置正弦曲线幅值为0.4
}
void loop() {
printf("%d\n",analogRead(A4)); // 读取DAC输出正弦值
Serial.print(" ");
printf("%d\n",analogRead(A5)); // 读取OPAMP输出正弦值
delay(100);
}
2.3 进阶任务(必做):通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
#include <ArduinoHA.h>
#include <Wire.h>
#include "WiFiS3.h"
#include "arduino_secrets.h"
int status = WL_IDLE_STATUS;
unsigned long lastUpdateAt = 0;
int freg=1;//max200 Hz imit by serial print
WiFiClient client;
HADevice device(MQTT_CLIENT_ID);//HADevice device (mac, sizeof (mac));
HAMqtt mqtt(client,device);
void setup() {
Serial.begin(9600);
wifi_and_mqtt_init();
}
void loop() {
mqtt.loop();
if ((millis() - lastUpdateAt) > 2000) { // update in 2s interval
lastUpdateAt = millis();
mqtt.publish(TOPIC_SUBSCRIBE,"Hi HA I'm Arduino UNO R4 WII");
}
}
void wifi_and_mqtt_init()
{
//check for the WiFi module:
////检查WiFi模块:
if(WiFi.status() == WL_NO_MODULE){
//WiFi模块通信失败
Serial.println("Communication with WiFi module failed!");
while(true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION){
Serial.println("Please upqrade the firmware");
}
//attempt to connect to WiFi network:
while(status!=WL_CONNECTED){
Serial.print("Attempting to connect to sID:");
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);
}
// mqtt.setDataPrefix("UNO");
if(!mqtt.begin(MQTT_SERVER,MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD)){
Serial.print("Failed,rc=");
Serial.print(mqtt.getState());
Serial.println("try again in f 5 seconds");
delay(5000);
}
printWifistatus();
}
void printWifistatus()
{
Serial.print("SSID:");
Serial.println(WiFi.SSID());
IPAddress ip= WiFi.localIP();
Serial.print("IP Address:");
Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("signal strength(RssI):");
Serial.print(rssi);
Serial.println("dBm");
}
3.扩展任务
3.1 SHT40传感器
SHT40传感器可以连接到Arduino UNO R4 WiFi Qwiic接口上,但需要注意几个关键点,以确保硬件的安全和正确的通信。
- 电压兼容性:
-
- Qwiic接口仅支持3.3V供电。这意味着SHT40传感器和其他通过Qwiic连接器连接的设备都应设计为在3.3V下工作。
- 切勿尝试将5V或其他高于3.3V的电压连接到Qwiic接口,因为这可能会损坏您的Arduino R4板或其他连接的组件。
- I2C总线选择:
-
- Arduino R4可能具有多个I2C总线。由于Qwiic连接器连接到次级I2C总线(通常标记为IIC0或Wire1),您需要在代码中指定使用Wire1库来初始化这个特定的I2C总线。
- 使用Wire1.begin()而不是默认的Wire.begin()来初始化I2C通信。
Wier1在Wier.h 的声明
#if WIRE_HOWMANY > 0
extern TwoWire Wire;
#endif
#if WIRE_HOWMANY > 1
extern TwoWire Wire1;
#endif
#if WIRE_HOWMANY > 2
extern TwoWire Wire2;
#endif
#if WIRE_HOWMANY > 3
extern TwoWire Wire3;
#endif
在pins_arduino.h 的引脚定义
#define WIRE_HOWMANY 2
#define WIRE_SDA_PIN 18 /* A4 */
#define WIRE_SCL_PIN 19 /* A5 */
#define WIRE1_SDA_PIN 27
#define WIRE1_SCL_PIN 26
static const uint8_t SDA = WIRE_SDA_PIN;
static const uint8_t SCL = WIRE_SCL_PIN;
示例代码
22行,要改为 if (! sht4.begin(&Wire1))
/***************************************************
This is an example for the SHT4x Humidity & Temp Sensor
Designed specifically to work with the SHT4x sensor from Adafruit
----> https://www.adafruit.com/products/4885
These sensors use I2C to communicate, 2 pins are required to
interface
****************************************************/
#include "Adafruit_SHT4x.h"
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
void setup() {
Serial.begin(115200);
while (!Serial)
delay(10); // will pause Zero, Leonardo, etc until serial console opens
Serial.println("Adafruit SHT4x test");
if (! sht4.begin(&Wire1)) {
Serial.println("Couldn't find SHT4x");
while (1) delay(1);
}
Serial.println("Found SHT4x sensor");
Serial.print("Serial number 0x");
Serial.println(sht4.readSerial(), HEX);
// You can have 3 different precisions, higher precision takes longer
sht4.setPrecision(SHT4X_HIGH_PRECISION);
switch (sht4.getPrecision()) {
case SHT4X_HIGH_PRECISION:
Serial.println("High precision");
break;
case SHT4X_MED_PRECISION:
Serial.println("Med precision");
break;
case SHT4X_LOW_PRECISION:
Serial.println("Low precision");
break;
}
// 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);
switch (sht4.getHeater()) {
case SHT4X_NO_HEATER:
Serial.println("No heater");
break;
case SHT4X_HIGH_HEATER_1S:
Serial.println("High heat for 1 second");
break;
case SHT4X_HIGH_HEATER_100MS:
Serial.println("High heat for 0.1 second");
break;
case SHT4X_MED_HEATER_1S:
Serial.println("Medium heat for 1 second");
break;
case SHT4X_MED_HEATER_100MS:
Serial.println("Medium heat for 0.1 second");
break;
case SHT4X_LOW_HEATER_1S:
Serial.println("Low heat for 1 second");
break;
case SHT4X_LOW_HEATER_100MS:
Serial.println("Low heat for 0.1 second");
break;
}
}
void loop() {
sensors_event_t humidity, temp;
uint32_t timestamp = millis();
sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
timestamp = millis() - timestamp;
Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
Serial.print("Read duration (ms): ");
Serial.println(timestamp);
delay(1000);
}
3.2 STH40温湿度数据上传HA
#include <ArduinoHA.h>
#include <OPAMP.h>
#include <Wire.h>
#include "WiFiS3.h"
#include "arduino_secrets.h"
#include "Adafruit_SHT4x.h"
sensors_event_t humidity, temp;
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
int status = WL_IDLE_STATUS;
unsigned long lastUpdateAt = 0;
int freg=1;//max200 Hz imit by serial print
WiFiClient client;
HADevice device(MQTT_CLIENT_ID);//HADevice device (mac, sizeof (mac));
HAMqtt mqtt(client,device);
HASensorNumber upSHT40_C_Sensor("SHT40_C");
HASensorNumber upSHT40_RH_Sensor("SHT40_RH");
void setup() {
Serial.begin(9600);
if (! sht4.begin(&Wire1)) {
Serial.println("Couldn't find SHT4x");
while (1) delay(1);
}
// You can have 3 different precisions, higher precision takes longer
sht4.setPrecision(SHT4X_HIGH_PRECISION);
switch (sht4.getPrecision()) {
case SHT4X_HIGH_PRECISION:
Serial.println("High precision");
break;
case SHT4X_MED_PRECISION:
Serial.println("Med precision");
break;
case SHT4X_LOW_PRECISION:
Serial.println("Low precision");
break;
}
// 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);
switch (sht4.getHeater()) {
case SHT4X_NO_HEATER:
Serial.println("No heater");
break;
case SHT4X_HIGH_HEATER_1S:
Serial.println("High heat for 1 second");
break;
case SHT4X_HIGH_HEATER_100MS:
Serial.println("High heat for 0.1 second");
break;
case SHT4X_MED_HEATER_1S:
Serial.println("Medium heat for 1 second");
break;
case SHT4X_MED_HEATER_100MS:
Serial.println("Medium heat for 0.1 second");
break;
case SHT4X_LOW_HEATER_1S:
Serial.println("Low heat for 1 second");
break;
case SHT4X_LOW_HEATER_100MS:
Serial.println("Low heat for 0.1 second");
break;
}
wifi_and_mqtt_init();
device.setName("Arduino_SHT40_MY");
device.setSoftwareVersion("1.0.1");
upSHT40_C_Sensor.setIcon("mdi:home");
upSHT40_C_Sensor.setName("SHT40_C");
//upSHT40_C_Sensor.setUnitOfMeasurement("C");
upSHT40_RH_Sensor.setIcon("mdi:home");
upSHT40_RH_Sensor.setName("SHT40_RH");
// upSHT40_RH_Sensor.setUnitOfMeasurement("RH");
}
void loop() {
mqtt.loop();
if ((millis() - lastUpdateAt) > 2000) { // update in 2s interval
sht4.getEvent(&humidity, &temp);
upSHT40_RH_Sensor.setValue(humidity.relative_humidity);
upSHT40_C_Sensor.setValue(temp.temperature);
Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
lastUpdateAt = millis();
mqtt.publish(TOPIC_SUBSCRIBE,"Hi EMQX I'm Arduino UNO R4 WII");
// you can reset the sensor as follows:
// analogSensor.setValue(nullptr);
}
}
void wifi_and_mqtt_init()
{
//check for the WiFi module:
////检查WiFi模块:
if(WiFi.status() == WL_NO_MODULE){
//WiFi模块通信失败
Serial.println("Communication with WiFi module failed!");
while(true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION){
Serial.println("Please upqrade the firmware");
}
//attempt to connect to WiFi network:
while(status!=WL_CONNECTED){
Serial.print("Attempting to connect to sID:");
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);
}
// mqtt.setDataPrefix("UNO");
if(!mqtt.begin(MQTT_SERVER,MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD)){
Serial.print("Failed,rc=");
Serial.print(mqtt.getState());
Serial.println("try again in f 5 seconds");
delay(5000);
}
printWifistatus();
}
void printWifistatus()
{
Serial.print("SSID:");
Serial.println(WiFi.SSID());
IPAddress ip= WiFi.localIP();
Serial.print("IP Address:");
Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("signal strength(RssI):");
Serial.print(rssi);
Serial.println("dBm");
}
4.ArduinoHA讲解补充
ArduinoHA是一个专为Arduino和ESP系列微控制器设计的开源库,其主要功能是实现这些设备与Home Assistant智能家居平台之间的无缝通信。使用MQTT(消息队列遥测传输)协议来完成通讯,MQTT是一种轻量级的、基于发布/订阅模式的消息传输协议,非常适合用于物联网(IoT)场景。
通过ArduinoHA库,开发者可以轻松地将Arduino或ESP设备集成到Home Assistant生态系统中,实现智能家居设备的智能化控制。这包括但不限于灯光控制、温湿度监测、门窗传感器、安防系统等。
ArduinoHA库提供了一系列API函数,用于设备的初始化、MQTT连接管理、设备状态更新以及处理来自Home Assistant的命令等。这些API函数使得开发者能够以简单、直观的方式编写代码,从而实现与Home Assistant的通信。
此外,ArduinoHA还支持MQTT自动发现功能,这意味着当设备首次连接到MQTT服务器时,它会自动向Home Assistant发送设备信息,从而避免了手动在Home Assistant中添加设备的繁琐过程。
使用方法与配置步骤:
1.连接到Home Assistant:
- 连接到WiFi网络。
- 初始化MQTT客户端并连接到MQTT服务器。
- 配置并添加设备到MQTT客户端。
- 在loop函数中处理MQTT消息并更新设备状态。
关键点:
全局初始化:
HADevice 和 HAMqtt 实例需要全局初始化,或者作为另一个全局对象的一部分进行初始化。
MQTT连接设置:
在Arduino的setup()逻辑结束时,需要调用HAMqtt::begin()方法。这个方法允许您提供MQTT代理(Broker)的IP地址和认证信息(如用户名和密码,如果有的话)。
MQTT循环处理:
HAMqtt::loop()方法需要被周期性地调用(不必在每个循环迭代中都调用)。这个方法负责处理MQTT通信中的接收和发送任务。
设备类型初始化:
设备类型(如传感器、开关等)需要在HAMqtt类之后进行初始化。关于如何初始化不同类型的设备,将在后面的文档中详细描述。
2.配置Home Assistant:
在Home Assistant中,无需手动添加设备,因为ArduinoHA支持MQTT自动发现。设备将自动出现在Home Assistant的设备列表中。
使用HADevice 配置设备信息
HADevice 类是一个用于表示将要注册到 Home Assistant 设备注册表中的设备的类。在智能家居自动化系统中,每个设备都会有一个唯一的标识符(ID),以便系统能够区分和控制它们。HADevice 类提供了构造函数来初始化设备对象,并允许设置设备的各种属性,如名称、制造商、型号等。
使用Device types API来设置实体信息
代码:>> 点击下载代码
项目总结
通过这次Follow me第二季第2期的活动,我有幸接触并深入学习了Arduino uNo R4 WIFI板卡的基本功能,以及HA物联网系统的搭建和ArduinoHA的相关知识。这次活动为我提供了一个宝贵的学习和实践机会,让我能够更深入地理解物联网技术及其在实际应用中的潜力。通过实际操作,成功搭建了一个简单的物联网系统,实现了对智能家居设备的远程控制和监控。学习了ArduinoHA的基本概念和工作原理,了解了其作为Arduino与HA系统之间的桥梁所发挥的重要作用。本次Follow me第二季第2期的活动让我收获颇丰。我不仅学到了许多新知识,还通过实际操作加深了对物联网技术的理解。未来,我将继续深入学习物联网领域的相关知识,不断提高自己的专业技能和实践能力,为未来的项目开发和研究打下坚实的基础。同时,我也期待能够有更多的机会参与类似的活动,与更多的同行交流和学习。