- 2024-10-31
-
发表了主题帖:
【2024 DigiKey创意大赛】AI赋能的智能家居系统
本帖最后由 夷则玖 于 2024-10-31 23:57 编辑
【项目背景与概述】
本项目利用乐鑫 ESP32-C6-DEVKITC-1-N8 开发板和矽递麦克风拓展版(MSM261S4030H0 麦克风 音频 Sipeed MAix 平台评估扩展板),打造一个智能家居控制系统,通过先进的传感技术实现对家庭环境的智能化管理和控制。该系统将集成多种传感器和技术,以实现对家居设备和环境的智能监测与控制。加入 Raspberry Pi 5,实现智能家居终端的部署(例如 HomeAsistant),并使用 EMQX,将绝大多数电器联网以供控制。
【视频链接】
视频
【系统功能框图】
通过Mqtt话题的订阅与发布,实现了家居的互联互通。
树莓派5作为Mqtt服务器和Socket服务器,其他设备均通过这两个协议与树莓派通信
【项目实现的功能】
86 面板控制家居
AI赋能的语音对话问答
语音控制智能家居
自动控制家居设备
基于MQTT的家居互联互通
其中前三个功能演示详见下面的视频,自动控制家居设备在视频中没有展示,以代码形式展示。
AI功能的实现大致如图:
具体实现详情见代码:
【可下载的代码】
代码
【分享链接】
https://bbs.eeworld.com.cn/thread-1295322-1-1.html
https://bbs.eeworld.com.cn/thread-1291489-1-1.html
-
上传了资料:
2024 DigiKey创意大赛代码
- 2024-10-06
-
发表了主题帖:
【Follow me第二季第2期】任务提交帖
一 、3-5分钟短视频
视频连接:Follow me第二季第2期视频
二、任务实现详情
项目简介:Follow me活动是DigiKey联合EEWorld发起的大型开发板体验活动,每期技术大咖推荐可玩性与可学性较强的开发板/仪器套件,带着大家实际操作,参与者完成任务即返京东卡。本季共四期活动,本次活动为第2期。
全部物料清单:Arduino UNO R4 WiFi:
Adafruit 8-Channel PWM:
DFRobot analog lightsensor:
各任务实现详情:
入门任务(必做):搭建环境并开启第一步Blink / 串口打印Hello EEWorld!搭配器件: Arduino UNO R4 WiFi
环境搭建十分简单:1、安装好Arduino IDE;2、安装板包;3、连接开发板选择端口即可,详细操作参见上面视频,也可参考官方文档。
Blink程序十分简单,只需要这几行代码:
void setup() {
// 初始化数字引脚 LED_BUILTIN 作为输出
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // 打开LED
delay(1000); // 延时一秒
digitalWrite(LED_BUILTIN, LOW); // 关闭LED
delay(1000); // 延时一秒
}
软件流程图:
效果:
串口输出程序代码:
int times = 1;
void setup() {
// 初始化串口
Serial.begin(9600);
}
void loop() {
// 串口输出
Serial.print(times);
Serial.println(": Hello EEWorld!");
// 计次自增
times ++;
// 延时1秒
delay(1000);
}
软件流程图:
效果:
基础任务(必做):驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线:搭配器件: Arduino UNO R4 WiFi
驱动12x8点阵LED可以使用内置的示例:
#include "Arduino_LED_Matrix.h"
#include "animation.h"
ArduinoLEDMatrix matrix;
void setup() {
Serial.begin(115200);
matrix.loadSequence(animation);
matrix.begin();
matrix.play(true);
}
void loop() {
delay(500);
Serial.println(millis());
}
软件流程图:
效果:
用DAC生成正弦波:
#include "analogWave.h"
analogWave wave(DAC);
int freq = 10;
void setup() {
Serial.begin(115200);
wave.sine(freq);
}
void loop() {
freq = 5000;
Serial.println("Frequent is now " + String(freq) + " Hz");
delay(1000);
wave.freq(freq);
}
程序下载后,可以用示波器看到波形:
也可以用ADC采集并且打印数据到串口,看到正弦波:
#include "analogWave.h"
analogWave wave(DAC);
int freq = 10;
void setup() {
Serial.begin(115200);
wave.sine(freq);
}
void loop() {
// 用ADC采集并且打印数据到串口
freq = 25;
int sensorValue = analogRead(A0);
// 将模拟值转换为电压值(0到5V)
float voltage = sensorValue * (5.0 / 1023.0);
// Print the updated frequency to the serial monitor
Serial.println("voltage is now " + String(voltage) + " v");
wave.freq(freq);
}
用OPAMP放大DAC信号:
#include <OPAMP.h>
void setup () {
Serial.begin(9600);
delay(2000); // serial monitor delay
// activate OPAMP, default channel 0
// Plus: Analog A1
// Minus: Analog A2
// Output: Analog A3
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(10); // do nothing
}
这样就开启了运放,可以当成一个普通的运放使用,视频中可以看到R1阻值为1165Ω,R2阻值为3718欧姆,放大倍数为1.313,实际将3.3v的信号放大为了4.27v,符合预期。
进阶任务(必做):通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant):搭配器件: Arduino UNO R4 WiFi
智能家居平台HA我使用的是自己在树莓派搭建的,具体搭建流程可以参考这篇帖子,当然用docker可能更为方便,docker部署我没有尝试,可以参考网友的。
代码如下:
#include "Arduino_LED_Matrix.h" //Include the LED_Matrix library
#include "animation.h" //Include animation.h header file
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include "mqtt_config.h"
ArduinoLEDMatrix matrix;
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = BROKER;
int port = 1883;
const char pub_topic[] = PUB_TOPIC;
const char sub_topic[] = SUB_TOPIC;
const long interval = 1000;
unsigned long previousMillis = 0;
int count = 0;
void setup() {
//配置led灯模式为输出
pinMode(LED_BUILTIN, OUTPUT);
//初始化串口,并等待串口打开
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
matrix.loadSequence(animation);
matrix.begin();
// turn on autoscroll to avoid calling next() to show the next frame; the paramenter is in milliseconds
// matrix.autoscroll(300);
matrix.play(true);
// 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("username", "password");
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
delay(3000);
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();
Serial.print("Subscribing to topic: ");
Serial.println(sub_topic);
Serial.println();
// subscribe to a topic
mqttClient.subscribe(sub_topic);
// topics can be unsubscribed using:
// mqttClient.unsubscribe(topic);
pinMode(LED_BUILTIN, OUTPUT);
Serial.print("Waiting for messages on topic: ");
Serial.println(sub_topic);
Serial.println();
//初始化成功提示
Serial.print("INIT success!");
}
void loop() {
int messageSize = mqttClient.parseMessage();
if (messageSize) {
// use the Stream interface to print the contents
while (mqttClient.available()) {
char msg = (char)mqttClient.read();
// Serial.print(msg);
// Serial.println();
led_switch(&msg);
}
//串口输出
Serial.print("Hello EEWorld!"); //串口打印Hello EEWorld
Serial.println(); //换行
}
}
还需要配置 mqtt_config.h文件:
#define SECRET_SSID "wifi名称"
#define SECRET_PASS "WiFi密码"
#define BROKER "192.168.3.49"
#define PUB_TOPIC "arduino/publish"
#define SUB_TOPIC "arduino/publish"
void led_switch(const char *data) {
if (*data == '1') {
Serial.println("Turn the Arduino LED on");
digitalWrite(LED_BUILTIN, HIGH); } // turn the LED on (HIGH is the voltage level)
else if (*data == '0') {
Serial.println("Turn the Arduino LED off");
digitalWrite(LED_BUILTIN, LOW ); } // turn the LED off (LOW is the voltage level)
}
还需要在HA的configuration.yaml文件中添加这段配置,添加教程:
mqtt:
switch:
unique_id: led_1 #设备ID
name: "arduino_led" #设备名称
state_topic: "arduino/publish" #订阅端口
command_topic: "arduino/publish" #同上
payload_on: "1" #开灯的指令
payload_off: "0" #关灯的指令
流程图:
扩展任务(必做):通过外部环境光传感器,上传光照度到HA,通过HA面板显示数据,并控制电机行为:搭配器件: Arduino UNO R4 WiFi、Adafruit 8-Channel PWM、DFRobot analog lightsensor:
首先是将传感器添加到HA面板:
在HA的configuration.yaml文件中添加这段配置:
sensor:
unique_id: arduino_sensor_1 #设备ID
name: "light_sensor" #设备名称
state_topic: "homeassistant/sensor/light" #订阅端口
unit_of_measurement: "%"
value_template: "{{value_json.light}}"
刷新后就可以在HA面板看到传感器:
然后完成Adafruit 8-Channel PWM的代码,可以用这个控制舵机转动:
import time
from adafruit_servokit import ServoKit
kit = ServoKit(channels=8)
kit.servo[0].angle = 180
kit.continuous_servo[1].throttle = 1
time.sleep(1)
kit.continuous_servo[1].throttle = -1
time.sleep(1)
kit.servo[0].angle = 0
kit.continuous_servo[1].throttle = 0
最后是完成Arduino UNO R4 WiF的代码:
#include <ArduinoJson.h>
#include <ArduinoJson.hpp>
#include "Arduino_LED_Matrix.h" //Include the LED_Matrix library
#include "animation.h" //Include animation.h header file
#include <ArduinoMqttClient.h>
#include <WiFiS3.h>
#include "mqtt_config.h"
ArduinoLEDMatrix matrix;
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = BROKER;
int port = 1883;
const char pub_topic[] = PUB_TOPIC;
const char sub_topic[] = SUB_TOPIC;
const long interval = 1000;
unsigned long previousMillis = 0;
int count = 0;
void setup() {
//配置led灯模式为输出
pinMode(LED_BUILTIN, OUTPUT);
//初始化串口,并等待串口打开
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
matrix.loadSequence(animation);
matrix.begin();
// turn on autoscroll to avoid calling next() to show the next frame; the paramenter is in milliseconds
// matrix.autoscroll(300);
matrix.play(true);
// 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);
delay(3000);
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();
Serial.print("Subscribing to topic: ");
Serial.println(sub_topic);
Serial.println();
// subscribe to a topic
mqttClient.subscribe(sub_topic);
// topics can be unsubscribed using:
// mqttClient.unsubscribe(topic);
pinMode(LED_BUILTIN, OUTPUT);
Serial.print("Waiting for messages on topic: ");
Serial.println(sub_topic);
Serial.println();
//初始化成功提示
Serial.print("INIT success!");
}
void loop() {
int lightsensor = analogRead(0);
int messageSize = mqttClient.parseMessage();
if (messageSize) {
// use the Stream interface to print the contents
while (mqttClient.available()) {
char msg = (char)mqttClient.read();
// Serial.print(msg);
// Serial.println();
led_switch(&msg);
}
//串口输出
}
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
update_sensor(lightsensor);
Serial.println("updated");
count++;
}
}
void servo(int msg) {
mqttClient.beginMessage("None/f/servo");
mqttClient.print(msg);
mqttClient.print("\0");
mqttClient.endMessage();
}
void update_sensor(int value){
StaticJsonDocument<200> doc;
int a = value*100/1024;
open_window(a);
doc["light"] = a;
String payload;
serializeJson(doc, payload);
mqttClient.beginMessage("homeassistant/sensor/light");
mqttClient.print(payload.c_str());
mqttClient.print("\0");
mqttClient.endMessage();
}
void open_window(int value){
if (value<25){
servo(1);
}
else if (value<50 && value>=25){
servo(2);
}
else if (value<75 && value>=50){
servo(3);
}
else if (value<101 && value>=75){
servo(4);
};
}
流程图:
舵机行为:
4)对本活动的心得体会
完整地使用Arduino开发出了一些东西,收获很多。不得不说Arduino真是宇宙级IDE,实在是太方便啦。
三、可编译下载的代码
代码:代码
-
上传了资料:
FollowMe第二季第二期代码
- 2024-10-02
-
发表了主题帖:
【2024 DigiKey 创意大赛】进度分享--HA和MQTT搭建&ESP32-C6接入HA控制RGB
本帖最后由 夷则玖 于 2024-10-2 15:39 编辑
本次活动用到三个板卡,分别是 ESP32-C6 开发板 、树莓派 Raspberry Pi5 和 SiPEED 的6+1麦克风阵列,在之前的开箱帖简单介绍过,下面是板卡图片:
下面是目前的进度:
一、树莓派 Raspberry Pi5:
完成了Home Assistant的部署和MQTT服务器的搭建:
第一步:刷入Ubuntu 24.04
使用Raspberry Pi Imager按如图选择设备,系统和储存卡:
烧录镜像会格式化存储卡,点击“是”:
接下来会自动下载镜像并写入:
然后会校验文件:
这样的提示就是烧录成功了:
第二步:设置Ubuntu系统:
将刚刚烧录的存储卡插入树莓派中,接入5V5A的PD电源(建议),随后按照提示逐步完成系统初始设置,需要注意的是这里设置的密码不要忘记,后面会用到:
第三步:安装Home Assiatant:
我尝试过所有的Home Assiatant安装方式,下面这种是最简单的,适合初学者:
进入Ubuntu后电机左边栏的应用中心:
搜索“Home Assiatant”:
直接点击安装:
然后会提示输入刚才设置的密码,输入密码之后回车会自动安装:
安装完成后点击打开:
第四步:初始化设置Home Assiatant:
点击上图的“open”之后会弹出以下页面:
随后根据提示设置即可:
如果需要用手机控制的话,这个账号密码也得记好:
看到这个页面就是设置好了:
第五步:安装EMQX:
参考EMQX官方文档完成设置:
打开终端,输入以下命令:
//通过以下命令配置 EMQX Apt 源:
curl -s https://assets.emqx.com/scripts/install-emqx-deb.sh | sudo bash
//运行以下命令安装 EMQX:
sudo apt-get install emqx
//运行以下命令启动 EMQX:
sudo systemctl start emqx
如果提示没有crul或其他类似命令,直接
sudo apt-get insatll <param>
//param为所需要的包,如curl
第六步:验证MQTT:
需要先打开Home Assistant控制台,可以参考上面直接点击open,也可以打开浏览器进入https://localhost:8123:
然后点击左下角的设置(setting)然后在弹出界面中选择设备与服务:
点击右下角添加集成:
搜索mqtt并点击:
点击这个mqtt:
在第一栏中填入localhost,然后点击提交:
查看刚刚添加的集成:
点击配置:
分别在发送数据包主题和监听主题中填入相同的话题,如test,然后开始监听:
在发送数据包的有效载荷(payload)中随意填入信息,如hello mqtt,点击发送,在监听主体中显示了即为部署成功:
二、ESP32-C6-DevKitC-1 开发板:
使用Ardino IDE开发,效果视频:
[localvideo]a573eeb20dbdfaf0c1a93b991dfb91eb[/localvideo]
三、SiPEED 6+1麦克风阵列:
暂时没有大的进展,后面提交最终任务再分享吧。
- 2024-09-01
-
上传了资料:
Followme第二季第1期代码
-
发表了主题帖:
【得捷Follow me第二季第1期】任务提交+红外功能使用
第一部分:3-5分钟短视频
视频链接:视频
第二部分:任务实现详情
(1)任务/项目介绍
①项目简介
Follow me活动是DigiKey联合EEWorld发起的大型开发板体验活动,每期技术大咖推荐可玩性与可学性较强的开发板/仪器套件,带着大家实际操作,参与者完成任务即返京东卡。
活动旨在带着电子爱好者一起学习实用的电子技术知识,一起积攒DIY经验,一起变成更好的自己!
②物料清单
1.购买的物料:
Adafruit Circuit Playground Express(核心板)
JOY FEATHERWING (摇杆按键控制板)
NEOKEY FEATHERWING (机械按键控制板)
2.非购买的物料:
NEC码红外无线通信控制板
Adafruit ESP32-S3 TFT Feather开发板
③设计思路
用Adafruit ESP32-S3 TFT Feather开发板、 NEOKEY FEATHERWING、 JOY FEATHERWING 和 NEC码红外无线通信控制板 组成一个红外遥控器,可以实现远程控制本期FollowMe的开发板(板载红外收发管)。通过NEC协议实现两个开发板的通信。
(2)软件流程图
(3)各任务对应的主要代码片段、功能展示及图文说明(每个任务需要包含至少一张对应的实物图)
入门任务(必做):开发环境搭建,板载LED点亮
主要代码:
import time
import board
import digitalio
led = digitalio.DigitalInOut(board.D13)
led.switch_to_output()
buttonA = digitalio.DigitalInOut(board.BUTTON_A)
buttonA.switch_to_input(pull=digitalio.Pull.DOWN)
buttonB = digitalio.DigitalInOut(board.BUTTON_B)
buttonB.switch_to_input(pull=digitalio.Pull.DOWN)
while True:
if buttonA.value:
led.value = True
elif buttonB.value:
led.value = False
time.sleep(0.01)
改编自Adafruit官网,按下A键led打开,按下B键关闭
基础任务一(必做):控制板载炫彩LED,跑马灯点亮和颜色变换
import time
import board
from rainbowio import colorwheel
import neopixel
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.2, auto_write=False)
color_chase_demo = 1
flash_demo = 1
rainbow_demo = 1
rainbow_cycle_demo = 1
def color_chase(color, wait):
for i in range(10):
pixels[i] = color
time.sleep(wait)
pixels.show()
time.sleep(0.5)
def rainbow_cycle(wait):
for j in range(255):
for i in range(10):
rc_index = (i * 256 // 10) + j * 5
pixels[i] = colorwheel(rc_index & 255)
pixels.show()
time.sleep(wait)
def rainbow(wait):
for j in range(255):
for i in range(len(pixels)):
idx = int(i + j)
pixels[i] = colorwheel(idx & 255)
pixels.show()
time.sleep(wait)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
OFF = (0, 0, 0)
while True:
if color_chase_demo:
color_chase(RED, 0.1)
color_chase(YELLOW, 0.1)
color_chase(GREEN, 0.1)
color_chase(CYAN, 0.1)
color_chase(BLUE, 0.1)
color_chase(PURPLE, 0.1)
color_chase(OFF, 0.1)
if flash_demo:
pixels.fill(RED)
pixels.show()
time.sleep(1)
pixels.fill(GREEN)
pixels.show()
time.sleep(1)
pixels.fill(BLUE)
pixels.show()
time.sleep(1)
pixels.fill(WHITE)
pixels.show()
time.sleep(1)
if rainbow_cycle_demo:
rainbow_cycle(0.05)
if rainbow_demo:
rainbow(0.05)
实现四种灯光效果
基础任务二(必做):监测环境温度和光线,通过板载LED展示舒适程度
import time
import neopixel
import adafruit_thermistor
import board
thermistor = adafruit_thermistor.Thermistor(
board.TEMPERATURE, 10000, 10000, 25, 3950)
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.2, auto_write=False)
warn = False
de_warn = False
while True:
temp_c = thermistor.temperature
print("Temperature is: %f C " % (temp_c))
if temp_c > 30 and not warn:
warn = True
de_warn = False
if temp_c < 30 and not de_warn:
de_warn = True
warn = False
if warn:
pixels.fill((15,0,0))
pixels.show()
if de_warn :
pixels.fill((0,0,0))
pixels.show()
time.sleep(0.25)
代码中设置了温度界限为30度,超过则红灯亮,否则熄灭。视频中可以看到通过打火机升高温度,红灯亮起,移开火源,红灯熄灭。
基础任务三(必做):接近检测——设定安全距离并通过板载LED展示,检测到入侵时,发起声音报警
import board
import digitalio
import analogio
import time
import math
from adafruit_circuitplayground.express import cpx
ir_tx = digitalio.DigitalInOut(board.IR_TX)
ir_tx.direction = digitalio.Direction.OUTPUT
proximity = analogio.AnalogIn(board.IR_PROXIMITY)
def detect_invade_vel():
ir_tx.value = True
time.sleep(0.001)
ir_tx.value = False
proximity_value = proximity.value
print("proximity value: %d" % proximity_value)
max_value = 42000
min_value = 20000
invade_step = (max_value - min_value) / 11
invade_level = math.floor((proximity_value - min_value) / invade_step)
return invade_level
while True:
invade_level = detect_invade_vel()
if invade_level > 0:
for item in range(invade_level):
cpx.pixels[item] = (math.floor(1.5*invade_level),math.floor(15-1.5*invade_level),0)
cpx.play_tone(262, 0.55-0.05*invade_level)
cpx.pixels.fill((0, 0, 0))
time.sleep(0.05)
接近报警器,距离越近,颜色越红(由绿到红),亮灯数量越多,同时报警频率越高。
进阶任务(必做):制作不倒翁——展示不倒翁运动过程中的不同灯光效果
这个任务需要用到加速度传感器,为了实现不倒翁,我的设计是将原始加速度数值转换为极坐标,再根据极坐标的角度判断应该亮哪个灯,根据极坐标的ρ计算颜色(由绿到红),同时设置容差,防止在静止状态的频繁跳变。
#将笛卡尔坐标系向极坐标系转化
def Cartesian2Polar(cor = (0,0)):
r = math.sqrt(cor[0]*cor[0]+cor[1]*cor[1])
if r == 0:
return None,None
else:
if cor[0]<0:
theta = math.pi - math.asin(cor[1]/r)
else:
theta = math.asin(cor[1]/r)
if theta<0:
theta += 2*math.pi
return r,theta*6/math.pi
完整代码:
import math
import time
from adafruit_circuitplayground import cp
cp.pixels.auto_write = False
cp.pixels.brightness = 0.3
def Cartesian2Polar(cor = (0,0)):
r = math.sqrt(cor[0]*cor[0]+cor[1]*cor[1])
if r == 0:
return None,None
else:
if cor[0]<0:
theta = math.pi - math.asin(cor[1]/r)
else:
theta = math.asin(cor[1]/r)
if theta<0:
theta += 2*math.pi
return r,theta*6/math.pi
def neo_be_light(polar_msg, mode, tolerance = 2):
degree = 90/9.8*(polar_msg[0]-tolerance)
if degree>90:
degree = 90
l_light = math.floor(float(polar_msg[1]))
r_light = math.ceil(float(polar_msg[1]))
if mode == "multi":
if polar_msg[1] - l_light < 0.2:
belight = (l_light - 1,l_light,r_light)
elif r_light - polar_msg[1] > 0.2:
belight = (l_light,r_light,r_light + 1)
else:
belight = (l_light,r_light)
elif mode == "single":
belight = r_light if (l_light - float(polar_msg[1])) > (r_light - float(polar_msg[1])) else l_light
return degree,belight
#返回倾斜程度(角度制)和要点亮的灯的弧度值
def judge_neopixle(data, degree):
if data > -1 and data < 3 :
cp.pixels[data + 7] = (15-15/degree*90, 15/degree*90, 0)
elif data == 3:
pass
elif data >3 and data < 9:
cp.pixels[data - 4] = (15-15/degree*90, 15/degree*90, 0)
elif data == 9:
pass
elif data > 9 and data < 12:
cp.pixels[data - 5] = (15-15/degree*90, 15/degree*90, 0)
elif data == 12:
cp.pixels[7] = (15-15/degree*90, 15/degree*90, 0)
elif data == 13:
cp.pixels[6] = (15-15/degree*90, 15/degree*90, 0)
else:
print("data error")
def tumbler(mode = "multi", tolerance = 2): #opt: "multi", "single"
r,area = Cartesian2Polar(cp.acceleration)
if not(r == None and area == None):
if r < tolerance:
cp.pixels.fill((15, 15, 15))
else:
a,b=neo_be_light(Cartesian2Polar(cp.acceleration), mode, tolerance)
cp.pixels.fill((0, 0, 0))
if isinstance(b,int):
judge_neopixle(b, a)
else:
for item in b:
judge_neopixle(item, a)
cp.pixels.show()
time.sleep(0.1)
while True:
tumbler( "single", 1)
此外我还设置了两种模式:单灯光模式(”single“)和多灯光模式(”multi“),以及参数容差(tolerance),方便设置不倒翁效果
创意任务一:有创意的可穿戴装饰——可结合多种传感器和灯光效果展示
搭配器件: Adafruit Circuit Playground Express、挂饰、自制遥控器
本任务核心是使用红外传感器,其他代码基本已经在上面出现过,故只放红外传感器代码:
import pulseio
import board
import adafruit_irremote
pulsein = pulseio.PulseIn(board.IR_RX, maxlen=120, idle_state=True)
decoder = adafruit_irremote.GenericDecode()
while True:
pulses = decoder.read_pulses(pulsein)
try:
do_msg_neokey(decoder.decode_bits(pulses)[2])
except adafruit_irremote.IRNECRepeatException: # unusual short code!
print("NEC repeat!")
except adafruit_irremote.IRDecodeException as e: # failed to decode
print("Failed to decode: ", e.args)
效果:
(4)对本活动的心得体会
感谢EEworld和Digikey得捷电子提供的活动平台,使我在玩板子的同时学到了很多,例如管理python内存,因为在嵌入式平台,内存资源极为有限。完成任务的过程中,多次遇到Memory Error,最终查阅资料,重新了解python,了解circuitpython,最终解决问题,实现功能
建议这样的活动继续办下去,让更多的人入门电子工程师。
第三部分:可编译下载的代码
源代码:代码
-
加入了学习《得捷电子Follow me第3期》,观看 得捷电子Follow me第3期
- 2024-08-25
-
发表了主题帖:
【2024 DigiKey 创意大赛】物料开箱
DigiKey 创意大赛所需物料都已经收到,在此感谢DigiKey,感谢EEworld提供这么好的比赛平台供像我这样的电子爱好者交流学习!
我选择的是Seeed的六麦克风阵列可以实现声源定位以及语音识别,ESP32-C6开发板用于提供更快更稳定的连接(支持 2.4 GHz Wi-Fi 6、Bluetooth 5),以及树莓派Raspberry Pi5(采用运行频率为2.4GHz的64位四核Arm Cortex-A76处理器)在我的创意中将扮演“中枢”的角色,提供包括但不限于HomeAssistant、Mqtt、Ap接入点、模型解算等的服务,支持我完成本次大赛。
物料全家福:
放一张树莓派5的特写:
接下来就是好好比赛咯,争取在截止日期前完善好整个创意,加油!
- 2024-02-25
-
加入了学习《【得捷Follow me第4期】项目任务提交》,观看 视频
-
加入了学习《 【得捷电子Follow me第4期】》,观看 【得捷Follow me第4期】简易FTP文件服务器
- 2024-02-24
-
加入了学习《 【得捷电子Follow me第4期】》,观看 【得捷Follow me第4期】综合实践之智能家居控制器
- 2024-02-23
-
加入了学习《直播回放: FollowMe 4 W5500-EVB-Pico 使用入门》,观看 W5500-EVB-Pico 使用入门
- 2024-01-30
-
加入了学习《得捷电子Follow me第2期》,观看 得捷电子Follow me第2期 活动视频
- 2023-12-17
-
上传了资料:
得捷电子 Follow me 第3期任务提交代码
-
发表了主题帖:
【得捷Follow me第3期】+ 自定分任务(Ros X ESP32-C3)
本帖最后由 夷则玖 于 2023-12-17 23:36 编辑
第一部分:
视频地址:视频
第二部分:
任务1:使用MicroPython系统
任务介绍:使用Thonny ide可以极其方便地安装MicroPython系统、安装官方库和编辑代码等等
功能展示:
安装好Thonny之后,打开Thonny,用c to usb线连接Seeed XIAO Esp32-C3和电脑
然后在Thonny右下角选择Configure interpreter
然后选择"MicroPython(Esp32-C3)" >>> "USB JTAG/serial debug..." >>>"安装或更新MicroPython(Esptool)"
接着在弹出窗口选择"USB JTAG/serial debug..." >>> "Esp32-C3" >>>"eapressif · Esp32-C3">>>选择版本
最后单击“安装”,这样就安装好MicroPython了。
说明:若下载缓慢,由于众所周知的原因,需科学上网。
心得建议:Micro是个非常易于使用的语言,有丰富的配套资源以及库,在以后的开发中利用其可以省时省力
任务2:驱动扩展板上的OLED屏幕
任务3:控制蜂鸣器播放音乐
任务介绍:这里将任务二三合并一起完成会更有趣。驱动屏幕显示文字和图形同时播放音乐。“Little star”是一首旋律极为简单的歌适合用蜂鸣器播放,同时用屏幕显示歌词并闪烁星星
主要代码:
导入库,random用于随机星星的尺寸以及位置,math用于计算星星关键点的坐标,ssd1306用于驱动屏幕,machine需要在micropython环境导入。
import machine
import time
from machine import Pin, SoftI2C
import ssd1306
import math
import random
屏幕参数设置
#Pin assignment
i2c = SoftI2C(scl=Pin(7), sda=Pin(6)) # Adjust the Pin numbers based on your connections
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
oled.fill(0) # Clear the screen
蜂鸣器参数设置,从官方例程中可以获得这些音符对应的频率
# Buzzer settings
buzzer_pin = machine.Pin(5, machine.Pin.OUT)
buzzer = machine.PWM(buzzer_pin)
#buzzer.freq(1047)
# Defining frequency of each music note
NOTE_C4 = 262
NOTE_D4 = 294
NOTE_E4 = 330
NOTE_F4 = 349
NOTE_G4 = 392
NOTE_A4 = 440
NOTE_B4 = 494
NOTE_C5 = 523
NOTE_D5 = 587
NOTE_E5 = 659
NOTE_F5 = 698
NOTE_G5 = 784
NOTE_A5 = 880
NOTE_B5 = 988
编辑小星星的音符以及时值
# Music notes of the song, 0 is a rest/pulse
notes = [
NOTE_C5,NOTE_C5,NOTE_G5,NOTE_G5,NOTE_A5,NOTE_A5,NOTE_G5,0,
NOTE_F5,NOTE_F5,NOTE_E5,NOTE_E5,NOTE_D5,NOTE_D5,NOTE_C5,0,
NOTE_G5,NOTE_G5,NOTE_F5,NOTE_F5,NOTE_E5,NOTE_E5,NOTE_D5,0,
NOTE_G5,NOTE_G5,NOTE_F5,NOTE_F5,NOTE_E5,NOTE_E5,NOTE_D5,0,
NOTE_C5,NOTE_C5,NOTE_G5,NOTE_G5,NOTE_A5,NOTE_A5,NOTE_G5,0,
NOTE_F5,NOTE_F5,NOTE_E5,NOTE_E5,NOTE_D5,NOTE_D5,NOTE_C5,0
]
# Durations (in ms) of each music note of the song
# Quarter Note is 250 ms when songSpeed = 1.0
durations = [
250,250,250,250,250,250,500,0,
250,250,250,250,250,250,500,0,
250,250,250,250,250,250,500,0,
250,250,250,250,250,250,500,0,
250,250,250,250,250,250,500,0,
250,250,250,250,250,250,500,0
]
编辑“Little Star”台词
lyrics = [
"Twinkle","twinkle","little","star",
"how i","wonder","what you","are",
"up a","-bove the","world so","high",
"like a","diamond","in the","sky",
"Twinkle","twinkle","little","star",
"how i","wonder","what you","are"
]
定义画星星函数
def draw_star(x,y,size):
angle = 72
outer_points = []
inner_points = []
for i in range(5):
outer_points.append((x + size * math.cos(math.radians(i * angle)), y + size * math.sin(math.radians(i * angle))))
inner_points.append((x + size / 2 * math.cos(math.radians(i * angle + angle / 2)), y + size / 2 * math.sin(math.radians(i * angle + angle / 2))))
for i in range(5):
oled.line(math.floor(outer_points[i][0]), math.floor(outer_points[i][1]), math.floor(inner_points[i][0]), math.floor(inner_points[i][1]),1)
oled.line(math.floor(inner_points[i][0]), math.floor(inner_points[i][1]), math.floor(outer_points[(i+1)%5][0]), math.floor(outer_points[(i+1)%5][1]),1)
定义播放歌曲函数
def play_song():
total_notes = len(notes)
for i in range(total_notes):
current_note = notes[i]
wait = durations[i]*2
lyric = lyrics[math.floor(i/2)]
oled.fill(0) # Clear the screen
oled.text(lyric, 20, 30)
if current_note != 0:
buzzer.freq(current_note) # Set frequency of the note
buzzer.duty(10) # Set duty cycle for sound
else:
buzzer.duty(0) # Turn off the sound
draw_star(random.randint(0,127),random.randint(0,63),random.randint(10,20))
oled.show() # Show the text
time.sleep_ms(wait-100)
buzzer.duty(0) # Turn off the sound
time.sleep_ms(100)
最后是主函数
while True:
# Play the song
play_song()
功能展示:
说明:使用这个程序实现了一边听小星星,一边看星星闪烁,还能看小星星英文歌词学英语
心得建议:要是屏幕是彩屏再大一些就好了
任务4:连接WiFi网络
任务5:使用外部传感器
任务介绍:将任务四五合并为一个任务完成,能获取室内外温度和湿度,更完善了桌面小助手
主要代码:
导入必要的库,便于从api获取信息
import time
from machine import Pin, SoftI2C
import ssd1306
import math
import ahtx0
import network
import urequests
import ujson
然后是相关配置,根据官方例程修改,然后获取一个天气api
# ESP8266 Pin assignment
i2c = SoftI2C(scl=Pin(7), sda=Pin(6)) # Adjust the Pin numbers based on your connections
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
sensor = ahtx0.AHT10(i2c)
station = network.WLAN(network.STA_IF)
station.active(True)
# Network settings
wifi_ssid = "你的WiFi名称"
wifi_password = "WiFi密码"
url = "https://api.seniverse.com/v3/weather/now.json?key=你的key&location=changsha&language=en&unit=c"
print("Scanning for WiFi networks, please wait...")
authmodes = ['Open', 'WEP', 'WPA-PSK' 'WPA2-PSK4', 'WPA/WPA2-PSK']
for (ssid, bssid, channel, RSSI, authmode, hidden) in station.scan():
print("* {:s}".format(ssid))
print(" - Channel: {}".format(channel))
print(" - RSSI: {}".format(RSSI))
print(" - BSSID: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}".format(*bssid))
print()
# Continually try to connect to WiFi access point
while not station.isconnected():
# Try to connect to WiFi access point
print("Connecting...")
station.connect(wifi_ssid, wifi_password)
time.sleep(10)
# Display connection details
print("Connected!")
print("My IP Address:", station.ifconfig()[0])
最后是主函数,隔十秒重新获取室外温度
while True:
# Perform HTTP GET request on a non-SSL web
response = urequests.get(url)
# Check if the request was successful
if response.status_code == 200:
# Parse the JSON response
data = ujson.loads(response.text)
temp = data["results"][0]["now"]["temperature"]
# Clear the OLED display
oled.fill(0)
# Display the New York date and time on separate lines
oled.text("R T :%0.2fC" % sensor.temperature, 0, 10)
oled.text("A T : %0.2fC" % float(temp), 0, 20)
oled.text("Humi:%0.2f%%" % sensor.relative_humidity, 0, 30)
oled.text("City:ChangSha" , 0, 40)
oled.show() # Show the text
else:
oled.text("Failed to get the time for Changsha",0,0)
# Update the display
oled.show()
time.sleep(10)
功能展示:
心得建议:第一次玩api,获取信息并显示出来,太酷啦
任务6:将esp32作为一个ros节点,控制ros外设
任务介绍:近期正好在研究ros,再加上esp32有的WiFi功能,于是想用esp作为一个jros节点,在主机端通过wifi控制esp32的外设。目前绝大部分机器人是无线连接,如果想要控制mcu就要通过无线的方式。可应用在智能家居与家居机器人的融合领域。由于micropython中没找到ros库,所以这个任务将使用vscode+platformio完成。
主要代码:
导入头文件并进行ros节点的初始化
#include <WiFi.h>
#include <ros.h>
#include <std_msgs/String.h>
// define relay_pin according to pin diagram
#define relay_pin D10
// connect setting
const char* ssid = "WiFi名称";//需要和ros主机在同一WiFi下
const char* password = "密码";
// Set the rosserial socket server IP address
IPAddress server(192,168,3,33);//ros主机的ip地址,用逗号分隔
// Set the rosserial socket server port
const uint16_t serverPort = 11411;
// Ros setting
ros::NodeHandle nh;
// Make a chatter publisher
std_msgs::String str_msg;
// node name: esp32relay
ros::Publisher chatter("esp32relay", &str_msg);
主函数,如果ros主机订阅esp32节点,则将10io口设为高电平,否则设为低电平
void loop() {
if (nh.connected()) {
Serial.println("Connected");
digitalWrite(relay_pin, HIGH);
delay(1000);
} else {
Serial.println("Not Connected");
digitalWrite(relay_pin, LOW);
delay(1000);
}
nh.spinOnce();
// Loop exproximativly at 1Hz
delay(1000);
}
此外还需要ros端安装相关依赖
sudo apt-get install ros-${ROS_DISTRO}-rosserial-arduino
sudo apt-get install ros-${ROS_DISTRO}-rosserial
然后在该1功能包下新建launch文件夹,在launch文件夹下创建esprelay.launch这个启动文件,输入以下代码
<launch>
<node name="rosserial_python" pkg="serial_node.py" type="serial_node" output="screen">
<param name="port" value="tcp" />
</node>
</launch>
最后打开ros主机终端,输入以下命令
roslaunch rosserial_python esprelay.launch
功能展示:
成功控制继电器打开了风扇
说明:ros端使用的是Ubuntu18.04 Ros版本是Melodic
心得建议:使用了与MQTT完全不同的方式,成功使用ros注册节点无线控制外设
第三部分:
可编译下载的代码:源码
- 2023-12-11
-
加入了学习《直播回放: FollowMe 3 与得捷一起解锁开发板的超能力》,观看 FollowMe 3 与得捷一起解锁开发板的超能力