tangye

  • 2024-10-08
  • 加入了学习《FollowMe 第二季:2 - Arduino UNO R4 Wi-Fi 及任务讲解》,观看 Arduino UNO R4 Wi-Fi 及任务讲解

  • 发表了主题帖: 【Follow me第二季第2期】任务汇总贴

    本帖最后由 tangye 于 2024-11-2 23:02 编辑 非常荣幸能够参加电子工程世界和得捷电子举办得Follow me 第二季第2期活动。 我以前没有接触过嵌入式系统的开发,对电子技术略有了解。本次活动让我有机会接触到一些新的领域,学习了不少新知识。实验过程中遇到不少问题,有些通过参考各位大佬的帖子解决了,有些还需要将来进一步探索。   我的代码:https://download.eeworld.com.cn/detail/tangye/634556 我的视频:https://training.eeworld.com.cn/video/41255   活动任务分4个阶段 入门任务:搭建环境并开启第一步 Blink / 串口打印 Hello EEWorld! 基础任务:驱动 12x8 点阵 LED;用 DAC 生成正弦波;用 OPAMP 放大 DAC 信号;用 ADC 采集并且打印数据到串口等其他接口可上传到上位机显示曲线 进阶任务:通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台 HA(HomeAssistant) 扩展任务: 1. 通过 LTR-329 环境光传感器,上传光照度到 HA,通过 HA 面板显示数据; 2. 通过 SHT40温湿度传感器,上传光照度到 HA,通过 HA 面板显示数据;   我拿到的物料包括 Arduino uno R4 wifi 以及 LTR-329 光照传感器,SHT40 湿温度传感器。这是全家福照片   这是 Arduino uno R4 wifi 引脚图。后续实验的接线依赖这张图片   任务完成思路: 1. 入门任务:搭建环境并开启第一步Blink / 串口打印Hello EEWorld! 这部分的主要内容是安装Arduino-IDE环境,连接到开发板,并且根据IDE提供的范例,完成相应的代码。 Arduino IDE的官方下载位于 https://www.arduino.cc/en/software 我下载了 arduino-ide_2.3.2,在Windows 10环境中双击安装即可。 安装完成后,在“文件”--“首选项” 中,可以修改项目文件夹地址等内容,便于后续备份和维护。   打开示例文件Blink,可以看到相应的代码。   在这个文件的基础上,我加上串口输出指令,完成入门任务。 流程图 void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); Serial.begin(9600); } void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) Serial.println("Hello World!"); delay(500); // wait for 0.5 second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW Serial.println("This is Arduino UNO R4!"); delay(500); // wait for 0.5 second } 串口监视器输出如图 开发板闪灯视频,可以看到受控的LED灯以1Hz的频率闪烁,同时TX指示灯每秒闪2下 [localvideo]a245e3b3be64bf0461c2552c13c0d95d[/localvideo]   2. 基础任务:驱动 12x8 点阵 LED;用 DAC 生成正弦波;用 OPAMP 放大 DAC 信号;用 ADC 采集并且打印数据到串口等其他接口可上传到上位机显示曲线 基础任务在任务讲解视频 https://training.eeworld.com.cn/video/40793 中有详细介绍。 根据视频和论坛的帮助,我设计了LED矩阵的驱动代码,在程序初始化阶段,显示红心持续2秒,然后转为字幕并滚动 流程图 #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); delay(2000); matrix.beginDraw(); matrix.stroke(0xFFFFFFFF); matrix.textFont(Font_4x6); matrix.beginText(0, 1, 0xFFFFFF); matrix.println("Hey"); matrix.endText(); matrix.endDraw(); delay(2000); } void loop() { matrix.beginDraw(); matrix.stroke(0xFFFFFFFF); matrix.textScrollSpeed(200); const char text[] = "Hello Digikey!"; matrix.textFont(Font_5x7); matrix.beginText(0, 1, 0xFFFFFF); matrix.println(text); matrix.endText(SCROLL_LEFT); matrix.endDraw(); delay(500); } [localvideo]89876f0a54b42e0f3882f4bc5a69e9d7[/localvideo] DAC生成正弦波,通过内部OPAMP放大,并输出到ADC最终显示在“串口绘图仪”,需要在模拟引脚上接线。 根据原理图,A0输出DAC波形,用导线连接到A1。在A2和A3之间接一个10K电阻,在A2和地之间接一个10K电阻。此时A3(即运放输出端)的电压信号为A0的2倍。 为了用内置的ADC测量并显示电压波形,需要分别连接A0和A4,A3和A5。我完成的接线如图 流程图 DAC/OPAMP/ADC代码 #include "analogWave.h" #include <OPAMP.h> // Create an instance of the analogWave class, using the DAC pin analogWave wave(DAC); int freq = 100; void setup() { wave.sine(freq); // Generate a sine wave 100Hz wave.amplitude(0.4); // 0.0 ~ 1.0 OPAMP.begin(OPAMP_SPEED_HIGHSPEED); analogWriteResolution(14); Serial.begin(230400); // baud rate 230.4k } void loop() { Serial.print(analogRead(A4)); Serial.print(" "); Serial.println(analogRead(A5)); } 示波器观察A0 示波器观察A3 “串口绘图仪” 的显示 [localvideo]be9b39364da2e81c3416ad28d1cf9f56[/localvideo]   3. 进阶任务:通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台 HA(HomeAssistant) 这个任务,需要准备HomeAssistant和EMQX。我在ubuntu系统里,用Docker方式搭建了HA环境,主要遇到的问题是docker镜像拉取困难。 经过一番折腾,发现home-assistant官方镜像托管在github上,可以直接pull(就是有些慢) $ docker pull ghcr.io/home-assistant/home-assistant:stable EMQX镜像是单独找的,实际上直接安装也很方便。 分别启动两个镜像 $ docker run -d --name="home-assistant" -v ~/HA_config:/config -p 8123:8123 ghcr.io/home-assistant:stable $ docker run -d --name="EMQX" --network host emqx/emqx:5.7.2 这里需要说明一下,EMQX启动的时候,我没有指定端口映射,而是直接让容器使用了host的IP。 原因是,如果让EMQX默认连接内部网络docker0,每次启动的时候容器会拿到dhcp地址。启动顺序会影响地址,配置home-assistant指定的地址有可能失效。 接下来,按照任务讲解视频,分别访问 http://ip:18083 和 http://ip:8123 完成 EMQX 和 home-assistant 的配置 后续内容参考了各位大佬的帖子,在此一并致谢。 通过“示例”--“WiFiS3”--“ConnectWithWPA” 这个例程,修改 arduino_secrets.h 文件,写入 ssid(设备只支持2.4GHz)和访问密码,编译运行后可以在串口监视器上确认无线网络是否正确连接。 然后在库管理中,安装ArduinoMqttClient,运行例程连接MQTT服务 最后,用开发板送出数据,在HomeAssistant面板上显示。 流程图 代码,通过DAC在A0引脚输出正弦波,开发板测量电压值,显示在HA面板上 #include <ArduinoMqttClient.h> #include "analogWave.h" #include <Wire.h> #include <WiFiS3.h> #include "arduino_secrets.h" ///////please enter your sensitive data in the Secret tab/arduino_secrets.h char ssid[] = SECRET_SSID; // your network SSID (name) char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) int status = WL_IDLE_STATUS; WiFiClient wifiClient; MqttClient mqttClient(wifiClient); analogWave wave(DAC); const char broker[] = "192.168.90.79"; //MQTT Server IP int port = 1883; //MQTT Server port const char topic[] = "UNO/R4/ADC/volt_d"; //Topic const char mqttuser[] = "admin"; const char mqttpassword[] = "admin"; //set interval for sending messages (milliseconds) const long interval = 5000; unsigned long previousMillis = 0; int count = 0; void setup() { // Generate Wave wave.sine(2); // Generate a sine wave 2Hz wave.amplitude(0.8); // 0.0 ~ 1.0 analogWriteResolution(10); Serial.begin(115200); // baud rate 115.2k // Try to connect WLAN: Serial.print("Attempting to connect to WPA SSID: "); Serial.println(ssid); while (WiFi.begin(ssid, pass) != WL_CONNECTED) { Serial.print("."); delay(5000); } Serial.println("You're connected to the network"); Serial.println(); Serial.print("Attempting to connect to the MQTT broker: "); Serial.println(broker); mqttClient.setUsernamePassword(mqttuser, mqttpassword); while (!mqttClient.connect(broker, port)) { Serial.print("MQTT connection failed! Error code = "); Serial.println(mqttClient.connectError()); delay(1000); } Serial.println("You're connected to the MQTT broker!"); Serial.println(); } void loop() { mqttClient.poll(); //通过ADC采集 A0上输出的波形 float A0_voltage = analogRead(A0) * 4.7/1023; //A0, 10bit ADC采样,修正为十进制数 mqttClient.beginMessage(topic); mqttClient.print(A0_voltage); //把计算出的电压值上传到MQTT服务器 mqttClient.endMessage(); delay(500); } 在HA面板显示数据,需要修改 configuration.yaml 增加以下部分 mqtt: - sensor: - unique_id: arduino uno Voltage name: "arduino Volt" state_topic: "UNO/R4/ADC/volt_d" suggested_display_precision: 3 unit_of_measurement: "V" value_template: "{{ value }}" 重新加载YAML配置后,HA面板显示变化的电压值   扩展任务: 1. 通过 LTR-329 环境光传感器,上传光照度到 HA,通过 HA 面板显示数据; 2. 通过 SHT40温湿度传感器,上传光照度到 HA,通过 HA 面板显示数据; 连接传感器,我直接用的I2C接口,在传感器上焊了插针,用跳线连接VCC/GND/SCL/SDA信号。 使用LTR-329的例程,直接可以在串口监视器上看到CH0和CH1的光照度   在例程的基础上,结合上一阶段的代码,就能把数据上传到MQTT服务器。 流程图 传感器有两个数据,上传到一个订阅里用了json格式。 #include <ArduinoMqttClient.h> #include <Wire.h> #include <WiFiS3.h> #include <Arduino_JSON.h> #include "arduino_secrets.h" ///////please enter your sensitive data in the Secret tab/arduino_secrets.h char ssid[] = SECRET_SSID; // your network SSID (name) char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) int status = WL_IDLE_STATUS; #include "Adafruit_LTR329_LTR303.h" Adafruit_LTR329 ltr = Adafruit_LTR329(); WiFiClient wifiClient; MqttClient mqttClient(wifiClient); const char broker[] = "192.168.90.79"; //MQTT Server IP int port = 1883; //MQTT Server port const char topic[] = "UNO/R4/LTR329"; //Topic const char mqttuser[] = "admin"; const char mqttpassword[] = "admin"; //set interval for sending messages (milliseconds) const long interval = 5000; unsigned long previousMillis = 0; int count = 0; JSONVar dataObj; void setup() { Serial.begin(115200); 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; } // Try to connect WLAN: Serial.print("Attempting to connect to WPA SSID: "); Serial.println(ssid); while (WiFi.begin(ssid, pass) != WL_CONNECTED) { Serial.print("."); delay(5000); } Serial.println("You're connected to the network"); Serial.println(); Serial.print("Attempting to connect to the MQTT broker: "); Serial.println(broker); mqttClient.setUsernamePassword(mqttuser, mqttpassword); while (!mqttClient.connect(broker, port)) { Serial.print("MQTT connection failed! Error code = "); Serial.println(mqttClient.connectError()); delay(1000); } Serial.println("You're connected to the MQTT broker!"); Serial.println(); } 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); } } if (ltr.newDataAvailable()) { valid = ltr.readBothChannels(visible_plus_ir, infrared); if (valid) { dataObj["dataCH0"] = visible_plus_ir; dataObj["dataCH1"] = infrared; String jsonString = JSON.stringify(dataObj); mqttClient.beginMessage(topic); mqttClient.print(jsonString); mqttClient.endMessage(); } } delay(500); } 同样要修改 HomeAssistant的configuration.yaml  mqtt: - sensor: - unique_id: CH0_Visible_IR name: "CH0_Visible_IR" state_topic: "UNO/R4/LTR329" suggested_display_precision: 1 unit_of_measurement: "lux" value_template: "{{ value_json.dataCH0 }}" - unique_id: CH1_IR name: "CH1_IR" state_topic: "UNO/R4/LTR329" suggested_display_precision: 1 unit_of_measurement: "lux" value_template: "{{ value_json.dataCH1 }}" 重新加载 YAML 配置,HA面板显示两个测量通道的数据 这是台灯的照度信息。关闭台灯后,照度下降,HA面板可以显示历史曲线 换上SHT40,可以测试温湿度数据。示例中的 SGP40_SHT40_Test 不能直接运行,需要删除SGP40的部分。 流程图 有了LTR329的使用经验,SHT40的代码如下: #include <ArduinoMqttClient.h> #include <Wire.h> #include <WiFiS3.h> #include <Arduino_JSON.h> #include "arduino_secrets.h" ///////please enter your sensitive data in the Secret tab/arduino_secrets.h char ssid[] = SECRET_SSID; // your network SSID (name) char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) int status = WL_IDLE_STATUS; #include "Adafruit_SHT4x.h" Adafruit_SHT4x sht4; WiFiClient wifiClient; MqttClient mqttClient(wifiClient); const char broker[] = "192.168.90.79"; //MQTT Server IP int port = 1883; //MQTT Server port const char topic[] = "UNO/R4/SHT40"; //Topic const char mqttuser[] = "admin"; const char mqttpassword[] = "admin"; //set interval for sending messages (milliseconds) const long interval = 5000; unsigned long previousMillis = 0; int count = 0; JSONVar dataObj; void setup() { Serial.begin(115200); Serial.println(); Serial.println(); Serial.println(F("##################################")); Serial.println(F("SHT40 test with compensation")); //********************************************************************* //*************ADVANCED SETUP - SAFE TO IGNORE!************************ //Here we can configure the SHT40 Temperature and Humidity Sensor //First we set the measurement precision //There are three precision levels: High, Medium and Low //The precision levels direclty affect the measurement duration, noise level and energy consumption //On doubt, just leave it on default (High precision) 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()) { 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("----------------------------------")); // Try to connect WLAN: Serial.print("Attempting to connect to WPA SSID: "); Serial.println(ssid); while (WiFi.begin(ssid, pass) != WL_CONNECTED) { Serial.print("."); delay(5000); } Serial.println("You're connected to the network"); Serial.println(); Serial.print("Attempting to connect to the MQTT broker: "); Serial.println(broker); mqttClient.setUsernamePassword(mqttuser, mqttpassword); while (!mqttClient.connect(broker, port)) { Serial.print("MQTT connection failed! Error code = "); Serial.println(mqttClient.connectError()); delay(1000); } Serial.println("You're connected to the MQTT broker!"); Serial.println(); } void loop() { sensors_event_t humidity, temp; sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data float t = temp.temperature; Serial.print("Temp *C = "); Serial.println(t); float h = humidity.relative_humidity; Serial.print("Hum. % = "); Serial.println(h); dataObj["SHT40_temp"] = t; dataObj["SHT40_humi"] = h; String jsonString = JSON.stringify(dataObj); mqttClient.beginMessage(topic); mqttClient.print(jsonString); mqttClient.endMessage(); delay(1000); } 修改 HomeAssistant的configuration.yaml  mqtt: - sensor: - unique_id: temperature name: "Temperature" state_topic: "UNO/R4/SHT40" suggested_display_precision: 1 unit_of_measurement: "掳C" value_template: "{{ value_json.SHT40_temp }}" - unique_id: humidity name: "Humidity" state_topic: "UNO/R4/SHT40" suggested_display_precision: 1 unit_of_measurement: "%" value_template: "{{ value_json.SHT40_humi }}" HA面板显示当前的温湿度   遗留问题 HA面板的 YAML配置重新加载以后,之前环节出现的传感器依然显示(呈现灰色)。后续看看如何清理这些内容。   对本活动的心得体会 Fellow me 活动对于我这类没有经验的新手非常友好,教学视频、论坛帖子帮助我完成了从入门到进阶的每项实验。 通过这次活动,我对Arduino 开发环境,各种传感器和相应的库,MQTT都有了初步认识。Arduino UNO R4 WiFi 功能丰富,以后可以继续深入学习。 最后,再次感谢电子工程世界,感谢得捷电子,感谢论坛各位大佬,感谢活动管理员lightxixi 

  • 2024-10-07
  • 上传了资料: R4_wifi_实验代码

  • 加入了学习《Follow me第二季第2期视频演示》,观看 演示视频

  • 2024-10-06
  • 加入了学习《【Follow me第二季第2期】任务提交》,观看 【Follow me第二季第2期】

  • 加入了学习《Follow Me 第二季第二期总结视频》,观看 follow me 集合

  • 2024-10-01
  • 加入了学习《【Follow me 第二季第2期任务】 各个任务实现的展示效果》,观看 【Follow me 第二季第2期任务】MQTT接入到HomeAssistant

  • 2024-09-29
  • 回复了主题帖: 【Follow me第二季第2期】DAC 生成正弦波

    这个DIY的示波器挺别致的

  • 加入了学习《Follow me 第二季第2期dvacos视频》,观看 Follow me 第二季第2期视频

  • 2024-09-26
  • 加入了学习《【Follow me第二季第2期】+开发板硬件介绍和实现任务一 LED灯闪烁和串口打印》,观看 【Follow me第二季第2期】+通过外部SHT40温湿度传感器,上传温湿度到HA

  • 2024-09-06
  • 回复了主题帖: 【Follow me第二季第2期】扩展任务二:通过外部SHT40温湿度传感器,上传温湿度到HA...

    效率很高啊,恭喜

最近访客

现在还没有访客

< 1/0 >

统计信息

已有--人来访过

  • 芯积分:24
  • 好友:--
  • 主题:1
  • 回复:2

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言