[作品提交] 【得捷Follow me第二季第1期】任务提交+红外功能使用

夷则玖   2024-9-1 19:58 楼主

第一部分:3-5分钟短视频

    视频链接:视频

 

第二部分:任务实现详情

(1)任务/项目介绍

        ①项目简介

            Follow me活动是DigiKey联合EEWorld发起的大型开发板体验活动,每期技术大咖推荐可玩性与可学性较强的开发板/仪器套件,带着大家实际操作,参与者完成任务即返京东卡。

            活动旨在带着电子爱好者一起学习实用的电子技术知识,一起积攒DIY经验,一起变成更好的自己!

        ②物料清单

            1.购买的物料:

                    Adafruit Circuit Playground Express(核心板)

board.jpg

                    JOY FEATHERWING (摇杆按键控制板)

joy.jpg

                    NEOKEY FEATHERWING (机械按键控制板)

key.jpg
neokey.jpg

            2.非购买的物料:

                    NEC码红外无线通信控制板

ir_remote.png

                   Adafruit ESP32-S3 TFT Feather开发板

adafruit.jpg

        ③设计思路

                用Adafruit ESP32-S3 TFT Feather开发板、 NEOKEY FEATHERWING、 JOY FEATHERWING 和 NEC码红外无线通信控制板 组成一个红外遥控器,可以实现远程控制本期FollowMe的开发板(板载红外收发管)。通过NEC协议实现两个开发板的通信。

remote.jpg

(2)软件流程图

                

remote_design.png

(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键关闭

TASK0.png

            基础任务一(必做):控制板载炫彩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)

实现四种灯光效果

TASK1.png

 

            基础任务二(必做):监测环境温度和光线,通过板载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度,超过则红灯亮,否则熄灭。视频中可以看到通过打火机升高温度,红灯亮起,移开火源,红灯熄灭。

TASK2.png

            基础任务三(必做):接近检测——设定安全距离并通过板载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)

接近报警器,距离越近,颜色越红(由绿到红),亮灯数量越多,同时报警频率越高。

TASK3_1.png
TASK3_2.png
TASK3_3.png
TASK3_4.png

            进阶任务(必做):制作不倒翁——展示不倒翁运动过程中的不同灯光效果

                这个任务需要用到加速度传感器,为了实现不倒翁,我的设计是将原始加速度数值转换为极坐标,再根据极坐标的角度判断应该亮哪个灯,根据极坐标的ρ计算颜色(由绿到红),同时设置容差,防止在静止状态的频繁跳变。

#将笛卡尔坐标系向极坐标系转化
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),方便设置不倒翁效果

TASK_improve_st.png
TASK_improve.png

            创意任务一:有创意的可穿戴装饰——可结合多种传感器和灯光效果展示

            搭配器件: 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)

效果:

task_final.png

(4)对本活动的心得体会

            感谢EEworld和Digikey得捷电子提供的活动平台,使我在玩板子的同时学到了很多,例如管理python内存,因为在嵌入式平台,内存资源极为有限。完成任务的过程中,多次遇到Memory Error,最终查阅资料,重新了解python,了解circuitpython,最终解决问题,实现功能

            建议这样的活动继续办下去,让更多的人入门电子工程师。

第三部分:可编译下载的代码

    源代码:代码

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复