在相机中为了完成照相,需要焦距、感光、光圈、快门等互相配合。按照这次活动的内容就是使用舵机、按钮配合BH1750测光模块模拟相机照相动作。在完成这个项目之前,先恶补下感光、光圈、快门和照相之间关系的知识。
相机中的快门、光圈、感光度三个参数的组合决定了一张照片的正确曝光。
快门也叫快门速度,以秒为单位,表示相机感光元件的曝光时间长度,传统机械快门通常以这些数值表示:1s、1/2s、1/4s、1/8s、1/15s、1/30s、1/60s、1/125s、1/250s、1/500s、1/1000s。现代电子快门将快门速度分的更精细,快门速度越快越能凝固被拍对象的动作,反之则会拍出运动物体的拖影。
光圈表示光线通过镜头的通光量,通常以f值表示,但通常所说的数字都是倒数。光圈在照片中决定清晰范围的宽度,也叫景深,照片中的光圈值越大,景深越浅,光圈值越大,景深越大。
感光度也叫iso,表示相机传感器或胶片对光的敏感度,通常表示为:50,100,200,400,800,1600,3200,6400…感光度数值越小,对光的敏感度越低,,反之则越高。但是照片的噪点数量和感光度成正比,感光度高,噪点多,感光度低,噪点少。照片图像质量和感光度成反比,感光度高,质量低,感光度低,质量高。
按照老师提供的课程PPT,这次活动中可以用BH1750测量光强,输出的数据是标定好的 Lux ,直接可以转换成曝光。按照以下公式(在 ISO100 下)计算出EV和快门速度,进而控制驱动舵机动作(模拟快门的动作)。
也就是说,
T=F*F/2^(2-log(LUX/10))
若BH1750测得的结果为400,则EV=2 + log2(160/10)=6。在光圈=4的话,则按照公式T=(4*4)/2^(2 + log2(160/10))=1/4S。为了计算方便,将公式进一步演算为:T = (F * F) / (4 * ( LUX/10 )),这样处理时,就不涉及对数处理。
以下是常见的EV值表(感光度为ISO100前提下)
根据以上资料,按照以下逻辑编程:
整机电路构成:
程序代码如下:
import time import math import board import adafruit_bh1750 import digitalio import terminalio from adafruit_display_text import label import adafruit_imageload import displayio import pwmio #文字尺寸 FONTSCALE = 2 # 文字颜色 TEXT_COLOR = 0xFFFFFF # 初始化I2C接口,BH1750传感器用 i2c = board.I2C() sensor = adafruit_bh1750.BH1750(i2c) # 初始化按钮 D5 和 D6 #模拟启动拍摄 button_start = digitalio.DigitalInOut(board.D5) button_start.direction = digitalio.Direction.INPUT button_start.pull = digitalio.Pull.UP #改变光圈 button_GQ = digitalio.DigitalInOut(board.D6) button_GQ.direction = digitalio.Direction.INPUT button_GQ.pull = digitalio.Pull.UP # D13,PWM输出,控制舵机 pwm = pwmio.PWMOut(board.D13, duty_cycle=2**15, frequency=50) # 启动快门 def start_km(duty_cycle): pwm.duty_cycle = duty_cycle # 调整 PWM 占空比来控制旋转 #停止马达转动 start_km(0) # 背景,为了显示汉字标签 display = board.DISPLAY # 背景 image, palette = adafruit_imageload.load( "images/ysqd.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette ) tile_grid = displayio.TileGrid(image, pixel_shader=palette) # 显示背景 splash = displayio.Group() splash.append(tile_grid) board.DISPLAY.root_group = splash # 光圈参数 label_GQ = label.Label(terminalio.FONT, text="", scale=FONTSCALE) label_GQ.x = 80 label_GQ.y = 15 splash.append(label_GQ) #光亮度 label_GL = label.Label(terminalio.FONT, text="", scale=FONTSCALE) label_GL.x = 80 label_GL.y = 50 splash.append(label_GL) #EV,根据光亮度计算出来的数据 label_EV = label.Label(terminalio.FONT, text="", scale=FONTSCALE) label_EV.x = 80 label_EV.y = 85 splash.append(label_EV) #快门,根据EV,光圈计算出来的数据 label_km = label.Label(terminalio.FONT, text="", scale=FONTSCALE) label_km.x = 80 label_km.y = 120 splash.append(label_km) # 初始设置 #光圈可选参数 sets_gq = [2, 2.8, 4, 5.6] #默认光圈初始值为4 index_gq=2 # 主循环 while True: lux = sensor.lux # 从传感器读取 Lux 值 # EV ev = 2 + math.log(lux / 10, 2) # 快门 km = (sets_gq[index_gq] * sets_gq[index_gq]) / (4 * (lux / 10)) # 切换光圈(蓝色按钮 D6) if not button_GQ.value: # D6 蓝色按钮被按下 index_gq = (index_gq + 1) % len(sets_gq) print("Adjust the aperture") time.sleep(0.2) # 启动拍照(D5,红色按钮) if not button_start.value: print("take a photo") # 转动马达 start_km(4000) time.sleep(km) # 停止转动 start_km(0) time.sleep(0.2) # 刷新显示 label_GQ.text = f"F/{sets_gq[index_gq]}" label_GL.text = f"{lux}" label_EV.text = f"{ev:.3f}" label_km.text = f"{km:.3f}" time.sleep(0.1)
整机效果:
视频:
链接:https://pan.baidu.com/s/19Ob2yIoUQf8F9UdjG1l6Ow
提取码:1234