【Follow me第二季第2期】Arduino UNO R4 WiFi全部任务汇总学习+Labview+自己扩展项目
[复制链接]
活动链接资料:https://www.eeworld.com.cn/huodong/digikey_follow_me_2024_02/
写在前面的:
很幸运能够在最后一批空余名额能够入围,很珍惜此次活动,下面学习将认真完成各项指标(多关注群里信息还是非常重要的)
下单也响应很快,很快物料都到齐了
自己给Arduino UNO R4 WiFi加了个外置电源,也非常适配,这不得不得益于其DC电源最新设计
关于Arduino UNO R4 WiFi是最新Arduino开发板,主控芯片为日本瑞萨电子的RA4M1芯片(因为使用“钞”能力了),WiFi芯片为中国的ESP32,个人觉得一个ESP32其实足以,非要说这样组合有什么优点,其实也是有点优势的:
1.系统电压兼容5V,适配Arduino UNO R3的扩展板接口,便于通用及产品迭代
2.冗余设计,联网WiFi功能与主控控制功能隔离提高产品安全性与产品开发维护
Arduino UNO R3与Arduino UNO R4 WiFi对比:可以看出集成度确实提高很多,功能更丰富
入门任务(必做):搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
▄▄▄▄▄▄▄▄▄▄▄▄▄
搭配器件:Arduino UNO R4 WiFi
搭建环境:
1.下载Arduino IDE 2.3.2链接:https://www.arduino.cc/en/software
2.打开IDE获取Arduino UNO R4 WiFi开发板相关扩展包
3.安装最新扩展包
4.选择Arduino UNO R4 WiFi开发板
搭建环境流程图:
5.打开默认案例库:点开启第一步Blink
6.通过USB连接Arduino UNO R4 WiFi开发板
7.编译代码,程序烧写到Arduino UNO R4 WiFi开发板
8.程序代码
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
}
9.显示效果
程序流程图:
10.串口打印Hello EEWorld!
打开案例库,在此基础进行修改代码
11.程序代码:
void loop() {
// read the input on analog pin 0:
//int sensorValue = analogRead(A0);
// print out the value you read:
//Serial.println(sensorValue);
Serial.println("Hello EEWorld!");
delay(100);
//delay(1); // delay in between reads for stability
}
12.打开电脑串口接收器:
13.电脑虚拟串口接收到数据
14.显示效果:
程序流程图:
基础任务(必做):驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
▄▄▄▄▄▄▄▄▄▄▄▄▄
搭配器件:Arduino UNO R4 WiFi
1.驱动12x8点阵LED
原理和一般点阵屏有点不一样,传统点阵屏只用单片机I/O的输出高、低电平两种状态,而Arduino UNO R4 WiFi 点阵屏使用I/O的输出高、低、高阻态电平三种种状态,理论上n个I/O可以实现n*(n-1)个LED控制,Arduino UNO R4 WiFi 点阵屏使用I/O原理可具体解读:IO口多路查理复用:三个单片机IO口控制六个LED:https://blog.csdn.net/zhuoqingjoking97298/article/details/116725947
具体控制方法可参考官网:https://docs.arduino.cc/tutorials/uno-r4-wifi/led-matrix/
当然可直接打开IDE中的案例库
代码:
/*
Single Frame
Displays single frames using matrix.loadFrame
See the full documentation here:
https://docs.arduino.cc/tutorials/uno-r4-wifi/led-matrix
*/
#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);
// Print the current value of millis() to the serial monitor
Serial.println(millis());
}
效果演示:
程序流程图:
扩展应用:参考内容:https://blog.csdn.net/blueskyspace/article/details/138769310
效果展示:
2.用DAC生成正弦波
打开案例库
修改代码;利用A5接口采集DAC的波形信号
硬件接法:
实物接法:
软件修改代码如下:
#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); // Initialize serial communication at a baud rate of 115200
wave.sine(freq); // Generate a sine wave with the initial frequency
wave.amplitude(0.5);//幅值倍数
}
void loop() {
Serial.println(analogRead(A5));
delay(10);
}
调试效果:
程序流程图:
3.用OPAMP放大DAC信号
没有插件电阻,自己DIY一个插件电阻
其实很简洁,连接好也很方便
为什么选择10K电阻的原因;
实验效果:
程序代码:
#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() {
Serial.print(analogRead(A4));
Serial.print(" ");
Serial.println(analogRead(A5));
delayMicroseconds(100);
}
测试波形
为了完成任务,搞了台示波器,真实为了完成任务蛮拼的
测试波形周期200hz
DAC输出幅值为:2.29V
运放输出幅值为:4.6V
程序流程图:
4.用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
实际上该部分和上部分基本重复了,为了更好展示波形数据,采用Labview上位机显示更多波形数据
Arduino UNO R4 WiFi下位机硬件图
程序代码:
#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() {
Serial.print(analogRead(A4));
Serial.print(",");
Serial.println(analogRead(A5));
delayMicroseconds(100);
}
通过Arduino IDE自带串口也可串口波形数据
连接方式:通过USB连接,labview上位机通过串口获取Arduino UNO R4 WiFi采集数据
打开labview案例库
在此基础修改增加波形显示插件
程序代码:
运行效果:波形正常显示无异常
labview程序附件:2015版本
相关程序流程图:
进阶任务(必做):通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
▄▄▄▄▄▄▄▄▄▄▄▄▄
搭配器件:Arduino UNO R4 WiFi
相关下载链接可参考(超级快Docker Desktop installer 4.32.0.exe):https://download.csdn.net/download/qq_72421395/89586495
电脑系统:window10家庭版
相关配置:docker Hyper-V可以不用配置
安装Docker界面:
安装完成:
运行Docker出现:Docker Engine stopped
按照教程视频一步步进行镜像下载:(需要科学上网,我是直接连接酒店公共WIFI进行下载的)
按照教程一步步很顺利
HA_container容器安装也很顺利
安装完成界面
启动EMQX_container
打开链接查看Arduino相关参数
Arduino Uno R4程序代码:
主程序代码:
#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);
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);
}
void loop()
{
mqtt.loop();
if((millis() - lastUpdateAt) > 1000)
{//update in 1s interval
uint16_t reading = analogRead(A5);
float voltage=reading *5.f / 16383.f;//0.0V-5.0V
Serial.print("volt:");
Serial.println(voltage);
analogSensor.setValue(voltage);
unsigned long uptimeValue=millis()/1000;
Serial.print("uptimeValue:");
Serial.println(uptimeValue);
uptimeSensor.setValue(uptimeValue);
lastUpdateAt =millis();
}
}
void onMqttMessage(const char* topic, const uint8_t* payload, uint16_t length)
{
char message[length];
memcpy(message,payload,length);
message[length]= '\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("[dbg]buttonON");// button A was clicked, do your logic hereelse
digitalWrite(LED_BUILTIN, HIGH);
}
else if(sender==&buttonOFF)
{
Serial.print("[dbg]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);
}
//printwifistatus();
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);
}
}
void printWifiStatus(){
Serial.print("SSID:");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("Ip Address:");
Serial.println(ip);
}
arduino_secrets.h代码
#define MQTT_SERVER "192.168.31.19"// 电脑无线网卡IP地址"xxx.xxx.xxx.xxX
#define MQTT_PORT 1883 //定义MQTT服务器的端口
#define MQTT_CLIENT_ID "arduino"// 定义客户端的ID'arduino'
#define MQTT_USERNAME "admin" // 定义用户名,EMQX定义"admin'
#define MQTT_PASSWORD "admin" // 定义密码,EMQX定义"admin"
#define TOPIC_SUBSCRIBE "UNO/arduino/switch/cmd_t"//定义订阅的主题
#define SECRET_SSID "Maker_kun" // 路由器WiFi名称 也可使用win移动热点"xxXXX
#define SECRET_PASS "12344321" // 路由器WiFi密码”xxxXX
程序界面:
程序流程图:
连接效果:
搭建HA环境花费一周时间,基本上是卡在镜像安装,其他问题基本上百度就可以搜到解决方案,视频教程讲的不够仔细,对于初学者很不友好
扩展任务
▄▄▄▄▄▄▄▄▄▄▄▄▄
■ 扩展任务一:通过外部LTR-329 环境光传感器,上传光照度到HA,通过HA面板显示数据
搭配器件: Arduino UNO R4 WiFi、5591(LTR-329光传感器扩展板)、PRT-14426(Qwiic缆线-50mm)
获取LTR-329 环境光传感器数据
安装库Adafruit LTR329 and LTR303
打开案例库:
串口打印出LTR-329 环境光传感器数据
程序流程图:
实物照片:
注意事项:
修改默认IIC接口以匹配QWIC
第13行增加 #include “Wire.h”
第20行修改为 if(!ltr.begin(&Wire1)){
通过外部LTR-329 环境光传感器,上传光照度到HA,通过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"
Adafruit_LTR329 ltr = Adafruit_LTR329();
#include "Wire.h"
analogWave wave(DAC);
int status= WL_IDLE_STATUS;
unsigned long lastUpdateAt=0;
int freg=1;//max200 Hz limit by serial print
bool valid;
uint16_t visible_plus_ir, infrared;
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);
if ( ! ltr.begin(&Wire1) ) {
Serial.println("Couldn't find LTR sensor!");
while (1) delay(10);
}
ltr.setGain(LTR3XX_GAIN_2);
switch (ltr.getGain()) {
case LTR3XX_GAIN_1: Serial.println(1); break;
case LTR3XX_GAIN_2: Serial.println(2); break;
case LTR3XX_GAIN_4: Serial.println(4); break;
case LTR3XX_GAIN_8: Serial.println(8); break;
case LTR3XX_GAIN_48: Serial.println(48); break;
case LTR3XX_GAIN_96: Serial.println(96); break;
}
ltr.setIntegrationTime(LTR3XX_INTEGTIME_100);
Serial.print("Integration Time (ms): ");
switch (ltr.getIntegrationTime()) {
case LTR3XX_INTEGTIME_50: Serial.println(50); break;
case LTR3XX_INTEGTIME_100: Serial.println(100); break;
case LTR3XX_INTEGTIME_150: Serial.println(150); break;
case LTR3XX_INTEGTIME_200: Serial.println(200); break;
case LTR3XX_INTEGTIME_250: Serial.println(250); break;
case LTR3XX_INTEGTIME_300: Serial.println(300); break;
case LTR3XX_INTEGTIME_350: Serial.println(350); break;
case LTR3XX_INTEGTIME_400: Serial.println(400); break;
}
ltr.setMeasurementRate(LTR3XX_MEASRATE_200);
Serial.print("Measurement Rate (ms): ");
switch (ltr.getMeasurementRate()) {
case LTR3XX_MEASRATE_50: Serial.println(50); break;
case LTR3XX_MEASRATE_100: Serial.println(100); break;
case LTR3XX_MEASRATE_200: Serial.println(200); break;
case LTR3XX_MEASRATE_500: Serial.println(500); break;
case LTR3XX_MEASRATE_1000: Serial.println(1000); break;
case LTR3XX_MEASRATE_2000: Serial.println(2000); break;
}
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()
{
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);
}
}
mqtt.loop();
if((millis() - lastUpdateAt) > 50)
{
Serial.print("infrared:");
Serial.println(infrared);
analogSensor.setValue(infrared);
Serial.print("visible_plus_ir:");
Serial.println(visible_plus_ir);
uptimeSensor.setValue(visible_plus_ir);
lastUpdateAt =millis();
}
}
void onMqttMessage(const char* topic, const uint8_t* payload, uint16_t length)
{
char message[length];
memcpy(message,payload,length);
message[length]= '\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("[dbg]buttonON");// button A was clicked, do your logic hereelse
digitalWrite(LED_BUILTIN, HIGH);
}
else if(sender==&buttonOFF)
{
Serial.print("[dbg]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);
}
//printwifistatus();
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);
}
}
void printWifiStatus(){
Serial.print("SSID:");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("Ip Address:");
Serial.println(ip);
}
程序流程图:
显示数据到HA界面上
显示效果:光线变化,HA界面传感器采集数据也变化
▄▄▄▄▄▄▄▄▄▄▄▄▄
■ 扩展任务二:通过外部SHT40温湿度传感器,上传温湿度到HA,通过HA面板显示数据
搭配器件: Arduino UNO R4 WiFi、4885(SHT40温湿度传感器扩展板)、PRT-14426(Qwiic缆线-50mm)
获取SHT40温湿度传感器数据
安装库Adafruit SHT4X
打开案例库:
串口打印出SHT40温湿度传感器数据
程序流程图:
实物照片:
代码:
#include "Adafruit_SHT4x.h"
#include "Wire.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);
}
注意事项:
修改默认IIC接口以匹配QWIC
第13行增加 #include “Wire.h”
第20行修改为 if(!ltr.begin(&Wire1)){
通过外部SHT40温湿度传感器,上传温湿度到HA,通过HA面板显示数据
移植代码如下:
#include<ArduinoHA.h>
#include<OPAMP.h>
#include<Wire.h>
#include"WiFiS3.h"
#include"arduino_secrets.h"
#include"analogWave.h"
#include "Adafruit_SHT4x.h"
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
#include "Wire.h"
analogWave wave(DAC);
int status= WL_IDLE_STATUS;
unsigned long lastUpdateAt=0;
int freg=1;//max200 Hz limit by serial print
sensors_event_t humidity, temp;
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);
if (! sht4.begin(&Wire1)) {
Serial.println("Couldn't find SHT4x");
while (1) delay(1);
}
Serial.println(sht4.readSerial(), HEX);
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();
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()
{
sht4.getEvent(&humidity, &temp);
mqtt.loop();
if((millis() - lastUpdateAt) > 50)
{
Serial.print("temp:");
Serial.println(temp.temperature);
analogSensor.setValue(temp.temperature);
Serial.print("humidity:");
Serial.println(humidity.relative_humidity);
uptimeSensor.setValue(humidity.relative_humidity);
lastUpdateAt =millis();
}
}
void onMqttMessage(const char* topic, const uint8_t* payload, uint16_t length)
{
char message[length];
memcpy(message,payload,length);
message[length]= '\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("[dbg]buttonON");// button A was clicked, do your logic hereelse
digitalWrite(LED_BUILTIN, HIGH);
}
else if(sender==&buttonOFF)
{
Serial.print("[dbg]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);
}
//printwifistatus();
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);
}
}
void printWifiStatus(){
Serial.print("SSID:");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("Ip Address:");
Serial.println(ip);
}
程序界面:
程序流程图:
上传HA数据界面:
显示效果:
以上内容即可完成项目全部任务
其它高阶应用:驱动全彩LED、WiFi局内网控制、WiFi云服务远程控制
▄▄▄▄▄▄▄▄▄▄▄▄▄
驱动全彩LED:点亮WS2812全彩LED
1.下载Adafruit_NeoPixel库
2.打开默认库程序,修改代码
3.修改代码部分
4.下载程序,进行调试
程序代码:
// NeoPixel test program showing use of the WHITE channel for RGBW
// pixels only (won't look correct on regular RGB NeoPixel strips).
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN 6
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 8
// NeoPixel brightness, 0 (min) to 255 (max)
#define BRIGHTNESS 50 // Set BRIGHTNESS to about 1/5 (max = 255)
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
void setup() {
// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
// Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// END of Trinket-specific code.
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(BRIGHTNESS);
}
void loop() {
// Fill along the length of the strip in various colors...
colorWipe(strip.Color(255, 0, 0) , 50); // Red
colorWipe(strip.Color( 0, 255, 0) , 50); // Green
colorWipe(strip.Color( 0, 0, 255) , 50); // Blue
colorWipe(strip.Color( 0, 0, 0, 255), 50); // True white (not RGB white)
whiteOverRainbow(75, 5);
pulseWhite(5);
rainbowFade2White(3, 3, 1);
}
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void whiteOverRainbow(int whiteSpeed, int whiteLength) {
if(whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1;
int head = whiteLength - 1;
int tail = 0;
int loops = 3;
int loopNum = 0;
uint32_t lastTime = millis();
uint32_t firstPixelHue = 0;
for(;;) { // Repeat forever (or until a 'break' or 'return')
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
if(((i >= tail) && (i <= head)) || // If between head & tail...
((tail > head) && ((i >= tail) || (i <= head)))) {
strip.setPixelColor(i, strip.Color(0, 0, 0, 255)); // Set white
} else { // else set rainbow
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
}
strip.show(); // Update strip with new contents
// There's no delay here, it just runs full-tilt until the timer and
// counter combination below runs out.
firstPixelHue += 40; // Advance just a little along the color wheel
if((millis() - lastTime) > whiteSpeed) { // Time to update head/tail?
if(++head >= strip.numPixels()) { // Advance head, wrap around
head = 0;
if(++loopNum >= loops) return;
}
if(++tail >= strip.numPixels()) { // Advance tail, wrap around
tail = 0;
}
lastTime = millis(); // Save time of last movement
}
}
}
void pulseWhite(uint8_t wait) {
for(int j=0; j<256; j++) { // Ramp up from 0 to 255
// Fill entire strip with white at gamma-corrected brightness level 'j':
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
delay(wait);
}
for(int j=255; j>=0; j--) { // Ramp down from 255 to 0
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
delay(wait);
}
}
void rainbowFade2White(int wait, int rainbowLoops, int whiteLoops) {
int fadeVal=0, fadeMax=100;
// Hue of first pixel runs 'rainbowLoops' complete loops through the color
// wheel. Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to rainbowLoops*65536, using steps of 256 so we
// advance around the wheel at a decent clip.
for(uint32_t firstPixelHue = 0; firstPixelHue < rainbowLoops*65536;
firstPixelHue += 256) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
// Offset pixel hue by an amount to make one full revolution of the
// color wheel (range of 65536) along the length of the strip
// (strip.numPixels() steps):
uint32_t pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
// strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
// optionally add saturation and value (brightness) (each 0 to 255).
// Here we're using just the three-argument variant, though the
// second value (saturation) is a constant 255.
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue, 255,
255 * fadeVal / fadeMax)));
}
strip.show();
delay(wait);
if(firstPixelHue < 65536) { // First loop,
if(fadeVal < fadeMax) fadeVal++; // fade in
} else if(firstPixelHue >= ((rainbowLoops-1) * 65536)) { // Last loop,
if(fadeVal > 0) fadeVal--; // fade out
} else {
fadeVal = fadeMax; // Interim loop, make sure fade is at max
}
}
for(int k=0; k<whiteLoops; k++) {
for(int j=0; j<256; j++) { // Ramp up 0 to 255
// Fill entire strip with white at gamma-corrected brightness level 'j':
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
}
delay(1000); // Pause 1 second
for(int j=255; j>=0; j--) { // Ramp down 255 to 0
strip.fill(strip.Color(0, 0, 0, strip.gamma8(j)));
strip.show();
}
}
delay(500); // Pause 1/2 second
}
程序流程图:
5.显示效果
WiFi局内网控制:WIFI控制彩灯颜色变化
打开案例库:
WiFi案例库
增加ws2812控制代码
程序代码:
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN 6 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 8 // Popular NeoPixel ring size
// When setting up the NeoPixel library, we tell it how many pixels,
// and which pin to use to send signals. Note that for older NeoPixel
// strips you might need to change the third parameter -- see the
// strandtest example for more information on possible values.
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
#include "WiFiS3.h"
#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key index number (needed only for WEP)
int led = LED_BUILTIN;
int status = WL_IDLE_STATUS;
WiFiServer server(80);
void setup() {
Serial.begin(9600); // initialize serial communication
pinMode(led, OUTPUT); // set the LED pin mode
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
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 Network named: ");
Serial.println(ssid); // print the network name (SSID);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
server.begin(); // start the web server on port 80
printWifiStatus(); // you're connected now, so print out the status
pixels.clear(); // Set all pixel colors to 'off'
}
void loop() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("new client"); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out to the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("<p style=\"font-size:7vw;\">Click <a href=\"/H\">here</a> turn the LED on<br></p>");
client.print("<p style=\"font-size:7vw;\">Click <a href=\"/L\">here</a> turn the LED off<br></p>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
digitalWrite(LED_BUILTIN, HIGH);
for(int i=0; i<NUMPIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(0, 150, 0));
}
pixels.show();
// GET /H turns the LED on
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(LED_BUILTIN, LOW); // GET /L turns the LED off
for(int i=0; i<NUMPIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(150, 0, 0));
}
pixels.show();
}
}
}
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
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");
// print where to go in a browser:
Serial.print("To see this page in action, open a browser to http://");
Serial.println(ip);
}
填写WiFi相关信息
程序流程图:
相关展示:
完成任务总结:
一 、3-5分钟短视频
视频上传到EE大学堂:https://training.eeworld.com.cn/video/41230
二、任务实现详情
本帖全部内容;
三、可编译下载的代码
源代码上传到EEWORLD论坛下载中心:https://download.eeworld.com.cn/detail/eew_TKwwQ7/634533
四、总结
个人觉得本次Follow me第二季第2期】Arduino UNO R4 WiF任务难度比较高,对于初学者有点难度:
1、需要硬件面包板搭建OPAMP及示波器测试DAC输出波形,对于搞纯软件的小伙伴有点难度,故本人通过labview串口上位机程序搭建波形显示功能
2、HA的搭建需要科学上网才能安装镜像,这对于对不熟悉Doker或者搭建HA的小伙伴来说是一个比较费时间和精力的,故本人通过Arduino UNO R4 WiF案例库搭建一个通过web控制全彩灯的项目来展现WiFi相关功能
3.这次Follow me第二季第2期学习遇到问题,群里的小伙伴能够积极讨论,并有大佬给出解决方案,确实受益匪浅
|