- 2024-09-23
-
回复了主题帖:
【Follow me第二季第2期】+ 作品提交
秦天qintian0303 发表于 2024-9-23 12:46
完成的非常不错
谢谢,我会继续努力学习。
-
发表了主题帖:
【Follow me第二季第2期】+ 作品提交
本帖最后由 lingxin_yuhe 于 2024-10-17 15:45 编辑
## 前言
大家好,我是一名电子爱好者。非常感谢DigiKey联合EEWorld发起的这次大型开发板体验活动Follow me,而且非常高兴能有机会学习Arduino UNO R4 WiFi主板,了解HA及传感器数据采集及传输的原理及实现过程。
## 物料展示
| 序号 | 物料名称 | 实物图片 |
| :----: | :----: | :----: |
| 1 | Arduino UNO R4 WiFi | |
| 2 | LTR-329光传感器扩展板 | |
| 3 | SHT40温湿度传感器扩展板 | |
## 设计思路
**入门任务(必做):搭建环境并开启第一步串口打印Hello EEWorld!**
搭配器件: Arduino UNO R4 WiFi
**基础任务(必做):驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线**
搭配器件: Arduino UNO R4 WiFi
**进阶任务(必做):通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)**
搭配器件: Arduino UNO R4 WiFi
**扩展任务(必做):传感器数据上传到HA,并通过HA面板显示数据**
通过外部SHT40温湿度传感器和通过外部LTR-329 环境光传感器,上传光照度和温湿度到HA,通过HA面板显示数据
搭配器件: Arduino UNO R4 WiFi、LTR-329光传感器扩展板、SHT40温湿度传感器扩展板、杜邦线以及Type-C数据线
## 视频整体介绍
[localvideo]ff20625b3152db33636c7fc4f56f1d57[/localvideo]
## 任务实现详情
### 一、入门任务
帖子地址:**[入门任务(必做):搭建环境并开启第一步串口打印Hello EEWorld!](http://https://bbs.eeworld.com.cn/thread-1291521-1-1.html "入门任务(必做):搭建环境并开启第一步串口打印Hello EEWorld!")**
软件流程图
```flow
st=>start: 开始
op1=>operation: 初始化串口1波特率为9600
op=>operation: 串口打印
op2=>operation: 延时1秒
op3=>operation: loop()
st->op1->op3->op->op2->op3
```
主要使用串口1的输出打印,代码如下所示
```
void setup() {
// put your setup code here, to run once:
//初始化串行通信,设置波特率为9600bps
Serchuial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
//向串口打印“Hello EEWorld!”
Serial.println("Hello EEWorld!");
//等待1秒
delay(1000);
}
```
输出串口监控如图所示
### 二、基础任务
帖子地址:**[开发板基础功能测试(DAC,OPAMP,ADC)](http://https://bbs.eeworld.com.cn/thread-1291975-1-1.html "开发板基础功能测试")**
#### 驱动12x8点阵LED
软件流程图
```flow
st=>start: 开始
op1=>operation: 初始化串口1波特率为115200
op=>operation: 初始化LEDMatrix
op2=>operation: 定义happy[]和heart[]
op4=>operation: loop()
op3=>operation: 输出happy等待1s
op5=>operation: 输出heart等待1s
st->op1->op->op2->op4->op3->op5->op4
```
根据用户教程Using the Arduino UNO R4 WiFi LED Matrix这个说明手册,我们可以知道点阵LED的显示原理,每一个LED代表一位,一共有96个LED,发送一次LED数据至少96位,手册中发送一个frame,内有96个点,例如
```
unsigned long frame[] = {
0x3184a444,
0x42081100,
0xa0040000
};
```
发送数据时需要发送转换后的二进制数值,
0x3184a444(110001100001001010010001000100)
0x42081100(1000010000010000001000100000000)
0xa0040000(10100000000001000000000000000000)
用串口发送二进制方式发送数据,
```
for (int b = 0; b < 3; b++) {
Serial.println(frame, BIN);
}
```
代码如下
```
#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;
void setup() {
// put your setup code here, to run once:
//初始化串行通信,设置波特率为115200bps
Serial.begin(115200);
matrix.begin();
}
const uint32_t happy[] = {
0x19819,
0x80000001,
0x81f8000
};
const uint32_t heart[] = {
0x3184a444,
0x44042081,
0x100a0040
};
void loop() {
// put your main code here, to run repeatedly:
//向串口打印“Hello EEWorld!”
//Serial.println("Hello EEWorld!");
matrix.loadFrame(happy);
//等待1秒
delay(1000);
matrix.loadFrame(heart);
delay(1000);
}
```
实际测试视频
[localvideo]3e45d97e70f578c770f499fa3dc6056c[/localvideo]
#### DAC生成正弦波
软件流程图
```flow
st=>start: 开始
op1=>operation: 初始化串口1波特率为115200
op=>operation: 初始化正弦波
op4=>operation: loop()
op3=>operation: 从A5脚输入
op5=>operation: 输出等待1s
st->op1->op->op4->op3->op5->op4
```
代码如下
```
#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
}
void loop() {
// Read an analog value from pin A5 and map it to a frequency range
freq = map(analogRead(A5), 0, 1024, 0, 10000);
// Print the updated frequency to the serial monitor
Serial.println("Frequency is now " + String(freq) + " hz");
wave.freq(freq); // Set the frequency of the waveform generator to the updated value
delay(1000); // Delay for one second before repeating
}
```
用示波器从A0上测试
[localvideo]c2980e044f78ffe7ef7991fb42664ec2[/localvideo]
#### OPAMP放大DAC信号
硬件接线图,因手里没有合适的电阻,就用了2个3.3K,一个1K的电阻进行的放大设计。
示波器测试如下所示
[localvideo]7c22ead58820d6e4f058222aef2c82c1[/localvideo]
#### ADC采集并且打印数据到串口上传到上位机显示曲线
流程图
```flow
st=>start: 开始
op1=>operation: 初始化串口1波特率为9600
op=>operation: 设置模拟输入14位
op4=>operation: loop()
op3=>operation: 从A3脚输入
op5=>operation: 串口输出等待0.1s
st->op1->op->op4->op3->op5->op4
```
程序代码
```
void setup(){
Serial.begin(9600);
analogReadResolution(14); //change to 14-bit resolution
}
void loop(){
int reading = analogRead(A3); // returns a value between 0-16383
Serial.println(reading);
delay(100);
}
```
串口监视曲线如图所示
### 三、进阶任务
帖子地址:**[MQTT协议接入到开源的智能家居平台HA(HomeAssistant)](http://https://bbs.eeworld.com.cn/thread-1292883-1-1.html "MQTT协议接入到开源的智能家居平台HA(HomeAssistant)")**
这一篇我完成的比视频老师的有些早,不过原理都是一样的。我的实现思路:在虚拟机里面安装了docker HA和mosquitto,使用 Docker 运行一个Python容器,并将其配置为一个简单的HTTP服务器,这样直接访问虚拟机的IP地址就可以访问HA了。
#### 1、下拉home-assistant镜像
```shell
Sudo docker run -d \
--name homeassistant \
--privileged \
--restart=unless-stopped \
-e TZ=Asia/Shanghai \
-v /home/alientek/homeassistant:/config \
-v /run/dbus:/run/dbus:ro \
--network=host \
ghcr.io/home-assistant/home-assistant:stable
```
#### 2、下拉eclipse-mosquitto镜像
```shell
sudo docker pull eclipse-mosquitto
```
启动镜像,注意启动前需要配置,查看我的帖子。
```shell
sudo docker run -it --name=mosquitto --privileged -p 1883:1883 -p 9001:9001 -v /mosquitto/config/mosquitto.conf:/mosquitto/config/mosquitto.conf -v /mosquitto/data:/mosquitto/data -v /mosquitto/log:/mosquitto/log -d eclipse-mosquitto
```
#### 3、使用Docker运行一个Python容器
```shell
docker run --name bjbook -p 8000:80 -it --rm python:3 python -m http.server
```
#### 4、浏览器打开HA并配置
a、浏览器输入http://:8123
b、配置mqtt
设置->设备与服务->搜素MQTT->点击后
配置MQTT
#### 5、使用mqtt客户端进行测试
连接MQTT,按照homeassistant自动发现规则发送数据。
面板上可以看到发送的数据了。
## 四、扩展任务
帖子地址:**[UNO R4 WIFI传感器上传HA](http://https://bbs.eeworld.com.cn/thread-1293037-1-1.html "UNO R4 WIFI传感器上传HA")**
#### 1、Arduino安装PubSubClient
#### 2、用MQTTX客户端注册设备(注:可以在ha界面里面自行配置)
```shell
Config No.1:
config topic: homeassistant/sensor/HA/HA-UNO-R4-WIFI-currentTemp/config
payload:
{
"device_class": "temperature",
"unique_id": "HA-UNO-R4-WIFI-currentTemp",
"name": "Temperature",
"icon": "mdi:thermometer",
"state_topic": "homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state",
"value_template":"{{ value_json.temperature}}",
"unit_of_measurement": "℃",
"device": {
"identifiers": "HA-UNO-R4-WIFI",
"manufacturer": "宏伟大业有限公司",
"model": "HA",
"name": "HA-UNO-R4-WIFI",
"sw_version": "1.0"
}
}
Config No.2:
config topic: homeassistant/sensor/HA/HA-UNO-R4-WIFI-currentHumi/config
payload:
{
"device_class": "humidity",
"unique_id": "HA-UNO-R4-WIFI-currentHumi",
"name": "Humidity",
"icon": "mdi:water-percent",
"state_topic": "homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state",
"value_template": "{{ value_json.humidity}}",
"unit_of_measurement": "%",
"device": {
"identifiers": "HA-UNO-R4-WIFI",
"manufacturer": "宏伟大业有限公司",
"model": "HA",
"name": "HA-UNO-R4-WIFI",
"sw_version": "1.0"
}
}
Config No.3:
config topic: homeassistant/sensor/HA/HA-UNO-R4-WIFI-currentLumi/config
payload:
{
"unique_id": "HA-UNO-R4-WIFI-currentLumi",
"name": "Luminance",
"icon": "mdi:thermometer",
"state_topic": "homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state",
"value_template": "{{ value_json.luminance}}",
"unit_of_measurement": "Lux",
"device": {
"identifiers": "HA-UNO-R4-WIFI",
"manufacturer": "宏伟大业有限公司",
"model": "HA",
"name": "HA-UNO-R4-WIFI",
"sw_version": "1.0"
}
}
Config No.4:
config topic: homeassistant/sensor/HA/HA-UNO-R4-WIFI-currentInfra/config
payload:
{
"unique_id": "HA-UNO-R4-WIFI-currentInfra",
"name": "Infrared",
"icon": "mdi:thermometer",
"state_topic": "homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state",
"value_template": "{{ value_json.infrared}}",
"unit_of_measurement": " ",
"device": {
"identifiers": "HA-UNO-R4-WIFI",
"manufacturer": "宏伟大业有限公司",
"model": "HA",
"name": "HA-UNO-R4-WIFI",
"sw_version": "1.0"
}
}
```
#### 3、编写程序发送数据
发布传感器数据:
```shell
state topic: homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state
Payload:
{"temperature": 23.20,"humidity": 43.70,"luminance": 56,"infrared": 100 }
```
程序流程图
```flow
st=>start: 开始
op1=>operation: 初始化屏幕串口
op=>operation: 初始化打印串口
cond=>condition: 打印串口初始化是否成功
op2=>operation: 获取时间
op3=>operation: 温湿度初始化
op4=>operation: 光强度初始化
op5=>operation: 设置LED GPIO
op6=>operation: Wifi初始化
op7=>operation: 连接mqtt服务器
op8=>operation: 设置mqtt回调函数
op9=>operation: loop()
cond1=>condition: mqtt是否连接
cond2=>condition: 3秒时间是否到
op10=>operation: 获取温湿度数据
op11=>operation: 获取光强度数据
op12=>operation: 转换float到str
op13=>operation: 格式化发送数据
op14=>operation: 发布信息
op15=>operation: 重连mqtt
st->op1->op->cond(yes)->op2->op3->op4->op5->op6->op7->op8->op9->cond1(yes)->cond2(yes)->op10->op11->op12->op13->op14->op9
cond(no)->op
cond1(no)->op15->cond2
cond2(no)->op9
```
程序代码
```
#include "Adafruit_SHT4x.h"
#include "Adafruit_LTR329_LTR303.h"
#include
#include
#include
//#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = "ZBWL002"; // your network SSID (name)
char pass[] = "24458871"; // your network password (use for WPA, or use as key for WEP)
// Add your MQTT Broker IP address, example:
const char* mqtt_server = "192.168.14.104"; //先测试本机mqtt服务,该地址在windows下通过ipconfig查看,要和esp32连接在同一个网络
//const char* mqtt_server = "YOUR_MQTT_BROKER_IP_ADDRESS";
const char *id = "UNO-R4-WIFI";
const char *user = "test";
const char *passwd = "test2024";
WiFiClient espClient;
PubSubClient client(espClient); // MQTT服务设置了非账号密码不能使用,所有在connect的时候要设置账号密码
long lastMsg = 0;
char msg[50];
int value = 0;
// LED Pin
const int ledPin = 13;
int status = WL_IDLE_STATUS; // the WiFi radio's status
Adafruit_LTR329 ltr = Adafruit_LTR329();
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
#define TJC Serial1
void SendEnd(){
TJC.write(0xff);
TJC.write(0xff);
TJC.write(0xff);
}
unsigned long nowtime,nettime,tjctime;
void Sht40Init(){
Serial.println("Adafruit SHT4x test");
if (! sht4.begin()) {
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 Lrt329Init(){
Serial.println("Adafruit LTR-329 advanced test");
if ( ! ltr.begin() ) {
Serial.println("Couldn't find LTR sensor!");
while (1) delay(10);
}
Serial.println("Found LTR sensor!");
ltr.setGain(LTR3XX_GAIN_2);
Serial.print("Gain : ");
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;
}
}
void printWifiData() {
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
printMacAddress(mac);
}
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
printMacAddress(bssid);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption, HEX);
Serial.println();
}
void printMacAddress(byte mac[]) {
for (int i = 0; i < 6; i++) {
if (i > 0) {
Serial.print(":");
}
if (mac < 16) {
Serial.print("0");
}
Serial.print(mac, HEX);
}
Serial.println();
}
void CheckWifi(){
// 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 WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network");
printCurrentNet();
printWifiData();
}
void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.print((char)message);
messageTemp += (char)message;
}
Serial.println();
// Feel free to add more if statements to control more GPIOs with MQTT
// If a message is received on the topic esp32/output, you check if the message is either "on" or "off".
// Changes the output state according to the message
if (String(topic) == "esp32/output") {
Serial.print("Changing output to ");
if(messageTemp == "on"){
Serial.println("on");
digitalWrite(ledPin, HIGH);
}
else if(messageTemp == "off"){
Serial.println("off");
digitalWrite(ledPin, LOW);
}
}
}
/* 重连mqtt服务器 */
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
//MQTT服务设置了非账号密码不能使用,所有在connect的时候要设置账号密码
if (client.connect(id, user, passwd)) {
Serial.println("connected");
// 订阅mqtt主题
client.subscribe("esp32/output");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
// put your setup code here, to run once:
//初始化串行通信,设置波特率为9600bps
TJC.begin(115200); //与串口屏通信
Serial.begin(115200);
while (!Serial)
delay(10); // will pause Zero, Leonardo, etc until serial console opens
tjctime = millis();//获取当前已运行的时间
nettime = tjctime;
Sht40Init();
Lrt329Init();
pinMode(ledPin, OUTPUT);
CheckWifi(); //连接WiFi
client.setServer(mqtt_server, 1883);
client.setCallback(callback); // 绑定回调函数
}
int a = 0;
//初始化金银铜牌数量
int gold = 0;
int silver = 0;
int bronze = 0;
// char url[]=
void loop() {
char str[100];
sensors_event_t humidity, temp;
bool valid;
uint16_t visible_plus_ir, infrared;
if (!client.connected()) {
reconnect();
}
client.loop();
nowtime = millis();
if(nowtime >= tjctime + 3000){
tjctime = millis();
char tempString[8];
// Convert the value to a char array
char humString[8];
sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
sprintf(str, "temp.val=%d",(int)(temp.temperature*100));
TJC.print(str);
SendEnd();
// Serial.print(str);
sprintf(str, "humd.val=%d",(int)(humidity.relative_humidity*100));
TJC.print(str);
SendEnd();
// Serial.print(str);
// Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
// Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
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);
sprintf(str, "lumi.val=%d",visible_plus_ir);
TJC.print(str);
SendEnd();
sprintf(str, "infrared.val=%d",infrared);
TJC.print(str);
SendEnd();
}
}
sprintf(str, "gold.val=%d",a);
TJC.print(str);
SendEnd();
sprintf(str, "silver.val=%d",a);
TJC.print(str);
SendEnd();
sprintf(str, "bronze.val=%d",a);
TJC.print(str);
SendEnd();
a++;
//mqtt send sensor {"temperature": 23.20,"humidity": 43.70,"luminance": 56,"infrared": 100 }
dtostrf((float)temp.temperature,2,2,tempString);
Serial.print("Temperature: ");
Serial.println(tempString);
dtostrf((float)humidity.relative_humidity,2,2,humString);
Serial.print("Humidity: ");
Serial.println(humString);
sprintf(str, "{\"temperature\":%s,\"humidity\":%s,\"luminance\":%d,\"infrared\":%d}",tempString,humString,visible_plus_ir,infrared);
Serial.println(str);
client.publish("homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state", str); // 发布信息,第一个参数是主题
}
}
```
#### 4、HA面板数据显示
每3秒发送一次传感器数据,面板显示如图所示。
## 总结
代码:附整体可执行代码
心得:通过本次活动,让我认识了新的开发板,学到了新的技能,若工作中需要这种场景,能够立马上手,并推荐咱的成熟方案,抓住机遇。非常感谢DigiKey和EEWorld共同组织的多种活动,值得大家去大力支持。
- 2024-09-19
-
加入了学习《Follow me第二季第2期视频演示》,观看 演示视频
- 2024-09-06
-
发表了主题帖:
【Follow me第二季第2期】+ UNO R4 WIFI传感器上传HA
安装PubSubClient
设备自动注册参考。
homeassist MQTT Discovery设备自发现参考。
用MQTTX客户端注册设备。
Config No.1:
config topic: homeassistant/sensor/HA/HA-UNO-R4-WIFI-currentTemp/config
payload:
{
"device_class": "temperature",
"unique_id": "HA-UNO-R4-WIFI-currentTemp",
"name": "Temperature",
"icon": "mdi:thermometer",
"state_topic": "homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state",
"value_template":"{{ value_json.temperature}}",
"unit_of_measurement": "℃",
"device": {
"identifiers": "HA-UNO-R4-WIFI",
"manufacturer": "宏伟大业有限公司",
"model": "HA",
"name": "HA-UNO-R4-WIFI",
"sw_version": "1.0"
}
}
Config No.2:
config topic: homeassistant/sensor/HA/HA-UNO-R4-WIFI-currentHumi/config
payload:
{
"device_class": "humidity",
"unique_id": "HA-UNO-R4-WIFI-currentHumi",
"name": "Humidity",
"icon": "mdi:water-percent",
"state_topic": "homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state",
"value_template": "{{ value_json.humidity}}",
"unit_of_measurement": "%",
"device": {
"identifiers": "HA-UNO-R4-WIFI",
"manufacturer": "宏伟大业有限公司",
"model": "HA",
"name": "HA-UNO-R4-WIFI",
"sw_version": "1.0"
}
}
Config No.3:
config topic: homeassistant/sensor/HA/HA-UNO-R4-WIFI-currentLumi/config
payload:
{
"unique_id": "HA-UNO-R4-WIFI-currentLumi",
"name": "Luminance",
"icon": "mdi:thermometer",
"state_topic": "homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state",
"value_template": "{{ value_json.luminance}}",
"unit_of_measurement": "Lux",
"device": {
"identifiers": "HA-UNO-R4-WIFI",
"manufacturer": "宏伟大业有限公司",
"model": "HA",
"name": "HA-UNO-R4-WIFI",
"sw_version": "1.0"
}
}
Config No.4:
config topic: homeassistant/sensor/HA/HA-UNO-R4-WIFI-currentInfra/config
payload:
{
"unique_id": "HA-UNO-R4-WIFI-currentInfra",
"name": "Infrared",
"icon": "mdi:thermometer",
"state_topic": "homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state",
"value_template": "{{ value_json.infrared}}",
"unit_of_measurement": " ",
"device": {
"identifiers": "HA-UNO-R4-WIFI",
"manufacturer": "宏伟大业有限公司",
"model": "HA",
"name": "HA-UNO-R4-WIFI",
"sw_version": "1.0"
}
}
发布传感器数据:
state topic: homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state
Payload:
{"temperature": 23.20,"humidity": 43.70,"luminance": 56,"infrared": 100 }
E、uno-r4-wifi编写测试程序,发布传感器数据。
测试代码:
#include "Adafruit_SHT4x.h"
#include "Adafruit_LTR329_LTR303.h"
#include <WiFiS3.h>
#include <PubSubClient.h>
#include <WiFiClient.h>
//#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = "xxxx"; // your network SSID (name)
char pass[] = "xxxx"; // your network password (use for WPA, or use as key for WEP)
// Add your MQTT Broker IP address, example:
const char* mqtt_server = "192.168.14.104"; //先测试本机mqtt服务,该地址在windows下通过ipconfig查看,要和esp32连接在同一个网络
//const char* mqtt_server = "YOUR_MQTT_BROKER_IP_ADDRESS";
const char *id = "UNO-R4-WIFI";
const char *user = "test";
const char *passwd = "test2024";
WiFiClient espClient;
PubSubClient client(espClient); // MQTT服务设置了非账号密码不能使用,所有在connect的时候要设置账号密码
long lastMsg = 0;
char msg[50];
int value = 0;
// LED Pin
const int ledPin = 13;
int status = WL_IDLE_STATUS; // the WiFi radio's status
Adafruit_LTR329 ltr = Adafruit_LTR329();
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
#define TJC Serial1
void SendEnd(){
TJC.write(0xff);
TJC.write(0xff);
TJC.write(0xff);
}
unsigned long nowtime,nettime,tjctime;
void Sht40Init(){
Serial.println("Adafruit SHT4x test");
if (! sht4.begin()) {
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 Lrt329Init(){
Serial.println("Adafruit LTR-329 advanced test");
if ( ! ltr.begin() ) {
Serial.println("Couldn't find LTR sensor!");
while (1) delay(10);
}
Serial.println("Found LTR sensor!");
ltr.setGain(LTR3XX_GAIN_2);
Serial.print("Gain : ");
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;
}
}
void printWifiData() {
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
printMacAddress(mac);
}
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
printMacAddress(bssid);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption, HEX);
Serial.println();
}
void printMacAddress(byte mac[]) {
for (int i = 0; i < 6; i++) {
if (i > 0) {
Serial.print(":");
}
if (mac[i] < 16) {
Serial.print("0");
}
Serial.print(mac[i], HEX);
}
Serial.println();
}
void CheckWifi(){
// 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 WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
// you're connected now, so print out the data:
Serial.print("You're connected to the network");
printCurrentNet();
printWifiData();
}
void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTemp += (char)message[i];
}
Serial.println();
// Feel free to add more if statements to control more GPIOs with MQTT
// If a message is received on the topic esp32/output, you check if the message is either "on" or "off".
// Changes the output state according to the message
if (String(topic) == "esp32/output") {
Serial.print("Changing output to ");
if(messageTemp == "on"){
Serial.println("on");
digitalWrite(ledPin, HIGH);
}
else if(messageTemp == "off"){
Serial.println("off");
digitalWrite(ledPin, LOW);
}
}
}
/* 重连mqtt服务器 */
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
//MQTT服务设置了非账号密码不能使用,所有在connect的时候要设置账号密码
if (client.connect(id, user, passwd)) {
Serial.println("connected");
// 订阅mqtt主题
client.subscribe("esp32/output");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
// put your setup code here, to run once:
//初始化串行通信,设置波特率为9600bps
TJC.begin(115200); //与串口屏通信
Serial.begin(115200);
while (!Serial)
delay(10); // will pause Zero, Leonardo, etc until serial console opens
tjctime = millis();//获取当前已运行的时间
nettime = tjctime;
Sht40Init();
Lrt329Init();
pinMode(ledPin, OUTPUT);
CheckWifi(); //连接WiFi
client.setServer(mqtt_server, 1883);
client.setCallback(callback); // 绑定回调函数
}
int a = 0;
//初始化金银铜牌数量
int gold = 0;
int silver = 0;
int bronze = 0;
// char url[]=
void loop() {
char str[100];
sensors_event_t humidity, temp;
bool valid;
uint16_t visible_plus_ir, infrared;
if (!client.connected()) {
reconnect();
}
client.loop();
nowtime = millis();
if(nowtime >= tjctime + 3000){
tjctime = millis();
char tempString[8];
// Convert the value to a char array
char humString[8];
sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
sprintf(str, "temp.val=%d",(int)(temp.temperature*100));
TJC.print(str);
SendEnd();
// Serial.print(str);
sprintf(str, "humd.val=%d",(int)(humidity.relative_humidity*100));
TJC.print(str);
SendEnd();
// Serial.print(str);
// Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
// Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
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);
sprintf(str, "lumi.val=%d",visible_plus_ir);
TJC.print(str);
SendEnd();
sprintf(str, "infrared.val=%d",infrared);
TJC.print(str);
SendEnd();
}
}
sprintf(str, "gold.val=%d",a);
TJC.print(str);
SendEnd();
sprintf(str, "silver.val=%d",a);
TJC.print(str);
SendEnd();
sprintf(str, "bronze.val=%d",a);
TJC.print(str);
SendEnd();
a++;
//mqtt send sensor {"temperature": 23.20,"humidity": 43.70,"luminance": 56,"infrared": 100 }
dtostrf((float)temp.temperature,2,2,tempString);
Serial.print("Temperature: ");
Serial.println(tempString);
dtostrf((float)humidity.relative_humidity,2,2,humString);
Serial.print("Humidity: ");
Serial.println(humString);
sprintf(str, "{\"temperature\":%s,\"humidity\":%s,\"luminance\":%d,\"infrared\":%d}",tempString,humString,visible_plus_ir,infrared);
Serial.println(str);
client.publish("homeassistant/sensor/HA-UNO-R4-WIFI/sensorBedroom/state", str); // 发布信息,第一个参数是主题
}
}
-
回复了主题帖:
【Follow me第二季第2期】+MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
秦天qintian0303 发表于 2024-9-5 20:41
感觉好复杂啊,不能和阿里云似的直接网页操作吗?
应该可以的,HA里面集成了mqtt docker,自己去设置一下吧,传感器应该也可以自己设置。
- 2024-09-05
-
发表了主题帖:
【Follow me第二季第2期】+MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
安装虚拟机
更换软件镜像源地址sudo vim /etc/apt/sources.list,更新如下文件保存退出。
# 阿里云镜像源(以Ubuntu 20.04为例)
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
更新软件包sudo apt update
允许APT使用HTTPSsudo apt-get install apt-transport-https ca-certificates curl software-properties-common
添加Docker官方GPG密钥curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
添加Docker的稳定版本仓库sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
再次更新软件包索引sudo apt-get update
安装Docker CE(社区版)sudo apt-get install docker-ce
验证Docker是否安装成功并运行sudo systemctl status docker
安装镜像
Sudo docker run -d \
--name homeassistant \
--privileged \
--restart=unless-stopped \
-e TZ=Asia/Shanghai \
-v /home/alientek/homeassistant:/config \
-v /run/dbus:/run/dbus:ro \
--network=host \
ghcr.io/home-assistant/home-assistant:stable
测试,网址http://<host>:8123
H、重启homeassistant,sudo docker restart homeassistant即可。
I、打开homeassistant配置embedded mqtt
J、安装mosquitto
K、查看安装的镜像
MOSQUITTO创建目录文件
p.1创建目录
mkdir -p /mosquitto/config
mkdir -p /mosquitto/data
mkdir -p /mosquitto/log
p.2初始化配置文件
vi /mosquitto/config/mosquitto.conf
# 输入一下命令内容
persistence true
persistence_location /mosquitto/data
log_dest file /mosquitto/log/mosquitto.log
p.3为目录授权
chmod -R 755 /mosquitto
chmod -R 777 /mosquitto/log #日志目录要最大权限
Mosquitto启动镜像
建立运行执行脚本 mosquitto.sh
sudo docker run -it --name=mosquitto --privileged -p 1883:1883 -p 9001:9001 -v /mosquitto/config/mosquitto.conf:/mosquitto/config/mosquitto.conf -v /mosquitto/data:/mosquitto/data -v /mosquitto/log:/mosquitto/log -d eclipse-mosquitto
根据Docker安装MQTT服务mosquitto进行配置(以上参考此博客)
exit后重启mqtt服务sudo docker restart d604755c81f3
Mqtt.fx设置
连接不上,查找原因经过各种测试,解决参考博客。
Tips:给docker容器加个网桥,mqtt.fx直接访问虚拟机的地址:端口号就连接上了。
测试一下:开两个终端,一个sub,一个pub,在mqtt.fx中提交topic hello/world,再次pub一个消息,sub端和mqtt.fx都收到了消息。
配置homeassistant中MQTT自动发现
配置MQTT,下一步,然后提交即可。
使用MQTTX进行测试,连接MQTT,按照homeassistant自动发现规则发送数据。
-
回复了主题帖:
【Follow me第二季第2期】+ 基础任务(DAC,OPAMP,ADC)
bigjiong 发表于 2024-8-30 14:28
想在串口看到波形的话,波特率得调大一些,要不波形会失真.
哦,我会再试一试。
- 2024-08-29
-
发表了主题帖:
【Follow me第二季第2期】+ 基础任务(DAC,OPAMP,ADC)
A、驱动12x8点阵LED
根据用户教程Using the Arduino UNO R4 WiFi LED Matrix这个说明手册,我们可以知道点阵LED的显示原理,每一个LED代表一位,一共有96个LED,发送一次LED数据至少96位,手册中发送一个frame,内有96个点,例如
unsigned long frame[] = {
0x3184a444,
0x42081100,
0xa0040000
};
发送数据时需要发送转换后的二进制数值,
0x3184a444(110001100001001010010001000100)
0x42081100(1000010000010000001000100000000)
0xa0040000(10100000000001000000000000000000)
用串口发送二进制方式发送数据,
for (int b = 0; b < 3; b++) {
Serial.println(frame, BIN);
}
开发板软件包内提供了LED Matrix library,只要包含头文件,定义一个ArduinoLEDMatrix matrix变量,使用matrix的loadFrame函数就可以显示了。如图所示。
[localvideo]5eb9d7e8b42f5d5bd66301714cf41e4e[/localvideo]
B、用DAC生成正弦波
使用sineWave的例子,下载到板子里面运行。
A0输出正弦波形,用示波器显示。
[localvideo]db567f579f3c1530a274d4993e110956[/localvideo]
C、用OPAMP放大DAC信号;
电压放大2倍电路接法如图所示。
这个输入A1是如何显示方波的呢?
[localvideo]9e54f2350de5c5bbbb289b82aff254f9[/localvideo]
不知道我这个测试方法是否正确?
用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
- 2024-08-26
-
回复了主题帖:
【Follow me第二季第2期】+ 搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
慕容雪花 发表于 2024-8-26 13:44
辣么快!!!感谢分享
大家还没到吗?我记得8月19日下的单,23号发货通知,25号就到了。
-
回复了主题帖:
【Follow me第二季第2期】+ 搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
rtyu789 发表于 2024-8-26 16:57
这到货的也太快了吧,学习学习,不知道用vscode的PlatformIO开发是否方便呢
需要您到时候验证一下啦,我电脑上有Arduino IDE,就用了这个。
-
回复了主题帖:
【Follow me第二季第2期】+ 搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
秦天qintian0303 发表于 2024-8-26 11:26
你这是第一个收到的吧,Arduino IDE编译速度怎么样
不错,这个IDE在我电脑上很快。
-
发表了主题帖:
【Follow me第二季第2期】+ 搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
找资料
首先搜Arduino UNO R4 WiFi,找到官网入口,点击DOCUMENTATION,找到左侧找到Hardware,点击展开,在Classic找到UNO R4 WiFi,点击里面就是各种资料了,如图1所示。
图1
我们在Tutorials页面里面找到Getting Started with UNO R4 WiFi,如图2所示。
图2
根据步骤看,可以使用Arduino IDE,也可以用Web Editor。
下载IDE,下载比较慢,用迅雷下载较快。
解压后直接使用即可。
安装环境
打开软件,如图所示。
安装开发板软件包,如图所示
安装过程如图所示。
选择开发板,如图所示
串口打印hello EEWorld!
用Type-C数据线连接电脑及开发板,编写个串口初始化及打印,如图所示,下载到板子内,串口打印完成。