查看: 2350|回复: 18

[项目] 基于树莓派的水滴摄影控制器

[复制链接]
  • TA的每日心情
    开心
    2019-7-17 13:13
  • 签到天数: 264 天

    [LV.8]以坛为家I

    发表于 2019-3-22 00:12 | 显示全部楼层 |阅读模式
    【什么是水滴摄影】
      水滴摄影是一种细分的小众门类,就是用电子+摄影拍摄水滴的碰撞、溅落等过程。又分为透明(一般逆光拍摄)以及不透明拍摄(比如牛奶皇冠)等。捕捉水滴稍纵即逝的美好瞬间。魅力来自于从不同平常的视角观察水滴的晶莹,凝固瞬间,即便是同样的参数,由于受到很多因素的影响,也不会呈现一模一样的照片。这种不确定性本身就是一种魅力,更是在用另外的角度诠释“无常”。


    拍摄背景:近似全黑的房间。
    透明拍摄:闪光灯+柔光板正对相机镜头,水滴在两者之间,水滴在溅落、碰撞的过程中,闪光灯适时引闪,通过柔光板之后的光线将晶莹的水滴曝光在相机的CCD上。
    不透明拍摄:闪光灯与相机在一个方向,其余同上,这样在拍摄过程中,就可以得到类似牛奶皇冠这样的画面。

    问题是:怎么就正好在水滴溅落、碰撞中,闪光灯适时引闪,相机快门正好打开呢?你可以选择手动方式去控制闪灯和快门,可以想象,成功率极低、对快门损耗极大。这条路,脑补一下就可以了,不必尝试。
    方法二就是高速摄影,把整个过程拍摄下来,然后选择需要的画面,这个问题不在本文讨论中。

    我们的目的,就是做一个自动控制器,把水滴的溅落(碰撞)以及拍摄过程全程控制起来。

    【控制器的主要功能和基本原理】
    主要功能:(1)控制闪光灯引闪;(2)控制相机快门;(3)控制水滴滴落(碰撞);上述三个环节的全过程用一个流程控制。
    基本原理:
       通过单片机或者树莓派,控制电磁阀的开断(实现水滴溅落、碰撞),控制闪光灯引闪,控制快门触发。所有的人机对话、参数设置以及逻辑控制在单片机或者树莓派上完成。驱动gpio完成上述控制行为。

    【第一版、第二版回顾】
      我从2012年开始学习arduino,第一个项目就是用arduino uno制作了一个水滴控制器,用了三个电位器做参数输入,用一片1602液晶作为显示器,使用UNO作为主控。实现单电磁阀、单闪光灯的控制,拍摄出来了第一张水滴碰撞的片子。
    v1.jpg
    这个项目虽然简单,但是串联起来了输入、输出、显示、控制等所有环节,是一个非常适合初学者学习的小项目。虽然很简陋,但还是非常有效实用。

        2014年开始构思第二个版本,就是树莓派版,当时树莓派刚刚推出,我觉得非常适合用于水滴控制,于是在2016年前后,就有了第二版,树莓派1A作为主控,控制两个电磁阀和一组闪灯,当时由于我对闪灯的控制设计不够合理,试图用四个IO口控制四个闪灯,实现引闪,结果造成了闪灯之间的引闪不同步,最后投入实用的只有一组闪灯。这个控制器也给我带来了很多学习的快乐。学习了python,以及pythonGUI编程以及gpio控制。这个控制器是用洞洞板+CMOS模块来合成的,大量飞线,也造成了运行中的稳定性不足。尤其是只能控制一盏闪灯成为了硬伤。于是从2017年开始构思第三版。
    version2.jpg

    第三版的目的:
    1)控制资源扩大:控制四个闪灯、八个电磁阀以及一个快门和一个“预对焦”(唤醒相机)
    2)多线程控制,将闪灯、电磁阀、对焦唤醒以及快门控制,分别建立线程,使用多线程控制,这个提升是单片机很难做到的。优点就是逻辑非常清晰,每个控制逻辑一条线程。相对关系一目了然,不用相互折算。
    3)设计了水冲洗逻辑,在拍摄前后,对电磁阀和管路进行冲洗,利于设备保养。
    4)树莓派3(最终作品由大赛提供开发板),平板电脑远程桌面方式访问树莓派,所有的控制界面在平板上实现,玩家关注参数设置以及拍摄过程,对于控制过程完全不必关注。
    v3.jpg


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

    Schematic_drip2.0_Sheet.png

    PCB板)
    pcb.png

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


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

    【代码及注释】
    代码一:drip代码

    kittenblock中小学创客名师推荐的图形化编程软件

    # -*- 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
    变量:
    
    游客,如果您要查看本帖隐藏内容请回复
                    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: 设置参数,本控制器目前可以控制每个电磁阀的两次开闭,这样就是可以出两个水滴。设置电磁阀开关时间就是设置水滴大小。设置闪灯触发时间,就是设置感光的时间,这个参数不同会影响到水滴在不同阶段曝光。
    控制界面.png
    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提供平台,感谢孝肃师兄一直鼓励我整理这个项目,和更多同好分享。
       水滴摄影让我感受瞬间凝固的魅力,让我感受因缘无常的变幻。也让我思考和明了:唯一不变的就是变化本身。我的拍摄对象,她们的状态往往只能存在千分之一秒,每一幅美丽的水滴背后,又是多少因缘和合而成?相对于岁月长河,你可以领悟她们和钻石并无分别。
       通过水滴摄影,你可以观察到一颗水滴的兴起、碰撞、绚烂和湮灭。实际在这样的一个瞬间,你有幸观察到了一个水滴的一生。

    珍惜当下每一个时刻,不惊不畏。
    沧海抱拳。


    控制器3.0.jpg

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

    code_upload.rar (7.99 KB, 下载次数: 7)
    打赏作者鼓励一下!
  • TA的每日心情
    擦汗
    2019-1-26 16:31
  • 签到天数: 446 天

    [LV.9]以坛为家II

    发表于 2019-4-7 23:46 | 显示全部楼层
    项目请尽快更新哈~
    PY让世界更美好~
  • TA的每日心情
    开心
    2019-7-17 13:13
  • 签到天数: 264 天

    [LV.8]以坛为家I

     楼主| 发表于 2019-4-26 00:07 | 显示全部楼层
    syl312 发表于 2019-4-7 23:46
    项目请尽快更新哈~

    4月25日已更新。剩余部分将按期完成。
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-7-17 13:13
  • 签到天数: 264 天

    [LV.8]以坛为家I

     楼主| 发表于 2019-6-20 23:34 | 显示全部楼层
    增加了PCB光绘图纸以及亚克力顶盖图纸分享。
    drip_top_0310.rar (11 KB, 下载次数: 6)
    打赏作者鼓励一下!
  • TA的每日心情
    难过
    2019-8-24 00:33
  • 签到天数: 68 天

    [LV.6]常住居民II

    发表于 2019-7-6 13:15 | 显示全部楼层
    漂亮漂亮,厉害厉害。顶!
  • TA的每日心情
    开心
    2019-8-23 19:40
  • 签到天数: 30 天

    [LV.5]常住居民I

    发表于 2019-7-6 16:32 | 显示全部楼层
    感谢楼主的分享。这是我看到的最牛的水滴拍摄装住贴了。
  • TA的每日心情
    开心
    2019-8-23 19:40
  • 签到天数: 30 天

    [LV.5]常住居民I

    发表于 2019-7-8 18:20 | 显示全部楼层
    本帖最后由 njdj 于 2019-7-8 18:22 编辑

    老师您好!看了您的帖子后我也想弄一个您那样的水滴拍摄装置,只是我对树莓派的编程一窍不通,只有电子制作的能力,也能看懂电子电路图,电脑的操作也可以。您可以给我一些帮助指导吗?
  • TA的每日心情
    开心
    2019-7-17 13:13
  • 签到天数: 264 天

    [LV.8]以坛为家I

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

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

    只要有热情,就没有什么挡得住的。另外,还有就是时间。你需要准备好这两样。
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-8-23 19:40
  • 签到天数: 30 天

    [LV.5]常住居民I

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

    感谢老师的回复!我就是不懂您的这个树莓派是靠什么与平板连通上并控制的。还有平板上的控制软件是什么?树莓派我现手头上还没有(想了解以后就请教老师买一个)。我下载了您帖子里提供的压缩文件,以及您所编的代码。但是不知道它们在您设计的这个拍摄系统中是起什么作用的?
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    Arduino lcd屏幕亮了但是不显示字符
    Arduino lcd屏幕亮了但是
    Arduino的lcd屏亮了但是上面没有字符显示,串进去的滑动变阻器也旋过了,但是还是没有
    【原创】全球最小口袋3D打印机mini one直播教程贴
    【原创】全球最小口袋3D打
    最近闲得蛋疼,没事搞个掌上3D打印机,先放效果图吧。 搞了半天,终于能正常打印,
    [限时福利]5分钟带你快速了解新一代开发板:M5STACK
    [限时福利]5分钟带你快速
    一、什么是M5Stack M5Stack是一种模块化、可堆叠扩展的开发板,每个模块
    【Arduino】108种传感器模块系列实验(98)---L298N电机驱动板
    【Arduino】108种传感器模
    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是
    两个ESP8266通过云端实现远程数据交互
    两个ESP8266通过云端实现
    原理简述:利用发布订阅模式。一个ESP8266作为消息发布者,另一个ESP8266作为消息订阅
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表