[作品提交] 【Follow me第二季第2期】+ 作品提交整合贴

御坂10032号   2024-9-12 23:40 楼主

前言

 

Hello,大家好,我是Wang Chong 非常高兴也非常荣幸能够参加电子工程世界和得捷电子举办得Follow me 第二期得活动。

 

物料展示

 

本次拿到得开发板是Arduino uno R4 wifi 以及 LTR-329 光照传感器,SHT40湿温度传感器, 和QWIIC连接线。

 

微信图片_20240912231209.jpg  

设计思路

 

入门任务(任务1) :

        任务一的主要点在于如何在原理图中确认IO的端口,从而使用GPIO控制闪烁

 

基础任务(任务2) :

        任务2的主要点在于如何读懂Arduino官方文档中对LED矩阵和ADC,运算放大器的使用(和电路搭建)

 

进阶任务(任务3) :

        任务三的主要点在于ESP32S3wifi库和MQTT库的使用,以及如何在HA中配置HA实体

 

拓展任务一:

        拓展任务一的主要点在于如何使用QWIIC和正确的库来连接读取光照传感器, 由于在进阶任务中已经连接了MQTT和WIFI,可以代码复用

 

拓展任务二:

        同拓展任务一,不过传感器驱动变成了SHT40

 

 

视频如下

 


 


 

任务实现详情

 

入门任务一:搭建环境并开启第一步Blink / 串口打印Hello EEWorld!

帖子地址:【Follow me第二季第2期】+ 入门任务【搭建环境,Blink / 串口日志打印】 https://bbs.eeworld.com.cn/thread-1293048-1-1.html

 

流程图如下

 

未命名绘图.png    

 

任务一的主要点在于如何在原理图中确认R4 IO的端口,从而使用GPIO控制闪烁

 

 

 

代码展示

 

void setup() {
  // sets the digital pin 13 as output 
  // 设置GPIO13 为输出模式
  pinMode(13, OUTPUT);    
}

void loop() {
  // sets the digital pin 13 on
  // 输出高电平
  digitalWrite(13, HIGH); 
  // waits for a second
  // 延时一秒
  delay(1000);      
  // sets the digital pin 13 off     
  // 输出低电平
  digitalWrite(13, LOW);  
  // 延时一秒
  delay(1000);         /
}

 

功能展示

【Follow me第二季第2期】+ 入门任务【搭建环境,Blink - 串口日志打印】 - DigiKey得捷技术专区 - 电子工程世界-论坛

 

二、串口打印HelloWorld

 

根据官方文档和用户手册得知,D0 和D1 被用于USB的串口输入和输出, 因此只需要在程序中配置即可。

 

 

代码如下

 

void setup() {
  // sets the digital pin 13 as output 
  // 设置GPIO13 为输出模式
  pinMode(13, OUTPUT);    

  // 设置波特率
  Serial.begin(115200);
  Serial.println("Hello World!");
  Serial.println("Hello DigiKey and EEWorld!");
}

void loop() {
  // sets the digital pin 13 on
  // 输出高电平
  digitalWrite(13, HIGH); 
  // waits for a second
  // 延时一秒
  delay(1000);      
  // sets the digital pin 13 off     
  // 输出低电平
  digitalWrite(13, LOW);  
  // 延时一秒
  delay(1000); 
}

 

实验现象如下:

 

 


 

基础任务:驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线

帖子地址:【Follow me第二季第2期】+ 基础任务【驱动LED矩阵+DAC正弦波+放大信号+ADC数据采集] https://bbs.eeworld.com.cn/thread-1293064-1-1.html

 

流程图如下:

 

未命名绘图.png    

 

 

实现思路:任务2的主要点在于如何读懂Arduino官方文档中对LED矩阵和ADC,运算放大器的使用(和电路搭建)

 

如下有三种点亮LED矩阵的方法

 

1- 使用帧的方式

 

// To use ArduinoGraphics APIs, please include BEFORE Arduino_LED_Matrix
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;


byte frame[8][12] = {
  { 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
  { 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0 },
  { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
  { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
  { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

void setup() {
  Serial.begin(115200);
  matrix.begin();
  matrix.renderBitmap(frame, 8, 12);
}

void loop() {

}

实验现象:

 

微信图片_20240912233416.jpg  

 

2- 同样使用帧,不过是十六进制(官方推荐)

// To use ArduinoGraphics APIs, please include BEFORE Arduino_LED_Matrix
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;


const uint32_t heart[] = {
    0x3184a444,
    0x44042081,
    0x100a0040
};

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

void loop() {

}

 

实验现象

 

微信图片_20240912233416.jpg  

 

3- 使用官方代码滚屏

 

// To use ArduinoGraphics APIs, please include BEFORE Arduino_LED_Matrix
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"

ArduinoLEDMatrix matrix;

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

  matrix.beginDraw();
  matrix.stroke(0xFFFFFFFF);
  // add some static text
  // will only show "UNO" (not enough space on the display)
  const char text[] = "UNO r4";
  matrix.textFont(Font_4x6);
  matrix.beginText(0, 1, 0xFFFFFF);
  matrix.println(text);
  matrix.endText();

  matrix.endDraw();

  delay(2000);
}

void loop() {

  // Make it scroll!
  matrix.beginDraw();

  matrix.stroke(0xFFFFFFFF);
  matrix.textScrollSpeed(50);

  // add the text
  const char text[] = "    Hello EEWorld and DigiKey!    ";
  matrix.textFont(Font_5x7);
  matrix.beginText(0, 1, 0xFFFFFF);
  matrix.println(text);
  matrix.endText(SCROLL_LEFT);

  matrix.endDraw();
}

 

实验现象

【Follow me第二季第2期】+ 基础任务【驱动LED矩阵+DAC正弦波+放大信号+ADC数据采集】 - DigiKey得捷技术专区 - 电子工程世界-论坛

 

 

 

4 - 使用工具进行动画效果的制作

 

#include "Arduino_LED_Matrix.h"   //Include the LED_Matrix library
#include "animation2.h"
// Create an instance of the ArduinoLEDMatrix class
ArduinoLEDMatrix matrix;  

void setup() {
  Serial.begin(115200);
  // you can also load frames at runtime, without stopping the refresh
  matrix.loadSequence(animation2);
  matrix.begin();
  matrix.play(true);
}

void loop() {
}

 

【Follow me第二季第2期】+ 基础任务【驱动LED矩阵+DAC正弦波+放大信号+ADC数据采集】2 - DigiKey得捷技术专区 - 电子工程世界-论坛

 

二、DAC 输出正弦波,放大信号,并且使用ADC采集显示在串口绘图中

 

流程图如下:

 

未命名绘图.png    

 

实现思路:这个任务主要分为三个部分, 分别是使用DAC输出正弦波, 然后使用信号放大器放大DAC输出,然后使用ADC采集输入.

 

1- DAC 输出

 

/*
  SineWave

  Generates a pre-generated sawtooth-waveform.

  See the full documentation here:
  https://docs.arduino.cc/tutorials/uno-r4-wifi/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
}

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
}

 

电路如下:

 

示波器输出如下

 

 

2- 使用信号放大器放大DAC输出

 

接线图如下:

 

 

 

电路如下:

 

205354rvcz3ymvplcxzkcy.jpg

 

代码如下(此时我们已经完成了正弦波和放大信号,那么现在我们将使用ADC来读取放大后的信号)

 

#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 = 10;  // in hertz, change accordingly

void setup() {
  OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
  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(50);      // Delay for one second before repeating
}

示波器输出如下所示(4V左右,滑动变阻器仍然可以调整输出频率):

 

 

参考官方文档, 我们可以使用如下API来配置ADC功能

1- analogReadResolution()

2- analogRead()

如果不需要修改分辨率的话, 可以不使用第一个API。我们在我们的代码上稍微修改下,使其可以把输出被串口绘图正确解析,同时可以获取A4的ADC输入

 

 

#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 = 10;  // in hertz, change accordingly
int reading = 0;
void setup() {
  OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
  Serial.begin(115200);  // Initialize serial communication at a baud rate of 115200
  analogWriteResolution(14); 
  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");
  reading = analogRead(A4);
  Serial.print(reading);
  wave.freq(freq);  // Set the frequency of the waveform generator to the updated value
  delay(50);      // Delay for one second before repeating
}

 

 

串口绘图工具输出如下(蓝色的为ADC读取的值,黄色的为当前的频率)

 

 

 


 

进阶任务:通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)

帖子地址:【Follow me第二季第2期】+ 进阶任务 :通过Wi-Fi,利用MQTT协议接入HA https://bbs.eeworld.com.cn/thread-1293101-1-1.html

 

流程图如下:

 

未命名绘图.png  

 

任务三的主要点在于ESP32S3wifi库和MQTT库的使用,以及如何在HA中配置HA实体

 

本地部署的镜像展示(HA 和 MQTT)

 

 

进行MQTT测试

 

 

前置工作已经准备好了,那么现在我们就可以开始我们的任务了。 那么这个任务一共分为以下两点

        1- 连接WIFI

        2- 连接MQTT并且发送消息

 

对于WIFI的连接比较简单, 我们可以参考S3的wifi连接示例,如下所示

 

 

代码如下

 

#include <WiFiS3.h>

char ssid[] = "ImmortalWrt";        
char pass[] = "mazha1997";  
int status = WL_IDLE_STATUS;   


void setup() {
  Serial.begin(9600);
  while (!Serial) {

  }

  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);
  }

  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();


}


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 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 loop() {

}



实验现象如下(成功连接上WIFI 获取到了IP地址)

 

 

 

现在我们便开始处理我们的第二个任务, 使用MQTT连接到HA(也就是MQTT服务器,使其HA中集成的MQTT自动发现我们的配置服务)。

 

参考Arduino的官方文档,我们得知,可以使用ArduinoMqttClient的库来连接MQTT。 我们在上述的代码上稍作修改。

 

#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>

char ssid[] = "ImmortalWrt";        
char pass[] = "mazha1997";  
int status = WL_IDLE_STATUS;   

const char broker[] = "192.168.1.113";
int        port     = 1883;
const char topic[]  = "/aht10/test";

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

void setup() {
  Serial.begin(9600);
  while (!Serial) {

  }

  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);
  }

  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();
  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());
    while (1);
  }
  Serial.println("You are connected to MQTT");

}


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 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 loop() {
    mqttClient.beginMessage(topic);
    mqttClient.print("Hello EEworld and Digikey!");
    mqttClient.endMessage();
    delay(500);
}



 

将程序烧录到开发板上后,我们打开MQTTX, 查看我们MQTT的目标主题.

 

 

配置HA实体

 

 

根据上述配置文件得知,我们可以往两个主题内发送消息,从而控制HA的中实体的状态

 

1- home/bedroom/switch1 状态主题

2- home/bedroom/switch1/set 命令主题

 

当我们想要关闭灯的时候,只需要向命令主题中发送OFF即可, 如果想要开灯则发送ON. 但是尽管它已经可以正常的控制灯的开关。但是HA中实体的状态并不会发生变化。 如果想要实体的状态也发送变化的话,则需要向状态主题中也发送一个OFF

 

我们简单的修改一下代码,使其每秒切换灯的状态。

 

 

#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>

char ssid[] = "ImmortalWrt";        
char pass[] = "mazha1997";  
int status = WL_IDLE_STATUS;   

const char broker[] = "192.168.1.113";
int        port     = 1883;
const char command_topic[]  = "home/bedroom/switch1/set";
const char state_topic[]  = "home/bedroom/switch1";

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

bool index = true;

void setup() {
  Serial.begin(9600);
  while (!Serial) {

  }

  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);
  }

  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();
  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());
    while (1);
  }
  Serial.println("You are connected to MQTT");

}


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 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 loop() {
  if(index)
  {
    mqttClient.beginMessage(command_topic);
    mqttClient.print("ON");
    mqttClient.endMessage();
    mqttClient.beginMessage(state_topic);
    mqttClient.print("ON");
    mqttClient.endMessage();
  }else {
    mqttClient.beginMessage(command_topic);
    mqttClient.print("OFF");
    mqttClient.endMessage();
    mqttClient.beginMessage(state_topic);
    mqttClient.print("OFF");
    mqttClient.endMessage();
  }
  index = !index;
  delay(1000);

}



 

【Follow me第二季第2期】+ 进阶任务 :通过Wi-Fi,利用MQTT协议接入HA - DigiKey得捷技术专区 - 电子工程世界-论坛

 


 

拓展任务一:扩展任务一  使用LTR-329 环境光传感器,上传到HA并显示

 

帖子地址:【Follow me第二季第2期】+ 扩展任务一  使用LTR-329 环境光传感器,上传到HA并显示 https://bbs.eeworld.com.cn/thread-1293104-1-1.html

 

流程图如下:
 

未命名绘图.png    

 

 

拓展任务一的主要点在于如何使用QWIIC和正确的库来连接读取光照传感器, 由于在进阶任务中已经连接了MQTT和WIFI,可以代码复用

 

   这个任务主要分为三个方面

        1- 使用R4读取LTR-329传感器数据

        2- 配置HA实体

        3- 将数据上传到HA

 

 

步骤一代码如下:

 

/***************************************************
  This is an example for the LTR329 light sensor that reads both channels
  and demonstrates how to set gain and check data validity

  Designed specifically to work with the LTR-329 light sensor from Adafruit
  ----> https://www.adafruit.com/product/5591

  These sensors use I2C to communicate, 2 pins are required to
  interface
 ****************************************************/

#include "Adafruit_LTR329_LTR303.h"

Adafruit_LTR329 ltr = Adafruit_LTR329();

void setup() {
  Serial.begin(115200);
  Serial.println("Adafruit LTR-329 advanced test");

  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;
  }
}

void loop() {
  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);
    }
  }

  delay(100);
}

 

串口数据打印如下:

 

 

2- 配置HA实体

 

    HA实体的配置主要是涉及到HA容器内的configuration.yml 根据官方文档得知我们可以配置一个如下的光照和举例的传感器

 

 

然后我们在HA的Web页面中重新加载一下配置信息

 

 

此时我们只需要向名称为 lux的主题内发送json数据即可

 

如下消息格式

 

{"psData":143,"brightness":117.2}

 

此时我们第二部分完成

 

 

步骤三: 上传数据到HA

 

由于我们上一个章节已经成功的连接到了WIFI 并且使用MQTT发送了数据,我们可以整合上一节的代码。 主要的逻辑就是初始化WIFI连接并且连接到MQTT服务器。 当获取到光照数据的时候结合Arduino的json库将数据序列化成JSON数据然后发送的MQTT服务器

 

代码如下:

/***************************************************
  This is an example for the LTR329 light sensor that reads both channels
  and demonstrates how to set gain and check data validity

  Designed specifically to work with the LTR-329 light sensor from Adafruit
  ----> https://www.adafruit.com/product/5591

  These sensors use I2C to communicate, 2 pins are required to
  interface
 ****************************************************/

#include "Adafruit_LTR329_LTR303.h"
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>
#include <Arduino_JSON.h>
Adafruit_LTR329 ltr = Adafruit_LTR329();

char ssid[] = "ImmortalWrt";        
char pass[] = "mazha1997";  
int status = WL_IDLE_STATUS;   

const char broker[] = "192.168.1.113";
int        port     = 1883;
const char command_topic[]  = "lux";

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

JSONVar dataObj;

void setup() {
  Serial.begin(115200);
  Serial.println("Adafruit LTR-329 advanced test");


  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);
  }

  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();
  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());
    while (1);
  }
  Serial.println("You are connected to MQTT");
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  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;
  }
}


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 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 loop() {
  bool valid;
  uint16_t visible_plus_ir, infrared;
  if (ltr.newDataAvailable()) {
    valid = ltr.readBothChannels(visible_plus_ir, infrared);
    if (valid) {
      dataObj["brightness"] = visible_plus_ir;
      dataObj["psData"] = infrared;
      String jsonString = JSON.stringify(dataObj);
      mqttClient.beginMessage(command_topic);
      mqttClient.print(jsonString);
      mqttClient.endMessage();
    }
  }

  delay(500);
}

 

此时便可以在HA的主界面中编辑Dashboard 在实体中搜索配置的实体的名称,如下图所示(成功的配置了光照传感器)

 

 

当点击传感器名称的时候还可以查看到历史数据

 

 


 

 

拓展任务一:扩展任务二  通过外部SHT40温湿度传感器,上传温湿度到HA

 

帖子地址:【Follow me第二季第2期】扩展任务二:通过外部SHT40温湿度传感器,上传温湿度到HA. https://bbs.eeworld.com.cn/thread-1293108-1-1.html

 

流程图如下:

 

1png.png    

 

 

实现思路:同拓展任务一,只不过传感器驱动变成了SHT40

 

通过上一章的练习我们已经学会了如何使用R4来读取传感器的数据并且上传到HA由HA进行显示(手机端或者Web端)。 那么本章节也是同样的道理,只不过传感器换成了SHT40. 我们可以直接使用上一个章节的代码, 不过需要替换掉原本的驱动函数以及对应的消息主题

 

 

代码如下

 

/***************************************************
  This is an example for the LTR329 light sensor that reads both channels
  and demonstrates how to set gain and check data validity

  Designed specifically to work with the LTR-329 light sensor from Adafruit
  ----> https://www.adafruit.com/product/5591

  These sensors use I2C to communicate, 2 pins are required to
  interface
 ****************************************************/

#include "Adafruit_SHT4x.h"
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>
#include <Arduino_JSON.h>

Adafruit_SHT4x sht4;

char ssid[] = "ImmortalWrt";        
char pass[] = "mazha1997";  
int status = WL_IDLE_STATUS;   

const char broker[] = "192.168.1.113";
int        port     = 1883;
const char command_topic[]  = "office/sensor1";

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

JSONVar dataObj;

void setup() {
  Serial.begin(115200);
    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;
  }   
  //*********************************************************************
  //*************ADVANCED SETUP - SAFE TO IGNORE!************************       
  
  // The SHT40 has a built-in heater, which can be used for self-decontamination.
  // The heater can be used for periodic creep compensation in prolongued high humidity exposure.
  // For normal operation, leave the heater turned off.

  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;
  }

  
  //*********************************************************************
  //*************ADVANCED SETUP IS OVER - LET'S CHECK THE CHIP ID!*******

  
  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);    
  } 
  Serial.println(F("----------------------------------"));
 

  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);
  }

  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();
  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());
    while (1);
  }
  Serial.println("You are connected to MQTT");
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

 
 
}


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 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 loop() {

  sensors_event_t humidity, temp;
  sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
  
  float t = temp.temperature;
  Serial.println("Temp *C = " + String(t)); 
  float h = humidity.relative_humidity;
  Serial.println("Hum. % = " + String(h)); 

  dataObj["temperature"] = t;
  dataObj["humidity"] = h;
  String jsonString = JSON.stringify(dataObj);
  mqttClient.beginMessage(command_topic);
  mqttClient.print(jsonString);
  mqttClient.endMessage();
  delay(500);
}

 

实验现象如下:

 

 

 

项目完整源码如下:

 

直链下载

官方下载

 

 

活动总结体会

 

非常感谢电子工程世界和得捷电子提供了这次宝贵的活动机会,使我受益匪浅。在活动中,我学到了很多新知识,例如如何使用 ESP32 S3 和 ESP8266 连接 Wi-Fi,以及相关 Arduino API 和库的使用。这次活动让我对 Arduino 的操作更加得心应手。

 

由于之前较少接触 Arduino IDE,本次活动中所有的代码都是参考并学习了 Arduino 官方文档后实现的,这不仅提升了我的技术水平,还增强了我的英文阅读能力。此外,我还学会了如何使用运算放大器来生成模拟信号等相关技巧。

 

再次感谢主办方的支持,这次活动给了我宝贵的学习机会!

本帖最后由 御坂10032号 于 2024-9-13 14:29 编辑

回复评论 (1)

作品提交整合贴,很棒,建议路过的网友收藏参考

点赞  2024-9-15 08:46
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复