- 2024-11-11
-
上传了资料:
【2024 DigiKey创意大赛】+便携式红外智能吸烟器-源码
- 2024-11-10
-
回复了主题帖:
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+结项贴
hellokitty_bean 发表于 2024-11-8 17:36
LVGL(light and versatile Graphics library)学习曲线这么陡峭吗?
还没尝试过。
可以试试,用gui来配置挺快的
-
回复了主题帖:
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+结项贴
本帖最后由 老杰瑞 于 2024-11-10 21:39 编辑
wangerxian 发表于 2024-11-7 17:48 没坏之前的效果视频是不是没有传成功?
好像是欸,我重新上传[localvideo]ada05516cd8330c0f90521b51ac6d466[/localvideo]
- 2024-11-07
-
发表了主题帖:
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+结项贴
本帖最后由 老杰瑞 于 2024-11-11 10:31 编辑
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+结项贴
先来看看(半)成品效果:
[localvideo]22f8b169f7022e1886ae700967c139f9[/localvideo]
Emmm,热成像模块给我玩坏了,下面是没玩坏之前的效果:
[localvideo]9060f93a8cc3f35bcf3d8bdf59751547[/localvideo]
[localvideo]ef301120630b267fd9541db17a3ed50e[/localvideo]
下面介绍一下项目想法:
我是一名自动化的电子开发者,在开发电路过程中老是需要焊接各种pcb元器件,有一天我在网上看到焊接烟雾会导致不孕不育,我害怕极了,我才20几.还没小孩呢!伤心~
我痛定思痛,决定开发一款桌面式焊接吸烟器.
在着手开发这款便携式红外智能吸烟器之前,我曾浏览淘宝,寻找市面上是否有类似产品。然而,我发现现有的吸烟器普遍存在体积庞大、必须连接电源且噪音大等问题,这与我心中理想的吸烟器相去甚远。因此,我决定自行设计一款既便携又智能的吸烟器。
作品目的:我们在焊接过程中用的焊锡丝,由焊锡和铅组成,并含有少量助焊剂。焊接时会产生金属颗粒物、金属氧化物和有机挥发物。长期吸入这些有害气体和颗粒物可能会导致焊工出现咳嗽、气喘、胸闷、慢性支气管炎、角膜炎等一系列呼吸道系统疾病。此外,焊接地点经常光线昏暗,不利于焊工的操作和视觉健康,容易导致疲劳和操作失误。,以及焊接环境光线昏暗的问题,设计一款智能吸烟器,以保护焊接人员的健康并改善工作环境。
采用方法:该智能吸烟器通过热电偶传感器检测烙铁是否开启,自动启动风扇和滤网系统,有效吸收和过滤焊接产生的有害气体和颗粒物。同时,内置可调光LED灯,提供充足照明,改善焊接环境。
项目启动与挑战
我在3D模型分享网站上找到了一款外壳模型,但它仅具备基本的开关功能,且必须连接电源。这激发了我对其进行改造的想法。Minimalist 3D Printed Fume Extractor by rdmmkr - Thingiverse
在尝试为其安装电池后,我面临了一个新问题:设备频繁耗尽电量,而我也经常忘记关闭它。由于焊接和调试是一个反复开关烙铁的过程,我决定开发一款能够通过红外检测温度自动控制风扇启停的吸烟器。幸运的是,本次大赛提供的物料中包含了一款红外热成像模块,这为项目的诞生提供了关键技术支持。
软硬件架构图:
流程图:
功能示意图:
系统工作的照片:
技术难题与解决方案
尽管项目本身难度不大,但使用ESP32C6芯片后,情况变得复杂。首先,我习惯使用PlatformIO进行代码开发,但发现其官方版本并未适配ESP32C6的Arduino环境。经过一番努力,我终于成功配置了ESP32C6。其次,屏幕驱动也是一个挑战。我通常使用TFT_eSPI库开发屏幕,但在ESP32C6上也未适配。经过数日的努力,我成功将屏幕库移植至ESP32C6。
接下来,热成像数据的读取成为了难题。最初,我尝试采用插值算法,但经过五六天的调试仍未达到预期效果,最终决定采用32×16像素的色块输出方案。
编码器配置是另一个技术挑战。通常情况下,编码器库可以解决这一问题,但ESP32C6的适配问题让我花费了两三天时间。由于涉及到底层脉冲寄存器配置,我尝试从ESP32C3的适配中逆向工程,但发现ESP32C3和ESP32S3系列的核心配置函数与ESP32C6并不相似。经过几天的努力,我最终放弃了库适配,转而采用中断方式实现编码器检测。然而,这又导致了一个新的问题:编码器快速转动时系统会卡死并重启。在朋友的指点下,我意识到可能是热成像数据读取时的中断导致的数据读取错误。最终,我改为使用定时器检测编码器状态,成功解决了这一问题。
界面设计与展示
在开发过程中,我还尝试了LVGL库,以期实现更高级的界面效果。以下是我的效果展示:
然而,由于时间限制与能力不够,发现热成像传感器只能通过打点函数进行显示。然后我又是用的图形化界面编辑的lvgl,不太会写lvgl的代码,经过五六天的努力尝试仍未能解决,我决定回归到更传统的显示方案。
源码及说明:
编码器与按键读取代码
编码器用定时器,按键用中断:
// 此函数将由定时器调用以检查编码器状态
void checkEncoder() {
static unsigned long lastChangeTime = 0; // 记录上次状态改变的时间
unsigned long currentTime = millis(); // 获取当前时间
int currentEncoderA = digitalRead(ENCODER_A); // 读取编码器A的状态
int currentEncoderB = digitalRead(ENCODER_B); // 读取编码器B的状态
static int lastEncoderB = LOW; // 添加B信号的上一个状态
// 检查编码器A状态是否发生变化,并加入时间间隔判断
if (currentEncoderA != lastEncoderA && (currentTime - lastChangeTime) > 5) { // 5ms去抖
if (currentEncoderA == HIGH) {
// 通过比较A和B的变化序列来判断方向
if (lastEncoderB != currentEncoderB) {
encoderDirection = (currentEncoderB == HIGH) ? 1 : -1;
}
lastChangeTime = currentTime; // 更新状态改变时间
}
lastEncoderA = currentEncoderA; // 更新前一个状态
lastEncoderB = currentEncoderB; // 更新B的前一个状态
}
}
// 风扇按钮中断服务例程
void IRAM_ATTR fanButtonISR() {
unsigned long currentMillis = millis(); // 获取当前时间
// 只有当当前时间与上次按下时间的间隔大于去抖动时间时,才认为是有效的按下
if (currentMillis - lastFanButtonPress > DEBOUNCE_TIME) {
fanButtonPressed = true; // 设置风扇按钮按下状态为真
lastFanButtonPress = currentMillis; // 更新上次按下时间
Serial.print("fanButtonPressed"); // 串口打印
}
}
// LED按钮中断服务例程
void IRAM_ATTR ledButtonISR() {
unsigned long currentMillis = millis(); // 获取当前时间
// 只有当当前时间与上次按下时间的间隔大于去抖动时间时,才认为是有效的按下
if (currentMillis - lastLedButtonPress > DEBOUNCE_TIME) {
ledButtonPressed = true; // 设置LED按钮按下状态为真
lastLedButtonPress = currentMillis; // 更新上次按下时间
Serial.print("ledButtonPressed"); // 串口打印
}
}
快速排列,得出温度最大值:
//快排-得到最大值
qusort(frame, 0, 32 * 24 - 1);
max_temp += frame[767];
//Quick sort
//通过递归分治的方式将一个大数组分为两个子数组,子数组的元素分别小于和大于基准值。
void qusort(float s[], int start, int end) //自定义函数 qusort()
{
int i, j; //定义变量为基本整型
i = start; //将每组首个元素赋给i
j = end; //将每组末尾元素赋给j
s[0] = s[start]; //设置基准值
while (i < j)
{
while (i < j && s[0] < s[j])
j--; //位置左移
if (i < j)
{
s[i] = s[j]; //将s[j]放到s[i]的位置上
i++; //位置右移
}
while (i < j && s[i] <= s[0])
i++; //位置左移
if (i < j)
{
s[j] = s[i]; //将大于基准值的s[j]放到s[i]位置
j--; //位置左移
}
}
s[i] = s[0]; //将基准值放入指定位置
if (start < i)
qusort(s, start, j - 1); //对分割出的部分递归调用qusort()函数
if (i < end)
qusort(s, j + 1, end);
}
关键的热成像数据显示代码:
//Display with 32*24 pixel-160*120 172-52-26
for (uint8_t h = 0; h < 24; h++)
{
for (uint8_t w = 0; w < 32; w++)
{
//看看什么原理
uint8_t colorIndex = map_f(temp_frame[h * 32 + w], MINTEMP, MAXTEMP);
tft.fillRect(5 * w, 5 * h+26, 5, 5, camColors[colorIndex]);
}
}
把温度值通过函数map_f转换为颜色值,通过tft色块代码显示
其余代码看下面这个链接,里面有完整的项目代码
download.eeworld.com.cn/detail/老杰瑞/634908
模型后续我会发在评论区,因为还不是最终版本,还在迭代中
项目展望
尽管面临重重挑战,我并未放弃。新的板子已经在来的路上,这次我将采用ESP32-WROOM-32芯片,并更换热成像模块为热电偶模块,类似于疫情期间用于检测人体温度的那种。这样的改动将使成本控制在50元以内,更适合大家复刻。敬请期待我的新作品!
下面是项目过程中的分享贴
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+ESP32C6使用MLX90640显示图像测试 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+ESP32C6驱动1.54寸st7789屏幕 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
-
回复了主题帖:
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+ESP32C6使用MLX90640显示图像测试
Jacktang 发表于 2024-11-6 07:30
这esp32c6做东西好多bug,各种各样的库不适配 是的
太苦了,真的,屏幕屏幕库不适配,编码器编码器不适配.中断还老是崩,那个热成像也是一言难尽,数据太不稳定了
- 2024-11-05
-
发表了主题帖:
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+ESP32C6使用MLX90640显示图像测试
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+ESP32C6使用MLX90640显示图像测试
先看看演示视频
[localvideo]40679bc04e3fa051a071648dfbb3dc43[/localvideo]
下面来教大家是如何实现这个功能的
先看看引脚图
开始注入灵魂
第一步是点亮屏幕,我使用的是tft-espi库,屏幕是172*320的1.47寸tft屏幕
在pio的库中搜索tft-espi库,安装到对应工程
开始配置tft屏幕
找到User_Setup_Select.h,里面默认应该是
//#include <User_Setup.h> // Default setup is root library folder
我测试的时候更换了几个屏幕,频繁修改User_Setup.h不方便,就在User_Setups文件夹中,新建了我的屏幕配置文件,这样切换屏幕就很方便了
如图我新建了两个文件适配不同的屏幕,这次用的屏幕是172*320的,这个屏幕文件如下
// 用户设置ID
#define USER_SETUP_ID 521
// 驱动程序
#define ST7789_DRIVER // 配置所有寄存器以适应ST7789驱动器
#define TFT_WIDTH 172 // 定义TFT LCD显示器的宽度为240像素
#define TFT_HEIGHT 320 // 定义TFT LCD显示器的高度为240像素
//#define TFT_INVERSION_ON // 启用显示器的颜色反转
#define TFT_BACKLIGHT_ON 1 // 定义LED背光控制为开启状态
// 颜色顺序(此行被注释掉,表示不使用)
//#define TFT_RGB_ORDER TFT_BGR // 仅适用于240x320分辨率的显示器,设置颜色顺序为BGR
// 引脚ESP32-C6
#define TFT_BL 23 // LED背光控制引脚,-1表示未连接或固定
#define TFT_MISO 20 // MISO引脚,-1表示未连接
#define TFT_MOSI 19 // MOSI引脚,用于SPI通信的数据线
#define TFT_SCLK 21 // SCLK引脚,用于SPI通信的时钟线
#define TFT_CS 18 // 片选引脚,用于选择SPI设备
#define TFT_DC 9 // 数据/命令引脚,用于区分数据或命令
#define TFT_RST -1 // 复位引脚,-1表示未连接或固定
// 字体
#define LOAD_GLCD // 加载GLCD字体
#define LOAD_FONT2 // 加载FONT2字体
#define LOAD_FONT4 // 加载FONT4字体
#define LOAD_FONT6 // 加载FONT6字体
#define LOAD_FONT7 // 加载FONT7字体
#define LOAD_FONT8 // 加载FONT8字体
//#define LOAD_FONT8N // 加载FONT8N字体(此行被注释掉,表示不使用)
#define LOAD_GFXFF // 加载GFX字体库
#define SMOOTH_FONT // 启用字体平滑功能
// 其他选项
//#define SPI_READ_FREQUENCY 20000000 // SPI读取操作的频率(此行被注释掉,表示不使用)
//#define SPI_FREQUENCY 40000000 // 另一个可选的SPI通信频率(此行被注释掉,表示不使用)
#define SPI_FREQUENCY 80000000 // 定义SPI通信的频率为80 MHz
这样tft屏幕的配置就结束了,下一步可以开始显示咋们的热成像数据了
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>
#include <SPI.h>
#include <FS.h>
#include "SPIFFS.h"
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip
#define TFT_GREY 0x5AEB // New colour
TFT_eSPI tft = TFT_eSPI(); // Invoke library
#include <Adafruit_MLX90640.h>
Adafruit_MLX90640 mlx;
float frame[32*24]; // buffer for full frame of temperatures
void setup() {
tft.init();
tft.setRotation(2); // Adjust rotation as needed
Serial.begin(115200);
delay(100);
Serial.println("Adafruit MLX90640 Simple Test");
Wire.begin(6,7);
if (! mlx.begin(MLX90640_I2CADDR_DEFAULT, &Wire)) {
Serial.println("MLX90640 not found!");
while (1) delay(10);
}
Serial.println("Found Adafruit MLX90640");
// ... (rest of the setup code remains the same)
}
void loop() {
if (mlx.getFrame(frame) != 0) {
Serial.println("Failed");
return;
}
// Clear the screen
tft.fillScreen(TFT_BLACK);
// Loop through each pixel and draw it on the TFT screen
for (uint8_t h = 0; h < 24; h++) {
for (uint8_t w = 0; w < 32; w++) {
float t = frame[h * 32 + w];
// Convert temperature to color
uint16_t color = tft.color565(map(t, 20, 37, 0, 255), 0, map(t, 20, 37, 255, 0));
tft.drawPixel(w, h, color);
}
}
// Update the screen with new frame
tft.pushImage(0, 0, 320, 240, (uint16_t *)frame);
}
,热成像显示的方法就到这里了
斯代码参考参考就可以了,后面会用esp32wroom再撸一份,这esp32c6做东西好多bug,各种各样的库不适配
- 2024-10-17
-
回复了主题帖:
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+ESP32C6驱动1.54寸st7789屏幕
wangerxian 发表于 2024-10-17 09:04
SPI驱动屏幕,底层驱动程序应该都差不多吧。
差不多的,只是各家库的一个适配问题,适配速度太慢了
- 2024-10-16
-
发表了主题帖:
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+ESP32C6驱动1.54寸st7789屏幕
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+ESP32C6驱动1.54寸st7789屏幕
想先用屏幕来显示MLX90640热成像传感器的图像,在这期间我遇到了两个很棘手的问题
1是platformio不支持esp32-c6-devkitc-1板子使用arduino的开发方式
2是arduino的TFT_eSPI库st7789库都不支持esp32c6显示(我看论坛有人分享了用st7789库来显示的教程)我尝试了,但还是用不了
问题1解决方法
esp32-c6使用教程wifi(espidf修改成arduino)附带代码websocket,舵机,点灯【2024年】-CSDN博客
参考这篇文章修改platfprmio.ini配置
第一步选择c6开发板,这里默认读者都有pio开发经验,不懂的可以去看看教程,大部分都是卡在下载esp32的包,我建议是网上电脑不关机,新建工程,第二天早上再看,如果还在转圈圈初始化就重新新建一次一般就可以了
Pio中esp32c6只有espidf的开发方式,这里不急,先新建完工程
对.ini配置文件进行编辑
替换内容为下列代码
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32-c6-devkitc-1]
platform = https://github.com/sgryphon/platform-espressif32.git
board = esp32-c6-devkitc-1
board_frameworks =
espidf
arduino
board_build.variant = esp32c6
framework = arduino
upload_speed = 921600
monitor_speed = 115200
monitor_filters =
direct
platform_packages =
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#master
platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1
build_flags =
-D CONFIG_ARDUHAL_LOG_COLORS=1
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
再把main.c文件改为main.cpp
在main函数中打印下面的代码测试彩灯点亮
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>
#include <SPI.h>
#include <FS.h>
#include "SPIFFS.h"
void setup() {
Serial.begin(115200); // 初始化串口通信
delay(1000); // 等待串口初始化
}
void loop() {
log_i("hello world");
rgbLedWrite(RGB_BUILTIN, 255, 0, 0); //设置显示颜色为红色
delay(500);
rgbLedWrite(RGB_BUILTIN, 255, 165, 0);
delay(500);
rgbLedWrite(RGB_BUILTIN, 255, 255, 0);
delay(500);
rgbLedWrite(RGB_BUILTIN, 0, 255, 0);
delay(500);
rgbLedWrite(RGB_BUILTIN, 0, 127, 255);
delay(500);
rgbLedWrite(RGB_BUILTIN, 0, 0, 255);
delay(500);
rgbLedWrite(RGB_BUILTIN, 139, 0, 255);
delay(500);
}
彩灯点亮即可完成esp32c6在pio中使用arduino开发
我发现的一些bug是在编译中经常会遇到头文件找不到的报错
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>
#include <SPI.h>
#include <FS.h>
#include "SPIFFS.h"
我在main文件开头手动include即可编译成功,这个问题我找到的解读是选择工程属于espidf于arduino环境混开发,在espidf中不会去编译arduino的spi库等,需要在main函数中手动inculude,否则在运行一些arduino的库会报错很多arduino的头文件找不到
解决了开发环境,下一步就是点亮屏幕了
问题2解决方法
我在github上的TFT_eSPI仓库找有没有类似的不过,发现有个哥们分享了他的方法,但还没被并入正式版本
链接如下:
Three-IPS-Displays-with-ST7789-170x320-240x280-240x320/ESP32_C6 at main · mboehmerm/Three-IPS-Displays-with-ST7789-170x320-240x280-240x320 (github.com)
我尝试了这个办法,他成功生效了
替换TFT_eSPI库的这四个文件,这个大佬针对esp32c6和esp32h2做了视频优化,亲测有用
下面是小白详细教程
安装成功后
找到这四个文件,替换为下面网站的代码(对着名称替换)
TFT_eSPI_ESP32_C3.c替换为下面网站的代码
Three-IPS-Displays-with-ST7789-170x320-240x280-240x320/ESP32_C6/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32_C3.c at main · mboehmerm/Three-IPS-Displays-with-ST7789-170x320-240x280-240x320 (github.com)
TFT_eSPI_ESP32_C3.h替换为下面网站的代码
Three-IPS-Displays-with-ST7789-170x320-240x280-240x320/ESP32_C6/Arduino/libraries/TFT_eSPI/Processors/TFT_eSPI_ESP32_C3.h at main · mboehmerm/Three-IPS-Displays-with-ST7789-170x320-240x280-240x320 (github.com)
TFT_eSPI.cpp替换为下面网站的代码
Three-IPS-Displays-with-ST7789-170x320-240x280-240x320/ESP32_C6/Arduino/libraries/TFT_eSPI/TFT_eSPI.cpp at main · mboehmerm/Three-IPS-Displays-with-ST7789-170x320-240x280-240x320 (github.com)
TFT_eSPI.h替换为下面网站的代码
Three-IPS-Displays-with-ST7789-170x320-240x280-240x320/ESP32_C6/Arduino/libraries/TFT_eSPI/TFT_eSPI.h at main · mboehmerm/Three-IPS-Displays-with-ST7789-170x320-240x280-240x320 (github.com)
这里已经完成了对esp32c6的适配
接下来修改User Setu文件适配屏幕,我用的屏幕是st7789驱动的240*240方屏幕
我在User Setu文件夹创建了一个Setup520_ST7789_ESP32C6_240-240.h文件
内容为下
// 用户设置ID
#define USER_SETUP_ID 520
// 驱动程序
#define ST7789_DRIVER // 配置所有寄存器以适应ST7789驱动器
#define TFT_WIDTH 240 // 定义TFT LCD显示器的宽度为240像素
#define TFT_HEIGHT 240 // 定义TFT LCD显示器的高度为240像素
//#define TFT_INVERSION_ON // 启用显示器的颜色反转
//#define TFT_BACKLIGHT_ON 1 // 定义LED背光控制为开启状态
// 颜色顺序(此行被注释掉,表示不使用)
//#define TFT_RGB_ORDER TFT_BGR // 仅适用于240x320分辨率的显示器,设置颜色顺序为BGR
// 引脚ESP32-C6
#define TFT_BL -1 // LED背光控制引脚,-1表示未连接或固定
#define TFT_MISO 20 // MISO引脚,-1表示未连接
#define TFT_MOSI 19 // MOSI引脚,用于SPI通信的数据线
#define TFT_SCLK 21 // SCLK引脚,用于SPI通信的时钟线
#define TFT_CS 18 // 片选引脚,用于选择SPI设备
#define TFT_DC 9 // 数据/命令引脚,用于区分数据或命令
#define TFT_RST -1 // 复位引脚,-1表示未连接或固定
// 字体
#define LOAD_GLCD // 加载GLCD字体
#define LOAD_FONT2 // 加载FONT2字体
#define LOAD_FONT4 // 加载FONT4字体
#define LOAD_FONT6 // 加载FONT6字体
#define LOAD_FONT7 // 加载FONT7字体
#define LOAD_FONT8 // 加载FONT8字体
//#define LOAD_FONT8N // 加载FONT8N字体(此行被注释掉,表示不使用)
#define LOAD_GFXFF // 加载GFX字体库
#define SMOOTH_FONT // 启用字体平滑功能
// 其他选项
//#define SPI_READ_FREQUENCY 20000000 // SPI读取操作的频率(此行被注释掉,表示不使用)
//#define SPI_FREQUENCY 40000000 // 另一个可选的SPI通信频率(此行被注释掉,表示不使用)
#define SPI_FREQUENCY 80000000 // 定义SPI通信的频率为80 MHz
再去导入配置文件
去找个例程
复制粘贴内容到main函数
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>
#include <SPI.h>
#include <FS.h>
#include "SPIFFS.h"
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip
#define TFT_GREY 0x5AEB // New colour
TFT_eSPI tft = TFT_eSPI(); // Invoke library
void setup(void) {
tft.init();
tft.setRotation(2);
}
void loop() {
// Fill screen with grey so we can see the effect of printing with and without
// a background colour defined
tft.fillScreen(TFT_GREY);
// Set "cursor" at top left corner of display (0,0) and select font 2
// (cursor will move to next line automatically during printing with 'tft.println'
// or stay on the line is there is room for the text with tft.print)
tft.setCursor(0, 0, 2);
// Set the font colour to be white with a black background, set text size multiplier to 1
tft.setTextColor(TFT_WHITE,TFT_BLACK); tft.setTextSize(1);
// We can now plot text on screen using the "print" class
tft.println("Hello World!");
// Set the font colour to be yellow with no background, set to font 7
tft.setTextColor(TFT_YELLOW); tft.setTextFont(7);
tft.println(1234.56);
// Set the font colour to be red with black background, set to font 4
tft.setTextColor(TFT_RED,TFT_BLACK); tft.setTextFont(4);
//tft.println(3735928559L, HEX); // Should print DEADBEEF
// Set the font colour to be green with black background, set to font 4
tft.setTextColor(TFT_GREEN,TFT_BLACK);
tft.setTextFont(4);
tft.println("Groop");
tft.println("I implore thee,");
// Change to font 2
tft.setTextFont(2);
tft.println("my foonting turlingdromes.");
tft.println("And hooptiously drangle me");
tft.println("with crinkly bindlewurdles,");
// This next line is deliberately made too long for the display width to test
// automatic text wrapping onto the next line
tft.println("Or I will rend thee in the gobberwarts with my blurglecruncheon, see if I don't!");
// Test some print formatting functions
float fnumber = 123.45;
// Set the font colour to be blue with no background, set to font 4
tft.setTextColor(TFT_BLUE); tft.setTextFont(4);
tft.print("Float = "); tft.println(fnumber); // Print floating point number
tft.print("Binary = "); tft.println((int)fnumber, BIN); // Print as integer value in binary
tft.print("Hexadecimal = "); tft.println((int)fnumber, HEX); // Print as integer number in Hexadecimal
delay(10000);
}
运行即可
- 2024-10-08
-
回复了主题帖:
Follow me第二季第2期+多功能HA传感器系统
秦天qintian0303 发表于 2024-10-8 12:17
你这来了这么多传感器啊,不过应该超限了吧
没啦,都是得捷买的,不同活动的都有,这不刚好一起智能化了
-
发表了主题帖:
Follow me第二季第2期+多功能HA传感器系统
本帖最后由 老杰瑞 于 2024-10-8 19:49 编辑
集成多功能Home Assistant (HA) 传感器系统
本系统集成了以下高性能传感器,实现了对环境参数的全面监测,并将数据实时上传至Home Assistant平台:
ArduinoU4wifi:通过wifi连接ha平台,上传传感器数据
SHT40温湿度传感器:精确测量环境温度和湿度,确保舒适的生活和工作条件。
SGP30空气质量传感器:实时监测室内空气质量,包括总挥发性有机化合物(TVOC)和等效二氧化碳(eCO2)的浓度,助力健康生活。
LTR-329环境光传感器:精确检测环境光线强度,包括可见光和红外光,以优化照明控制。
通过将这些传感器集成至一串电路板,本系统不仅简化了安装过程,还提高了数据收集的效率。所有监测数据均可通过HA面板直观展示,便于用户实时监控和远程控制家庭环境。
介绍视频:
[localvideo]778f857ab693ca4d2fa16d3a85d16115[/localvideo]
流程图
设计思路就是u4读取传感器数据,通过wifi发送给mqtt服务器,ha在配置好mqtt服务器的条件下进行话题监听,更新传感器数据
扩展任务功能演示:
进阶任务(必做):通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
通过AlexxIT/HassWP v2024.4.3 (github.com)这个项目实现了ha平台的一键部署
再向隔壁的二舅妈借用了一个mqtt服务器,在ha种添加对应MQTT服务器
到HA的 [开发者工具 – Home Assistant](http://localhost:8123/developer-tools/yaml) 的 -> YAML 配置重新加载 -> 点击 所有YAML 配置 -> 如果代码无异常,则会显示绿色 代表配置已经更新
mqtt:
- sensor:
- unique_id: arduino uno Voltage
name: "arduino Volt"
state_topic: "UNO/arduino/myAnalogInput/stat_t"
suggested_display_precision: 3
添加完这个实体以后就需要上传数据了,使用下面的代码来实现数据上传
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>
#include "Arduino_LED_Matrix.h" /*包含官方的驱动库*/
#include "analogWave.h" // 包含波形输出的模拟文件
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = "quest2"; //WIFI名字
char pass[] = "meiyijia"; //WIFI密码
int status = WL_IDLE_STATUS;
//实例化
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
analogWave wave(DAC); //实例化一个对象
const char broker[] = "210.38.161.158"; //MQTT服务器地址
int port = 1883; //MQTT服务器端口
const char topic1[] = "UNO/arduino/SHT40-Temp/stat_t"; //发布的主题
const char topic2[] = "UNO/arduino/SHT40-humidity/stat_t"; //发布的主题
const char topic3[] = "UNO/arduino/SGP30-brightness/stat_t"; //发布的主题
const char topic4[] = "UNO/arduino/myAnalogInput/stat_t"; //发布的主题
const char mqttuser[] = "admin"; //MQTT服务器的用户名
const char mqttpassword[] = "jyu123456"; //MQTT服务器密码
//set interval for sending messages (milliseconds)
const long interval = 8000;
unsigned long previousMillis = 0;
int count = 0;
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
//A0 DAC 输出一个波形
wave.sine(50); //产生一个50HZ的sin波形
wave.amplitude(0.25); //设置幅度值为4.7 的1/4
// 设置ADC的分辨率
analogReadResolution(14); //change to 14-bit resolution
// attempt to connect to Wifi network:
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// failed, retry
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() {
// call poll() regularly to allow the library to send MQTT keep alive which
// avoids being disconnected by the broker
mqttClient.poll();
//通过ADC采集 A0上输出的sin波形
float Rvalue = analogRead(A3) * 4.7/16383; //读取A0引脚的值 A3和 A0连接 14bit ADC采样
mqttClient.beginMessage(topic4);
mqttClient.print(Rvalue); //把读取的值进行上传到MQTT服务器
Serial.println(Rvalue);
mqttClient.endMessage();
delay(10);
}
我通过mqttx软件来查看mqtt连接数据MQTTX 下载
通过配置mqtt服务器,订阅我的话题“UNO/arduino/myAnalogInput/stat_t”
就可读取到U4的数据
再到ha面板来看数据,成功显示数据
基础任务(必做):驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
点阵部分参考官方例程Using the Arduino UNO R4 WiFi LED Matrix | Arduino Documentation
#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;
void setup() {
Serial.begin(115200);
matrix.begin();
}
const uint32_t happy[] = {
0x19819,
0x80000001,
0x81f8000
};
const uint32_t heart[] = {
0x3184a444,
0x44042081,
0x100a0040
};
void loop(){
matrix.loadFrame(happy);
delay(500);
matrix.loadFrame(heart);
delay(500);
}
撸了个笑脸和爱心的图形
下面来写
用DAC生成正弦波;
Arduino UNO R4 WiFi Digital-to-Analog Converter (DAC) | Arduino Documentation
还是先来到官方wiki看看官方的写法
官方给的应用实例是用电位器来改变驱动蜂鸣器频率
把蜂鸣器电位器注释掉就能输出dac了
#include "analogWave.h" // 包含用于模拟波形生成的库
analogWave wave(DAC); // 创建analogWave类的一个实例,使用DAC引脚
int freq = 10; // 频率,以赫兹为单位,根据需要更改
void setup() {
Serial.begin(115200); // 初始化串行通信,波特率为115200
wave.sine(freq); // 使用初始频率生成正弦波
}
void loop() {
// 从A5引脚读取模拟值,并将其映射到频率范围内
freq = map(analogRead(A5), 0, 1024, 0, 10000);
// 将更新的频率打印到串行监视器
//Serial.println("当前频率为 " + String(freq) + " 赫兹");
//wave.freq(freq); // 将波形发生器的频率设置为更新的值
delay(1000); // 在重复之前延迟一秒钟
}
下一步是用OPAMP放大DAC信号;
用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
老规矩,来看看官方wiki
Arduino UNO R4 WiFi 运算放大器 |Arduino 文档
运算放大器的放大率主要取决于所选的电阻值=1+(R2/R1)
R1 = 接地电阻 (Ω)顾名思义,连接运放反馈口与地的
R2 = 反馈电阻 (Ω)连接输出与反馈口的
具体原理看这一篇原理解释,讲的非常好(不过需要小小翻一下)
Non-inverting Operational Amplifier Configuration (electronics-tutorials.ws)
由图可得,A1为输入脚,A2为反馈脚,A3为输出脚,为了实现用OPAMP放大DAC信号的需求,我们需要把A1与A0(DAC输出脚短接)
R2与R1都选择10k,得到1+(10k/10K)=2倍的放大倍率
代码部分只需在之前的代码中加下面的
#include <OPAMP.h>
void setup () {
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
}
实际情况:
不知道为什么不是很对头,但也有2倍放大了
下一个任务:用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
把A4连A0测dac输出
把A5连A3测OPAMP放大输出
#include "analogWave.h" // 包含用于模拟波形生成的库
#include <OPAMP.h>
analogWave wave(DAC); // 创建analogWave类的一个实例,使用DAC引脚
int freq = 5; // 频率,以赫兹为单位,根据需要更改
void setup() {
Serial.begin(115200); // 初始化串行通信,波特率为115200
wave.sine(freq); // 使用初始频率生成正弦波
wave.amplitude(0.4); //设置正弦曲线幅值为0.4,默认的太大了,超过adc采样电压了
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
}
void loop() {
printf("%d\n",analogRead(A4)); // 读取DAC输出正弦值
Serial.print(" ");
printf("%d\n",analogRead(A5)); // 读取OPAMP输出正弦值
delay(100); // 在重复之前延迟一秒钟
}
结果如下
原因是我delay的太久了,改为delay1
哈哈哈又快过头了,改为10
结果欧克了
最后是入门任务(必做):搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
轻轻松松秒杀
拿到板子后先谷歌一下arduino-UNO R4 WiFi
找到这个网址UNO R4 WiFi 入门 |Arduino 文档
打开官方教程就可以开始配置环境了,点击图中的arduino软件页面。
下载安装完成后就可以开始配置一下arduino的设置,我推荐暗黑和中文配置,顺眼很多
下一步就是安装板基支持包
在右边的开发板管理器搜索UNO R4即可安装。
安装完成后插上UNO R4 WiFi板子,在开发板中选择UNO R4 WiFi
上面我们的开发环境就配置好了,硬件软件都ok,下面开始实现任务
我最喜欢的就是arduino的示例了,在里面有很多示例代码可以帮我我们快速开发自己需要的功能,再也不要天天为基础代码跑不通调试半天了~
在内置示例中找到blink,编译下载即可实现点灯功能,代码为下
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
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
}
代码其实就是让led口亮,如何停顿一下,在暗,再停顿一下,如此循环实现
给第一次使用arduino的小伙伴解释一下setup和loop在arduino中,必须有这两个函数,setup为开机运行一次,loop函数在setup运行完后就会不断循环运行,所以在上面的代码中,要先在setup中吧led口的pin配置好为输出模式,LED_BUILTIN在一些头文件中会对应板子上的ledpin脚位,这也是arduino的优势之一,代码可以在多个板子上不动运行
下面我们来实现串口打印功能
照例打开内置示例的AnalogReadSerial,程序功能是将ADC并且将值不断传输给串口
我们对代码进行修改实现我们需要的功能
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// print out the value you read:
Serial.println("Hello EEWorld!");
delay(1); // delay in between reads for stability
}
简单编辑一下即可
打开右上角arduino自带的串口工具即可查看打印的Hello EEWorld!内容!
好了到此为止我们就实现了入门任务
下面是这次项目用到的全部代码
第二季第2期任务源码-伤心杰瑞-嵌入式开发相关资料下载-EEWORLD下载中心
本活动的心得体会:在这次的任务过程中,十分感谢EEWORLD大学堂的直播帮助,让我学习了很多mqtt的相关知识也学会了ha平台的搭建及使用,这对我这个网络软件小白来说很难,但是我真的学到了很多,了解了很多不懂的东西,这就是follow me的意义把!不懂的时候可以去论文看看别人怎么实现的,看看老师直播怎么做的,也能在五花八门的办法中找到最适合自己,最轻松的答案,特别是写文章总结的时候,很难写出我为了解决一些问题付出的时间与精力,只想把1最简单的办法分享给大家,让大家少走一点我踩过的坑。谢谢这次机会,下次我还要参加
-
上传了资料:
第二季第2期任务源码-伤心杰瑞
-
加入了学习《FollowMe 第二季:2 - Arduino UNO R4 Wi-Fi 及任务讲解》,观看 Arduino UNO R4 Wi-Fi 及任务讲解
- 2024-10-07
-
发表了主题帖:
Follow me第二季第2期-4 8种数据的HA传感器系统
本帖最后由 老杰瑞 于 2024-10-8 19:51 编辑
开始做扩展任务
我选择使用3块传感器,分别是SHT40,温湿度传感器、SGP30空气质量传感器、LTR-329 环境光传感器做出来了一块多功能ha传感器,上传数据到HA,通过HA面板显示数据.
SHT40,温湿度传感器
SHT40-Temp
SHT40-humidity
SGP30是一款用于检测室内空气质量的传感器,它能够测量总挥发性有机化合物(TVOC)和等效二氧化碳(eCO2)的浓度,氢气(H2)的原始值,乙醇(Ethanol)的原始值
SGP30-TVOC *.ppb
SGP30-eCO2 *.ppm
SGP30-Raw H2
SGP30-Raw Ethanol
LTR329是一款环境光传感器,能够测量可见光和红外光。该传感器有两个通道,CH0和CH1,它们分别代表:
CH0 (Channel 0):可见光 + 红外光(Visible + IR)
CH1 (Channel 1):红外光(Infrared)
LTR-329-Visible + IR
LTR-329-Infrared
定义一下mqtt主题名称
const char topic1[] = "UNO/arduino/SHT40-Temp/stat_t"; // SHT40温度
const char topic2[] = "UNO/arduino/SHT40-humidity/stat_t"; // SHT40湿度
const char topic3[] = "UNO/arduino/SGP30-TVOC/stat_t"; // SGP30 TVOC
const char topic4[] = "UNO/arduino/SGP30-eCO2/stat_t"; // SGP30 eCO2
const char topic5[] = "UNO/arduino/SGP30-RawH2/stat_t"; // SGP30 原始H2
const char topic6[] = "UNO/arduino/SGP30-RawEthanol/stat_t";// SGP30 原始乙醇
const char topic7[] = "UNO/arduino/LTR329-VisibleIR/stat_t"; // LTR329 可见光+红外光
const char topic8[] = "UNO/arduino/LTR329-Infrared/stat_t"; // LTR329 红外光
const char topic10[] = "UNO/arduino/myAnalogInput/stat_t"; //发布的主题
改一下ha面板中的实体配置
mqtt:
- sensor:
- unique_id: arduino_uno_SHT40_Temp
name: "SHT40 Temp"
state_topic: "UNO/arduino/SHT40-Temp/stat_t"
suggested_display_precision: 1
unit_of_measurement: "°C"
value_template: "{{ value | float }}"
- unique_id: arduino_uno_SHT40_humidity
name: "SHT40 Humidity"
state_topic: "UNO/arduino/SHT40-humidity/stat_t"
suggested_display_precision: 1
unit_of_measurement: "%"
value_template: "{{ value | float }}"
- unique_id: arduino_uno_SGP30_TVOC
name: "SGP30 TVOC"
state_topic: "UNO/arduino/SGP30-TVOC/stat_t"
suggested_display_precision: 0
unit_of_measurement: "ppb"
value_template: "{{ value | int }}"
- unique_id: arduino_uno_SGP30_eCO2
name: "SGP30 eCO2"
state_topic: "UNO/arduino/SGP30-eCO2/stat_t"
suggested_display_precision: 0
unit_of_measurement: "ppm"
value_template: "{{ value | int }}"
- unique_id: arduino_uno_SGP30_RawH2
name: "SGP30 Raw H2"
state_topic: "UNO/arduino/SGP30-RawH2/stat_t"
suggested_display_precision: 0
unit_of_measurement: ""
value_template: "{{ value | int }}"
- unique_id: arduino_uno_SGP30_RawEthanol
name: "SGP30 Raw Ethanol"
state_topic: "UNO/arduino/SGP30-RawEthanol/stat_t"
suggested_display_precision: 0
unit_of_measurement: ""
value_template: "{{ value | int }}"
- unique_id: arduino_uno_LTR329_VisibleIR
name: "LTR329 Visible + IR"
state_topic: "UNO/arduino/LTR329-VisibleIR/stat_t"
suggested_display_precision: 0
unit_of_measurement: "lx"
value_template: "{{ value | float }}"
- unique_id: arduino_uno_LTR329_Infrared
name: "LTR329 Infrared"
state_topic: "UNO/arduino/LTR329-Infrared/stat_t"
suggested_display_precision: 0
unit_of_measurement: "lx"
value_template: "{{ value | float }}"
- unique_id: arduino uno Voltage
name: "arduino Volt"
state_topic: "UNO/arduino/myAnalogInput/stat_t"
suggested_display_precision: 3
unit_of_measurement: "V"
value_template: "{{ value }}"
value_template: "{{ value }}"
- unique_id: arduino uno SGP30-brightness
name: "SGP30-brightness"
state_topic: "UNO/arduino/SGP30-brightness/stat_t"
suggested_display_precision: 1
unit_of_measurement: ".nit"
value_template: "{{ value }}"
- unique_id: arduino uno Voltage
name: "arduino Volt"
state_topic: "UNO/arduino/myAnalogInput/stat_t"
suggested_display_precision: 3
unit_of_measurement: "V"
value_template: "{{ value }}"
下面是arduino的功能实现代码
#include <Wire.h>
#include "Adafruit_SGP30.h"
#include "Adafruit_LTR329_LTR303.h"
#include "Adafruit_SHT4x.h"
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include <WiFiClient.h>
#include "arduino_secrets.h"
#include "analogWave.h" // 包含波形输出的模拟文件
Adafruit_SGP30 sgp;
Adafruit_LTR329 ltr = Adafruit_LTR329();
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
//wifi
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = "quest2"; // your network SSID (name)
char pass[] = "meiyijia"; // 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[] = "210.38.161.158"; //MQTT服务器地址
int port = 1883; //MQTT服务器端口
const char topic1[] = "UNO/arduino/SHT40-Temp/stat_t"; // SHT40温度
const char topic2[] = "UNO/arduino/SHT40-humidity/stat_t"; // SHT40湿度
const char topic3[] = "UNO/arduino/SGP30-TVOC/stat_t"; // SGP30 TVOC
const char topic4[] = "UNO/arduino/SGP30-eCO2/stat_t"; // SGP30 eCO2
const char topic5[] = "UNO/arduino/SGP30-RawH2/stat_t"; // SGP30 原始H2
const char topic6[] = "UNO/arduino/SGP30-RawEthanol/stat_t";// SGP30 原始乙醇
const char topic7[] = "UNO/arduino/LTR329-VisibleIR/stat_t"; // LTR329 可见光+红外光
const char topic8[] = "UNO/arduino/LTR329-Infrared/stat_t"; // LTR329 红外光
const char topic10[] = "UNO/arduino/myAnalogInput/stat_t"; //发布的主题
const char mqttuser[] = "admin"; //MQTT服务器的用户名
const char mqttpassword[] = "jyu123456"; //MQTT服务器密码
//set interval for sending messages (milliseconds)
const long interval = 8000;
unsigned long previousMillis = 0;
int count = 0;
/* return absolute humidity [mg/m^3] with approximation formula
* @param temperature [°C]
* @param humidity [%RH]
*/
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
// approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
return absoluteHumidityScaled;
}
void setup() {
Serial.begin(115200);
while (!Serial) { delay(10); } // Wait for serial console to open!
////A0 DAC 输出一个波形
wave.sine(50); //产生一个50HZ的sin波形
wave.amplitude(0.25); //设置幅度值为4.7 的1/4
// 设置ADC的分辨率
analogReadResolution(14); //change to 14-bit resolution
//wifi
// attempt to connect to WiFi network:
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// failed, retry
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();
//SHT40
Wire1.begin(); //Join I2C bus
if (! sht4.begin(&Wire1)) {
Serial.println("Couldn't find SHT4x");
while (1) delay(1);
}
Serial.println("Found SHT4x sensor");
Serial.print("Serial number 0x");
Serial.println(sht4.readSerial(), HEX);
//SGP30
Serial.println("SGP30 test");
if (sgp.begin(&Wire1) == false){
Serial.println("Sensor not found :(");
while (1);
}
Serial.print("Found SGP30 serial #");
Serial.print(sgp.serialnumber[0], HEX);
Serial.print(sgp.serialnumber[1], HEX);
Serial.println(sgp.serialnumber[2], HEX);
// If you have a baseline measurement from before you can assign it to start, to 'self-calibrate'
//sgp.setIAQBaseline(0x8E68, 0x8F41); // Will vary for each sensor!
//LTR329
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.println("Gain : 2");
ltr.setIntegrationTime(LTR3XX_INTEGTIME_100);
Serial.println("Integration Time (ms):100 ");
ltr.setMeasurementRate(LTR3XX_MEASRATE_200);
Serial.println("Measurement Rate (ms): 200");
}
int counter = 0;
void loop() {
//ADC
// call poll() regularly to allow the library to send MQTT keep alive which
// avoids being disconnected by the broker
mqttClient.poll();
//通过ADC采集 A0上输出的sin波形
float Rvalue = analogRead(A3) * 4.7/16383; //读取A0引脚的值 A3和 A0连接 14bit ADC采样
mqttClient.beginMessage(topic10);
mqttClient.print(Rvalue); //把读取的值进行上传到MQTT服务器
Serial.println(Rvalue);
mqttClient.endMessage();
//SHT40
sensors_event_t humidity, temp;
uint32_t timestamp = millis();
timestamp = millis() - timestamp;//看循环时间的
sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
// Publish SHT40 Temperature-MQTT
mqttClient.beginMessage(topic1);
mqttClient.print(temp.temperature);
mqttClient.endMessage();
// Publish SHT40 Humidity-MQTT
mqttClient.beginMessage(topic2);
mqttClient.print(humidity.relative_humidity);
mqttClient.endMessage();
//温度与湿度
Serial.print("Temperature: "); Serial.print(temp.temperature); Serial.println(" degrees C");
Serial.print("Humidity: "); Serial.print(humidity.relative_humidity); Serial.println("% rH");
//SGP30
// If you have a temperature / humidity sensor, you can set the absolute humidity to enable the humditiy compensation for the air quality signals
//float temperature = 22.1; // [°C]
//float humidity = 45.2; // [%RH]
//sgp.setHumidity(getAbsoluteHumidity(temperature, humidity));
if (! sgp.IAQmeasure()) {
Serial.println("Measurement failed");
return;
}
Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");
// Publish SGP30 TVOC-MQTT
mqttClient.beginMessage(topic3);
mqttClient.print(sgp.TVOC);
mqttClient.endMessage();
// Publish SGP30 eCO2-MQTT
mqttClient.beginMessage(topic4);
mqttClient.print(sgp.eCO2);
mqttClient.endMessage();
if (! sgp.IAQmeasureRaw()) {
Serial.println("Raw Measurement failed");
return;
}
Serial.print("Raw H2 "); Serial.print(sgp.rawH2); Serial.print(" \t");
Serial.print("Raw Ethanol "); Serial.print(sgp.rawEthanol); Serial.println("");
// Publish SGP30 Raw H2
mqttClient.beginMessage(topic5);
mqttClient.print(sgp.rawH2);
mqttClient.endMessage();
// Publish SGP30 Raw Ethanol
mqttClient.beginMessage(topic6);
mqttClient.print(sgp.rawEthanol);
mqttClient.endMessage();
//看代码循环时间的
Serial.print("Read duration (ms): ");
Serial.println(timestamp);
delay(1000);
counter++;
if (counter == 30) {
counter = 0;
uint16_t TVOC_base, eCO2_base;
if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
Serial.println("Failed to get baseline readings");
return;
}
Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX);
Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);
}
//LTR329
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);
// Publish LTR329 Visible + IR
mqttClient.beginMessage(topic7);
mqttClient.print(visible_plus_ir);
mqttClient.endMessage();
// Publish LTR329 Infrared
mqttClient.beginMessage(topic8);
mqttClient.print(infrared);
mqttClient.endMessage();
}
}
//delay(100);
//delay(1000);
}
演示成果:
以下是踩坑
我想使用arduino的Qwiic接口来连接设备的时候怎么都检测不到i2C设备,找了半天发现是
Arduino UNO R4 WiFi Qwiic 连接器 |Arduino 文档
这个实际使用要在begin(&wir1)要加上&才能正常跑通使用板子上的Qwiic接口
我接了三个传感器,分别对应三个库,我把例程缝缝补补出来了一个可以用的代码,在把上一个任务的代码缝合得出上面的那份代码,实现本次功能要求
下面是展示部分
终于接进去了,小小添加几个卡片来展现我的数据
[localvideo]c5ed7ee4a22690e596c7acda386e15bd[/localvideo]
感谢这次follow me的机会,让我成功学习到了U4的功能使用与HA智能家居系统的使用安装,更让我这个网络小白学习并使用了mqtt,谢谢得捷平台提供的机会
-
发表了主题帖:
Follow me第二季第2期-3通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(Home...
开始做进阶任务
通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
Emmm,我没有HA,国际惯例,看看官网Raspberry Pi - Home Assistant (home-assistant.io)
我刚好有块树莓派4b,拿出来用
有树莓派的打开这个官方烧录工具
选择 其他特定用途的操作系统 > Home assistants 和 Home automation > Home Assistant。
下载安装到sd卡(我下载有点慢,有条件的挂一下梯,嘎嘎快)
下载好后拔出SD卡插入树莓派4B,与路由器连接网线和电源开机
出现IP地址就放心了,输入http://192.168.31.35:8123/,进入ha后台
第一次开机,等初始化配置这些
GG,一直卡在初始化,百度了一下,是应为需要访问github,国内网络环境太复杂访问不上
开始想别的法子来装HA
来试试win10安装,找了半天教程决定用这个AlexxIT/HassWP v2024.4.3 (github.com)
解压后双击这个脚本一件部署
当当当!!!一步搞定啊,真的泪崩,找了一堆方法,就这个最简单了
开始配置mqtt连接
下面是我的知识盲区,我看大家用的方法都太复杂了,我不懂mqtt,于是找了个库
home-assistant-integration,项目地址:arduino-home-assistant:ArduinoHA allows to integrate an Arduino/ESP based device with Home Assistant using MQTT. - GitCode
我在官方网站找了了传感器的例程
示例 - ArduinoHA (dawidchyrzynski.github.io)
下面开始为arduino编写代码
首先需要导入一下wifi的头文件
#include <WiFiS3.h>
#include <WiFiClient.h>
开始做进阶任务
通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
Emmm,我没有HA,国际惯例,看看官网Raspberry Pi - Home Assistant (home-assistant.io)
我刚好有块树莓派4b,拿出来用
有树莓派的打开这个官方烧录工具
选择 其他特定用途的操作系统 > Home assistants 和 Home automation > Home Assistant。
下载安装到sd卡(我下载有点慢,有条件的挂一下梯,嘎嘎快)
下载好后拔出SD卡插入树莓派4B,与路由器连接网线和电源开机
出现IP地址就放心了,输入http://192.168.31.35:8123/,进入ha后台
第一次开机,等初始化配置这些
GG,一直卡在初始化,百度了一下,是应为需要访问github,国内网络环境太复杂访问不上
开始想别的法子来装HA
来试试win10安装,找了半天教程决定用这个AlexxIT/HassWP v2024.4.3 (github.com)
解压后双击这个脚本一件部署
当当当!!!一步搞定啊,真的泪崩,找了一堆方法,就这个最简单了
开始配置mqtt连接
下面是我的知识盲区,我看大家用的方法都太复杂了,我不懂mqtt,于是找了个库
home-assistant-integration,项目地址:arduino-home-assistant:ArduinoHA allows to integrate an Arduino/ESP based device with Home Assistant using MQTT. - GitCode
我在官方网站找了了传感器的例程
示例 - ArduinoHA (dawidchyrzynski.github.io)
下面开始为arduino编写代码
首先需要导入一下wifi的头文件
#include <WiFiS3.h>
#include <WiFiClient.h>
-
加入了学习《【Follow me 第二季第2期任务】 各个任务实现的展示效果》,观看 【Follow me 第二季第2期任务】MQTT接入到HomeAssistant
-
发表了主题帖:
Follow me第二季第2期-2-2生成正弦波;放大DAC信号;打印数据显示曲线
开始做基础任务
用DAC生成正弦波;
用OPAMP放大DAC信号;
用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
还是先来到官方wiki看看官方的写法
Arduino UNO R4 WiFi Digital-to-Analog Converter (DAC) | Arduino Documentation
官方给的应用实例是用电位器来改变驱动蜂鸣器频率
#include "analogWave.h" // 包含用于模拟波形生成的库
analogWave wave(DAC); // 创建analogWave类的一个实例,使用DAC引脚
int freq = 10; // 频率,以赫兹为单位,根据需要更改
void setup() {
Serial.begin(115200); // 初始化串行通信,波特率为115200
wave.sine(freq); // 使用初始频率生成正弦波
}
void loop() {
// 从A5引脚读取模拟值,并将其映射到频率范围内
freq = map(analogRead(A5), 0, 1024, 0, 10000);
// 将更新的频率打印到串行监视器
Serial.println("当前频率为 " + String(freq) + " 赫兹");
wave.freq(freq); // 将波形发生器的频率设置为更新的值
delay(1000); // 在重复之前延迟一秒钟
}
其实很简单的代码,我们注释void loop中电位器调节freq值的代码就能实现用DAC生成正弦波的需求
#include "analogWave.h" // 包含用于模拟波形生成的库
analogWave wave(DAC); // 创建analogWave类的一个实例,使用DAC引脚
int freq = 10; // 频率,以赫兹为单位,根据需要更改
void setup() {
Serial.begin(115200); // 初始化串行通信,波特率为115200
wave.sine(freq); // 使用初始频率生成正弦波
}
void loop() {
// 从A5引脚读取模拟值,并将其映射到频率范围内
freq = map(analogRead(A5), 0, 1024, 0, 10000);
// 将更新的频率打印到串行监视器
//Serial.println("当前频率为 " + String(freq) + " 赫兹");
//wave.freq(freq); // 将波形发生器的频率设置为更新的值
delay(1000); // 在重复之前延迟一秒钟
}
好了下载到arduino U4中看看效果,A0口是DAC口,示波器测量需要共地
输出DAC成功!
下一步是用OPAMP放大DAC信号;
老规矩,来看看官方wiki
Arduino UNO R4 WiFi 运算放大器 |Arduino 文档
运算放大器的放大率主要取决于所选的电阻值=1+(R2/R1)
R1 = 接地电阻 (Ω)顾名思义,连接运放反馈口与地的
R2 = 反馈电阻 (Ω)连接输出与反馈口的
具体原理看这一篇原理解释,讲的非常好(不过需要小小翻一下)
Non-inverting Operational Amplifier Configuration (electronics-tutorials.ws)
由图可得,A1为输入脚,A2为反馈脚,A3为输出脚,为了实现用OPAMP放大DAC信号的需求,我们需要把A1与A0(DAC输出脚短接)
R2与R1都选择10k,得到1+(10k/10K)=2倍的放大倍率
代码部分只需在之前的代码中加下面的
#include <OPAMP.h>
void setup () {
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
}
实际情况:
不知道为什么不是很对头,但也有2倍放大了
下一个任务:用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
把A4连A0测dac输出
把A5连A3测OPAMP放大输出
#include "analogWave.h" // 包含用于模拟波形生成的库
#include <OPAMP.h>
analogWave wave(DAC); // 创建analogWave类的一个实例,使用DAC引脚
int freq = 5; // 频率,以赫兹为单位,根据需要更改
void setup() {
Serial.begin(115200); // 初始化串行通信,波特率为115200
wave.sine(freq); // 使用初始频率生成正弦波
wave.amplitude(0.4); //设置正弦曲线幅值为0.4,默认的太大了,超过adc采样电压了
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
}
void loop() {
printf("%d\n",analogRead(A4)); // 读取DAC输出正弦值
Serial.print(" ");
printf("%d\n",analogRead(A5)); // 读取OPAMP输出正弦值
delay(100); // 在重复之前延迟一秒钟
}
结果如下
原因是我delay的太久了,改为delay1
哈哈哈又快过头了,改为10
结果欧克了
-
发表了主题帖:
Follow me第二季第2期-2-1驱动点阵LED
本帖最后由 老杰瑞 于 2024-10-7 19:47 编辑
开始做基础任务
驱动12x8点阵LED;
还是先来到官方wiki看看官方的写法
Using the Arduino UNO R4 WiFi LED Matrix | Arduino Documentation
先加个库来驱动
#include "Arduino_LED_Matrix.h"
然后创建一个 LED 矩阵对象
ArduinoLEDMatrix matrix;
最后,在viod setup()中添加初始化
matrix.begin();
结合在一起就是
#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;
void setup() {
Serial.begin(115200);
matrix.begin();
}
通过创建一些二维数组就能撸出不同的图案了,下面撸一个简单的心跳和笑脸图案
#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;
void setup() {
Serial.begin(115200);
matrix.begin();
}
const uint32_t happy[] = {
0x19819,
0x80000001,
0x81f8000
};
const uint32_t heart[] = {
0x3184a444,
0x44042081,
0x100a0040
};
void loop(){
matrix.loadFrame(happy);
delay(500);
matrix.loadFrame(heart);
delay(500);
}
插播视频
其中
const uint32_t happy[] = {
0x19819,
0x80000001,
0x81f8000
};
U4一共有12*8=96颗led可以驱动,想要理解驱动原理就要理解这三个无符号长数组
0x19819,
0x80000001,
0x81f8000
把上面的这种十六进制值转换为二进制值
110001100001001010010001000100
1000010000010000001000100000000
10100000000001000000000000000000
再将其分成 12 位一组,您就得到了心形:
001100011000
010010100100
010001000100
001000001000
000100010000
000010100000
000001000000
000000000000
就是能出现心型图案的原理
开始做基础任务
驱动12x8点阵LED;
用DAC生成正弦波;
用OPAMP放大DAC信号;
用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
一个一个来,先是驱动12x8点阵LED
还是先来到官方wiki看看官方的写法
Using the Arduino UNO R4 WiFi LED Matrix | Arduino Documentation
先加个库来驱动
#include "Arduino_LED_Matrix.h"
然后创建一个 LED 矩阵对象
ArduinoLEDMatrix matrix;
最后,在viod setup()中添加初始化
matrix.begin();
结合在一起就是
#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;
void setup() {
Serial.begin(115200);
matrix.begin();
}
通过创建一些二维数组就能撸出不同的图案了,下面撸一个简单的心跳和笑脸图案
#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;
void setup() {
Serial.begin(115200);
matrix.begin();
}
const uint32_t happy[] = {
0x19819,
0x80000001,
0x81f8000
};
const uint32_t heart[] = {
0x3184a444,
0x44042081,
0x100a0040
};
void loop(){
matrix.loadFrame(happy);
delay(500);
matrix.loadFrame(heart);
delay(500);
}
看看效果
[localvideo]046bd85ccb95e143b5e04308601316d4[/localvideo]
想要做出不同效果的灯效就要理解这个数组
const uint32_t happy[] = {
0x19819,
0x80000001,
0x81f8000
};
U4一共有12*8=96颗led可以驱动,想要理解驱动原理就要理解这三个无符号长数组
0x19819,
0x80000001,
0x81f8000
把上面的这种十六进制值转换为二进制值
110001100001001010010001000100
1000010000010000001000100000000
10100000000001000000000000000000
再将其分成 12 位一组,您就得到了心形:
001100011000
010010100100
010001000100
001000001000
000100010000
000010100000
000001000000
000000000000
就是能出现心型图案的原理,笑脸也是同理。
- 2024-09-11
-
发表了主题帖:
【2024 DigiKey创意大赛】+便携式红外智能吸烟器+开箱贴
本帖最后由 老杰瑞 于 2024-9-11 21:47 编辑
收到包裹了!开心,顺丰来的
拆包拆包
每一个元器件都用防静电包装包好了,很好
热传感模块包装很好,还有硬包装保证引脚完好
我选取的开发板是ESP32-C6-DevKitC-1
模块是SGP30空气质量模块和MLX90640ESF-BAA-000-TU – 熱敏式影像感測器32H x 24V
官方文档链接ESP32-C6-DevKitC-1 v1.2 - - — esp-dev-kits latest 文档 (espressif.com)
查询得知默认i2c口为io6和io7
在进行硬件连接前我发现个问题
SGP30模块是1.8v供电的,所以要注意vin的输入,一开始我是用5v供电,但是测了一下i2c口上拉电压就是5v,这样直接连esp32有概率会烧坏io口,
所以SGP30模块需要供电跟mcu同一个工作电压才行。这跟其他模块不太一样,因为其他模块一般板载芯片是3v3供电,不会跟mcu有电压差
更换模块供电为3v3后进行接线
开始敲代码,打开arduino,查找sgp30库,找到安装
打开库示例~嘿嘿嘿
读不到i2c,排查了一下,应该是默认i2c引脚不对,arduino中没有这个板对应的板子,只能用其他c6的板代替,问题不大,重新定义一下引脚
读到收工,下面录了个视频测试
收到包裹了!开心,顺丰来的
拆包拆包
每一个元器件都用防静电包装包好了,很好
热传感模块包装很好,还有硬包装保证引脚完好
我选取的开发板是ESP32-C6-DevKitC-1
模块是SGP30空气质量模块和MLX90640ESF-BAA-000-TU – 熱敏式影像感測器32H x 24V
官方文档链接ESP32-C6-DevKitC-1 v1.2 - - — esp-dev-kits latest 文档 (espressif.com)
查询得知默认i2c口为io6和io7
在进行硬件连接前我发现个问题
SGP30模块是1.8v供电的,所以要注意vin的输入,一开始我是用5v供电,但是测了一下i2c口上拉电压就是5v,这样直接连esp32有概率会烧坏io口,
所以SGP30模块需要供电跟mcu同一个工作电压才行。这跟其他模块不太一样,因为其他模块一般板载芯片是3v3供电,不会跟mcu有电压差
更换模块供电为3v3后进行接线
开始敲代码,打开arduino,查找sgp30库,找到安装
打开库示例~嘿嘿嘿
读不到i2c,排查了一下,应该是默认i2c引脚不对,arduino中没有这个板对应的板子,只能用其他c6的板代替,问题不大,重新定义一下引脚
读到收工,下面录了个视频测试
[localvideo]53b525478df4361e16b99daa7dc71051[/localvideo]
- 2024-09-08
-
加入了学习《【Follow me第二季第2期】+开发板硬件介绍和实现任务一 LED灯闪烁和串口打印》,观看 【Follow me第二季第2期】实现任务二 驱动12x8点阵LED;用DAC生成正弦波并放大采集
-
发表了主题帖:
【Follow me第二季第2期】1-入门任务搭建环境并开启第一步Blink / 串口打印
拿到
拿到板子后先谷歌一下arduino-UNO R4 WiFi
找到这个网址UNO R4 WiFi 入门 |Arduino 文档
打开官方教程就可以开始配置环境了,点击图中的arduino软件页面。
下载安装完成后就可以开始配置一下arduino的设置,我推荐暗黑和中文配置,顺眼很多
下一步就是安装板基支持包
在右边的开发板管理器搜索UNO R4即可安装。
安装完成后插上UNO R4 WiFi板子,在开发板中选择UNO R4 WiFi
上面我们的开发环境就配置好了,硬件软件都ok,下面开始实现任务
我最喜欢的就是arduino的示例了,在里面有很多示例代码可以帮我我们快速开发自己需要的功能,再也不要天天为基础代码跑不通调试半天了~
在内置示例中找到blink,编译下载即可实现点灯功能,代码为下
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
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
}
代码其实就是让led口亮,如何停顿一下,在暗,再停顿一下,如此循环实现
给第一次使用arduino的小伙伴解释一下setup和loop在arduino中,必须有这两个函数,setup为开机运行一次,loop函数在setup运行完后就会不断循环运行,所以在上面的代码中,要先在setup中吧led口的pin配置好为输出模式,LED_BUILTIN在一些头文件中会对应板子上的ledpin脚位,这也是arduino的优势之一,代码可以在多个板子上不动运行
下面我们来实现串口打印功能
照例打开内置示例的AnalogReadSerial,程序功能是将ADC并且将值不断传输给串口
我们对代码进行修改实现我们需要的功能
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// print out the value you read:
Serial.println("Hello EEWorld!");
delay(1); // delay in between reads for stability
}
简单编辑一下即可
打开右上角arduino自带的串口工具即可查看打印的Hello EEWorld!内容!
好了到此为止我们就实现了入门任务