大家好,以下是此次Follow me第二季第一期的任务汇总,欢迎交流。
【视频汇总】:
入门任务,0:12
基础任务一,1:10
基础任务二,1:42
基础任务三,2:25
进阶任务,3:32
创意任务二,4:16
【源码链接】:https://download.eeworld.com.cn/detail/andy11112/634234
【总体心得】:
关于此次活动,从中学到了Adafruit Circuit Playground Express(CPX)的使用,具备多种传感器是这个板子的特点。
此次使用CircuitPython,大部分设计的思路,可以通过官网以及lib中的example中找到。
1、【任务介绍】首先搭建开发环境,然后尝试点亮板载的红色LED指示灯。
3、【代码片段】
from adafruit_circuitplayground import cp
while True:
cp.red_led = True #赋值,True为点亮,False为熄灭
4、【功能展示】
1、【任务介绍】
2、【软件流程图】
3、【代码片段】
import time
from rainbowio import colorwheel
from adafruit_circuitplayground import cp
cp.pixels.brightness = 0.1 #设置彩灯的亮度,0为最暗(熄灭),1为最亮
cp.pixels.auto_write = False #设置False不会立即生效,需要调用pixels.show()
pixels_on = 1 #点亮彩灯,1为开启,0为关闭
pixels_color = 0 #彩灯颜色变换,1为开启,0为关闭
pixels_cycle = 0 #彩灯跑马灯,1为开启,0为关闭
#定义不同颜色
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)
def turn_on(wait): #定义点亮彩灯函数
cp.pixels[0] = (RED) #第1颗彩灯点亮,颜色为红色
cp.pixels.show()
time.sleep(wait) #间隔特定时间
cp.pixels.fill((YELLOW)) #全部彩灯点亮,颜色为黄色
cp.pixels.show()
time.sleep(wait) #间隔特定时间
cp.pixels.fill((OFF))
cp.pixels.show()
def color_change(wait): #定义颜色变换函数
for i in range(0,255,51): #颜色变化步进,一轮循环5个颜色
cp.pixels.fill((colorwheel(i & 255))) #colorwheel函数可以将一个HSV颜色值转换为RGB颜色值。idx & 255表示将idx除以256取余数,可得一个0-255之间的整数
cp.pixels.show()
time.sleep(wait)
def rainbow_cycle(wait): #定义跑马灯函数
for j in range(255):
for i in range(cp.pixels.n):
idx = int((i * 256 / cp.pixels.n) + j) #10个彩灯,彩色轮盘上的颜色值等间隔分配给各灯,同步变换颜色
cp.pixels[i] = colorwheel(idx & 255)
cp.pixels.show()
time.sleep(wait)
while True:
if pixels_on:
turn_on(1)
if pixels_color:
color_change(1)
if pixels_cycle:
rainbow_cycle(0.001)
4、【功能展示】
1、【任务介绍】
2、【软件流程图】
3、【代码片段】
import time
from adafruit_circuitplayground import cp
def scale_range(value): #定义函数,将光线传感器读数范围(0~320)转换为0~9
return round(value / 320 * 9)
def light_monitor():
l = scale_range(cp.light)
print("Light level:", l)
if l >= 1 and l < 6:
return True
else:
return False
def temperature_monitor():
t = cp.temperature
print("Temperature:", t)
if t > 17 and t < 30:
return True
else:
return False
cp.pixel_brightness = 0.1
cp.pixels.auto_write = False
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 light_monitor():
print("Light is normal!")
if temperature_monitor():
print("Temperature is normal!")
if light_monitor() and temperature_monitor():
cp.pixels.fill(GREEN)
cp.pixels.show()
else:
cp.pixels.fill(RED)
cp.pixels.show()
time.sleep(1)
4、【功能展示】
1、【任务介绍】
2、【软件流程图】
3、【代码片段】
import time
import board
import digitalio
import analogio
from adafruit_circuitplayground import cp
# 定义红外接近传感器引脚
IR_TX_PIN = board.IR_TX # 指定红外发射引脚
PROX_PIN = board.IR_PROXIMITY # 指定红外接近传感器引脚
# 初始化引脚
ir_tx = digitalio.DigitalInOut(IR_TX_PIN) # 配置红外发射引脚
ir_tx.direction = digitalio.Direction.OUTPUT # 设置红外发射引脚为输出模式
ir_tx.value = False # 设置初始值为低电平,关闭红外发射
prox_in = analogio.AnalogIn(PROX_PIN) # 配置红外接近传感器引脚
cp.pixels.auto_write = False # 关闭自动写入,以便手动控制 NeoPixel
cp.pixels.brightness = 0.1 # 设置 NeoPixel 亮度
def distance_convert(value): # 将红外接近传感器的值转换为距离
return round((value-30000) / (42000-30000) * 10) # 将红外接近传感器的值转换为距离
def pixels_indicator(distance): # 设置 NeoPixel 指示灯
if distance <5: # 如果距离小于5
color = (0,255,255) # 设置颜色为蓝绿色
else:
color = (255,0,0) # 距离大于5,设置颜色为红色,用于警示
for i in range(10): #用于粗略量化指示距离情况
if i <= distance:
cp.pixels[i] = (color)
else:
cp.pixels[i] = (0, 0, 0)
cp.pixels.show()
def alarm(distance): # 定义报警函数
if distance > 5: # 如果距离小于5
cp.play_tone(262, 0.0001) # 播放音调
# 主循环
while True:
total = 0 # 重置总距离
for i in range(10):
ir_tx.value = True # 打开红外发射
time.sleep(0.01) # 等待一段时间,使红外发射器发射红外光
ir_tx.value = False # 关闭红外发射
#time.sleep(0.01) # 等待一段时间,使红外发射器停止发射红外光
prox = prox_in.value # 读取红外接近传感器的值
distance = distance_convert(prox) # 将红外接近传感器的值转换为距离
print("proximity:",prox,"distance:",distance,"temperature:",cp.temperature) # 打印红外接近传感器的值
total =total + distance # 计算总距离
time.sleep(0.01) #等待一段时间
avg = total / 10 # 计算平均距离
print("average distance:",avg) # 打印平均距离
pixels_indicator(avg) # 设置 NeoPixel 指示灯
alarm(avg) # 调用报警函数
4、【功能展示】
1、【任务介绍】
2、【软件流程图】
3、【代码片段】
import time
import math
from adafruit_circuitplayground import cp
PIXEL_SPACING_ANGLE = 30 # 像素之间,间隔30°
STANDARD_GRAVITY = 9.81 # 标准重力加速度
BACKGROUND_COLOR = 0, 0, 64 # 背景颜色,蓝色
MIN_BRIGHTNESS = 15 # 最小亮度,15
LIGHTING_ARC_LENGTH = 45 # 照明弧长,45°
def compute_pixel_angles(): # 计算像素角度,排除第5和第11个像素(像素从0开始计数)
return [
(300 + PIXEL_SPACING_ANGLE * n) % 360 for n in range(12) if n not in (5, 11)
] # % 360 是为了确保角度在0到360之间,因为角度是循环的
def degrees_between(a1, a2): # 计算两个角度之间的最小度数差
smaller = min(a1, a2) # 取两个角度中的较小值
larger = max(a1, a2) # 取两个角度中的较大值
return min(larger - smaller, 360 + smaller - larger) # 返回两个角度之间的最小度数差
def pixel_brightness(distance_from_down, accel_magnitude):
'''
计算像素亮度,
distance_from_down表示像素距离地面的距离,
accel_magnitude表示加速度计测量的重力加速度的大小。
'''
half_lighting_arc_length = LIGHTING_ARC_LENGTH / 2 # 照明弧长的一半
if accel_magnitude < 0.1 or distance_from_down > half_lighting_arc_length: # 如果加速度小于0.1或者距离超过一半的照明弧长,则返回None
return None
normalized_nearness = 1 - distance_from_down / half_lighting_arc_length # 计算归一化的接近度
scale_factor = (255 - MIN_BRIGHTNESS) * accel_magnitude # 计算缩放因子
color_part = MIN_BRIGHTNESS + round(normalized_nearness * scale_factor) # 计算颜色部分
return color_part
def angle_in_degrees(x, y): # 计算点(x, y)的角度,返回-180到180之间的角度
return math.atan2(y, x) / math.pi * 180 # math.atan2(y, x)返回的是弧度,需要转换为角度
def positive_degrees(angle): # 将-180到180的角度转换为0到360的角度
return (angle + 360) % 360 # (angle + 360) % 360 是为了确保角度在0到360之间,因为角度是循环的
cp.pixels.brightness = 0.1 # 设置像素亮度为0.1
pixel_positions = compute_pixel_angles() # 计算像素角度
while True:
debug = cp.switch #滑动开关,启用调试模式
accel_x, accel_y = cp.acceleration[:2] # Ignore z,cp.acceleration[:2]获取加速度计的加速度值,并转换为列表
down_angle = positive_degrees(angle_in_degrees(accel_x, accel_y)) # 计算地面的角度
magnitude_limit = STANDARD_GRAVITY # 设置加速度计测量的重力加速度的大小为标准重力加速度
normalized_magnitude = (
min(math.sqrt(accel_x * accel_x + accel_y * accel_y), magnitude_limit)
/ magnitude_limit
) # 计算归一化的重力加速度的大小
pixels_lit = [] #创建一个空列表,用于存储被照亮的像素
for i, pixel_position in enumerate(pixel_positions): # 遍历每个像素
pe = pixel_brightness(
degrees_between(pixel_position, down_angle), normalized_magnitude
) # 计算像素亮度
cp.pixels[i] = (pe, 0, 0) if pe else BACKGROUND_COLOR # 设置像素颜色
if pe:
pixels_lit.append((i, pe)) # 如果像素被照亮,则将其添加到pixels_lit列表中
cp.play_tone(262+i*150, 0.1) # 播放音调,音调频率为262+i*150,持续时间为0.1秒
if debug:
lit_formatted = ", ".join(("{}: {:>3d}".format(p, i) for p, i in pixels_lit))
print(
"x: {:>6.2f}, y: {:>6.2f}, angle: {:>6.2f}, mag: {:>3.2f}, pixels: [{}]".format(
accel_x, accel_y, down_angle, normalized_magnitude, lit_formatted
)
)
time.sleep(0.5)
4、【功能展示】
1、【任务介绍】
2、【软件流程图】
3、【代码片段】
import array #导入array模块
import math #导入math模块
import board #导入board模块
import audiobusio #导入audiobusio模块
import pwmio
import time
from adafruit_motor import servo #导入servo模块
from adafruit_circuitplayground import cp
def constrain(value, floor, ceiling):
return max(floor, min(value, ceiling)) #将value限制在floor和ceiling之间,如果value小于floor,则返回floor,如果value大于ceiling,则返回ceiling,否则返回value
def log_scale(input_value, input_min, input_max, output_min, output_max): #定义一个log_scale函数,用于将输入值映射到输出值
normalized_input_value = (input_value - input_min) / (input_max - input_min) #将输入值归一化到0-1之间,即输入值减去最小值除以最大值减去最小值
return output_min + math.pow(normalized_input_value, 0.630957) * (
output_max - output_min
) #将归一化后的输入值映射到输出值,即输出最小值加上归一化后的输入值乘以输出最大值减去输出最小值,再乘以0.630957
def normalized_rms(values):
minbuf = int(sum(values) / len(values)) #计算输入信号的均值,即输入信号的总和除以输入信号的长度,并将结果转换为整数,作为输入信号的底值
return math.sqrt(
sum(float(sample - minbuf) * (sample - minbuf) for sample in values)
/ len(values)
) # 计算输入信号的均方根值,即输入信号的总和除以输入信号的长度,并将结果转换为浮点数,再乘以输入信号的总和除以输入信号的长度,最后取平方根
mic = audiobusio.PDMIn(
board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16
) #创建一个PDMIn对象,用于从麦克风读取音频数据,采样率为16000,位深度为16,时钟引脚为MICROPHONE_CLOCK,数据引脚为MICROPHONE_DATA,并将结果赋值给mic
samples = array.array("H", [0] * 160) #创建一个array对象,用于存储采样数据,长度为160,类型为H,即16位无符号整数,并将结果赋值给samples
mic.record(samples, len(samples)) #开始录音,将录音数据存储到samples中,长度为160
input_floor = normalized_rms(samples) + 10 #计算输入信号的均方根值,并加上10作为输入信号的底值
sensitivity = 500 # 设置灵敏度,即输入信号的底值与输入信号的顶值之间的差值
input_ceiling = input_floor + sensitivity #计算输入信号的顶值,即输入信号的底值加上灵敏度
pwm = pwmio.PWMOut(board.A1, frequency=50) #创建一个PWMOut对象,用于控制舵机,频率为50Hz,引脚为A1,并将结果赋值给pwm
my_servo = servo.ContinuousServo(pwm) #创建一个ContinuousServo对象,用于控制舵机,并将结果赋值给my_servo
peak = 0 #初始化峰值,即输入信号的顶值,用于在NeoPixels上显示峰值
while True:
mic.record(samples, len(samples)) #开始录音,将录音数据存储到samples中,长度为160
magnitude = normalized_rms(samples) #计算输入信号的均方根值,并将结果赋值给magnitude
print((magnitude,)) #打印输入信号的均方根值
c = log_scale(
constrain(magnitude, input_floor, input_ceiling),
input_floor,
input_ceiling,
0,
10,
) #将输入信号的均方根值映射到0-10之间,并将结果赋值给c
print(("c =", c))
cp.pixels.fill((0, 0, 0)) #将NeoPixels填充为黑色
for i in range(10): #遍历NeoPixels,用于指示音量的大小
if i < c:
cp.pixels[i] = (i * (255 // 10), 50, 0)
if c >= peak:
peak = min(c, 10 - 1)
elif peak > 0:
peak = peak - 1
if peak > 0:
cp.pixels[int(peak)] = (80, 0, 255)
cp.pixels.show()
if c >= 5 and c < 10: #中等音量,舵机向前缓慢转动
print("forward_slow")
my_servo.throttle = 0.1
time.sleep(0.05)
print("stop")
my_servo.throttle = 0.0
time.sleep(1)
if c >= 10: #高音量,舵机向前快速转动
print("forward_fast")
my_servo.throttle = 1
time.sleep(0.7)
print("stop")
my_servo.throttle = 0.0
time.sleep(1)
if cp.button_a or cp.button_b: #按下A或B按钮,舵机向后缓慢转动,用于手动回位
print("backward_slow")
my_servo.throttle = -0.1
time.sleep(0.1)
print("stop")
my_servo.throttle = 0.0
time.sleep(1)
4、【功能展示】
本帖最后由 andy11112 于 2024-9-1 17:43 编辑