本次活动已经接近尾声了,我们一起通过学习实现了物联网的基本流程,本次活动是DigiKey联合EEWorld发起的Follow me活动第二季的第二期,精选高可玩性与教育价值的开发板及仪器套装,携手共赴实践盛宴。
一、物料展示
主控板卡:Arduino UNO R4 WiFi
Arduino UNO R4 WiFi 是一款基于32位Arm® Cortex®-M4 Renesas RA4M1微控制器,具有用于 Wi-Fi® 和蓝牙连接的ESP32模块,具备强大的计算能力和多种连接功能。该板SRAM 32kB,闪存256kB,时钟频率为48MHz,USB端口升级为USB-C,并且最大电源供应电压增加到24V。该板提供了一个CAN总线,允许用户通过连接多个扩展板来最小化布线并执行不同的任务。板载的Qwiic 连接器可以方便地创建即插即用风格的项目。
传感器一:LTR-329光传感器扩展板
LTR-329ALS-01是一款低压I2C数字光传感器[ALS],采用低成本的微细片状无铅表面贴装封装。该传感器将光强度转换为能够直接I2C接口的数字输出信号。它在0.01勒克斯到64k勒克斯的宽动态范围内提供线性响应,非常适合高环境亮度下的应用。共有六种增益设置(1X, 2X, 4X, 8X, 48X和96X)可供用户配置。
传感器二:SHT40温湿度传感器扩展板
SHT4x是一个数字传感器平台,用于测量不同精度等级的相对湿度和温度。其I2C接口提供多个预配置的I2C地址,同时保持超低功耗预算(0.4 μW)。电源修剪的内部加热器可以在三个加热级别使用,从而使传感器在苛刻的环境中运行。四针双平面无引线封装适用于表面贴装技术(SMT)加工,包括可选的封装上专利PTFE[1]膜或可拆卸的保护罩。根据ISO17025的传感器特定校准证书,可通过唯一序列号识别。
二、整体思路
本次的两个传感器板都是通过Qwiic 连接器进行沟通的,不过本次采购并没有采购连接线,超限了,不过多来了一个传感器还是很超值的,连接线就自己做了,通过连连串的方式进行连接,实现传感器和主控板的连接,然后开发板上有wifi模块可以实现无线连接,通过MQTT协议实现和HA平台的通信。
三、任务实现
这一部分主要写在了各个分贴中了,进行一下介绍和传送.
开箱:
【Follow me第二季第2期】开箱 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
配置开发环境:
【Follow me第二季第2期】配置开发环境 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
入门任务:
入门任务是搭建环境并开启第一步Blink / 串口打印Hello EEWorld!,环境我们在上一个章节已经搭建好了,这里主要是实现LED的翻转了和串口打印,这两个小功能也是我们熟悉新的开发板的开始,实际上就setup()和loop()两个函数,一个执行一次相当于初始化,一个是循环操作的。arduino方便的地方在于,很多操作都已经封装好,直接使用就可以,代码如下:
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
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
Serial.println("Hello EEWorld!");
}
启动GPIO和串口只用了两个函数,然后就是通过延时的方法进行循环控制实现LED的翻转:
并在执行一次后串口打印一次"Hello EEWorld!":
【Follow me第二季第2期】任务一 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
基础任务:
基础任务是驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线,实际上这个可以划分成若干个任务.96个LED的组成的矩阵,这个实际上是个单独实现的控制,每一个LED对应一位,为此我们需要设计几个字符进行循环显示并在loop()中定时循环现实:
循环显示代码如下:
ArduinoLEDMatrix matrix;
void setup() {
// put your setup code here, to run once:
matrix.begin();
}
void loop() {
// put your main code here, to run repeatedly:
matrix.loadFrame(show_1);
delay(500); // wait for a second
matrix.loadFrame(show_2);
delay(500); // wait for a second
matrix.loadFrame(show_3);
delay(500); // wait for a second
matrix.loadFrame(show_4);
delay(500); // wait for a second
matrix.loadFrame(show_E);
delay(400); // wait for a second
matrix.clear();
delay(100); // wait for a second
matrix.loadFrame(show_E);
delay(500); // wait for a second
matrix.loadFrame(show_W);
delay(1000); // wait for a second
}
效果如下:
视频效果可以看最后的效果视频中的任务二-LED整列显示部分;
其他部分是对ADC、DAC、放大等部分的操作,并且用到了我们任务一中使用的串口打印,这个时候需要一些外部连接:
放大器的外部配置更加重要,硬件的基本配置通过正向放大器的方式进行,ADC连接到OPAMP的正输入,也就是A1,A2的电压就虚短等于A1处电压,然后通过两个等大的电阻进行2被放大,A2到地连接一个,到输出连接一个,这样A3处的输出就是A1处的2倍了,通过ADC采集进行串口输出绘图。
部分代码如下:
void setup() {
// put your setup code here, to run once:
pinMode(A0, OUTPUT);
pinMode(A5, INPUT);
analogReadResolution(12);// 设置 ADC 分辨率为 12 位
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
matrix.begin();
matrix.loadFrame(show_4);
}
void loop() {
// put your main code here, to run repeatedly:
for(int i = 0; i < 360; i++){
float rad = i * PI / 180.0;
int outputValue = (127 + 127 * sin(rad))/5;// 生成正弦波信号
analogWrite(A0, outputValue);// 输出到 DAC
// 控制输出频率
delay(100);
int value = analogRead(A5);// 读取 ADC 值
Serial.println(value);
}
}
软件流程如下:
部分效果如下:
显示是通过arduino自带的串口工具查看的,由于只能显示50个数值,所以只能看到正弦波的一部分,详细的可以查看视频讲解中任务二-ADC采集部分;
详细内容可以进入分贴查看:
【Follow me第二季第2期】任务二 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
进阶任务:
通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)。这里主要就包含两部分了,一个是wifi的使用,还有一个是智能家居平台HA(HomeAssistant)的建立,当然了有很多坛友可能这一部分都已经创建了,毕竟玩物联网或者无线的很多都接触过,这个可以参照官方文件选择一个适合自己的方式创建就可以,之后通过MQTT模拟器进行实体的创建,之后我们就可以直接通过MQTT协议进行发送数据了,这一部分我们还可以不通过连接任何传感器,只是随机发送数据进行测试,只是验证MQTT协议和智能家居平台HA是否导通:
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>
#include <Arduino_JSON.h>
char ssid[] = "xxx";
char pass[] = "xxx";
const char broker[] = "192.168.72.127";
int port = 1883;
const char state_topic2[] = "homeassistant/sensor/sensorsth40/state";
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
JSONVar dataObj;
const long interval = 1000;
unsigned long previousMillis = 0;
int count = 0;
void setup() {
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("HA com test");
Serial.println("connect to WPA SSID: ");
Serial.println(ssid);
// attempt to connect to WiFi network:
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
Serial.print("......");
delay(5000);
}
Serial.print("connect wifi succeed!");
Serial.println();
Serial.println(WiFi.localIP());
// You can provide a unique client ID, if not set the library uses Arduino-millis()
// Each client must have a unique client ID
mqttClient.setId("clientId");
// You can provide a username and password for authentication
mqttClient.setUsernamePassword("admin", "admin");
Serial.print("connect to the MQTT broker: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("connected to the MQTT succeed!");
Serial.println();
}
void loop() {
// put your main code here, to run repeatedly:
mqttClient.poll();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time a message was sent
previousMillis = currentMillis;
dataObj["cnt"] = count;
String jsonString = JSON.stringify(dataObj);
// send message, the Print interface can be used to set the message contents
mqttClient.beginMessage(state_topic);
mqttClient.print(jsonString);
mqttClient.endMessage();
count++;
if(count>=90)
count = 0;
delay(1000);
}
}
整体软件流程如下:
详细内容可以进入分贴查看:
【Follow me第二季第2期】进阶任务 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
拓展任务一起:
我们这次选用了两个传感器,将资源利用最大化,为此我们需要制作连接线,arduino板子上直接有现成的接口,和板子是匹配的,一字串联皆可以了,这两个传感器的接口地址是不同,串联就可以,幸亏之前买过这个端子,确实不好掐啊:
接下来只要实现这两个传感器的驱动就可以了,依然得益于arduino的高集成,我们只要需要使用对应的应用函数就可以,不过我们需要配置一些传感器忙着一部分在初始化中完成:
#include "Adafruit_SHT4x.h"
#include "Adafruit_LTR329_LTR303.h"
Adafruit_SHT4x sht4;
Adafruit_LTR329 ltr = Adafruit_LTR329();
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
if ( ! ltr.begin(&Wire1) ) {
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;
}
sht4.setPrecision(SHT4X_HIGH_PRECISION);
switch (sht4.getPrecision()) {
case SHT4X_HIGH_PRECISION:
Serial.println(F("SHT40 set to High precision"));
break;
case SHT4X_MED_PRECISION:
Serial.println(F("SHT40 set to Medium precision"));
break;
case SHT4X_LOW_PRECISION:
Serial.println(F("SHT40 set to Low precision"));
break;
}
sht4.setHeater(SHT4X_NO_HEATER);
switch (sht4.getHeater()) {
case SHT4X_NO_HEATER:
Serial.println(F("SHT40 Heater turned OFF"));
break;
case SHT4X_HIGH_HEATER_1S:
Serial.println(F("SHT40 Heater: High heat for 1 second"));
break;
case SHT4X_HIGH_HEATER_100MS:
Serial.println(F("SHT40 Heater: High heat for 0.1 second"));
break;
case SHT4X_MED_HEATER_1S:
Serial.println(F("SHT40 Heater: Medium heat for 1 second"));
break;
case SHT4X_MED_HEATER_100MS:
Serial.println(F("SHT40 Heater: Medium heat for 0.1 second"));
break;
case SHT4X_LOW_HEATER_1S:
Serial.println(F("SHT40 Heater: Low heat for 1 second"));
break;
case SHT4X_LOW_HEATER_100MS:
Serial.println(F("SHT40 Heater: Low heat for 0.1 second"));
break;
}
if (! sht4.begin(&Wire1)) {
Serial.println(F("SHT40 sensor not found!"));
while (1) ;
}
else
{
Serial.print(F("SHT40 detected!\t"));
Serial.print(F("Serial number:\t"));
Serial.println(sht4.readSerial(), HEX);
}
}
循环中不断获取数据就可以,最后和上传数据进行一下关联,我们在HA中看到的就是传感器实时采集到的数据了:
void loop() {
// put your main code here, to run repeatedly:
bool valid;
uint16_t visible_plus_ir, infrared;
if (ltr.newDataAvailable()) {
valid = ltr.readBothChannels(visible_plus_ir, infrared);
if (valid) {
Serial.print("CH0 Visible + IR: ");
Serial.print(visible_plus_ir);
Serial.print("\t\tCH1 Infrared: ");
Serial.println(infrared);
}
}
sensors_event_t humidity, temp;
sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
float tem = temp.temperature;
Serial.println("Temp *C = " + String(tem));
float hum = humidity.relative_humidity;
Serial.println("Hum. % = " + String(hum));
dataObj["cnt"] = count;
dataObj["hum"] = hum;
dataObj["tem"] = tem;
String jsonString1 = JSON.stringify(dataObj);
mqttClient.beginMessage(state_topic1);
mqttClient.print(jsonString1);
mqttClient.endMessage();
dataObj["LTR"] = visible_plus_ir;
String jsonString2 = JSON.stringify(dataObj);
mqttClient.beginMessage(state_topic2);
mqttClient.print(jsonString2);
mqttClient.endMessage();
delay(1000);
}
整体的软件流程如下:
【Follow me第二季第2期】传感器数据上传到HA - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
相关的配置和重点注意事项大家可以去对应的帖子查看。
四、代码分享
所有任务代码可以直接放到对应的工程中打开,注意支持的库函数要进行适配下载,以及一些配置的地方配置成自己的内容。
(下载次数: 4, 2024-10-10 19:08 上传)
五、视频讲解
得捷电子Follow Me第二季第2期 - 得捷电子Follow Me第二季第2期 - EEWORLD大学堂
或者直接点开下面的视频查看:
六、活动总结
本次活动可以是第一次实现了物联网的功能,这一次使用的HA平台,可以说这个是本次最大的收获之一,就是实现了HA平台的搭建,再有一个就是Arduino的使用真的是非常便捷,对于功能模块的验证非常方便,为活动点赞!也期待更多的坛友加入EEW的大家庭!