9. D600のシーケンス制御プログラムVer.1.0

 8.で示したフォームとその裏側にあるソースで、日食の時刻等を入力したカンマ区切りのテキストファイルを読み込み、秒数に変換、基本的に時間指定でD600 の撮像シーケンスを実行するプログラムを組みました。
 取り敢えず狙ったように、タイムラプス撮像~C2前のダイヤモンドリング撮像~皆既後多段階露光~C3前にダイヤモンドリング撮像の開始&指定時間で終了~タイムラプス開始~10分後(ここは固定)と言うプログラムを作成しました。単写では1コマ撮像すると3.5秒程待たされるので、タイムラプスではその間隔を4秒より長くしないとダメとか、フールプルーフは出来ていないです。この辺りはフォームのプログラムの改造が必要ですね。単写では1コマの撮像完了信号が来るまで次の撮像が出来なさそうで、私の狙う2EVステップで1/4000~1/4秒の6コマ1セットを撮像するのに24秒ほどかかってしまいます。今回の日食では6セット撮像できるかどうかと言ったところです。クライマックス画像を撮像すること、と決めているので、まあ、こんなもんでしょう。
 アップの画像はD7100に任せることにしているので、それほど詰めてセット数を稼ぐ必要は無いと割り切っています。
 あ、このプログラムにはD7100の撮像開始のためのBeep音出力コマンドを組んでいないです。これは実験したいこともあり、後ほど工面することとします。あと、タブレットPCで使用するので、撮像開始ボタンをマウスによるクリックからタッチパネルのタップに切り替えないといけません。そこもまだです。

Index Next
//
// This work is licensed under a Creative Commons Attribution 3.0 Unported License.
//Thomas Dideriksen (thomas@dideriksen.com)
// 
// Modification is done by The M_shi for imaging automatic Total Solar Eclips
//

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using Nikon;

namespace demo_capture
{
    class DemoCapture
    {
        NikonDevice _device;
        AutoResetEvent _waitForDevice = new AutoResetEvent(false);
        AutoResetEvent _waitForCaptureComplete = new AutoResetEvent(false);
        //NikonImage image;
        //NikonDevice sender;
        //NikonDevice device;
        public int Speed { get; private set; }
        public int MaxSpeed { get; private set; }
        public int EVStep { get; private set; }
        public int DownStep { get; private set; }
        public int LapsSS { get; private set; }
        public int Present_time { get; private set; }
        public int n { get; private set; }
        public string [] cols =new string[17];

        // Create manager object - make sure you have the correct MD3 file for your Nikon DSLR
        //(see https://sdk.nikonimaging.com/apply/)

        NikonManager manager = new NikonManager("Type0008.md3");
        public int Hour;
        public int Minute;
        public int Second;
        //private Stream arg;
        private object test;
        private string stResult;
        private object row2;
        private int ContSS;

        public void Run()
        {
            //ファイルの読み出しルーチン
            System.IO.StreamReader cReader = (new System.IO.StreamReader(@"E:\M_shi\新しいフォルダー (3)\DSLR Ctrler\Caputor_Main\bin\x86\Release\D600CaptureSetting.txt", System.Text.Encoding.Default));
            while (cReader.Peek() >= 0)
            {
                // ファイルを 1 行ずつ読み込む
                string stBuffer = cReader.ReadLine();
                // 読み込んだものを追加で格納する
                stResult += stBuffer + System.Environment.NewLine;
            }
            // cReader を閉じる
            cReader.Close();
            Console.WriteLine(stResult);

            // カンマ区切りで個々の要素の文字列に分離する
            char delimiter = ',';
            for (int i = 0; i <= 16; i++)
            {
                cols = stResult.Split(delimiter);
            }
            
            // 分離した個々の要素を整数に変換・変数に導入する
            int index_LapsSS =Convert.ToInt32(cols[0]);
            int index_Speed = Convert.ToInt32(cols[1]);
            int index_Maxspeed = Convert.ToInt32(cols[2]);
            int index_EVStep = Convert.ToInt32(cols[3]);
            int index_DownStep = Convert.ToInt32(cols[4]);
            int Interval = Convert.ToInt32(cols[5]);
            int C2_hour = Convert.ToInt32(cols[6]);
            int C2_min = Convert.ToInt32(cols[7]);
            int C2_sec = Convert.ToInt32(cols[8]);
            int C2_before = Convert.ToInt32(cols[9]);
            int C2_after = Convert.ToInt32(cols[10]);
            int C3_hour = Convert.ToInt32(cols[11]);
            int C3_min = Convert.ToInt32(cols[12]);
            int C3_sec = Convert.ToInt32(cols[13]);
            int C3_before = Convert.ToInt32(cols[14]);
            int C3_after = Convert.ToInt32(cols[15]);

            // 時刻を秒単位に変換しておく
            int C2time = C2_hour * 3600 + C2_min * 60 + C2_sec;
            int C2Before = C2time + C2_before;
            int C2After = C2time + C2_after;
            int C3time = C3_hour * 3600 + C3_min * 60 + C3_sec;
            int C3Before = C3time - C3_before;
            int C3After = C3time + C3_after;

            System.IO.StreamWriter index_LapsSS2 = new System.IO.StreamWriter(Console.OpenStandardOutput());
            
            // 規定値から入力した値の数値化
            switch (index_LapsSS)   //タイムラプス時のシャッター速度
            {
                case 0:
                    LapsSS = 36;
                    break;
                case 1:
                    LapsSS = 34;
                    break;
                case 2:
                    LapsSS = 32;
                    break;
            }

            switch (index_Speed)    //ダイヤモンドリング撮像時のシャッター速
            {
                case 0:
                    ContSS = 36;
                    break;
                case 1:
                    ContSS = 34;
                    break;
                case 2:
                    ContSS = 32;
                    break;
            }

            switch (index_Maxspeed) //多段階撮像時のシャッター速度
            {
                case 0:
                    MaxSpeed = 36;
                    break;
                case 1:
                    MaxSpeed = 34;
                    break;
                case 2:
                    MaxSpeed = 32;
                    break;
            }

            switch (Convert.ToInt32(index_EVStep))  //EVの間隔
            {
                case 0:
                    EVStep = 6;
                    break;
                case 1:
                    EVStep = 5;
                    break;
                case 2:
                    EVStep = 4;
                    break;
                case 3:
                    EVStep = 3;
                    break;
                case 4:
                    EVStep = 2;
                    break;
                case 5:
                    EVStep = 1;
                    break;
            }

            switch (Convert.ToInt32(index_DownStep))    //EV間隔ごとに何回撮像するか
            {
                case 0:
                    DownStep = 11;
                    break;
                case 1:
                    DownStep = 10;
                    break;
                case 2:
                    DownStep = 9;
                    break;
                case 3:
                    DownStep = 8;
                    break;
                case 4:
                    DownStep = 7;
                    break;
                case 5:
                    DownStep = 6;
                    break;
                case 6:
                    DownStep = 5;
                    break;
                case 7:
                    DownStep = 4;
                    break;
                case 8:
                    DownStep = 3;
                    break;
                case 9:
                    DownStep = 2;
                    break;
                case 10:
                    DownStep = 1;
                    break;
            }

            try
            {
                // Listen for the 'DeviceAdded' event
                manager.DeviceAdded += manager_DeviceAdded;

                // Wait for a device to arrive
                _waitForDevice.WaitOne();

                // Hook up capture events
                _device.ImageReady += _device_ImageReady;
                _device.CaptureComplete += _device_CaptureComplete;

            //C2までのタイムラプス撮像ルーチン
                DateTime dtNow = DateTime.Now;
                int iHour = dtNow.Hour;
                int iMinute = dtNow.Minute;
                int iSecond = dtNow.Second;
                int iPresent_time = iHour * 3600 + iMinute * 60 + iSecond;
                //C2前ダイヤモンドリング撮像までのタイムラプス撮像
                while (C2Before - Interval >= iPresent_time+3)
                {
                    Speed = LapsSS;
                    Captor(Speed);

                    dtNow = DateTime.Now;
                    iHour = dtNow.Hour;
                    iMinute = dtNow.Minute;
                    iSecond = dtNow.Second;
                    iPresent_time = iHour * 3600 + iMinute * 60 + iSecond;
                    if (C2Before-Interval <= iPresent_time+3)
                    {
                        break;
                    }
                    System.Threading.Thread.Sleep((Interval-3) * 1000);//カメラ側の関係で3秒位時間を食うのでその調整
                }

            //C2ダイヤモンドリング撮像のための連写ルーチン
                uint Count = ((uint)C2_before + (uint)C2_after) * 3;  //枚数はC2前後撮像する秒数の合計の3倍です
                Speed = ContSS;
                ContinuousCapture(Speed, Count);    //サブルーチンに飛びます

            //多段階撮像ルーチン//
                //最低速度を計算します。
                int MinSpeed = MaxSpeed - EVStep * DownStep;
                Speed = MaxSpeed;

                //多段階にSSを減速させつつ撮像するルーチン
                //1ループごとにC3前連写時刻と現時刻を比較しつつ回す必要がありますが、それは後に。

                while (iPresent_time - 3 <= C3Before)   //C3連写前の多段階撮像の肝・
                {
                    Captor(Speed);

                    dtNow = DateTime.Now;
                    iHour = dtNow.Hour;
                    iMinute = dtNow.Minute;
                    iSecond = dtNow.Second;
                    iPresent_time = iHour * 3600 + iMinute * 60 + iSecond;

                    if (iPresent_time - 3 >= C3Before)
                    {
                        break;
                    }

                    if (Speed - EVStep > MinSpeed)
                    {
                        Speed = Speed - EVStep;
                    }
                    else
                    {
                        Speed = MaxSpeed;
                    }
                }
 
            //C3ダイヤモンドリング撮像のための連写ルーチン
                Count = ((uint)C3_before + (uint)C3_after) * 3; //撮像コマ数の指定
                Speed = LapsSS;                     //シャッター速度の指定
                ContinuousCapture(Speed, Count);    //SSとコマ数を持って撮像サブルーチンに飛びます

            //C3ダイヤモンドリング撮像後のタイムラプス撮像の指定(ここでは600秒としている)
                DateTime dt = DateTime.Now;
                iHour = dtNow.Hour;
                iMinute = dtNow.Minute;
                iSecond = dtNow.Second;
                iPresent_time = iHour * 3600 + iMinute * 60 + iSecond;
                int Ending_time = iPresent_time + 600;

                while (iPresent_time <= Ending_time)
                {
                    dtNow = DateTime.Now;
                    iHour = dtNow.Hour;
                    iMinute = dtNow.Minute;
                    iSecond = dtNow.Second;
                    iPresent_time = iHour * 3600 + iMinute * 60 + iSecond;

                    Captor(Speed);
                    System.Threading.Thread.Sleep((Interval-3) * 1000); //カメラ側の関係で3秒位時間を食うのでその調整
                }

                // Shutdown
                manager.Shutdown();
            }
            catch (NikonException ex)
            {
                Console.WriteLine();
            }
        }

        // C2,C3前後の連写のためのサブルーチン
        private void ContinuousCapture(int Speed, uint Count)
        {
            NikonEnum shutterSpeed = _device.GetEnum(eNkMAIDCapability.kNkMAIDCapability_ShutterSpeed);
            shutterSpeed.Index = Speed;
            _device.SetEnum(eNkMAIDCapability.kNkMAIDCapability_ShutterSpeed, shutterSpeed);

            // Set number of continuous captures - in this case I set Count
            _device.SetUnsigned(eNkMAIDCapability.kNkMAIDCapability_ContinuousShootingNum, Count);

            // Capture
            _device.Capture();

            // Wait for the capture to complete
            _waitForCaptureComplete.WaitOne();

            return;
        }

        // タイムラプス・多段階露光時の単写のためのサブルーチン
        private void Captor(int Speed)
        {
            //C2前の連写枚数になっているので、これをリセット
            _device.SetUnsigned(eNkMAIDCapability.kNkMAIDCapability_ContinuousShootingNum, 1);
            
            //シャッター速度を変えるコード
            NikonEnum shutterSpeed = _device.GetEnum(eNkMAIDCapability.kNkMAIDCapability_ShutterSpeed);
            shutterSpeed.Index = Speed; 
            _device.SetEnum(eNkMAIDCapability.kNkMAIDCapability_ShutterSpeed, shutterSpeed);

            // Capture
            _device.Capture();

            // Wait for the capture to complete
            _waitForCaptureComplete.WaitOne();
            return;
        }

        void _device_ImageReady(NikonDevice sender, NikonImage image)
        {
           // Save captured image to disk
            string filename = "image" + ((image.Type == NikonImageType.Raw) ? ".jpg" : ".nef");

            using (FileStream s = new FileStream(filename, FileMode.Create, FileAccess.Write))
            {
                 s.Write(image.Buffer, 0, image.Buffer.Length);
            }
        }

        void _device_CaptureComplete(NikonDevice sender, int data)
        {
            // Signal the the capture completed
            _waitForCaptureComplete.Set();
        }

        void manager_DeviceAdded(NikonManager sender, NikonDevice device)
        {
            if (_device == null)
            {
                // Save device
                this._device = device;
                device.SetUnsigned(eNkMAIDCapability.kNkMAIDCapability_SaveMedia, (uint)eNkMAIDSaveMedia.kNkMAIDSaveMedia_Card);

                // Signal that we got a device
                _waitForDevice.Set();
            }
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            DemoCapture demo = new DemoCapture();
            demo.Run();
        }
    }
}
inserted by FC2 system