简单来说,在完成了阶段的过程,对每一个模块的驱动后,终于可以开始我们的项目的设计。
主要设计了一个曝光控制系统,可以通过不同的曝光模式(光圈优先和快门优先)来调整相机的曝光参数。能够根据环境光线强度(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