基于树莓派的水滴摄影控制器-Arduino中文社区 - Powered by Discuz! Archiver

沧海笑1122 发表于 2019-3-22 00:12

基于树莓派的水滴摄影控制器

【什么是水滴摄影】水滴摄影是一种细分的小众门类,就是用电子+摄影拍摄水滴的碰撞、溅落等过程。又分为透明(一般逆光拍摄)以及不透明拍摄(比如牛奶皇冠)等。捕捉水滴稍纵即逝的美好瞬间。魅力来自于从不同平常的视角观察水滴的晶莹,凝固瞬间,即便是同样的参数,由于受到很多因素的影响,也不会呈现一模一样的照片。这种不确定性本身就是一种魅力,更是在用另外的角度诠释“无常”。http://player.youku.com/player.php/sid/XNDE2NDQ5MTQ0MA==/v.swf

拍摄背景:近似全黑的房间。透明拍摄:闪光灯+柔光板正对相机镜头,水滴在两者之间,水滴在溅落、碰撞的过程中,闪光灯适时引闪,通过柔光板之后的光线将晶莹的水滴曝光在相机的CCD上。不透明拍摄:闪光灯与相机在一个方向,其余同上,这样在拍摄过程中,就可以得到类似牛奶皇冠这样的画面。
问题是:怎么就正好在水滴溅落、碰撞中,闪光灯适时引闪,相机快门正好打开呢?你可以选择手动方式去控制闪灯和快门,可以想象,成功率极低、对快门损耗极大。这条路,脑补一下就可以了,不必尝试。方法二就是高速摄影,把整个过程拍摄下来,然后选择需要的画面,这个问题不在本文讨论中。
我们的目的,就是做一个自动控制器,把水滴的溅落(碰撞)以及拍摄过程全程控制起来。
【控制器的主要功能和基本原理】主要功能:(1)控制闪光灯引闪;(2)控制相机快门;(3)控制水滴滴落(碰撞);上述三个环节的全过程用一个流程控制。基本原理:   通过单片机或者树莓派,控制电磁阀的开断(实现水滴溅落、碰撞),控制闪光灯引闪,控制快门触发。所有的人机对话、参数设置以及逻辑控制在单片机或者树莓派上完成。驱动gpio完成上述控制行为。
【第一版、第二版回顾】我从2012年开始学习arduino,第一个项目就是用arduino uno制作了一个水滴控制器,用了三个电位器做参数输入,用一片1602液晶作为显示器,使用UNO作为主控。实现单电磁阀、单闪光灯的控制,拍摄出来了第一张水滴碰撞的片子。这个项目虽然简单,但是串联起来了输入、输出、显示、控制等所有环节,是一个非常适合初学者学习的小项目。虽然很简陋,但还是非常有效实用。
    2014年开始构思第二个版本,就是树莓派版,当时树莓派刚刚推出,我觉得非常适合用于水滴控制,于是在2016年前后,就有了第二版,树莓派1A作为主控,控制两个电磁阀和一组闪灯,当时由于我对闪灯的控制设计不够合理,试图用四个IO口控制四个闪灯,实现引闪,结果造成了闪灯之间的引闪不同步,最后投入实用的只有一组闪灯。这个控制器也给我带来了很多学习的快乐。学习了python,以及python的GUI编程以及gpio控制。这个控制器是用洞洞板+CMOS模块来合成的,大量飞线,也造成了运行中的稳定性不足。尤其是只能控制一盏闪灯成为了硬伤。于是从2017年开始构思第三版。
第三版的目的:(1)控制资源扩大:控制四个闪灯、八个电磁阀以及一个快门和一个“预对焦”(唤醒相机)(2)多线程控制,将闪灯、电磁阀、对焦唤醒以及快门控制,分别建立线程,使用多线程控制,这个提升是单片机很难做到的。优点就是逻辑非常清晰,每个控制逻辑一条线程。相对关系一目了然,不用相互折算。(3)设计了水冲洗逻辑,在拍摄前后,对电磁阀和管路进行冲洗,利于设备保养。(4)树莓派3(最终作品由大赛提供开发板),平板电脑远程桌面方式访问树莓派,所有的控制界面在平板上实现,玩家关注参数设置以及拍摄过程,对于控制过程完全不必关注。

【控制器硬件准备】
内容数量
1树莓派31
2控制器PCB(自制)1
3ULN28032
4TLN-521-42
5三极管S80502
6电阻(1K,110OM)3/6只


(PCB板)
使用sprint lyout 6.0绘制pcb,输出光绘图后,交TB打板。黑色一共打了10片。

【软件准备】
内容备注
1树莓派官方系统2018-06-27-raspbian-stretch
2Tkiner库
3Wxpython
4RPi.GPIO库

【代码及注释】代码一:drip代码# -*- coding=utf-8 -*-
__author__ = 'sebnil'
#coding utf-8
'''
项目名称:树莓派3B(摄影水滴控制器的第二版(多线程控制四只电磁阀,带相机唤醒)
基本情况:GUI界面,设置五只电磁阀释放水滴以及间隔时间,控制闪光灯(四只)以及相机快门
软件工具:wxFormBuilder/wing 101/wxpython/gpio的python RPI.GPIO官方库0.6.2
          使用wx.MilliSleep(),尝试毫秒级延时
          threading--多线程控制,从第一版的单线程扩展,每个电磁阀以及闪灯、快门,一共8个线程,并行调度控制,同一个时间轴
硬件:RASPBERRY PI 3B//电磁阀五只,闪光灯四只,ULN2803 TLN-521-4
V0.23: 实现8个线程、同一时间轴控制四只电磁阀以及闪灯、快门,并且唤醒相机,五只电磁阀,实现两喷+三滴
date:2018-10-13
变量:
**** Hidden Message *****
                dcf1 = 18#对应电磁阀1--GPIO18
                dcf2 = 23#对应电磁阀2--GPIO23
                dcf3 = 24#对应电磁阀3--GPIO24
                dcf4 = 25#对应电磁阀4--GPIO25
                dcf5 = 12 #对应电磁阀5--GPIO12
                flash1= 17 #闪光灯1,2,3,4---GPIO17
                door= 5 #快门---GPIO5
                call=13 #唤醒---GPIO13
                GPIO.setmode(GPIO.BCM)
                #设置OUTPUT状态
                GPIO.setup(dcf1, GPIO.OUT)
                GPIO.setup(dcf2, GPIO.OUT)
                GPIO.setup(dcf3, GPIO.OUT)
                GPIO.setup(dcf4, GPIO.OUT)
                GPIO.setup(dcf5, GPIO.OUT)
                GPIO.setup(flash1, GPIO.OUT)
                GPIO.setup(door, GPIO.OUT)
                GPIO.setup(call, GPIO.OUT)
'''
import wx
import mthreadgui #mthreadgui.py就是使用wxFormBuilder写的界面描述
import time
import RPi.GPIO as GPIO #树莓派GPIO库
import threading #多线程库
from time import ctime
from datetime import datetime

class MyWin(mthreadgui.MyWin):
      def __init__(self, parent, title):
                mthreadgui.MyWin.__init__(self, parent)      
      def on_button_click_event( self, event ):#OK按钮
                global flash1,door,call
                #初始化GPIO口
                dcf1 = 18#对应电磁阀1--GPIO18
                dcf2 = 23#对应电磁阀2--GPIO23
                dcf3 = 24#对应电磁阀3--GPIO24
                dcf4 = 25#对应电磁阀4--GPIO25
                dcf5 = 12#对应电磁阀5--GPIO12
                flash1= 17 #闪光灯1,2,3, 4---GPIO17
                door= 5 #快门---GPIO5
                call=13 #唤醒--GPIO13
                GPIO.setmode(GPIO.BCM)
                #设置OUTPUT状态
                GPIO.setup(dcf1, GPIO.OUT)
                GPIO.setup(dcf2, GPIO.OUT)
                GPIO.setup(dcf3, GPIO.OUT)
                GPIO.setup(dcf4, GPIO.OUT)
                GPIO.setup(dcf5, GPIO.OUT)
                GPIO.setup(flash1, GPIO.OUT)
                GPIO.setup(door, GPIO.OUT)
                GPIO.setup(call, GPIO.OUT)
                #设置多线程,电磁阀1~5,闪灯、快门
                threads = []
                t1 = threading.Thread(target=fun_drip,args=(self.drip11.GetValue(),self.drip12.GetValue(),self.drip13.GetValue(),self.drip14.GetValue(),dcf1)) #电磁阀1线程
                threads.append(t1)
                t2 = threading.Thread(target=fun_drip,args=(self.drip21.GetValue(),self.drip22.GetValue(),self.drip23.GetValue(),self.drip24.GetValue(),dcf2)) #电磁阀2线程
                threads.append(t2)
                t3 = threading.Thread(target=fun_drip,args=(self.drip31.GetValue(),self.drip32.GetValue(),self.drip33.GetValue(),self.drip34.GetValue(),dcf3)) #电磁阀3线程
                threads.append(t3)
                t4 = threading.Thread(target=fun_drip,args=(self.drip41.GetValue(),self.drip42.GetValue(),self.drip43.GetValue(),self.drip44.GetValue(),dcf4)) #电磁阀4线程
                threads.append(t4)
                t5 = threading.Thread(target=fun_drip,args=(self.drip51.GetValue(),self.drip52.GetValue(),self.drip53.GetValue(),self.drip54.GetValue(),dcf5)) #电磁阀5线程
                threads.append(t5)
                t6 = threading.Thread(target=fun_flash,args=(self.t_flash.GetValue(),)) #闪灯线程
                threads.append(t6)
                t7 = threading.Thread(target=fun_shutter,args=(self.t_shutter.GetValue(),)) #快门线程
                threads.append(t7)
                t8 = threading.Thread(target=fun_call,args=(self.t_call.GetValue(),)) #唤醒线程
                threads.append(t8)
                #组装并且激活各线程
                for t in threads:
                  t.setDaemon(True)
                  t.start()
                for t in threads:
                  t.join()
                print "all over %s" %ctime()
                GPIO.cleanup()#GPIO设置清除释放,这一条很重要
               
def fun_drip(delta1,delta2,delta3,delta4,dcf):
      start = datetime.now()
      #延时delta1
      wx.MilliSleep(delta1)
      #第一滴水,尺寸delta2
      GPIO.output(dcf, GPIO.HIGH)
      wx.MilliSleep(delta2)
      GPIO.output(dcf, GPIO.LOW)
      #延时delta3
      wx.MilliSleep(delta3)
      #第二滴水,尺寸delta4
      GPIO.output(dcf, GPIO.HIGH)
      wx.MilliSleep(delta4)
      GPIO.output(dcf, GPIO.LOW)
      end = datetime.now()
      delta = end-start
      print "set"
      print delta1+delta2+delta3+delta4
      print "value"
      print delta.microseconds/1000

def fun_flash(delta5):#闪灯引闪函数
      #延时delta5毫秒
      wx.MilliSleep(delta5)
      #闪灯打开
      GPIO.output(flash1, GPIO.HIGH)
      #GPIO.output(flash2, GPIO.HIGH)
      #GPIO.output(flash3, GPIO.HIGH)
      #GPIO.output(flash4, GPIO.HIGH)
      wx.MilliSleep(100)#保持固定脉冲100ms
      GPIO.output(flash1, GPIO.LOW)
      #GPIO.output(flash2, GPIO.LOW)
      #GPIO.output(flash3, GPIO.LOW)
      #GPIO.output(flash4, GPIO.LOW)      
      print "flash %s" %ctime()

def fun_shutter(delta6):#快门函数
      #延时delta6毫秒
      wx.MilliSleep(delta6)
      #打开快门,我们设置快门时间0.4S,足够完成这一动作
      GPIO.output(door, GPIO.HIGH)
      wx.MilliSleep(100)#固定延时100ms给快门
      GPIO.output(door, GPIO.LOW)
      print "shutter %s" %ctime()

def fun_call(delta7):#唤醒函数
      #延时delta7毫秒
      wx.MilliSleep(delta7)
      GPIO.output(call, GPIO.HIGH)
      wx.MilliSleep(100)#固定延时100ms给唤醒
      GPIO.output(call, GPIO.LOW)
      print "call %s" %ctime()

# Create wxpython app
class MyApp(wx.App):
    def OnInit(self):
      self.frame = MyWin(None, "      RPI-3B-Drop Control V0.23")
      self.SetTopWindow(self.frame)
      self.frame.Show(True)
      print("wxApp created.")

      return True

if __name__ == "__main__":
    app = MyApp(redirect=False) # do not redirect stdout to the gui
    app.MainLoop() # render gui continuously


【装配过程】1、焊接:PCB打板回来后,将元器件一一焊接,因为都是直插件,所以没有焊接难度。2、连接电磁阀、快门以及闪光灯(永诺560/四只)。3、装配整个拍摄体系。其中支架部分的设计,来自于高速水滴摄影群的林师兄。
【拍摄过程】Step1: 设置参数,本控制器目前可以控制每个电磁阀的两次开闭,这样就是可以出两个水滴。设置电磁阀开关时间就是设置水滴大小。设置闪灯触发时间,就是设置感光的时间,这个参数不同会影响到水滴在不同阶段曝光。Step2器材摆放及对焦。屋子在全黑条件下,配置好闪灯位置以及水滴装置、相机位置。可以用一个棒状物在水滴滴落下来的路线上进行对焦。一个一个电磁阀进行调试,不要急于碰撞,先把每一个电磁阀的滴落以及曝光调出来。注意:即便是一模一样的参数,在室温、水的粘稠度、拍摄时间等因素不同的情况下,效果完全不一样,同样的参数,在拍摄时很难简单套用,这一点很麻烦,也是魅力所在。Step3:拍摄,这个环节漫长和充满期待甚至挫折。我一般都会拍摄2~3小时,甚至曾经拍摄过一个通宵。每次拍摄后,都建议看一下片子,找出存在的问题,及时调整。所以我觉得很有必要在下一个版本中,对拍摄出来的结果立即在PC中显示,避免出现错误不能发现,浪费了时间和器材。
【注意事项】1、关于距离设置:在四只闪光灯灯情况下,闪灯与柔光板之间距离约为60cm,柔光板至水滴之间约为65cm。要想让画面柔和,光线摄入也应该尽可能小。这就是为什么要用多灯+柔光板(保持足够距离)+小光圈,如果光线强烈,就会造成画面锐利和玻璃感。2、关于光圈设置:小光圈(小于F22)。3、关于快门速度:使用熟练后,完全可以缩短,比如我现在一般就用1.0S左右,刚开始使用的B门(黑暗常开)。4、关于水滴增稠剂:一是瓜儿豆胶比较常用,二是TB有一种食物增稠剂,价廉物美,配出的水清澈透明无杂质,根本也不用过滤,粘度也比较好,长时间保存不变质,碰撞后也不易出现微小的空气泡,个人觉得比瓜胶好用。用量也不多,3-4g/1000ml左右。唯一不方便的是,不是十分溶于水,搅拌时间较长,一旦完全溶解,十分清澈,感觉就像甘油兑的一样。搅拌建议用食物料理机来搅拌,人工搅拌工作量很大而且效果达不到要求。
【小结】这个控制器是我从2012年接触arduino时的第一个作品,也是一个实用器,伴随我一路而行。有了第二版、第三版。在制作控制器的过程中,学习了arduino的编程,学习了树莓派、debian基础知识以及python的gui和gpio控制编程。如果说这些知识点都是宝贵的珍珠,那么这个小小的控制器就是串起珍珠的一根银线。
注:控制器本身并不复杂,但是高速水滴摄影是一个比较复杂的体系,建议作为进阶爱好来尝试。如果有兴趣的玩家可以去高速水滴拍摄群进行交流。

【鸣谢】
[*]首先致谢、致敬的是林师兄(cadboy),他是一位软硬件技术非常全面的香港的工程师,从3D建模、摄影到单片机控制,无所不精。但又是一名非常有爱心、无私宽容、甘于奉献和分享的师兄。和林师兄学习的过程,本身也是一个向他学习做人、被他人格魅力感染、洗涤的过程。在此对师兄表达深深敬意,毫不夸张地说,没有林师兄的指导,不会有今天的第三版树莓派控制器和大家分享。
[*]其次致谢高速摄影群的各位师兄,不胜枚举、一并鞠躬致谢。
[*]感谢Arduino.cn提供平台,感谢孝肃师兄一直鼓励我整理这个项目,和更多同好分享。
   水滴摄影让我感受瞬间凝固的魅力,让我感受因缘无常的变幻。也让我思考和明了:唯一不变的就是变化本身。我的拍摄对象,她们的状态往往只能存在千分之一秒,每一幅美丽的水滴背后,又是多少因缘和合而成?相对于岁月长河,你可以领悟她们和钻石并无分别。   通过水滴摄影,你可以观察到一颗水滴的兴起、碰撞、绚烂和湮灭。实际在这样的一个瞬间,你有幸观察到了一个水滴的一生。
珍惜当下每一个时刻,不惊不畏。沧海抱拳。





分享源代码,如果引用请注明出处。




syl312 发表于 2019-4-7 23:46

项目请尽快更新哈~

沧海笑1122 发表于 2019-4-26 00:07

syl312 发表于 2019-4-7 23:46
项目请尽快更新哈~

4月25日已更新。剩余部分将按期完成。:P

海神 发表于 2019-5-27 13:57

手动点赞

沧海笑1122 发表于 2019-6-20 23:34

增加了PCB光绘图纸以及亚克力顶盖图纸分享。

wangyirun 发表于 2019-7-6 13:15

漂亮漂亮,厉害厉害。顶!

njdj 发表于 2019-7-6 16:32

感谢楼主的分享。这是我看到的最牛的水滴拍摄装住贴了。:lol

njdj 发表于 2019-7-8 18:20

本帖最后由 njdj 于 2019-7-8 18:22 编辑

老师您好!看了您的帖子后我也想弄一个您那样的水滴拍摄装置,只是我对树莓派的编程一窍不通,只有电子制作的能力,也能看懂电子电路图,电脑的操作也可以。您可以给我一些帮助指导吗?

沧海笑1122 发表于 2019-7-13 10:20

njdj 发表于 2019-7-8 18:20
老师您好!看了您的帖子后我也想弄一个您那样的水滴拍摄装置,只是我对树莓派的编程一窍不通,只有电子制作 ...

看得出您有一定的电子基础,当然愿意共同和您研究。
由于参赛和篇幅所限,这次写的重点是控制器。实际上如果希望能够拍摄出漂亮的碰撞照片,还需要有摄影以及一点点机械知识(需要装配一个拍摄框架以及电磁阀等)。这个项目的难度属于进阶难度。树莓派做控制器,主要是利用其gui界面开发的便捷性以及直接驱动gpio的能力,不需要配置很高的树莓派,你可以入手。

只要有热情,就没有什么挡得住的。另外,还有就是时间。你需要准备好这两样。

njdj 发表于 2019-7-13 19:01

沧海笑1122 发表于 2019-7-13 10:20
看得出您有一定的电子基础,当然愿意共同和您研究。
由于参赛和篇幅所限,这次写的重点是控制器。实际上 ...

感谢老师的回复!我就是不懂您的这个树莓派是靠什么与平板连通上并控制的。还有平板上的控制软件是什么?树莓派我现手头上还没有(想了解以后就请教老师买一个)。我下载了您帖子里提供的压缩文件,以及您所编的代码。但是不知道它们在您设计的这个拍摄系统中是起什么作用的?
页: [1] 2 3
查看完整版本: 基于树莓派的水滴摄影控制器