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

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 32810|回复: 29

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

[复制链接]
发表于 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代码
[mw_shl_code=python,true]# -*- 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[/mw_shl_code]



【装配过程】
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, 下载次数: 19)


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

4月25日已更新。剩余部分将按期完成。
 楼主| 发表于 2019-6-20 23:34 | 显示全部楼层
增加了PCB光绘图纸以及亚克力顶盖图纸分享。
drip_top_0310.rar (11 KB, 下载次数: 14) drop_pcb_Final.rar (292.21 KB, 下载次数: 11)
发表于 2019-7-6 13:15 | 显示全部楼层
漂亮漂亮,厉害厉害。顶!
发表于 2019-7-6 16:32 | 显示全部楼层
感谢楼主的分享。这是我看到的最牛的水滴拍摄装住贴了。
发表于 2019-7-8 18:20 | 显示全部楼层
本帖最后由 njdj 于 2019-7-8 18:22 编辑

老师您好!看了您的帖子后我也想弄一个您那样的水滴拍摄装置,只是我对树莓派的编程一窍不通,只有电子制作的能力,也能看懂电子电路图,电脑的操作也可以。您可以给我一些帮助指导吗?
 楼主| 发表于 2019-7-13 10:20 | 显示全部楼层
njdj 发表于 2019-7-8 18:20
老师您好!看了您的帖子后我也想弄一个您那样的水滴拍摄装置,只是我对树莓派的编程一窍不通,只有电子制作 ...

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

只要有热情,就没有什么挡得住的。另外,还有就是时间。你需要准备好这两样。
发表于 2019-7-13 19:01 | 显示全部楼层
沧海笑1122 发表于 2019-7-13 10:20
看得出您有一定的电子基础,当然愿意共同和您研究。
由于参赛和篇幅所限,这次写的重点是控制器。实际上 ...

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

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-27 23:42 , Processed in 0.104127 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表