金玉其中

  • 2024-10-03
  • 发表了主题帖: 【Follow me第二季第2期】一文全面完成任务

    本帖最后由 金玉其中 于 2024-10-31 15:40 编辑   视频链接:https://training.eeworld.com.cn/video/41231 [localvideo]06051b9dd994149c47eb26948d9b04bf[/localvideo]         本次有幸参与得捷电子Follow Me第二季第2期活动,非常感谢论坛和得捷电子。Follow me活动是DigiKey联合EEWorld发起的大型开发板体验活动,每期技术大咖推荐可玩性与可学性较强的开发板/仪器套件,带着大家实际操作,我这次也是主要秉承着学习的态度进行本次的活动,实际上很早就已经收到了采购到的器件,不过还是等到大佬们都完成了才开始我的学习之旅。 一、主要器件 主开发板: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 连接器可以方便地创建即插即用风格的项目。本次的传感板也都是符合Qwiic 连接器接口的传感器。同时本次活动也提供详尽的开发板资料供我们查略。 传感器1:LTR-329光传感器扩展板         LTR-329ALS-01是一款低压I2C数字光传感器[ALS],采用低成本微型芯片无铅表面贴装封装。该传感器将光强度转换为能够直接I2C接口的数字输出信号。它在0.01勒克斯至64k勒克斯的宽动态范围内提供线性响应,非常适合高环境亮度下的应用。总共有六种增益设置(1X、2X、4X、8X、48X和96X)可供用户配置。 传感器2:SHT40温湿度传感器扩展板         SHT4x是一个数字传感器平台,用于测量不同精度等级的相对湿度和温度。其I2C接口提供多个预配置的I2C地址,同时保持超低功耗预算(0.4μW)。功率微调的内部加热器可以在三个加热水平下使用,从而使传感器能够在要求苛刻的环境中运行。四针双扁平无引线封装适用于表面贴装技术(SMT)加工,包括可选的封装专利PTFE[1]膜或可拆卸的保护盖。可提供符合ISO17025的传感器特定校准证书,可通过唯一序列号进行识别。         秉承着尽可能多的学习,这次直接采购的两个传感器来完成任务,说实话,正好极限的覆盖了,最好的利用方式,线就没有买了,自己做一下就可以了,而且这两个传感器可以直接串联起来,使用一个Qwiic 连接器接口皆可以,毕竟就是多了几个现实参数,在完成物联网显示的时候,显示一个和显示两个没什么差异。 二、学习成果展示 1、配置开发环境         本次使用的是官方的开发环境,Arduino IDE,可以通过官网下载适配系统的最新版:         注意哦,还有免安装版本,秉承着能省一步是一本,直接免安装无脑启动;         通过USB线连接开发板和PC,软件可以直接检测到连接到的开发板:         然后就可以通过开发板安装对应的基础库了,通过开发板管理器进行搜索: 2、入门任务:搭建环境并开启第一步Blink / 串口打印Hello EEWorld!         编程的开始就是实现点灯,我们新建一个工程:         显然,存在两个关键函数:setup()和 loop()。其中,setup()扮演着初始化配置的角色,仅执行一次以设置初始状态;而 loop()则负责循环执行的内容,持续不断地运行以维持或改变程序的状态。         Arduino的卓越之处,在于其高度集成化的特性,让我们无需深究硬件的繁复细节,仅凭固件内预设的函数便能轻松驾驭。尽管如此,为了更全面地理解,我们还是简要概览一下LED的硬件配置:         可以看出来只有DL4是实际上我们可以控制的,DL3是供电只是等,另外两个是串口传输指示。对于LED和串口的控制不需要而外的固件,板载固件就可以使用,我们实现一下任务: 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:   // turn the LED on (HIGH is the voltage level)   digitalWrite(LED_BUILTIN, HIGH);   // wait for a second   delay(500);   // turn the LED off by making the voltage LOW   digitalWrite(LED_BUILTIN, LOW);   // wait for a second   delay(500);   Serial.println("Hello EEWorld!"); }         本次的任务还是比较简单,毕竟是入门的第一个任务,对上面的程序进行一下简单的介绍,本次任务主要用到的LED串口口,我们需要进行一下相应的初始化,可以看到初始化直接调用一个函数就本上就完成了,通过不同的板子的库文件,内部都已经进行好了关联,直接配置重要的参数就可以,然后就是阻塞式的实现LED的闪烁,并同时循环的发送“Hello EEWorld!”。         点击上传会自动进行工程的编译和下载,然后就可以通过观察板子的L等和IDE自带的串口监视器进行效果观察了:         注意配置好波特率。 3、基础任务:驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线。         其实这个任务是一个组合任务,可以拆分出多个任务,比如驱动LED、DAC输出正弦波、OPAMP信号放大、ADC的采集并通过接口上传显示。可以拆分出多个不相关的任务,为了实现更好的效果展示,我们经过拆分和再组合,分成了下面三个小任务:         第一个就是12x8点阵LED点阵的控制;         第二个就是DAC生成正弦波,然后通过OPAMP放大2倍,在通过ADC采集信号进行串口输出,这里面我们可以通过示波器进行对应节点的一个测量,例如DAC的输出,放大信号的输出,都可以通过示波器进行状态展示。         接下来我们先看看12x8点阵LED点阵的控制:         基本硬件如上图,也通过各位大佬的学习,有的人是通过静态显示的方法实现点阵的设计实现不同字符的显示,也有人通过不同的库文件实现动态的显示,个人也比较喜欢动态显示的方式,有点大街上小店的横幅的感觉。         点阵的LED的基础库是"Arduino_LED_Matrix.h",而动态显示文本的库是"ArduinoGraphics.h",注意ArduinoGraphics需要单独安装: #include "Arduino_LED_Matrix.h" #include "ArduinoGraphics.h" ArduinoLEDMatrix matrix; void setup() {   matrix.begin(); } void loop() {   matrix.beginDraw();   matrix.stroke(0xFFFFFFFF);   matrix.textScrollSpeed(50);   const char text[] = "  EEWorld && DigiKey  ";   matrix.textFont(Font_5x7);   matrix.beginText(0, 1, 0xFFFFFF);   matrix.println(text);   matrix.endText(SCROLL_LEFT);   matrix.endDraw(); }         接下来就是模拟部分的控制:         DAC输出:我们直接使用内置的"analogWave.h",由于后面的实验要求,我们需要限制一下幅值,具体代码如下: #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   pinMode(A0, OUTPUT);   wave.amplitude(0.25); //设置幅度值为4.7 的1/4   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   delay(500); }         结果如下:         接下来是放大部分,需要使用OPAMP,启动OPAMP很方便: #include "analogWave.h" #include <OPAMP.h> void setup() {   Serial.begin(115200);   pinMode(A0, OUTPUT);   wave.amplitude(0.25);   wave.sine(freq);         OPAMP.begin(OPAMP_SPEED_HIGHSPEED); }         同时需要进行外部的连接:         有上图也可以看到,Vpp的幅值有1.23V增加到了2.44V,我是用的是两个一样的电阻,所以是增加两倍的效果。         接下来我们将A3和A5连接,是的,我们准备用A5进行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() {   Serial.begin(115200);  // Initialize serial communication at a baud rate of 115200   pinMode(A0, OUTPUT);   pinMode(A5, INPUT);   analogReadResolution(12);// 设置 ADC 分辨率为 12 位   wave.amplitude(0.25); //设置幅度值为4.7 的1/4   wave.sine(freq);       // Generate a sine wave with the initial frequency   OPAMP.begin(OPAMP_SPEED_HIGHSPEED); } void loop() {   // Read an analog value from pin A5 and map it to a frequency range   int value = analogRead(A5);// 读取 ADC 值   Serial.println(value); }         效果显示还是不太理想,主要是显示个数限制太厉害了,不过也是可以看到趋势的: 4、进阶任务及扩展任务         通过对任务的分析,实际上进阶任务和扩展任务是一致的内容,都是通过本开发板实现和HomeAssistant智能家居平台进行通信,这里通过时板载的wifi功能,通信协议为Mqtt。 将任务打碎后重组,我们需要完成一下三个工作:         第一:实现传感器数据的采集,也就是SH40和光传感器数据的采集,这一部分还不涉及无线通信能力,通过接口连接,实现数据采集后通过串口进行数据打印即可,可以通过串口工具进行查看;         第二:HomeAssistant智能家居平台的操作实现,HA支持很多种系统,我们需要实现HA平台的搭建工作;         第三:实现wifi的驱动,同时配置Mqtt协议的相关参数,实现和HomeAssistant智能家居平台的沟通,实现SH40和光传感器数据的在线查看。         接下来就实现过程:         通过串联的方式连接传感器,安装对应的传感器库:         首先进行两个传感器的初始化: #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(9600);   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;   } // You can have 3 different precisions, higher precision takes longer   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;   } // 6 different heater settings   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);       } }         初始化成功:         循环读取程序就简单的多了:  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));         读取成功:         接下来就是实现HA的通信和数据上传,这一部分主要包括的事HA系统的安装和,由于每个人使用的都不一样,可以看到有容器版的,有用树莓派的,也有用虚拟机的,对于当前的情况来说,使用虚拟机会比较方便一点,毕竟没有多余的硬件。这里根据官方的安装指南可以实现非常方便的安装,咱们打开HA看一下:         主要是需要加入mqtt固件,并通过MQTT模拟器进行设备和实体的注册,我们需要确认光照传感器有一个参数,SH40有两个参数,为此,我们创建三个实体:         接下来就是通过Mqtt,配置基本参数,主要是往"homeassistant/sensor/Roomsensor/state"写对应的数据: char ssid[] = "开发板连接的wifi";         char pass[] = "开发板连接的wifi密码";   const char broker[] = "目标地址ip"; int        port     = 1883; const char state_topic[]  = "homeassistant/sensor/Roomsensor/state"; 然后就是循环采集发送: 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["light"] = visible_plus_ir;   dataObj["hum"] = hum;   dataObj["tem"] = tem;   String jsonString1 = JSON.stringify(dataObj);   mqttClient.beginMessage(state_topic);   mqttClient.print(jsonString1);   mqttClient.endMessage();   delay(1000); }         整体软件流程:           结果如下:         遮挡一下:         这里需要注意一下,串口的通信可能会影响Mqtt的连接,之前一直报错,反应的是目标地址访问被拒绝,后来加个while (!Serial)解决的。 代码汇总:         大家可以下载代码直接进行修改测试,入门任务以及进阶任务都是比较简单的,进阶任务还是挺让人回味的 总结:         本次的活动主要依着学习的态度进行,确实Arduino的各种丰富的固件非常适合功能验证,也感谢论坛和各位网友的精彩分享。

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

  • 2024-02-06
  • 回复了主题帖: “写一副工程师专属的对联,赢新年甜蜜首礼!”颁奖啦!

    个人地址确认无误,估计到不了了,我们三十放假

  • 2024-01-29
  • 回复了主题帖: 写一副工程师专属的对联,赢新年甜蜜首礼!

    上联:代码间调试器,电子精英创未来 下联:创新中实践者,科技力量谱新篇 横批:智造辉煌

  • 回复了主题帖: 来聊个五毛钱的天,聊聊未来科技发展

    相对于未来的憧憬,我刚喜欢对过于的未知,南无袈裟理科佛申请出战

最近访客

< 1/1 >

统计信息

已有2人来访过

  • 芯积分:254
  • 好友:--
  • 主题:1
  • 回复:22

留言

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


现在还没有留言