简单来说,在完成了阶段的过程,对每一个模块的驱动后,终于可以开始我们的项目的设计。
主要设计了一个曝光控制系统,可以通过不同的曝光模式(光圈优先和快门优先)来调整相机的曝光参数。能够根据环境光线强度(LUX)和传感器数据实时计算适当的曝光值(EV),并通过按键调节光圈、快门速度和ISO。
项目目标
实现基于光圈优先(AV)和快门优先(TV)模式的曝光控制系统。
根据实时环境光强(LUX)计算曝光值(EV)。
提供用户友好的操作界面,通过按键调节光圈、快门速度和ISO。
显示当前曝光模式、光圈值、ISO、快门速度和EV,帮助用户了解当前相机状态。
曝光模式选择:
光圈优先模式(AV优先):用户选择光圈大小,系统自动调整快门速度。
快门优先模式(TV优先):用户选择快门速度,系统自动调整光圈值。
使用显示屏实时展示当前的曝光参数,包括曝光模式、光圈、快门速度、ISO和曝光值。
import time
import board
from digitalio import DigitalInOut, Direction, Pull
import terminalio
import math
import adafruit_bh1750
import displayio
from adafruit_display_text import label
# 初始化 I2C 总线
i2c = board.I2C()
# 创建 BH1750 传感器对象
sensor = adafruit_bh1750.BH1750(i2c)
# display
BORDER = 20
TEXT_HIGH = 26
FONTSCALE = 2
TEXT_COLOR = 0x00ff00 #
TEXT_COLOR_WHITE = 0xFFFFFF # White
# 假设 AV, SV, TV 是预定义的列表
Mode = [
'AV ',
'TV ',
]
#FLAG
current_mode = "TV优先"
#光圈优先情况下,
def calculate_shutter_speed(EV, aperture, ISO):
aperture = float(aperture)
ISO = int(ISO)
return aperture ** 2 / (2 ** EV * ISO / 100)
# 根据 EV 调整 ISO 值的函数
def adjust_iso(EV, aperture, shutter_speed):
return int((100 * aperture ** 2) / (shutter_speed * (2 ** EV)))
#快门优先情况下
# 根据 EV 计算光圈值
def calculate_aperture(EV, shutter_speed, ISO):
ISO = int(ISO)
return math.sqrt(shutter_speed * (2 ** EV) * (ISO / 100))
# 根据 EV 调整 ISO
def adjust_iso(EV, shutter_speed, aperture):
return int((100 * aperture ** 2) / (shutter_speed * (2 ** EV)))
ISO = [
'100 ',
'200 ',
'400 ',
'800 ',
'1600 ',
'3200 ',
'6400 ',
'12800 ',
]
F = [
'1 ',
'1.4',
'2 ',
'2.8',
'4 ',
'5.6',
'8 ',
'11 ',
'16 ',
'22 ',
'32 '
]
T = [
'32 ',
'16 ',
'8 ',
'4 ',
'2 ',
'1 ',
'1/2 ',
'1/4 ',
'1/8 ',
'1/15 ',
'1/30 ',
'1/60 ',
'1/125 ',
'1/250 ',
'1/500 ',
'1/1000'
]
# 定义按键值
KEY_NULL = 0
KEY_D0 = 1
KEY_D1 = 2
KEY_D2 = 4
KEY_D3 = 8
KEY_D4 = 16
# 定义按键 GPIO 引脚
key0 = DigitalInOut(board.BOOT0) # BOOT0 按键
key1 = DigitalInOut(board.A1) # A1 按键
key2 = DigitalInOut(board.A2) # A2 按键
key3 = DigitalInOut(board.A4) # A2 按键
key4 = DigitalInOut(board.A5) # A2 按键
# 按键初始化
def keyInit():
key0.direction = Direction.INPUT
key0.pull = Pull.UP # BOOT0 使用上拉
key1.direction = Direction.INPUT
key1.pull = Pull.DOWN # A1 使用下拉
key2.direction = Direction.INPUT
key2.pull = Pull.DOWN # A2 使用下拉
key3.direction = Direction.INPUT
key3.pull = Pull.DOWN # 11 使用下拉
key4.direction = Direction.INPUT
key4.pull = Pull.DOWN # 9 使用下拉
# 按键检测
def keyDetect():
key_value = KEY_NULL
if key0.value == 0: # 判断 BOOT0 是否按下
key_value += KEY_D0
if key1.value: # 判断 A1 是否按下
key_value += KEY_D1
if key2.value: # 判断 A2 是否按下
key_value += KEY_D2
if key3.value: # 判断 11 是否按下
key_value += KEY_D3
if key4.value: # 判断 9 是否按下
key_value += KEY_D4
return key_value
# 检查按键是否按下
def isKeyPressed():
key_value = keyDetect()
if key_value: # 如果检测到按键被按下
time.sleep(0.01) # 防抖
if key_value == keyDetect(): # 再次确认按键状态
return key_value
return 0 # 没有按键按下
def menu0():
# 设置文本
text1 = "Hello EEPW & DigiKey"
text2 = "LeslieZhuang"
# 获取屏幕的宽度和高度
screen_width = board.DISPLAY.width
screen_height = board.DISPLAY.height
# 使用 terminalio 中的默认字体
font = terminalio.FONT
# 创建文本标签,并设置颜色为绿色
text_area1 = label.Label(font, text=text1, color=0x00FF00)
text_area2 = label.Label(font, text=text2, color=0x00FF00)
# 将字体的尺寸进行放大
text_area1.scale = 2 # 放大1倍
text_area2.scale = 2 # 放大1倍
# 计算文本的高度
text1_height = text_area1.bounding_box[1]
text2_height = text_area2.bounding_box[1]
# 设置文本的垂直位置
text_area1.x = 0
text_area2.x = 0
text_area1.y = screen_height // 4 - text1_height // 2
text_area2.y = 3 * screen_height // 4 - text2_height // 2
# 创建显示组
group = displayio.Group()
group.append(text_area1)
group.append(text_area2)
# 显示内容
board.DISPLAY.root_group = group
# 默认模式和索引
# global svIdx, avIdx, shutter_speed_idx
# svIdx = 2 # 默认 ISO 索引
# avIdx = 3 # 默认 光圈 (AV) 索引
# shutter_speed_idx = 5 # 默认快门速度 (索引)
svIdx = 2 # 默认 ISO 索引
avIdx = 3 # 默认 光圈 (AV) 索引
shutter_speed_idx = 5 # 默认快门速度 (索引)
modeIdx = 0
lux = sensor.lux # 获取光强值
if lux <= 0:
lux = 0.1 # 防止 lux 为零,避免 log(0) 错误
ev = math.floor(2 + math.log(lux / 10) / math.log(2)) # 计算 EV
ISO_value = int(ISO[svIdx].strip()) # 获取 ISO,转换为整数
aperture_value = float(F[avIdx].strip()) # 获取光圈值,转换为浮动点数
shutter_speed = int(T[shutter_speed_idx].split()[0]) # 获取快门速度值
def menu1(svIdx: int, avIdx: int, shutter_speed_idx: int):
global modeIdx
svIdx, avIdx, shutter_speed_idx # 声明为全局变量
display = board.DISPLAY
splash = displayio.Group()
display.root_group = splash
# 计算每行的高度,避免超出屏幕
line_height = TEXT_HIGH # 每行文本的高度
# 缩小字体大小
# 显示模式
if modeIdx == 0:
mode_text = "Mode: AV"
else:
mode_text = "Mode: TV"
mode_area = label.Label(terminalio.FONT, text=mode_text, color=TEXT_COLOR, scale=FONTSCALE)
mode_group = displayio.Group(x=0, y=TEXT_HIGH // 2)
mode_group.append(mode_area)
splash.append(mode_group)
# 合成 LUX 和 EV 文字,并显示在同一行
lux_ev_text = "LUX: %0.2f EV: %d" % (lux, ev)
lux_ev_area = label.Label(terminalio.FONT, text=lux_ev_text, color=TEXT_COLOR, scale=FONTSCALE)
lux_ev_group = displayio.Group(x=0, y=TEXT_HIGH * 2 - TEXT_HIGH // 2) # 第2行,强制转换为整数
lux_ev_group.append(lux_ev_area)
splash.append(lux_ev_group)
# 显示光圈 F (AV) 值
text_Line2 = "F/TV: " + F[avIdx]
text_Line2_area = label.Label(terminalio.FONT, text=text_Line2, color=TEXT_COLOR, scale=FONTSCALE)
text_Line2_group = displayio.Group(x=0, y=TEXT_HIGH * 3 - TEXT_HIGH // 2) # 第3行,强制转换为整数
text_Line2_group.append(text_Line2_area)
splash.append(text_Line2_group)
# 显示 ISO 值
text_Line3 = "ISO/AV: " + ISO[svIdx]
text_Line3_area = label.Label(terminalio.FONT, text=text_Line3, color=TEXT_COLOR, scale=FONTSCALE)
text_Line3_group = displayio.Group(x=0, y=TEXT_HIGH * 4 - TEXT_HIGH // 2) # 第4行,强制转换为整数
text_Line3_group.append(text_Line3_area)
splash.append(text_Line3_group)
shutter_speed_idx = max(0, min(shutter_speed_idx, len(T) - 1)) # 限制索引范围在 0 到 len(T) - 1 之间
text_Line4 = "S: " + T[shutter_speed_idx]
text_Line4_area = label.Label(terminalio.FONT, text=text_Line4, color=TEXT_COLOR, scale=FONTSCALE)
text_Line4_group = displayio.Group(x=0, y=TEXT_HIGH * 5 - TEXT_HIGH // 2) # 第5行,强制转换为整数
text_Line4_group.append(text_Line4_area)
splash.append(text_Line4_group)
def main():
# 初始化按键
global modeIdx
global ev
global lux
global svIdx, avIdx, shutter_speed_idx
# ev = math.floor(2 + math.log(lux / 10) / math.log(2)) # 计算 EV
keyInit()
key_value = 0
# 初始化显示,首先显示menu0
menu0()
modeIdx = 0
while True:
key_value = isKeyPressed() # 检测是否有按键按下
if key_value:
menu1(svIdx, avIdx, shutter_speed_idx)
if key_value == KEY_D0:
modeIdx = 1 - modeIdx
menu1(svIdx, avIdx, shutter_speed_idx)
print(f"modeIdx is now: {modeIdx}")
elif key_value == KEY_D2: # 增加光圈 / 快门速度
if modeIdx == 0: # 光圈优先
if avIdx < len(F) - 1:
avIdx += 1
shutter_speed = calculate_shutter_speed(ev, F[avIdx], ISO_value)
else: # 快门优先
if shutter_speed_idx < len(T) - 1:
shutter_speed_idx += 1
print(f"shutter_speed_idx = {shutter_speed_idx}")
# aperture = calculate_aperture(ev, int(T[shutter_speed_idx].split()[0]), ISO_value)
elif key_value == KEY_D1: # 增加光圈 / 快门速度
if modeIdx == 0: # 光圈优先
if avIdx > 0:
avIdx -= 1
shutter_speed = calculate_shutter_speed(ev, F[avIdx], ISO_value)
else: # 快门优先
if shutter_speed_idx > 0:
shutter_speed_idx -= 1
print(f"shutter_speed_idx = {shutter_speed_idx}")
# aperture = calculate_aperture(ev, int(T[shutter_speed_idx].split()[0]), ISO_value)
time.sleep(0.1) # 延时,防止按键过于频繁
main()视频展示
https://www.bilibili.com/video/BV19xzEYLEtR/share_source=copy_web&vd_source=8ec8a0cb875921c69ae671711837bd63
我要赚赏金
