[作品提交] 【Follow me第二季第2期】任务汇总

王嘉辉   2024-9-29 01:11 楼主
UNO R4 WIFI
文档:
零、写在前面
很荣幸参加此次Follow me第二季第二期活动,通过这次活动学到了Arduino的一些知识,以及HA相关的知识。完成了活动所要求的一些任务LED、UART、LED矩阵、WIFI连接HA通过MQTT传输数据、SHT40传感器数据获取、DAC、ADC等等。所用到的器件有Arduino R4 WIFI主板一块,SHT40传感器小板一块和4P连接线一根。
一、环境搭建
1.1 硬件环境及硬件介绍
此次参加FOLLOW ME第二季第二期的活动,使用的主控板子是Arduino R4 WIFI开发板,还买了一个SHT40温湿度传感器模块,还有一根4P的线。
wd_005807ozz48oan8et6o2t6.jpg
根据官网以及网络上各个帖子的介绍,可以了解到这块开发板有了很大的升级,主控芯片升级为了瑞萨的32位Arm Cortex-M4内核的RA4M1微控制器,拥有256KB Flash和32KB SRAM,时钟频率来到了48MHz,接口可以与之前的R3进行兼容,但是这次与电脑的接口换上了更为先进的TYPE-C接口。这块板子让人眼前一新的地方就是12*8的LED矩阵,可以用来显示数字、字母、简单的图形甚至汉字。其有丰富的接口和片上外设,内置6个PWM接口、6个ADC接口、1个12bit的DAC以及1个SPI、2个IIC和1个CAN接口,可以连接非常多的外设传感器,可玩性极高。
1.2 软件环境
打开Arduino IDE搜索R4板子,下载对应的包,下载的时间较久,耐心等待一下。
wd_005807jvdn5jv3vld7mzov.png
1.3 上电测试
wd_005807y75dxeo5j551vx7h.jpg
使用TYPE-C进行上电,上电后,可以看到Arduino官方烧录的Blink代码,但是这块板子有一个很大面积的LED矩阵,上电后演示了一段积木搭建的效果,并最终停留在了一颗爱心的图案。
二、点灯(Blink)
wd_005807yrwwbcuuw5w3b92k.png
点灯需要使用到的外设为GPIO,查询相关的函数发现和GPIO相关的函数有pinMode,用来设置引脚的输入或输出模式,digitalRead用来读取引脚上的电平状态,digitalWrite用来写入引脚上的电平状态。
新建文件后,可以看到两个大函数,setup函数中用于写初始化配置的相关代码,这一部分的代码在上电后会执行一次。loop函数中用于写循环执行的代码,这一部分的代码会在setup执行完成后重复不断的执行。
因此要在setup里写pinMode函数,将LED对应的引脚配置成输出模式。然后在loop里写digitalWrite函数,分别配置写入高电平和低电平,在两个函数之间加入延时函数,实现LED灯闪烁的效果。
void setup() {
// put your setup code here, to run once:
}

void loop() {
// put your main code here, to run repeatedly:
}
最终呈现的代码如下所示,代码实现的效果是,板子上的LED以5Hz的频率进行闪烁。
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN,OUTPUT);
}

void loop() {
// put your main code here, to run repeatedly:
digitalWrite(LED_BUILTIN,HIGH);
delay(100);
digitalWrite(LED_BUILTIN,LOW);
delay(100);
}
1.png

 

三、串口
串口的使用需要在setup中进行串口的初始化配置,主要是串口波特率的配置。
在loop中进行串口的数据发送,通过调用Serial.println("Hello EEWorld!")函数,可以将Hello EEWorld!通过串口发送到电脑的监视器窗口。
2.png

 

wd_005807rlwz29buaoes7ayq.png
四、板载LED矩阵
首先应该包含Arduino提供的矩阵库文件#include "Arduino_LED_Matrix.h"
然后在这个文件中有一个ArduinoLEDMatrix类,我们利用这个类定义一个新的对象matrix。代码实现为ArduinoLEDMatrix matrix;
初始化矩阵matrix.begin();
定义矩阵显示,矩阵的显示无非就是控制每个LED处于高电平还是低电平,当对应的LED为高电平时,LED点亮,与此同时矩阵中对应的位置数字为1。反之为低电平,LED熄灭,矩阵对应的位置数字为0。
Arduino R4 WIFI的板子上的LED矩阵为8*12,因此我们定义一个二维数组用来存放显示图形的数据。这里设置了三个图形,分别是笑脸、眨眼和哭脸。
uint8_t smile[8][12] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

uint8_t wink[8][12] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

uint8_t cry[8][12] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
最后调用matrix.renderBitmap(smile, 8, 12);函数便可以实现将数组数据加载到LED矩阵中去,在每个表情切换中间加上适当的延时,实现表情的显示。
同样的可以进行汉字、数字等的显示,更改对应的数组信息即可。
3.png

 

完整代码:
#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;

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

uint8_t smile[8][12] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

uint8_t wink[8][12] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

uint8_t cry[8][12] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

void loop()
{
matrix.renderBitmap(smile, 8, 12);
delay(1000);
matrix.renderBitmap(wink, 8, 12);
delay(1000);
matrix.renderBitmap(cry, 8, 12);
delay(1000);
}
视频演示:
LED矩阵

 
五、DAC产生正弦波形
DAC就是模数转换器,可以将数字信号转换为模拟信号,这个功能可以用来制作函数发生器也可以用来驱动蜂鸣器实现音频的播放,相比于PWM频率控制,可以实现更加连续的波形产生,比如正弦波、锯齿波等等。
首先是驱动DAC能够产生一个稳定的电压信号,然后通过每次更换输入的数字值,从而改变每次输出的电压信号,让电压信号的变化遵循正弦信号的变化,即可实现正弦信号的生成。下面我们一步一步来实现。
通过调用函数analogWriteResolution(8);设置了DAC的分辨率为8bit。然后调用函数analogWrite(DAC, 具体数值(0-255));就可以实现产生一个稳定的直流电压信号。我们分别设置数值为100和150来查看电压是否会发生变化。当为100时,使用万用表测量的数据为1.76V,当为150时,使用万用表测量的数据为2.637V。当为255时,即可以设置的最大数字时,电压表显示的电压值为4.46。因此可以得出当DAC设置为8bit模式时,每一个值代表的电压大约为0.01754V,根据你想要的电压值,除于该数值便可以得到要输入的数值。比如需要3V电压值,3/0.01754=171(省略小数位),输入171,则可以得到3V的电压值。
void setup()
{
analogWriteResolution(8); // set the analog output resolution to 12 bit (4096 levels)
}

void loop()
{
analogWrite(DAC, 171); // write the selected waveform on DAC0
}
wd_005807tftytyirrrlgeqyt.jpg
那么我们将产生正弦信号的数值依次存放在数组中,间隔一定的时间(与频率有关)将数组的每一位依次传入该函数中,使用DAC将数据输出成模拟信号,便可以实现正弦波的生成。同时还找到一个锯齿波的数组,但是锯齿波的数据仅有120位,且要求DAC的分辨率为12,因此需要修改analogWriteResolution(8);中的8改为12,analogWrite(DAC, wave_sin);中的wave_sin改为waveformsTable,同时将if (i == 256)中的256修改为120即可。
#ifndef _Waves_h_
#define _Waves_h_

static int waveformsTable[120] = {

0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x110, 0x132, 0x154,
0x176, 0x198, 0x1ba, 0x1dc, 0x1fe, 0x220, 0x242, 0x264, 0x286, 0x2a8,
0x2ca, 0x2ec, 0x30e, 0x330, 0x352, 0x374, 0x396, 0x3b8, 0x3da, 0x3fc,
0x41e, 0x440, 0x462, 0x484, 0x4a6, 0x4c8, 0x4ea, 0x50c, 0x52e, 0x550,
0x572, 0x594, 0x5b6, 0x5d8, 0x5fa, 0x61c, 0x63e, 0x660, 0x682, 0x6a4,
0x6c6, 0x6e8, 0x70a, 0x72c, 0x74e, 0x770, 0x792, 0x7b4, 0x7d6, 0x7f8,
0x81a, 0x83c, 0x85e, 0x880, 0x8a2, 0x8c4, 0x8e6, 0x908, 0x92a, 0x94c,
0x96e, 0x990, 0x9b2, 0x9d4, 0x9f6, 0xa18, 0xa3a, 0xa5c, 0xa7e, 0xaa0,
0xac2, 0xae4, 0xb06, 0xb28, 0xb4a, 0xb6c, 0xb8e, 0xbb0, 0xbd2, 0xbf4,
0xc16, 0xc38, 0xc5a, 0xc7c, 0xc9e, 0xcc0, 0xce2, 0xd04, 0xd26, 0xd48,
0xd6a, 0xd8c, 0xdae, 0xdd0, 0xdf2, 0xe14, 0xe36, 0xe58, 0xe7a, 0xe9c,
0xebe, 0xee0, 0xf02, 0xf24, 0xf46, 0xf68, 0xf8a, 0xfac, 0xfce, 0xff0


};

static int wave_sin[256] = {
0x80,0x83,0x85,0x88,0x8A,0x8D,0x8F,0x92,
0x94,0x97,0x99,0x9B,0x9E,0xA0,0xA3,0xA5,
0xA7,0xAA,0xAC,0xAE,0xB1,0xB3,0xB5,0xB7,
0xB9,0xBB,0xBD,0xBF,0xC1,0xC3,0xC5,0xC7,
0xC9,0xCB,0xCC,0xCE,0xD0,0xD1,0xD3,0xD4,
0xD6,0xD7,0xD8,0xDA,0xDB,0xDC,0xDD,0xDE,
0xDF,0xE0,0xE1,0xE2,0xE3,0xE3,0xE4,0xE4,
0xE5,0xE5,0xE6,0xE6,0xE7,0xE7,0xE7,0xE7,
0xE7,0xE7,0xE7,0xE7,0xE6,0xE6,0xE5,0xE5,
0xE4,0xE4,0xE3,0xE3,0xE2,0xE1,0xE0,0xDF,
0xDE,0xDD,0xDC,0xDB,0xDA,0xD8,0xD7,0xD6,
0xD4,0xD3,0xD1,0xD0,0xCE,0xCC,0xCB,0xC9,
0xC7,0xC5,0xC3,0xC1,0xBF,0xBD,0xBB,0xB9,
0xB7,0xB5,0xB3,0xB1,0xAE,0xAC,0xAA,0xA7,
0xA5,0xA3,0xA0,0x9E,0x9B,0x99,0x97,0x94,
0x92,0x8F,0x8D,0x8A,0x88,0x85,0x83,0x80,
0x7D,0x7B,0x78,0x76,0x73,0x71,0x6E,0x6C,
0x69,0x67,0x65,0x62,0x60,0x5D,0x5B,0x59,
0x56,0x54,0x52,0x4F,0x4D,0x4B,0x49,0x47,
0x45,0x43,0x41,0x3F,0x3D,0x3B,0x39,0x37,
0x35,0x34,0x32,0x30,0x2E,0x2D,0x2C,0x2A,
0x29,0x28,0x26,0x25,0x24,0x23,0x22,0x21,
0x20,0x1F,0x1E,0x1D,0x1D,0x1C,0x1C,0x1B,
0x1B,0x1A,0x1A,0x1A,0x19,0x19,0x19,0x19,
0x19,0x19,0x19,0x19,0x1A,0x1A,0x1A,0x1B,
0x1B,0x1C,0x1C,0x1D,0x1D,0x1E,0x1F,0x20,
0x21,0x22,0x23,0x24,0x25,0x26,0x28,0x29,
0x2A,0x2C,0x2D,0x2F,0x30,0x32,0x34,0x35,
0x37,0x39,0x3B,0x3D,0x3F,0x41,0x43,0x45,
0x47,0x49,0x4B,0x4D,0x4F,0x52,0x54,0x56,
0x59,0x5B,0x5D,0x60,0x62,0x65,0x67,0x69,
0x6C,0x6E,0x71,0x73,0x76,0x78,0x7B,0x7D
};

#endif

 

4.png
#include "Waves.h"

int i = 0;

void setup()
{
analogWriteResolution(8); // set the analog output resolution to 12 bit (4096 levels)
}

void loop()
{
analogWrite(DAC, wave_sin); // write the selected waveform on DAC0
i++;

if (i == 256) // Reset the counter to repeat the wave
i = 0;
delayMicroseconds(10); // Hold the sample value for the sample time
}
wd_005807r1do7y1i5l8j6xbs.jpg
wd_005807sg9m23ddmv3m19qd.jpg
六、板载放大器
Arduino R4 WIFI板子上自带一个内置的放大器,可以将A1作为正向输入、A2作为反向输入、A3作为输出。因此设计一个放大倍数两倍的同相比例放大器,来放大我们产生的正弦信号。
想要使用内置的放大器,首先要引入一个库,#include <OPAMP.h>然后开启放大器即可,使用函数OPAMP.begin(OPAMP_SPEED_HIGHSPEED);即可开启放大器。
除此之外的代码analogWrite(DAC, wave_sin/2);仅在此处加了一个除2的操作,若不加除2放大后的波形会出现削顶失真,当然也可以通过更改数组的数值进行调整。其余的均与DAC代码保持一致,包括Waves.h库文件。
5.png

 

#include "Waves.h"
#include <OPAMP.h>

int i = 0;

void setup()
{
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
analogWriteResolution(8); // set the analog output resolution to 12 bit (4096 levels)
}

void loop()
{
analogWrite(DAC, wave_sin/2); // write the selected waveform on DAC0
i++;

if (i == 256) // Reset the counter to repeat the wave
i = 0;
delayMicroseconds(10); // Hold the sample value for the sample time
}
其原理可由该图来解释。该图构成一个简易的同相比例放大器,其中放大倍数由黄色的公式给出。可以调整两个电阻的大小,更改放大倍数。红色为放大电路主体,将A0和A1短接,即将DAC产生的模拟信号输入到放大器的正向输入端,输出和反向输入端构成反馈。蓝色为波形的示意,A1输入的正弦峰值为1V,A3输出的正弦峰值为2V。
实物搭建较为简陋,但是通过示波器,可以明显看出输出波形相较于输入波形有了明显的放大,且放大倍数大约在2倍。
wd_005807geedh2e9f2mywey1.png
wd_005807tqiuiovzzne96w9o.jpg
wd_005808onnkpdzkpngar03r.jpg
wd_005808hbido26z5ek2qwqt.jpg
七、ADC采集数据并使用串口打印绘制波形。
ADC就是模数转换器,其工作方式与DAC恰好相反。可以将输入的模拟信号转换为数字信号,然后进行数字上的处理,更适应这个数字化发展的趋势。
在硬件上的连接,需要将放大器的A3输出引脚连接在A4的ADC采集引脚上。
使用ADC首先需要初始化ADC,调用函数analogReadResolution(8); 。并使用函数int reading = analogRead(A4);将A4引脚上的模拟数值转换为数字数值并存储在reading变量中。然后通过串口进行数据的打印以及波形图的绘制。
6.png

 

#include "Waves.h"
#include <OPAMP.h>

int i = 0;

void setup()
{
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
analogWriteResolution(8); // set the analog output resolution to 12 bit (4096 levels)
analogReadResolution(8); //change to 14-bit resolution
Serial.begin(9600);
}

void loop()
{
analogWrite(DAC, wave_sin/2); // write the selected waveform on DAC0
i++;

if (i == 256) // Reset the counter to repeat the wave
i = 0;

int reading = analogRead(A4); // returns a value between 0-16383

delayMicroseconds(10); // Hold the sample value for the sample time

Serial.print(reading);
Serial.print("\n");
}
wd_005808t1jddwurc5ewz6vf.png
wd_005808ev98fivxii7lrqmf.png
八、HA平台搭建
此次主要就是想借此次活动来学习HA相关的知识,之前有了解到HA是一个功能非常庞大的物联网平台,但是由于自己的知识储备不足(大部分是没有学习的动力,hhh),一直没有接触到相关的知识。正好有这次活动,让我能够“被迫”学习HA相关的内容,发现要是实现数据的上传功能也不是很难,但是HA的庞大还需要继续进行探索。这篇就是简单介绍一下在Windows中使用VMware搭建HA的过程,以及怎么在HA中安装MQTT相关的内容和与Arduino R4 WIFI板子进行数据的交互。
首先是在Windows中安装VMware,我用的是VMware PRO 17的版本,这个的安装过程我参考了网上的一篇博客,相关的内容还是很多,大家可以自行去搜索安装。(当然其他版本的VMware应该也是可以的,网上相关的信息较多,大家可以自行尝试)
然后就是安装HomeAssistant,打开官网https://www.home-assistant.io/,按照下图中的顺序,依次点击,就可以下载到最新的版本。
wd_005808w5vznncv3jvrjjo9.png
然后打开安装好的VMware开始进行HA平台的搭建。详细的过程大家可以去网上搜索帖子学习搭建,需要注意的两个地方(被坑了一个多小时),第一个是网络类型要选择桥接网络,第二个是要修改虚拟机的固件类型为UEFI。(我是被卡了一个小时,然后找到一篇帖子改了这两项后,就可以用了,具体的原理还没有深究,有懂的大佬可以指点一下)完成虚拟机的创建和配置后,直接一键开机。。。然后就会虚拟机就会打印出当前虚拟机的网络相关的信息,找到ipv4的地址,然后在浏览器中输入ipv4地址:8123就会进入到虚拟机中创建的HA的网页,大概需要等待20分钟的时间(网上的普遍说法,但是我大概等了几分钟的样子)就会进入HA的登陆界面,点击创建账户,输入一些信息,就可以创建属于自己的HA账户。
wd_005808dtvi2jd61p1jpf1t.png
进入HA网页后,点击设置,选择加载项
wd_005808ag940kitgtigl76i.png
点击右下角的加载项商店,搜索Mosquitto进行下载。
下载完后,点击设置->设备与服务->MQTT->配置对MQTT进行一些配置。用户名和密码填写创建HA的用户名和密码即可,也可以添加成员,使用新成员的用户名和密码。其余的可以保持默认不变。完成后,可以在MQTT设置页面进行PUB和SUB的测试。
wd_005808n8jlmgl4momgd583.png
下图所示,配置两个的主题保持一致,然后开启监听主题的开始监听,在上面发送信息,就会在下面收到。
wd_005808d5twqvp6prqeu5xf.png
然后就是怎么把Arduino的数据上传到HA中了,这第一步就是要在HA中创建一个设备。(这一步也难了一个小时,因为网上大部分的方案都是用NAS或者树莓派搭建的HA,使用命令行和修改yaml文件就实现了新建设备的功能,但是我使用虚拟机加网页的形式,没有找到yaml文件,所以找了很多的资料)最终,发现可以开启MQTT的自发现功能,然后向这个代理发送符合规则的PUB就可以添加设备。
下载一个MQTTX(也可以使用其他的相关模拟软件),免费、有中文。然后建立一个新的连接。填入的信息和创建的HA信息保持一致即可。
然后发送一个标准的PUB就可以添加设备到HA中了。topic填写在输入栏上方的topic栏中,信息填写在输入栏中,然后点击右下角的小飞机,就可以了。
topic:homeassistant/sensor/sensorBedroomH/config
{
"device_class":"humidity",
"name":"Humidity",
"state_topic":"homeassistant/sensor/sensorBedroom/state",
"unit_of_measurement":"%",
"value_template":"{{ value_json.humidity}}",
"unique_id":"hum01ae",
"device":{
"identifiers":[
"bedroom01ae"
],
"name":"Bedroom"
}
}
wd_005808k5rr12aebrr2zqpv.png
然后打开HA的网页,设置->设备与服务->MQTT->1个设备就可以看到传感器栏上有一个新的条目信息。说明添加设备成功了。
然后我们开始使用Arduino更新这个条目信息。先安装两个MQTT相关的库。
wd_005808hpll8pl0l3clclcz.png
复制下面的代码,记得更改WIFI和MQTT相关的配置信息,然后下载到板子上,打开串口查看打印信息。并打开HA查看数据是否更新。(数据应该是21.5)
7.png

 

#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

// 替换为你的网络信息
const char* ssid = "WIFI名称";
const char* password = "WIFI密码";

// 替换为你的Mosquitto broker信息
const char* mqtt_server = "IPV4地址";
const int mqtt_port = 1883;
const char* mqtt_user = "HA用户名";
const char* mqtt_password = "HA密码";

// 初始化WiFi和MQTT客户端
WiFiClient espClient;
PubSubClient client(espClient);

// 传感器数据发布主题
const char* topic = "homeassistant/sensor/sensorBedroom/state";

void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
}

void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();

// 假设你有一个温度传感器,获取温度数据
float temperature = readTemperature();

StaticJsonDocument<200> jsonDoc;
jsonDoc["humidity"] = temperature;

char jsonBuffer[512];
serializeJson(jsonDoc, jsonBuffer);

client.publish(topic, jsonBuffer);

// 每隔5秒发送一次数据
delay(5000);
}

void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}

void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("ArduinoClient", mqtt_user, mqtt_password)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}

float readTemperature() {
// 在这里读取实际传感器的数据
// 示例中返回一个固定值
return 21.5;
}
wd_005808j055y3ovuaurwaoa.png
wd_005808zgq0fenu8gfxob0l.png
这样就完成了HA的搭建以及Arduino R4 WIFI上传数据到HA平台。
 
在HA学习过程中遇到很多问题,借助了强大的AI工具,帮助我解决了很多疑惑,大家可以擅用AI工具,帮助自己对代码进行分析以及对问题进行处理。
九、SHT40传感器以及上传温湿度数据到HA
这次的扩展任务选择了温湿度传感器SHT40,之前使用过SHT30,想体验一下SHT40与之前的传感器有什么区别。除此之外还选购了一条线(为了逼近300块钱,但是又不超过300,究极白嫖怪,hhh),但是就是这个多买的线,坑了我一个小时,还好查看了一下相关的文档,解决了这个问题。
SHT40的通讯协议是IIC,按照以前的思路,找一个SHT40的库,然后改一下代码,加入串口打印就可以实现SHT40数据的获取,但是我找了一个大佬的测试例程,串口打印SHT40设备无法找到,我以为我SHT40插反了,然后又重新接线测试,发现还是不行,我一度以为这个模块是不是有问题。
后来查看文档发现,Arduino R4 WIFI上能与这个线完美结合的那个接口是QWIIC,用的是wire1,我测试的例程使用的IIC是wire0。发现问题,开始解决问题。首先查询了一下QWIIC怎么使用,发现还是比较简单的。
只需要调用Wire1.begin();然后在传感器初始化的函数中添加wire1的参数即可。
#include <Wire.h>
#include "Adafruit_SHT4x.h"

Adafruit_SHT4x sht4 = Adafruit_SHT4x();

void setup()
{
// put your setup code here, to run once:
Serial.begin(115200);
Wire1.begin();
if(sht4.begin(&Wire1) == false)
{
Serial.println("SHT40 not detected. Please check wiring. Freezing.");
while (1)
;
}

sht4.setPrecision(SHT4X_HIGH_PRECISION);
sht4.setHeater(SHT4X_NO_HEATER);
Serial.println("SHT40 acknowledged.");
}

void loop() {
// put your main code here, to run repeatedly:
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("℃");
Serial.print("Humidity: ");
Serial.print(humidity.relative_humidity);
Serial.println("%");
delay(1000);
}
测试代码下载到板子上,打开串口监视器查看一下数据。
wd_005808swt4c0ypwz02y2wk.png
数据可以正常获取,完美!
下面开始将SHT40获取数据和HA结合在一起。首先是用MQTTX在创建一个条目。按照上一篇帖子的方法进行创建即可。(不仅要修改发送的信息,还要修改topic,别忘记)创建完成后检查一下HA有无问题。
然后将两个代码进行整合。得到最终的代码。依旧记得更改信息连接自己的WIFI和MQTT。
8.png

 

#include <Wire.h>
#include "Adafruit_SHT4x.h"
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

Adafruit_SHT4x sht4 = Adafruit_SHT4x();

// 替换为你的网络信息
const char* ssid = "WIFI名称";
const char* password = "WIFI密码";

// 替换为你的Mosquitto broker信息
const char* mqtt_server = "IPV4地址";
const int mqtt_port = 1883;
const char* mqtt_user = "HA用户名";
const char* mqtt_password = "HA密码";

// 初始化WiFi和MQTT客户端
WiFiClient espClient;
PubSubClient client(espClient);

// 传感器数据发布主题
const char* topic = "homeassistant/sensor/sensorBedroom/state";

void setup()
{
// put your setup code here, to run once:
Serial.begin(115200);

setup_wifi();
client.setServer(mqtt_server, mqtt_port);

Wire1.begin();
if(sht4.begin(&Wire1) == false)
{
Serial.println("SHT40 not detected. Please check wiring. Freezing.");
while (1)
;
}

sht4.setPrecision(SHT4X_HIGH_PRECISION);
sht4.setHeater(SHT4X_NO_HEATER);
Serial.println("SHT40 acknowledged.");
}

void loop() {
// put your main code here, to run repeatedly:

delay(1000);

if (!client.connected()) {
reconnect();
}
client.loop();

// 假设你有一个温度传感器,获取温度数据
float temperature = readTemperature();
float humidity = readHumidity();

StaticJsonDocument<200> jsonDoc;
jsonDoc["humidity"] = humidity;
jsonDoc["temperature"] = temperature;

char jsonBuffer[512];
serializeJson(jsonDoc, jsonBuffer);

client.publish(topic, jsonBuffer);

// 每隔5秒发送一次数据
delay(5000);
}

void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}

void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("ArduinoClient", mqtt_user, mqtt_password)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
}
}
}

float readTemperature() {
// 在这里读取实际传感器的数据
// 示例中返回一个固定值

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("℃");
// Serial.print("Humidity: ");
// Serial.print(humidity.relative_humidity);
// Serial.println("%");

return temp.temperature;
}

float readHumidity() {
// 在这里读取实际传感器的数据
// 示例中返回一个固定值

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("℃");
// Serial.print("Humidity: ");
// Serial.print(humidity.relative_humidity);
// Serial.println("%");

return humidity.relative_humidity;
}
下载程序,然后打开HA进行查看,发现数据已经可以正常进行上传了。测试一下SHT40的性能。发现数据变化的速度非常快,基本手指触碰到传感器后,数据就已经开始上涨了。
wd_005808cfefrt1trikxh06k.png
十、心得体会
非常荣幸能够参加到这次FM的活动,从这次活动中学习到了很多的知识,也对Arduino有了完完全全的重新的认识。之前使用51单片机或者32单片机关于模拟的功能仅使用过ADC和DAC,在这个板子上见到了内置的OPA,并使用内置的OPA实现了放大的功能。当然通过这次活动,最大的收获便是对HA有了初步的认识,并在网络的帮助下实现了HA环境的搭建,以及将传感器的数据上传到HA的平台中,遗憾的是由于目前身边没有低功耗的开发板(树莓派之类的,可以长时间运行HA的板子或设备),使用虚拟机搭建的HA环境也没有长时间的运行下去。希望后面有时间可以学习一下Linux的开发,搭建一套真正属于自己的可以长时间工作的HA的环境,并继续使用这块板子实现更多传感器的数据获取和上传。
在这次活动中,能提出的意见是,希望活动的直播可以早一些开始。在这次活动的制作过程中,大家的热情都很高涨,很多人在直播开始前基本就做完了大部分的内容,直播就没有了带大家入门的效果,当然自己从网上搜寻资料,进行开发也是一项必备的技能。但是还是希望如果有更多的活动,希望直播可以尽早的开启,这样也不会浪费官方的老师为我们大家精心准备的课程。
最后的最后,还是要希望论坛能够多多推出更多有趣有意思,能够带领大家学到更多知识的活动、课程、直播等等。也希望各位工程师朋友在今后的工作中顺利,学到更多的知识,掌握更多的本领。

本帖最后由 王嘉辉 于 2024-10-31 22:40 编辑

回复评论 (3)

wave_sin[256] 这种方式是不是曲线更加的平滑啊啊

在爱好的道路上不断前进,在生活的迷雾中播撒光引
点赞 (1) 2024-10-2 11:37
引用: 秦天qintian0303 发表于 2024-10-2 11:37 wave_sin[256] 这种方式是不是曲线更加的平滑啊啊

数组位数越多,能形成的波形应该会越还原。DAC应该也是可以调整到12位精度的,这两个方式应该都可以让波形更加的平滑一些。

点赞  2024-10-2 17:27

了解学习学习

点赞 (1) 2024-10-2 19:22
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复