- 2024-10-28
-
发表了主题帖:
【2024 DigiKey 创意大赛】家庭环境检测器-完成贴
本帖最后由 白菜虫虫 于 2024-10-29 12:32 编辑
家庭环境检测器
作者:白菜虫虫
一、作品简介
作品照片:
作品功能介绍:
本作品旨在实现家庭智能环境检测,实现的主要功能有如下几点:
1.使用大尺寸LCD屏开发板结合LVGL制作精美界面,实时显示家庭环境质量。
2.使用BME680等传感器获取家庭环境数据,并通过网络传输到LCD屏幕开发板上实时显示。
3.通过网络获取天气预报信息并在LCD屏幕开发板上实时显示。
4.根据事先设定的条件,控制其他家庭智能设备,调节室内温度,湿度等等环境条件。
物料清单:
本次使用的的板卡是乐鑫官方的ESP32-S3-LCD-EV-BOARD开发板,配备了ESP32-S3-WROOM-1作为主控,搭配了3.95
寸480x480LCD 触摸屏,屏幕驱动IC为GC9503CV触摸IC为FT5x06
BME680传感器,BME680是一款多功能高精度传感器,可以检测温度,湿度,气压,和有机气体。我购买的是单独芯片,然后自己制作了配套的底板。
ESP32C3开发板,用来进行数据的采集和开发板发送数据。
二、系统框图
本系统设计主要分为3个部分:
1.LVGL大屏显示部分。2.家庭环境信息采集部分。3.家庭环境调节部分。
各部分之间通过MQTT相互传递数据。
三、各部分功能说明
1.LVGL大屏显示部分:
这部分的程序主要完成三个部分的功能:一是LVGL界面的初始化和显示;二是连接到心知天气服务器并获取天气预报数据;三是连接MQTT服务器并订阅获取传感器信息数据。
2.家庭环境信息采集部分:
本部分功能为通过BME680传感器采集家庭环境信息,并格式化为JSON数据,通过MQTT对应主题发送到MQTT服务器。
3.家庭环境调节部分:
本部分主要演示根据MQTT接收到的传感器数据和设定值,自动开始和关闭家庭环境调节设备(本部分中以LED代替通风扇热系统进行演示)。
四、作品源码
本次程序均使用arduino完成,压缩包内包含三个部分:
1、Porting20241024:为LVGL显示部分,对应ESP32-S3-LCD-EV-BOARD开发板。
2、mqtt_esp32c3_bme680:为BME680传感器信息采集及上传部分,对应ESP32-C3开发板。
3、mqtt_esp32c3_hot:为接收传感器信息并进行环境调节部分,对应ESP32-C3开发板。
五、作品功能演示视频
[localvideo]f180c40ea94c9227a64c713fc98b89b9[/localvideo]
六、项目总结
第一次参加大赛,很荣幸也很激动,能和这么多大佬一起参赛,亚历山大。
经过两个月的努力,受限于个人技术水平,项目堪堪完成了个大概,距离开始的预想还有一些距离,跟各位大佬的作品相比更显稚嫩。但两个月我也收获了很多,对LVGL的使用有了新的认识,学会了MQTT通讯,HTTP通讯的实现,掌握了BME680高精度传感器,还自己打了传感器底板,也可谓收获满满。
最后感谢得捷和电子工程世界给了这么一次锻炼提高的机会,祝大赛越办越好。
开箱帖链接:https://bbs.eeworld.com.cn/thread-1291882-1-1.html
传感器打板帖链接:https://bbs.eeworld.com.cn/thread-1292331-1-1.html
花絮分享贴链接:https://bbs.eeworld.com.cn/thread-1295998-1-1.html
WORD版文档:
- 2024-10-14
-
发表了主题帖:
【2024 DigiKey 创意大赛】90年代风格的UI界面
、
画了个UI界面,越看越想笑,被兄弟们评价为90年代风格,发上来大家一起笑一下。
- 2024-09-26
-
回复了主题帖:
【Follow me第二季第2期】arduinoUNOR4+homeassistant任务提交
慕容雪花 发表于 2024-9-26 11:15
感谢大佬无私分享!
大佬不敢当,小小学徒一枚
-
回复了主题帖:
【Follow me第二季第2期】arduinoUNOR4+homeassistant任务提交
修改补充了DAC增加负反馈分压电阻的部分,请各位大佬指正
- 2024-09-25
-
上传了资料:
【Follow me第二季第2期】arduinoUNOR4+homeassistant代码汇总
-
回复了主题帖:
【Follow me第二季第2期】arduinoUNOR4+homeassistant任务提交
Maker_kun 发表于 2024-9-25 08:46
运放要加反馈电阻不加波形失真严重,起不到运放的作用
是滴,手上没有直插的电阻,所以偷懒这么搞了
- 2024-09-24
-
发表了主题帖:
【Follow me第二季第2期】arduinoUNOR4+homeassistant任务提交
本帖最后由 白菜虫虫 于 2024-11-2 22:59 编辑
很开心又一次参加得捷和eeworld联合举办的follow me活动。
这次活动使用的板卡是Arduino UNO R4 WiFi。其实对于arduino还是有一些小情结的,因为当时虽然第一款学的MCU是51,但真正入门并领略了微电子的乐趣,还是arduino UNO R3,所以这次能参加follow me的活动还是很nice的。
[localvideo]c51648a519370934a0b4a947eabf6b92[/localvideo]
任务实现简介:
这次完成的任务主要有以下这些,具体实现方式相见后面。
入门任务(必做):搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
基础任务(必做):驱动12x8点阵LED;
用DAC生成正弦波;
用OPAMP放大DAC信号;
用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
进阶任务(必做):通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
扩展任务(必做,自选任务):
1.通过外部AHT20温湿度传感器,上传温湿度到HA,通过HA面板显示数据
2.连接XiaoC3到HA,并用板载LED模拟灯泡。用HA面板控制LED亮灭模拟控制家庭照明灯的亮灭。
物料清单:
本次使用的物料主要由:
1、arduino UNO R4 wifi 开发板
2、AHT20温湿度传感器
3、Seeed XIAO C3开发板
任务实现详情:
入门任务(必做):搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
搭配器件: Arduino UNO R4 WiFi
设计思路:初始化数字引脚,重复点亮LED和熄灭LED并添加适当延时;初始化串口,输出文字“Hello EEWorld!”。
软件流程图:
每次做入门任务,其实最重要的还是环境的搭建。既然板卡是Arduino UNO R4 WiFi,那么使用的编程软件自然首选arduinoIDE。
1.下载安装软件
首先,打开arduino官网的软件下载页面
https://www.arduino.cc/en/software
根据自己的操作系统,选择合适的软件版本下载。
然后按照默认设置一路next安装完毕。
在右侧的侧边栏点第二个图标,出现开发板管理器栏,输入Arduino UNO R4并
回车搜索,选择arduino官方的arduino UNO R4 Boards板卡进行安装。
3.点亮板卡
3.1依次点击文件→示例→内置示例 01.basics→blink。
3.2依次点击→工具→开发板→arduino UNO R4 boards→arduino UNO R4 wifi
3.3然后点击(→)编译上传。
等待软件编译上传完成,开发板上的小灯开始闪烁,blink程序烧录完成。
4.串口打印Hello EEWorld!
将刚才的程序进行修改
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
Serial.print("Hello EEWorld!");
}
// 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
}
点击工具→串口监视器。
再次点击(→)编译上传,串口监视器输出Hello EEWorld!
基础任务(必做):1、驱动12x8点阵LED;2、用DAC生成正弦波;3、用OPAMP放大DAC信号;4、用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
搭配器件: Arduino UNO R4 WiFi
设计思路:1、点阵LED的驱动很简单,找到相应的库简单修改就行,以二维数组,一维数组,字符串数组三选一的方式将需要显示的内容表示出来,然后通过驱动库进行显示。因为步骤太简单了,就不画流程图了。
2-4生成波形及采集的部分,主要就是通过DAC生成一个波形,将波形通过分压电阻输入给运算放大器的正负反馈输入端,然后进行放大并输出给ADC进行采样,并将采集到的数据通过串口输出,通过ARDUINO IDE自带的串口绘图仪进行观察。
软件流程图:
1.驱动12x8点阵LED;
Arduino UNO R4 WiFi开发板自带了一个12X8的led矩阵,还是挺好玩的。
这个LED矩阵的驱动也是比较简单的,使用Arduino_LED_Matrix库就可以轻松驱动。(具体可以参考示例当中LED_Martrix相关例程。)
而操作起来一般也就三种方式,
①8x12数组,具体参见 Matrix Frame Buffer例程
②三组8位16进制数,具体参见Displays single frames例程
③字符串显示,具体参见ArduinoGraphics例程
我这次选择体验的是第三种方式,只需要修改例程中的text[]数组,编译上传即可。
2.用DAC生成正弦波;
开始研究了半天没找到资料,后来还是在arduinoIED的示例立马找到了。
//FollowMe第二季第2期-白菜虫虫-任务2.1(驱动12x8点阵LED)
#include "analogWave.h"
analogWave wave(DAC);
int freq = 10;
void setup() {
wave.sine(freq);
}
void loop() {
}
A0引脚是波形输出,把示波器接好A0和GND。
3.用OPAMP放大DAC信号;
OPAMP运算放大器的例程同样可以在arduino里面找到。
//FollowMe第二季第2期-白菜虫虫-任务2.3(用DAC生成正弦波)
#include "analogWave.h"
#include <OPAMP.h>
analogWave wave(DAC);
int freq = 10;
void setup () {
Serial.begin(9600);
delay(2000);
wave.sine(freq);
if (!OPAMP.begin(OPAMP_SPEED_HIGHSPEED)) {
Serial.println("Failed to start OPAMP!");
}
bool const isRunning = OPAMP.isRunning(0);
if (isRunning) {
Serial.println("OPAMP running on channel 0!");
} else {
Serial.println("OPAMP channel 0 is not running!");
}
}
void loop() {
delay(2000);
}
编译上传,把A0的输入接到A1,然后用示波器接OPAMP运算放大器的输出A3。
这个波形有点失真,想了想应该是偷懒没接负反馈的问题。
把A3的输出接到A2的负反馈输入。
波形恢复正常。
这里由于是又偷懒没给负反馈做分压,所以A3的输出波形虽然正常了,但是放大倍数有点忒小了,需要增大放大倍数的同学可以给负反馈做一个分压,用分压后A3输出波形给A2做输入。
负反馈增加分压电阻:
后续找到了几颗直插电阻,现在添加上使用分压电阻的做法。
首先是直接给A3的输出增加分压电阻,取大约1/2的电压输入到A2。通过示波器和ADC查看均存在削峰的情况,波谷倒是显示正常。、
猜测是超过了ARUDINO的上限,于是考虑给输入也增加分压。
A0的输出通过2/3的分压输入给A1,依旧削峰。再次改变电路,把A0的1/3分压给A1作为输入,波形全部正常显示。
电路图如下:
分压后的输入波形:
接负反馈后的输出波形:
4.用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
这一步就比较简单了。
在上一个任务的基础上简单修改就可以了。
//FollowMe第二季第2期-白菜虫虫-任务2.4(用DAC生成正弦波)
#include "analogWave.h"
#include <OPAMP.h>
analogWave wave(DAC);
int freq = 10;
int sensorPin = A5;
void setup () {
Serial.begin(9600);
delay(2000);
wave.sine(freq);
if (!OPAMP.begin(OPAMP_SPEED_HIGHSPEED)) {
Serial.println("Failed to start OPAMP!");
}
bool const isRunning = OPAMP.isRunning(0);
if (isRunning) {
Serial.println("OPAMP running on channel 0!");
} else {
Serial.println("OPAMP channel 0 is not running!");
}
}
void loop() {
Serial.println(analogRead(sensorPin));
}
编译上传,然后点击arduinoIED菜单栏 工具→串口绘图仪就能看到波形。
再给大家看看不加负反馈时候的波形。
因为放大之后的波形超过了ADC采样的范围,所以波峰波谷都被削平了。想用ADC看波形的兄弟们也可以给ADC输入加上分压电路。
这里也补充增加了输入和负反馈分压后的ADC采样波形:
输入波形
负反馈分压输出波形
进阶任务(必做):通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
搭配器件: Arduino UNO R4 WiFi
设计思路:这一步主要是HA平台的搭建,平台搭建好了之后使用UNO R4通过MQTT发送一个注册传感器的消息,HA平台接收到后就会显示一个温湿度传感器的标签。
软件流程图:
1.搭建HomeAssistant。
homeassistant的安装坑很多,建议按照官网的说明进行。我个人是选择的VMware虚拟机的方式进行安装的。
打开homeassistant官网https://www.home-assistant.io/installation/
参照官网说明,按照自己设备或操作系统选择合适的方式进行安装。
安装完毕在浏览器输入IP地址:8123打开homeassistant,比如我的就是http://192.168.11.135:8123/
第一次启动经过漫长的等待,进行科学上网可以有效缩短等待时间。
更新完毕会进入注册和设置页面,需要设置登录使用的账号密码和一些其他东西,按照提示进行设置就可以。
2.安装mqtt 服务器
点击设置,点右下角加载项商店,搜索emqx并安装。
打开emqx,添加自己的一个自己的mqtt账号。
3.配置
在设置→设备与服务→集成中搜索添加并配置mqtt项目。
配置mqtt集成的时候,建议单独注册一个HA用户分配给mqtt使用,不要使用默认管理账户。
4.Arduino UNO R4 WiFi连接HA
homeassistant端配置完毕之后,来看UNO R4端,UNO R4主要是配置并连接到mqtt服务器。
先搜索安装ArduinoMqttClient库,然后根据示例修改为我们的程序:
//FollowMe第二季第2期-白菜虫虫-进阶任务
#include <ArduinoJson.h>
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
char ssid[] = "BAICAICHONGCHONG";
char pass[] = "PASSWORD";
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = "192.168.66.121";
int port = 1883;
const char register_topic[] = "homeassistant/sensor/sensorBedroomT/config";
const char refresh_topic[] = "homeassistant/followme/state";
const long interval = 1000;
unsigned long previousMillis = 0;
int count = 0;
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
String register_doc1="{\"device_class\":\"temperature\",\"name\":\"Temperature\",\"state_topic\":\"homeassistant/followme/state\",\"unit_of_measurement\":\"C\",\"value_template\":\"{{value_json.temp}}\",\"unique_id\":\"temp01ae\",""\"device\":{\"identifiers\":[\"bedroom01ae\"],\"name\":\"FollowMe\"}}";
String register_doc2="{\"device_class\":\"temperature\",\"name\":\"Temperature\",\"state_topic\":\"homeassistant/followme/state\",\"unit_of_measurement\":\"C\",\"value_template\":\"{{value_json.temp}}\",\"unique_id\":\"temp01ae\",""\"device\":{\"identifiers\":[\"bedroom01ae\"],\"name\":\"FollowMe\"}}"; // 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();
// You can provide a unique client ID, if not set the library uses Arduino-millis()
// Each client must have a unique client ID
mqttClient.setId("clientId");
// You can provide a username and password for authentication
mqttClient.setUsernamePassword("unor4", "test123");
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("You're connected to the MQTT broker!");
Serial.println();
mqttClient.poll();
Serial.print("register sensor");
Serial.println();
mqttClient.beginMessage(register_topic);
mqttClient.print(register_doc1);
mqttClient.print(register_doc2);
mqttClient.endMessage();
}
void loop() {
String refresh_doc= "{\"temp\": 23.20, \"hum\": 43.70}";
mqttClient.poll();
Serial.print("refresh data");
mqttClient.beginMessage(refresh_topic);
mqttClient.print(refresh_doc);
mqttClient.endMessage();
Serial.println();
delay(1000);
}
编译并上传后,刷新HA界面,可以看到新的传感器。
扩展任务(必做,自选任务)
1.通过外部AHT20温湿度传感器,上传温湿度到HA,通过HA面板显示数据
搭配器件: Arduino UNO R4 WiFi、AHT20温湿度传感器
设计思路:UNO R4通过IIC采集AHT20等传感器的温湿度数据,并以MQTT的方式上传到HA。
软件流程图:
首先要将AHT20温湿度传感器接在UNO R4上,如果传感器有Qwiic接口,可以使用PRT-14426(Qwiic缆线-50mm)把传感器连接到UNO R4上,或者也可以使用杜邦线进行连接,注意按照VCC→3.3V,GND→GND,SCL→A5,SDA→A4的顺序进行连接。
然后搜索并安装驱动库,我使用的是DFRobot_AHT20库
接下来将我们进阶任务的程序进行修改:
//FollowMe第二季第2期-白菜虫虫-扩展任务1
#include <ArduinoJson.h>
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include "DFRobot_AHT20.h"
DFRobot_AHT20 aht20;
char ssid[] = "sishuiyouyu"; // your network SSID (name)
char pass[] = "Jj19860123"; // your network password (use for WPA, or use as key for WEP)
// char ssid[] = "FAST_7664"; // your network SSID (name)
// char pass[] = "12345678";
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = "192.168.66.121";
// const char broker[] = "192.168.11.140";
int port = 1883;
const char register_topicT[] = "homeassistant/sensor/sensorBedroomT/config";
const char register_topicH[] = "homeassistant/sensor/sensorBedroomH/config";
const char refresh_topic[] = "homeassistant/followme/state";
const long interval = 1000;
unsigned long previousMillis = 0;
int count = 0;
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
String register_docT="{\"device_class\":\"temperature\",\"name\":\"Temperature\",\"state_topic\":\"homeassistant/followme/state\",\"unit_of_measurement\":\"C\",\"value_template\":\"{{value_json.temp}}\",\"unique_id\":\"temp01ae\",\"device\":{\"identifiers\":[\"bedroom01ae\"],\"name\":\"FollowMe\"}}";
String register_docH="{\"device_class\":\"humidity\",\"name\":\"Humidity\",\"state_topic\":\"homeassistant/followme/state\",\"unit_of_measurement\":\"%\",\"value_template\":\"{{value_json.hum}}\",\"unique_id\":\"hum01ae\",\"device\":{\"identifiers\":[\"bedroom01ae\"],\"name\":\"FollowMe\"}}";
uint8_t status;
while((status = aht20.begin()) != 0){
Serial.print("AHT20 sensor initialization failed. error status : ");
Serial.println(status);
delay(1000);
}
// 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();
// You can provide a unique client ID, if not set the library uses Arduino-millis()
// Each client must have a unique client ID
mqttClient.setId("clientId");
// You can provide a username and password for authentication
mqttClient.setUsernamePassword("unor4", "test123");
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("You're connected to the MQTT broker!");
Serial.println();
mqttClient.poll();
Serial.print("register sensor");
Serial.println();
mqttClient.beginMessage(register_topicT);
mqttClient.print(register_docT);
mqttClient.endMessage();
mqttClient.poll();
mqttClient.beginMessage(register_topicH);
mqttClient.print(register_docH);
mqttClient.endMessage();
}
void loop() {
if(aht20.startMeasurementReady(/* crcEn = */true)){
Serial.print("temperature(-40~85 C): ");
Serial.print(aht20.getTemperature_C());
Serial.print(" C, ");
Serial.print("humidity(0~100): ");
Serial.print(aht20.getHumidity_RH());
// String refresh_doc= +gcvt()++gcvt()+;
mqttClient.poll();
Serial.print("refresh data");
mqttClient.beginMessage(refresh_topic);
mqttClient.print("{\"temp\": ");
mqttClient.print(aht20.getTemperature_C());
mqttClient.print(", \"hum\": ");
mqttClient.print(aht20.getHumidity_RH());
mqttClient.print("}");
mqttClient.endMessage();
Serial.println();
delay(1000);
}
else{
mqttClient.poll();
Serial.print("wait aht20");
delay(1000);
}
}
编译并上传到开发板。
刷新HA页面就能看到不断变化的温度湿度值了。
2.连接XiaoC3到HA,并用板载LED模拟灯泡。用HA面板控制LED亮灭模拟控制家庭照明灯的亮灭。
搭配器件:Seeed XIAO C3开发板
设计思路:使用ESPHome配合HA来控制XIAO C3为代表的智能终端设备
软件流程图:
下面我来演示一种更简单的把设备加入HA的方式,这种方式适用于ESP32和ESP8266的驱动板,这里我选择的是XiaoC3。
在HA设置→加载项中搜索并安装ESPHome然后启动它。
添加一个新的设备,选择ESP32-C3,添加完毕后点edit编辑yaml文件,修改SSID和密码,在文件最后添加代码
light:
- platform: binary
name: "FollowMeLED"
output: bin_led
output:
- id: bin_led
platform: gpio
pin: GPIO2
inverted: true
要注意缩进,yaml和python类似,是以缩进代表归属的语言。
烧录代码到XiaoC3,刷新HA就可以看到我们的LED。
点击LED标签上的按钮,就可以控制LED的亮灭。
活动心得体会:这是活动总体来说收获巨大,以这次活动为契机督促自己详细的研究了homeassistant智能家居的实现方式。期间遇坑无数,爬坑也不少,尤其是HA的搭建,说多了都是泪啊。
重要完成了,也大体学会了,HA还是很好玩的,尤其在生活中也能用得上,监测一下屋里的温湿度和空气质量情况呀,控制一下灯光亮灭啦,控制一些职能家电等等,还能自定义定时或者定条件的自动事项,灰常的方便。
最后,再次感谢主办方得捷和电子工程世界。
- 2024-09-07
-
回复了主题帖:
【2024 DigiKey 创意大赛】家庭环境检测器-BME680焊接成功
秦天qintian0303 发表于 2024-9-4 09:29
数字通信好使很方便的,总感觉自己上锡膏不爱沾呢
我给锡膏加了点料,稀释了一下,也更好焊接,缺点就是板子会更脏一些
- 2024-09-04
-
回复了主题帖:
【2024 DigiKey 创意大赛】家庭环境检测器-BME680焊接成功
wangerxian 发表于 2024-9-2 17:45
这种传感器外围电路还是挺简单的。
是呀,出乎意料的简单
- 2024-09-02
-
发表了主题帖:
【2024 DigiKey 创意大赛】家庭环境检测器-BME680焊接成功
本帖最后由 白菜虫虫 于 2024-9-2 16:41 编辑
书接上回,上回书说到了收到BEM680传感器之后,看着这小小的封装,一个头两个大。
不过事已至此,只能闷着头上了。
首先打开立创开源广场,搜索BME680
点开第一位大佬的项目分享,看了一下原理图,BME680需要的驱动电路还是很简单的,4个上下拉电阻,两个电源滤波电容,LED和它的限流电阻可有可没有。
但是他的PCB设计元器件靠的比较近,本人眼花手笨的,怕焊补了,而且大佬的电容电阻封装都是0805的,我下单的物料是0603的。
于是乎,新建个工程自己画吧。
站在大佬的肩上完成的还是挺快的。
预览一下:
下单打板,感谢嘉立创每月两次的免费打板。
收到PCB,正反面再拍一下:
涂好锡膏
热风枪开310度,小风慢慢的吹
用万用表对照PCB设计挨个检测,发现一个虚焊,补焊一下。
这时候发现传感器上的孔和PCB上的位置不一样,吓出了一脑门子的汗。
NND刚才放传感器的时候明明下面的点是一样的位置啊,怎么旁边的点不一样啊,赶紧回去看PCB封装图。
果然好坑,传感器盖住的位置有个点,引脚旁边有个点,俩点位置就是不一样,这可咋办,万一上电测试别烧了。
赶紧去得捷网站上翻数据手册。
原来传感器上的圆孔叫通气孔,不是引脚标记,吓死宝宝了,又学到了新的知识。
虚惊一场,焊接好排针,翻出个树莓派PICO,打开ARDUINO IDE,搜索一下BME680的驱动库,选了adafruit的驱动库。
安装好驱动之后点开示例里面的bme680test,配置好管脚,接好线,编译上传。
卧槽,报错了,啥情况,不是芯片真焊反了吧。
稳住,先别慌,想想有啥地方还能出错,要不把SDO,SDI换过来试试。
哎呀,这次出数据了。
一波三折,虚惊一场,好事多磨。
唠唠叨叨说了一大堆,感谢各位看到了这里,谢谢!
-
回复了主题帖:
【2024 DigiKey 创意大赛】家庭环境检测器-开箱帖
有点太小了,耍了一点小心机,有惊无险的焊接成功了。
- 2024-08-29
-
发表了主题帖:
【2024 DigiKey 创意大赛】家庭环境检测器-开箱帖
本帖最后由 白菜虫虫 于 2024-8-29 10:52 编辑
很荣幸能参加这次的大赛,很开心,很荣幸,压力也山大。
下单的物料来到了,激动的心,颤抖的手,开箱看一下物料:
得捷的包装真是没话说,每个元件都有自己的包装,上面也有详细的贴纸,另外箱子里也附了好几页各种说明文档。最外层的大纸箱的风口还有塑料线加强。
这次选的开发板做工也很好,屏幕很清晰,触摸灵敏,板子的边也都打磨过,摸起来很舒服,就是第一次玩RGB屏幕,心里还没有一点底。
BMP680模块已经打好版了,看到实物才知道这么小,不知道自己能不能焊的了。
-
回复了主题帖:
【Follow me第二季第1期】学习总结
关于水果钢琴的最新进展,如果出现了水果钢琴无论如何都不响,或者就只能偶尔响一下的情况,可以多接一根鳄鱼夹到GND,然后另外一头夹个水果攥在手里,然后用这只手去触摸其他水果,就可以正常使用。
- 2024-08-28
-
上传了资料:
followme第二季第1期2024-白菜虫虫-代码汇总
-
发表了主题帖:
【Follow me第二季第1期】学习总结
本帖最后由 白菜虫虫 于 2024-10-10 18:06 编辑
【Follow me第二季第1期】
很开心可以参加这一期的Follow me活动,感谢EEworld和得捷联合举办的这次活动给了我一次很好的学习提高的机会,通过这次的学习,我基本掌握了CircuitPython和SAMD21的使用,受益颇丰。下面是我这次学习情况汇报:
这次活动的开发板是Adafruit Circuit Playground Express(名字太长了,后面就叫小圆板吧)。
开发方式我选择的是官方的CircuitPython(后面简称CPY),选择CPY的愿意有以下几个:一是这是官方固件,稳定性有保障;二是CPY的库很全面,不需要再到网上去找库;三是以前没有接触过,以这次活动为契机学习提高下自己。
[localvideo]9717ff3df4b03c52b1e7b222aeffa2ec[/localvideo]
物料展示:
首先展示一下本次使用的所有器件:
从左到右依次是USB数据线,Adafruit Circuit Playground Express小圆板本体,小圆板外壳,还有小圆板专用电池盒。
入门任务(必做):开发环境搭建,板载LED点亮
操作过程:
1.下载最新的CircuitPython固件。
1.1下载固件:打开CircuitPython官网,点击DOWNLOAD,选择Adafruit Circuit Playground Express,就可以下载小圆板的专用固件,固件有英文、拼音等等各个语言的版本,我先尝试了一下拼音的版本,感觉挺别扭的,得一个一个字读出音来再连起来品意思,所以还是换回英文吧,英文有美国英语和英国英语,也不知道啥区别就随便下个吧。
CircuitPython固件下载地址:
https://CircuitPython.org/board/circuitplayground_express/
1.2烧录CircuitPython固件:
Adafruit Circuit Playground Express小圆板烧录固件还是很简单的,简单到都不需要额外的软件。使用USB数据线连接小圆板,等待驱动安装完毕。这时候自带的出厂固件就会开始跑马灯,按D4键会发出音乐,按D5件会改变亮度(貌似),拨动D7则会改变跑马灯的方向。
按住D4再按reset键,会弹出U盘,把下载好的固件拖进U盘里面,等待重启(到这里跟树莓派PICO差不多),会弹出一个名为CIRCUITPY的U盘,则说明固件烧录成功(这里则跟树莓派PICO不一样)。
固件烧录前:
固件烧录后:
2.编辑软件准备。
2.1安装Thonny:
本来听说Mu和CircuitPython更配,但折腾了一下,发现还是Thonny更好用。
下载安装Thonny就不细说了,常玩MPY的大佬们朋友们都有,没有的兄弟们浏览器搜索一下很好找。
2.1配置Thonny:
在使用Thonny开始我们的编程前,我们还需要做一些配置。
①打开Thonny,点击右下角开发板串口标志,点击配置编辑器。
或者点击菜单栏运行,在点击配置编辑器。
②在Thonny应该使用那种解释器来运行您的代码选项中点击下拉菜单,选择CircuitPython(通用),然后点击好的。
③用USB数据线连接板子到电脑,再次点击右下角开发板串口标志,选择自己的开发板串口号就可以了。
连接成功的话Thonny就会出现类似下图的显示,开发板同时会亮起白光。如果连接失败可以尝试按下开发板RESET,点击Thonny的STOP按钮,或者组合使用。
3.点亮一个LED。
CircuitPython其实和MicroPython很多地方是类似的,都要先引用开发板定义和相关库。为了点亮板载的WS2812,我们需要引用board和neopixel,前者是开发板定义,后者是WS2812的驱动库。
然后我们输入如下程序:
import neopixel
from board import *
pixels = neopixel.NeoPixel(NEOPIXEL, 10)
pixels[0] = 0x100010
点击运行当前脚本(绿圈白三角的按钮),开发板上的第一个LED就成功的被点亮了。
基础任务一(必做):控制板载炫彩LED,跑马灯点亮和颜色变换
首先,在活动页面下载使用指南。
打开指南16页,可以看到WS2812彩灯的介绍。
下面细说一下程序:
①首先还是引用需要的库文件
import neopixel
from board import *
import time
②定义颜色代码:
COLOR = [
[255, 0, 0], # 红色
[255, 60, 0], # 橙色
[255, 255, 0], # 黄色
[0, 255, 0], # 绿色
[0, 255, 255], # 青色
[0, 0, 255], # 蓝色
[180, 0, 255], # 紫色
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
]
③初始化NeoPixel
pixels = neopixel.NeoPixel(NEOPIXEL, 10, brightness=0.1,auto_write=False)
④编写NeoPixel流水灯代码:
def one_cycle(color):
pixels.fill(0)
pixels.show()
time.sleep(DELAY)
for i in range(10):
pixels.fill(0)
pixels[i] = color
pixels.show()
time.sleep(DELAY)
下面是完整的任务一代码:
#【Follow me第二季第1期】白菜虫虫
# 基础任务一(必做):控制板载炫彩LED,跑马灯点亮和颜色变换
import neopixel
from board import *
import time
DELAY = 0.1
COLOR = [
[255, 0, 0], # 红色
[255, 60, 0], # 橙色
[255, 255, 0], # 黄色
[0, 255, 0], # 绿色
[0, 255, 255], # 青色
[0, 0, 255], # 蓝色
[180, 0, 255], # 紫色
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
]
pixels = neopixel.NeoPixel(NEOPIXEL, 10, brightness=0.1,auto_write=False)
def one_cycle(color):
pixels.fill(0)
pixels.show()
time.sleep(DELAY)
for i in range(10):
pixels.fill(0)
pixels[i] = color
pixels.show()
time.sleep(DELAY)
def rainbow_cycle(n):
pixels.fill(0)
for i in range(n+10,n,-1):
pixels[(i)%10] = COLOR[10+n-i]
pixels.show()
time.sleep(DELAY)
def main():
for i in range(7):
one_cycle(COLOR)
for i in range(70):
rainbow_cycle(i)
main()
运行效果如图:
基础任务二(必做):监测环境温度和光线,通过板载LED展示舒适程度
小圆板搭载了A8:光线传感器和A9:温度传感器。
其中A8:光线传感器采用的是ALS-PT19光敏三极管,虽然是三极管但没引出基极,第一眼看到还以为是个光敏二极管。
A9:温度传感器采用的是NCP15XH103F03RC热敏电阻。
二者均采用了直接读取模拟量的方式获取数值。
手册18页两个传感器的介绍:
小圆板搭载了A8:光线传感器和A9:温度传感器。
其中A8:光线传感器采用的是ALS-PT19光敏三极管,虽然是三极管但没引出基极,第一眼看到还以为是个光敏二极管。
手册214页可以看到A8光线传感器的例程
import time
import board
import neopixel
import analogio
import simpleio
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.05, auto_write=False)
pixels.fill((0, 0, 0))
pixels.show()
light = analogio.AnalogIn(board.LIGHT)
while True:
# light value remapped to pixel position
peak = simpleio.map_range(light.value, 2000, 62000, 0, 9)
print(light.value)
print(int(peak))
for i in range(0, 9, 1):
if i <= peak:
pixels[i] = (0, 255, 0)
else:
pixels[i] = (0, 0, 0)
pixels.show()
time.sleep(0.01)
手册216页顶部则有A9温度传感器的例程
import time
import adafruit_thermistor
import board
thermistor = adafruit_thermistor.Thermistor(
board.TEMPERATURE, 10000, 10000, 25, 3950)
while True:
temp_c = thermistor.temperature
temp_f = thermistor.temperature * 9 / 5 + 32
print("Temperature is: %f C and %f F" % (temp_c, temp_f))
time.sleep(0.25)
结合二者制作出我们任务二的程序:
①由于光线传感器是使用 analogio库进行的读取,数值范围是0-65535,所以把读取到的数值除以0x1000并取整进行转换,方便后续使用。
light=int(light_pin.value/0x1000)
print(f"Light:{light}")
if light>=9:
pixels[4]=COLOR[8]
else:
pixels[4]=COLOR[light]
采用转换后的light值的高低并以相应颜色来进行表示,因为比较懒就制作了一个9色数组,所以9以上数值都显示红色,经测试也基本符合对光线强弱的直观感受。
②温度传感器由于采用的是adafruit_thermistor库,读取温度是摄氏温度数值,所以选取了13℃-40℃的范围,每3℃一档的方式进行不同温度表示,高于40℃显示红色,低于13℃显示冰蓝色。
celsius = thermistor.temperature
print(f"Temperature:{celsius}")
temp=int((celsius-13)/3)
print
if temp>=9:
pixels[5]=COLOR[8]
else:
if temp<=0:
pixels[5]=COLOR[0]
else:
pixels[5]=COLOR[temp]
完整程序如下:
import analogio
from board import *
import time
import neopixel
import adafruit_thermistor
COLOR = [
[0, 0, 255], #0 蓝色
[0, 255, 255], #1 青色
[0, 127, 127], #2 浅绿
[0, 255, 0], #3 绿色
[127, 127, 0], #4 浅黄色
[255, 127, 0], #5黄色
[255, 255, 0], #6黄色
[255, 60, 0], #7 橙色
[255, 0, 0], #8红色
]
pixels = neopixel.NeoPixel(NEOPIXEL,10, brightness=0.1)
pixels.fill(0)
light_pin = analogio.AnalogIn(A8)
resistor = 10000
resistance = 10000
nominal_temp = 25
b_coefficient = 3950
thermistor = adafruit_thermistor.Thermistor(
TEMPERATURE, resistor, resistance, nominal_temp, b_coefficient
)
while True:
light=int(light_pin.value/0x1000)
print(f"Light:{light}")
if light>=9:
pixels[4]=COLOR[8]
else:
pixels[4]=COLOR[light]
celsius = thermistor.temperature
print(f"Temperature:{celsius}")
temp=int((celsius-13)/3)
print
if temp>=9:
pixels[5]=COLOR[8]
else:
if temp<=0:
pixels[5]=COLOR[0]
else:
pixels[5]=COLOR[temp]
time.sleep(1)
温度检测演示:
[localvideo]a1204e7f836429ffe9347d2bc24b400c[/localvideo]
亮度检测演示:
[localvideo]7e111b2b393e7d2f4fe7b0784ab3198a[/localvideo]
基础任务三(必做):接近检测——设定安全距离并通过板载LED展示,检测到入侵时,发起声音报警
接近检测这个任务,一开始我是懵逼的,因为在板子上没有找到接近传感器,难道我要外接一个超声波测距模块?那多不优雅。
不是有光线传感器吗,那拿你试试行不行吧。
结果是,行,但不完全行,因为得靠的很近才能出现明显的数值变化,离远了变化都没传感器跳动的误差大。继续想办法吧。
继续翻指南,在22页有了收获:
这段话翻译过一下:
这不就有了吗。
基本思路是使用红外LED照一下,然后关闭红外LED,再读取A10的数值。一定不要一直开着红外LED,一会就烫手,吓得我还以为烧了呢。
A10的数值会在一个范围内波动,将这个范围平均分成10份(稍微多一点也成),然后对应10颗灯珠,测试一下选个合适的距离触发报警,我这里选择的是大于等于6时报警。
下面是完整程序:
#【Follow me第二季第1期】白菜虫虫
#基础任务三(必做):接近检测——设定安全距离并通过板载LED展示,检测到入侵时,发起声音报警
from board import *
import time
import neopixel
pixels = neopixel.NeoPixel(NEOPIXEL,10, brightness=0.1)
pixels.fill(0)
from digitalio import *
from analogio import *
ir_tx = DigitalInOut(IR_TX)
ir_tx.direction = Direction.OUTPUT
proximity = AnalogIn(IR_PROXIMITY)
button5 = DigitalInOut(D5)
button4 = DigitalInOut(D4)
import array
import math
try:
from audiocore import RawSample
except ImportError:
from audioio import RawSample
try:
from audioio import AudioOut
except ImportError:
try:
from audiopwmio import PWMAudioOut as AudioOut
except ImportError:
pass # not always supported by every board!
FREQUENCY = 440 # 440 Hz middle 'A'
SAMPLERATE = 8000 # 8000 samples/second, recommended!
# Generate one period of sine wav.
length = SAMPLERATE // FREQUENCY
sine_wave = array.array("H", [0] * length)
for i in range(length):
sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15)
# Enable the speaker
speaker_enable = DigitalInOut(SPEAKER_ENABLE)
speaker_enable.direction = Direction.OUTPUT
speaker_enable.value = True
audio = AudioOut(SPEAKER)
sine_wave_sample = RawSample(sine_wave)
max_value = 42000
min_value = 37000
interval_value = 500
while True:
time.sleep(0.4)
pixels.fill(0)
print("max_value: %d" % max_value)
print("min_value: %d" % min_value)
print("interval_value: %d" % interval_value)
if button4.value == True:
max_value = 22300
min_value = 41200
interval_value = 100
if button5.value == True:
ir_tx.value = True
time.sleep(0.001)
ir_tx.value = False
proximity_value = proximity.value
print("proximity Level: %d" % proximity_value)
if max_value < proximity_value:
max_value = proximity_value
print("max_value: %d" % max_value)
if min_value > proximity_value:
min_value = proximity_value
print("min_value: %d" % min_value)
interval_value = (max_value - min_value) / 10
print("interval_value: %d" % interval_value)
elif interval_value > 1:
ir_tx.value = True
time.sleep(0.001)
ir_tx.value = False
proximity_value = proximity.value
print("proximity Level: %d" % proximity_value)
proximity_index = int((proximity_value - min_value) / interval_value)
print(proximity_index)
for p in range(10):
if p <= proximity_index:
pixels[p] = 0x000f0f
else:
pixels[p] = 0
if proximity_index >= 6:
audio.play(sine_wave_sample, loop=True)
time.sleep(0.4)
audio.stop()
本来是想用两个按键实现自适应范围的功能来着,但是发现会有一些数据毛刺形象范围的自动调整,时间太紧也没再优化,有机会再搞。
[localvideo]07d026cc6c27fab0d04b1c0e80c48892[/localvideo]
进阶任务(必做):制作不倒翁——展示不倒翁运动过程中的不同灯光效果
制作不倒翁,就需要使用三轴传感器LIS3DH,查看手册19页有三轴传感器介绍
从网上搜索资料,发现一个好网站:http://www.circuitpython.cn/projects/circuitplayground/en/latest/api.html
和一个好的库CP,前者有详细的CPY和小圆板的资料,后者则是为小圆板量身定制的几乎包含小圆板所有的库。
通过一下简单的测试程序,我们就可以查看X,Y,Z三个方向的偏转情况:
from adafruit_circuitplayground import cp
while True:
x, y, z = cp.acceleration
print(x, y, z)
摇动小圆板,可以观察X,Y,Z轴向数据的变化规律,其数值都是在-10到10之间变化,静止不动时接近于0,但有少量跳动的误差。
我们需要知道小圆板向哪个方向倾斜,其实倾斜方向与X,Y轴正好构成了一个直角三角形,运用我们中学学过的三角函数知识,X/Y就是角度的正切值,而atan(X/Y)便是角度值
t=(math.atan2(y,x)*180/math.pi+180)
t便是小圆板倾斜的角度值,修改程序并打印t值发现,其与与WS2812彩灯的编号方向存在90度的偏转;同时 10颗彩灯和USB口和电源接口正好接近于12等分排列,每个占据12分之一也就是30度,于是角度值计算可以更新为:
t=int((math.atan2(y,x)*180/math.pi+ 270+15)%360/30)
将10颗WS2812彩灯和USB接口、电池接口按照位置重新编组,编写三轴传感器控制WS2812在对应角度下点亮的部分,得到完整不倒翁程序如下:
#【Follow me第二季第1期】白菜虫虫
# 进阶任务(必做):制作不倒翁——展示不倒翁运动过程中的不同灯光效果
from adafruit_circuitplayground import cp
print(1)
# WS2812=('',cp.pixels[0],cp.pixels[1],cp.pixels[2],cp.pixels[3],cp.pixels[4],'',cp.pixels[5],cp.pixels[6],cp.pixels[7],cp.pixels[8],cp.pixels[9])
print(2)
import time
import math
while True:
x, y, z = cp.acceleration
if (int(y)==0)and(int(x)==0):
t=0 #消除开发板平放静止时传感器误差产生的错误角度值
else:
t=int((math.atan2(y,x)*180/math.pi+ 270+15)%360/30)
print(t)
if t==None or t==0 or t==6:
cp.pixels.fill(0)
else:
t=t-1
if t>5:
t=t-1
cp.pixels.fill(0)
cp.pixels[t]=0x0f000f
time.sleep(0.1)
PS:使用CP库和atan2()函数编写的程序真是简洁,比我开始不用CP库加上使用atan()函数然后根据XY正负情况再进行修正的那版程序行数少了一多半。
[localvideo]040914d774c2616f86687d0adc92b473[/localvideo]
创意任务(创意任务我选择的是创意任务三)
■ 创意任务三:水果钢琴——通过触摸水果弹奏音乐,并配合灯光效果
搭配器件: Adafruit Circuit Playground Express、水果自备
创意任务三--1 触摸钢琴
查看指南第20页,有触摸IO功能介绍
打开指南160页,有touchio的例程,可以复制例程运行测试。
import time
import board
import touchio
touch_A1 = touchio.TouchIn(board.A1)
touch_A2 = touchio.TouchIn(board.A2)
touch_A3 = touchio.TouchIn(board.A3)
touch_A4 = touchio.TouchIn(board.A4)
touch_A5 = touchio.TouchIn(board.A5)
touch_A6 = touchio.TouchIn(board.A6)
touch_TX = touchio.TouchIn(board.TX)
while True:
if touch_A1.value:
print("A1 touched!")
if touch_A2.value:
print("A2 touched!")
if touch_A3.value:
print("A3 touched!")
if touch_A4.value:
print("A4 touched!")
if touch_A5.value:
print("A5 touched!")
if touch_A6.value:
print("A6 touched!")
if touch_TX.value:
print("TX touched!")
time.sleep(0.01)
通过观察例程,我们可以了解touchio库的使用方式。
使用CP库可以更好更精炼的使用touchio,同时CP库也包含了PIXELS和TONE,真是一库在手,小圆板不发愁。
①首先还是引用所需的库:
import time
from adafruit_circuitplayground import cp
使用了CP库之后真心简洁,就CP和TIME两个齐活。
②然后是从网上扒来的音调频率对照数组
tones=(0,392,440,494,523,587,659,698,784)
不要问我tones[0]为啥是0,问就是因为开始的时候不仔细看手册,以为A0也可以触摸,结果写完程序验证发现不行,然后就也懒得该回去了,直接赋0算了。
③下面以A1触摸来进行介绍每个触摸按键的程序。
1、判断A1是否被触摸
if cp.touch_A1:
2、当A1被触摸时蜂鸣器播放dao的音,同时与A1临近的两个WS2812亮起,因为触摸IO和WS2812的位置对应不好,所以亮起的都是临近的彩灯。
cp.start_tone(tones[1])
cp.pixels[6]=0x0f000f
cp.pixels[7]=0x0f000f
print("A1 touched!")
3、同理处理其他触摸IO被触摸时的逻辑。
elif cp.touch_A2:
cp.start_tone(tones[2])
cp.pixels[7]=0x0f000f
cp.pixels[8]=0x0f000f
print("A2 touched!")
elif cp.touch_A3:
cp.start_tone(tones[3])
cp.pixels[8]=0x0f000f
cp.pixels[9]=0x0f000f
print("A3 touched!")
elif cp.touch_A4:
cp.start_tone(tones[4])
cp.pixels[0]=0x0f000f
cp.pixels[1]=0x0f000f
print("A4 touched!")
elif cp.touch_A5:
cp.start_tone(tones[5])
cp.pixels[1]=0x0f000f
cp.pixels[2]=0x0f000f
print("A5 touched!")
elif cp.touch_A6:
cp.start_tone(tones[6])
cp.pixels[2]=0x0f000f
cp.pixels[3]=0x0f000f
print("A6 touched!")
elif cp.touch_TX:
cp.start_tone(tones[7])
cp.pixels[3]=0x0f000f
cp.pixels[4]=0x0f000f
print("A7 touched!")
4、当所有IO都没有被触摸时,关闭蜂鸣器,所有彩灯熄灭,延时0.1秒开始下一次检测。
else:
cp.stop_tone()
cp.pixels.fill(0)
time.sleep(0.1)
完整程序如下:
#【Follow me第二季第1期】白菜虫虫
# 创意任务三:水果钢琴——通过触摸水果弹奏音乐,并配合灯光效果
import time
from adafruit_circuitplayground import cp
tones=(0,392,440,494,523,587,659,698,784)
cp.pixels.fill(0)
while True:
if cp.touch_A1:
cp.start_tone(tones[1])
cp.pixels[6]=0x0f000f
cp.pixels[7]=0x0f000f
print("A1 touched!")
elif cp.touch_A2:
cp.start_tone(tones[2])
cp.pixels[7]=0x0f000f
cp.pixels[8]=0x0f000f
print("A2 touched!")
elif cp.touch_A3:
cp.start_tone(tones[3])
cp.pixels[8]=0x0f000f
cp.pixels[9]=0x0f000f
print("A3 touched!")
elif cp.touch_A4:
cp.start_tone(tones[4])
cp.pixels[0]=0x0f000f
cp.pixels[1]=0x0f000f
print("A4 touched!")
elif cp.touch_A5:
cp.start_tone(tones[5])
cp.pixels[1]=0x0f000f
cp.pixels[2]=0x0f000f
print("A5 touched!")
elif cp.touch_A6:
cp.start_tone(tones[6])
cp.pixels[2]=0x0f000f
cp.pixels[3]=0x0f000f
print("A6 touched!")
elif cp.touch_TX:
cp.start_tone(tones[7])
cp.pixels[3]=0x0f000f
cp.pixels[4]=0x0f000f
print("A7 touched!")
else:
cp.stop_tone()
cp.pixels.fill(0)
time.sleep(0.1)
[localvideo]d32142352f6e07518dc38fa92050e162[/localvideo]
创意任务三--2 陈皮水果钢琴
其实吧本来做完触摸钢琴就想着结束来着,但是家里有小朋友吧,就想着真让他们试试水果钢琴。
在我的小仓库里面翻出来鳄鱼夹接上,运行程序傻眼了,直接不用触摸就开始响了,取下鳄鱼夹就不响,试了试用镊子搭上触摸IO也是一样响。
尝试了CP库的touch和手册例程的touchio库都是这样(猜测这俩是一样的),没办法就只能从最基础的地方下手了。触摸这东西猜一下原理应该是通过模拟值来实现的,先用analogio 库读取A1的值并循环显示。
触摸时数值如下:
而不触摸时数值如下:
观察可知,不触摸的时候,数值是类似随机数的波动(物理随机数,真随机)。而触摸时,数值会在0和65535两个数之间来回波动,于是我们就可以自己写一个触摸逻辑:
A_1 = analogio.AnalogIn(A1)
while True:
if A_1.value==0 or A_1.value==65535:
cp.start_tone(tones[1])
cp.pixels[6]=0x0f000f
cp.pixels[7]=0x0f000f
print("A1 touched!")
同样的逻辑完成整个程序的修改,完成程序如下:
import analogio
from board import *
import time
from adafruit_circuitplayground import cp
tones=(0,392,440,494,523,587,659,698,784)
A_1 = analogio.AnalogIn(A1)
A_2 = analogio.AnalogIn(A2)
A_3 = analogio.AnalogIn(A3)
A_4 = analogio.AnalogIn(A4)
A_5 = analogio.AnalogIn(A5)
A_6 = analogio.AnalogIn(A6)
A_7 = analogio.AnalogIn(TX)
while True:
if A_1.value==0 or A_1.value==65535:
cp.start_tone(tones[1])
cp.pixels[6]=0x0f000f
cp.pixels[7]=0x0f000f
print("A1 touched!")
elif A_2.value==0 or A_2.value==65535:
cp.start_tone(tones[2])
cp.pixels[7]=0x0f000f
cp.pixels[8]=0x0f000f
print("A2 touched!")
elif A_3.value==0 or A_3.value==65535:
cp.start_tone(tones[3])
cp.pixels[8]=0x0f000f
cp.pixels[9]=0x0f000f
print("A3 touched!")
elif A_4.value==0 or A_4.value==65535:
cp.start_tone(tones[4])
cp.pixels[0]=0x0f000f
cp.pixels[1]=0x0f000f
print("A4 touched!")
elif A_5.value==0 or A_5.value==65535:
cp.start_tone(tones[5])
cp.pixels[1]=0x0f000f
cp.pixels[2]=0x0f000f
print("A5 touched!")
elif A_6.value==0 or A_6.value==65535:
cp.start_tone(tones[6])
cp.pixels[2]=0x0f000f
cp.pixels[3]=0x0f000f
print("A6 touched!")
elif A_7.value==0 or A_7.value==65535:
cp.start_tone(tones[7])
cp.pixels[3]=0x0f000f
cp.pixels[4]=0x0f000f
print("A7 touched!")
else:
cp.stop_tone()
cp.pixels.fill(0)
print("null")
time.sleep(0.2)
接好鳄鱼夹测试,可以正常演奏。
但是手头上没有水果,只好从水杯里扒拉出几片陈皮擦干顶一下,没想到竟然也能演奏。
于是乎,陈皮钢琴闪亮诞生。
[localvideo]8b983a2972e36658d5df54dba6bae6f6[/localvideo]
心得体会
总体来说这是一次很快乐的活动,难度不是很高,以我这种老菜鸟的水平也没有遇到什么困难。小圆板硬件设计的很出色,集成了很多功能还保持了合适的体积。circuitPython使用起来也非常的方便,用一个大佬兄弟的话来说就是已经把饭喂到了你的嘴里。这次的软硬件非常适合新手入门和小朋友学编程使用。
通过这次活动我进一步的熟悉了WS2812彩色LED、音乐播放的操作,学习了光线传感器、三轴运动传感器、触摸按键等功能的使用。通过这次的活动,我加深了对各种硬件的了解,增长了自己的编程技巧,同时也积累的调试的经验,可以说是收获满满。
以上就是我惨这这次follow me活动的学习总结,如有错漏欢迎各位大佬斧正,最后再次感谢主办方EEworld和得捷提供的这次学习提高的机会,谢谢各位的能看到这里。
- 2023-12-11
-
加入了学习《【得捷电子Follow me第3期】可以使用ESPNOW同步获取数据的家庭气象站》,观看 【得捷电子Follow me第3期】可以使用ESPNOW同步获取数据的家庭气象站
- 2023-11-29
-
回复了主题帖:
【得捷电子Follow me第3期】任务5:使用外部传感器
wangerxian 发表于 2023-11-29 17:14
micropython就是好,两条语句就能获取温度数据。
就是,而且不用编译,弄点对性能要求不高,不是很复杂的程序的时候特别舒服
- 2023-11-28
-
上传了资料:
【得捷电子Follow me第3期】可以使用ESPNOW同步获取数据的家庭气象站
-
发表了主题帖:
【得捷电子Follow me第3期】可以使用ESPNOW同步获取数据的家庭气象站
【得捷电子Follow me第3期】可以使用ESPNOW同步获取数据的家庭气象站
视频:
[localvideo]0f31ff01a05568b08763da6bd0f7835b[/localvideo]
[localvideo]63cad3663581e7c4055179323f5a3c04[/localvideo]
[localvideo]31a842ee93fe18d39be2b00abd125e8c[/localvideo]
[localvideo]2184f3ed1feb2933c917529666bca183[/localvideo]
[localvideo]0f9c31a9947a6a635542d83fad7736f6[/localvideo]
[localvideo]f4f982773449c2890aecdd9011b667fc[/localvideo]
[localvideo]0642e8dfca1bd9e49287c766360e92a7[/localvideo]
任务1:使用MicroPython系统(必做任务)
熟悉Seeed Studio XIAO ESP32C3开发板基本操作,安装esptool,并给开发板刷写MicroPython系统,完成入门程序的运行
搭配器件:Seeed Studio XIAO ESP32C3
操作过程:
1.安装最新的python。
这个就不细讲了,各位大佬都会,不会的兄弟们可以上网搜索一下。
2.安装esptool。
2.1方法一:这种方法是大佬都推荐的使用命令行的方式。
首先用管理员权限打开命令行,然后输入
复制
pip install esptool
命令安装。
这种方式我尝试了多次,死活没有成功。
2.2方法二:github下载安装包进行安装。
首先打开github网址:https://github.com/espressif/esptool
然后选择Code->Cownload ZIP,下载安装包。
将安装包解压到一个你喜欢的位置,路径上不要有中文,比如我就是解压到了桌面(不建议跟我学,然后文件夹名字我也改成了esptool),现在我的路径就是”C:\Users\HP\Desktop\esptool”。在这个目录下打开管理员权限的命令行(或者打开命令行之后切换到自己的文件夹),然后输入
复制
python setup.py install
回车进行安装。
3.烧录固件:
3.1下载固件:打开microPython官网,点击DOWNLOAD,选择SEEED,如果现在你发现有了XIAO C3的专用固件就下载他,还是没有的话就下载一个通用版的ESP32C3固件。
通用固件地址https://micropython.org/download/ESP32_GENERIC_C3/
3.2烧录microPython固件:
使用USB数据线连接SEEED XIAO C3到电脑,等待驱动安装完毕,查看串口号。
将下载bin固件放到esptool的文件夹中,还是打开命令行,按照网页说明输入
复制
esptool.py --chip esp32c3 --port com4 erase_flash
擦除flash,com4是你自己的XIAO C3的串口号。
等待擦除完毕,输入
复制
esptool.py --chip esp32c3 --port COM78 --baud 460800 write_flash -z 0x0 ESP32_GENERIC_C3-20231005-v1.21.0.bin
烧录MPY固件,com4同样是XIAO C3的串口号,esp32c3-20220117-v1.18.bin
是下载的固件的文件名。
3.3测试:
打开串口工具,选择XIAO C3的串口。按下XIAO C3的RST按钮,查看是否有microPython的提示字符,如果有的话输入help()进行测试,如果有提示文字回应,说明microPython环境搭建成功。
任务2:驱动扩展板上的OLED屏幕(必做任务)
使用扩展板上的OLED屏幕显示文字和图形
搭配器件:Seeed Studio XIAO ESP32C3、Seeed Studio Expansion Board Base for XIAO
操作过程:
1.安装microPython编辑软件。
我是使用的thoony软件,理由是文件的上传下载很方便。
下载地址:https://thonny.org/ (莫谈国事)
同样的,也可以使用
pip install esptool
命令进行安装。
打开thonny,在右下角选择python解释器,选择ESP32+自己的串口号的选项
在shell窗口看到类似如下显示,就说明连接成功了。
2.下载SSD1306驱动库。
microPython官方固件没有集成SSD1306的驱动,需要自己编写或者下载一个,编写就算了,咱是菜鸟没那个本事,所以我选择下载一个。打开活动界面的“XIAO ESP32C3 MicroPython库”(链接地址:https://github.com/IcingTomato/micropython_xiao_esp32c3)
依次选择driver->display->ssd1306.py
复制代码或者直接下载py文件。
文件网址:https://github.com/IcingTomato/micropython_xiao_esp32c3/blob/master/drivers/display/ssd1306.py
3.上传ssd1306驱动文件:
在文件窗口选择下载的ssd1306.py驱动文件,右键、上传到/。或者新建一个空白文件,将复制的ssd1306.py的文件内容粘贴进去,点击保存,选择保存到microPython设备,文件名自然是“ssd1306.py”。
4.连接好电路,新建文件并输入以下程序
复制
import ssd1306
from machine import SoftI2C,Pin,
# 设置IIC
i2c = SoftI2C(scl=Pin(7),sda=Pin(6),freq=100000)
# 设置根据活动给出的引脚图可知IIC的scl引脚为D5,也就是7脚
# 同样的IIC的sda引脚为D4,也就是6脚
# 初始化SSD1306显示屏,分辨率为128X64
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# 清除屏幕
oled.fill(0)
# 显示文字
oled.text("hello seeed", 0, 20)
oled.text("hello xiao C3", 0, 40)
oled.show()
点击运行按钮,如SSD1306有如下显示,说明本次任务圆满成功。
9a68256832d9731f7f53b6c1095da5f.jpg (377.18 KB, 下载次数: 0)
下载附件 保存到相册
前天 11:42 上传
任务3:控制蜂鸣器播放音乐(必做任务)
使用Seeed Studio XIAO ESP32C3控制蜂鸣器发出不同频率的声音,并播放一段音乐
搭配器件:Seeed Studio XIAO ESP32C3、Seeed Studio Expansion Board Base for XIAO
操作过程:
1.蜂鸣器播放音乐简单原理。
大家都知道,声音源于震动,SEEED的扩展板上集成了一颗压电蜂鸣器,可以把电信号转换成相应频率的震动。
2.确定引脚。
查看扩展板引脚图,得知蜂鸣器buzzer的引脚是A3,再结合XIAO C3的引脚图得知使用的引脚是GPIO5。
3.初始化PWM引脚。
引用PWM库,初始化频率为440hz。
复制
from machine import PWM,Pin
beep = PWM(Pin(5),freq=440,duty=500)
点击运行,我们就可以听到持续的蜂鸣器的响声。
4.播放音乐。
从网上寻找一个同年经典游戏超级玛丽的音乐,移植到我们的XIAO C3上面,废话不多说,直接贴代码。
复制
from machine import PWM,Pin
import time
import _thread
beep = PWM(Pin(5),freq=50000,duty=500)
#cdefgab
s2 = [50000,262 ,294, 330 ,349 ,392 ,220 ,247 ]
s3 = [50000,523,587,659,698,784,440,494]
s4 = [50000,1044, 1175 ,1318, 1397 ,1568 ,880 ,988]
def play(level,power = 1,deltatime = 200):
if power == 0:
beep.freq(s2[level])
elif power == 1:
beep.freq(s3[level])
elif power == 2:
beep.freq(s4[level])
time.sleep_ms(deltatime)
beep.freq(50000)
def plays(l):
for i in l:
if len(i) == 3:
play(i[0],i[1],i[2])
else:
play(i[0],i[1])
def test():
plays([(3,2),(3,2),(0,2),(3,2),(0,2),(1,2),(3,2),(0,2),(5,2),(0,2,500)])
plays([(1,2,600),(5,1,600),(3,1,600),(6,1,400),(7,1,400),(7,1),(6,1,400)])
plays([(5,1),(3,2,400),(5,2),(6,2,400),(4,2),(5,2,400),(3,2,400),(1,2),(2,2),(7,1)])
plays([(1,2,600),(5,1,600),(3,1,600),(6,1,400),(7,1,400),(7,1),(6,1,400)])
plays([(5,1),(3,2,400),(5,2),(6,2,400),(4,2),(5,2,400),(3,2,400),(1,2),(2,2),(7,1)])
_thread.start_new_thread(test,())
[localvideo]6199d51143bbbd03709d4bdb58fe7fbc[/localvideo]
任务4:连接WiFi网络(必做任务)
将Seeed Studio XIAO ESP32C3连接到WiFi网络,并访问互联网信息
搭配器件:Seeed Studio XIAO ESP32C3、Seeed Studio Expansion Board Base for XIAO、RF ANT 2.4GHZ/5.5GHZ PCB TRACE
操作过程:
1.简单的说明。
XIAO C3使用microPython连接wifi网络还是比较简单的,我们先来梳理一下步骤。
①引用network库。
②声明wifi工作方式,因为我们需要连接wifi,所以工作方式选择STA_IF模式。
③连接到wifi。
2.连接到WIFI。
输入以下代码,将SSID和password修改成你自己的wifi的名称和密码。
复制
import utime
import network
#引用库
ssid = "baicaichongchong" #设置你的WiFi名称
password = "12345678" #设置你的WiFi密码
station = network.WLAN(network.STA_IF)#设置工作方式
station.active(True)#打开XIAO C3无线网络
station.connect(ssid, password)#连接wifiwhile station.isconnected() == False:
pass
print("Connection successful")
print(station.ifconfig())
点击运行,如果得到类似下面的输出,说明已经成功将你的XIAO C3连接到了你的wifi。
简易网络时钟。
通过几个步骤,我们可以制作一个简单的网络时钟:
①连接WiFi网络使得XIAO C3可以连接到互联网。
②通过ntptime库连接网络授时服务器,获取网络事件并更新给扩展版板载的pcf8563 RTC芯片。
③读取时间并在SSD1306上进行显示。
复制
import utime
import network
from machine import RTC
import time
from machine import I2C
import ntptime
import pcf8563
import ssd1306
ssid = "bai'cai'chong'chong"
password = "12345678"
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
print("Connection successful")
print(station.ifconfig())
rtc = RTC()
ntptime.settime()
time.sleep(1)
print('sync success')
utime.localtime()
i2c = I2C(scl=7, sda=6)
r = pcf8563.PCF8563(i2c)
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
print('rtc time')
r.datetime()
print(r.datetime()[3])
time.sleep(1)
print('sync system to pcf8563')
r.write_now()
station.active(False)
while True:
nt = r.datetime()
oled.fill(0)
oled.text(f"{nt[0]}-{nt[1]}-{nt[2]}", 20, 20)
oled.text(f"{nt[4]}:{nt[5]}:{nt[6]}", 40, 40)
print(f"{nt[0]}-{nt[1]}-{nt[2]} {nt[4]}:{nt[5]} {nt[6]}")
#显示日期时间
oled.show()
time.sleep(1)
点击运行
[localvideo]4751853bffa8efdaa382c97e84a15db6[/localvideo]
任务5:使用外部传感器(必做任务)
连接环境光传感器或温湿度传感器,获取传感器的数值,并转换成真实的物理量
搭配器件: Seeed Studio XIAO ESP32C3、Seeed Studio Expansion Board Base for XIAO、 Grove - AHT20 I2C Industrial Grade Temperature and Humidity Sensor、Grove - Light Sensor v1.2
操作过程:
1.下载驱动文件。
通过help(‘modules’)命令查看,可以知道ESP32C3的标准microPython固件里面没有包含aht20的驱动文件,大家可以自行选择喜欢的aht20驱动文件,我是在github上搜索并下载了一个文件,地址如下:
https://github.com/targetblank/micropython_ahtx0
2.尝试获取温湿度。
同时,在这个GitHub界面也给出了一个例程,让我们复制并测试一下。
import utime
from machine import Pin, I2C
import ahtx0
# I2C for the Wemos D1 Mini with ESP8266
i2c = I2C(scl=Pin(7), sda=Pin(6))
# Create the sensor object using I2C
sensor = ahtx0.AHT10(i2c)
while True:
print("\nTemperature: %0.2f C" % sensor.temperature)
print("Humidity: %0.2f %%" % sensor.relative_humidity)
utime.sleep(5)
注意IIC引脚要和SSD1306一样替换成我们的XIAO C3的引脚。
将SEEED的aht20模块连接到扩展版上,点击运行程序,如果有类似下面的输出内容,则说明aht20模块驱动成功。
3.使用SSD1306显示温湿度。
下面我们对历程进行扩展,使用SSD1306来显示温湿度。
程序如下:
复制
import machine
import ssd1306
import utime
import ahtx0
from machine import SoftI2C,Pin,
i2c = SoftI2C(scl=Pin(7),sda=Pin(6),freq=100000)
Pin(4).value(0)
Pin(5).value(1)
# 初始化SSD1306显示屏
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
sensor = ahtx0.AHT10(i2c)
# 清除屏幕
while True:
oled.fill(0)
oled.text("Temperature:", 0, 10)
oled.text("{:.2f} C".format(sensor.temperature), 40, 20)
print("\nTemperature: %0.2f C" % sensor.temperature)
oled.text("Humidity: ", 0, 40)
oled.text("{:.2f} %".format(sensor.relative_humidity), 40, 50)
print("Humidity: %0.2f %%" % sensor.relative_humidity)
oled.show()
utime.sleep(2)
# 在屏幕上显示文本
点击运行,就可以同步在SSD1306屏幕显示温湿度了。
[localvideo]705adef6d3533802d3b67d84d8309216[/localvideo]
任务6:综合实践(选做,非必做)
自选任务:可以使用ESPNOW同步获取数据的家庭气象站
本次我想要实现的功能是简单的家庭气象站。
使用的硬件有XIAO C3 两个,相应的扩展板一个,aht20温湿度传感器一个。
首先利用XIAO C3驱动aht20读取当前环境温湿度,然后使用SSD1306进行显示,最后通过网络使用ESPNOW共享给其他的XIAO C3设备,这样就不用每次都跑到设备跟前去查看了。
具体就不讲了,直接上程序
气象站+发送端程序:
import utime
import network
from machine import RTC
import time
from machine import I2C
import ntptime
import pcf8563
import ssd1306
import ahtx0
import espnow
ssid = "baicaichongchong"
password = "12345678"
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
print("Connection successful")
print(station.ifconfig())
rtc = RTC()
ntptime.settime()
time.sleep(1)
print('sync success')
utime.localtime()
i2c = I2C(scl=7, sda=6)
r = pcf8563.PCF8563(i2c)
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
sensor = ahtx0.AHT10(i2c)
print('rtc time')
r.datetime()
print(r.datetime()[3])
time.sleep(1)
print('sync system to pcf8563')
r.write_now()
station.active(False)
time.sleep(1)
station.active(True)
e= espnow.ESPNow()
e.active(True)
peer1 = b'4\x85\x18\x06\xca\x18'
e.add_peer(peer1)
while True:
nt = r.datetime()
oled.fill(0)
oled.text(f"{nt[0]}-{nt[1]}-{nt[2]}", 4, 2)
oled.text(f"{nt[4]}:{nt[5]}:{nt[6]}", 50, 12)
e.send(peer1,f"{nt[0]}-{nt[1]}-{nt[2]} {nt[4]}:{nt[5]} {nt[6]}".encode())
print(f"{nt[0]}-{nt[1]}-{nt[2]} {nt[4]}:{nt[5]} {nt[6]}")
#显示日期时间
oled.text("Temperature:", 4, 23)
oled.text("{:.2f} C".format(sensor.temperature), 60, 33)
e.send(peer1,"\nTemperature: %0.2f C" % sensor.temperature)
print("\nTemperature: %0.2f C" % sensor.temperature)
#显示温度
oled.text("Humidity: ", 4, 44)
oled.text("{:.2f} %".format(sensor.relative_humidity), 60, 54)
e.send(peer1,"Humidity: %0.2f %%" % sensor.relative_humidity)
print("Humidity: %0.2f %%" % sensor.relative_humidity)
#显示湿度
oled.rect(0, 0, 128, 64, 1)
oled.rect(0, 21, 128, 21, 1)
# oled.hline(3, 20, 1, 124)
# oled.hline(3, 40, 1, 124)
oled.show()
time.sleep(1)
要记得把WIFI账号密码改成自己的,然后要获取一下接收端的MAC地址也在这里修改一下。
接收端程序:
import network
import espnow
from machine import Pin
sta = network.WLAN(network.STA_IF)
sta.active(True)
e = espnow.ESPNow()
e.active(True)
while True:
host, msg = e.recv()
if msg:
print(host,msg)
else:
time.sleep(0.1)
接收端的程序相比就简单很多了,有多余的屏幕的兄弟们可以在这个基础上添加上OLED显示,不会的同学翻看前面的任务。
心得体会
感谢电子工程世界和得捷举办的这次活动,这是第一次参加类似的活动,感觉收获颇丰。
通过本次活动,加深了对ESP32C3的了结,掌握了不少以前不知道的硬件细节。
学会了ssd1306,温湿度传感器,espnow等等新的新的硬件和功能。
深入学习了MPY的使用,感觉MPY真的很方便,能够很方便的调试程序,不像arduino那样修改一个参数也要等好久重新编译。
参加活动更好的一点感受就是,有了活动时限的要求,感觉可以很大程度上的消除惰性,更主动更积极的去学习。和我一样有拖延症又想学东西的兄弟们强烈建议也来参加eeworld的活动试试。
下次有合适的活动希望还能有机会参加。
最后,附上全部六个任务的代码,方便兄弟们测试。
-
回复了主题帖:
【得捷电子Follow me第3期】任务3:控制蜂鸣器播放音乐
suncat 发表于 2023-11-27 09:33
转换一个乐曲的话,有相关的转换软件吗?就是把乐曲转换为对应的和频率有关的数据。
替换相应的list就行,频率是跟音乐音符对应的,不用替换