Arduinoで作るカメラタイマー①

Arduinoで作るカメラタイマー(秋月電子製テンキー版)

カメラタイマーを使って星景写真を撮るんだけど、
星景写真を撮る以上、当然暗いわけで、よくあるリモートタイマーだと暗闇で操作しにくいし、そんなに機能は必要ない。
そこで、一番安上がりそうなAruduinoを使ったカメラタイマー作成に挑戦。
HPをググれば同じようなのはいっぱいあるので、備忘録的にUp。

まずは秋月電子の「4×3キーパッド作成キット」を使ったもの。

これがソースコード、稚拙なのは言いっこなしで!

欠点:チャタリングが起こりやすく、防ごうとキー判断の時間を増すとイライラする。

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Arduino.h>
#include <AE_KEYPAD4X3.h>

//—————————————-//
// AE_KEYPAD4X3 —— Arduino UNO //
// //
// |> <—— 5.0V //
// X ——> 8 //
// Y ——> 7 //
// Z ——> 6 //
// A <—— 5 //
// B <—— 4 //
// C <—— 3 //
// D <—— 2 //
//—————————————-//

AE_KEYPAD4X3 KEYPAD = AE_KEYPAD4X3(8,7,6,5,4,3,2);

LiquidCrystal_I2C lcd(0x3F, 16, 2); // I2C: 0x3F, 16×2 LCD

unsigned long PreShotTime=3000; //撮影開始の待ち時間(秒)
int ShotNo=5; //撮影枚数(枚)
unsigned long IntTime=5000; //撮影間隔(秒)
unsigned long ShotTime=60000; //撮影時間(秒)
unsigned long TimeS; //開始時間
unsigned long TimeN; //今の時間
unsigned long TimeE; //終了時間
unsigned long InTTN; //今のインターバル時間
unsigned long InTTS; //今のインターバル開始時間
unsigned long InTTE; //今のインターバル終了時間
int SoTN; //今の撮影枚数
int BrkSW=0; //途中やめのフラグ
int Kdata; //キーパッドからのデータ(数値)
int KWaitTime=130; //チャタリング防止のキー待ち時間(150じゃ長いが100じゃ短い)
//unsigned long ShotModeT=0; //LCD一秒以下表示のためのショットタイムメモリ
int SotNoMem=0; //LCD書き換えのためのメモリ
unsigned long SotTMem=0; //LCD書き換えのためのメモリ
unsigned long IntTMem=0; //LCD書き換えのためのメモリ

void setup() {
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);

KEYPAD.Init();

lcd.begin();
lcd.backlight();
lcd.setCursor(1, 0);
lcd.print(“Interval Timer”);
lcd.setCursor(4, 1);
lcd.print(“v180309”);

delay(3000);
LcdOut(ShotNo, IntTime, ShotTime, “”, ShotTime);
}

void loop() {
Kdata = KEYPAD.getKey();
delay(KWaitTime);

BrkSW=0;

switch (Kdata) {
case 12: //shot stop
ShutterOFF();
BrkSW=1;
break;

case 11: { //test shutter 30sec
TimeS=millis();
TimeN=millis();
TimeE=TimeS+30000;
BrkSW=0;

ShutterON();
while(TimeN<TimeE){

//delay(200);
LcdOut(1, 0,TimeE-TimeN, “TS”, 30000);

Kdata = KEYPAD.getKey();
delay(KWaitTime);
if (Kdata==12){
ShutterOFF();
BrkSW=1;
break;
}
TimeN=millis();
}
ShutterOFF();
LcdOut(ShotNo, IntTime, ShotTime, “”, ShotTime);
break;
}

case 10: { //shot start

SoTN=1;
BrkSW=0;

InTTS=millis();
InTTE=InTTS+PreShotTime;
InTTN=millis();
ShutterOFF();

while(InTTN<InTTE){
//プレインターバルタイムの処理
//delay(200);
LcdOut(ShotNo, InTTE-InTTN, ShotTime, “RP”, ShotTime);

Kdata = KEYPAD.getKey();
delay(KWaitTime);
if (Kdata==12){
BrkSW=1;
break;
}
InTTN=millis();
}

for(int i=1; i<=ShotNo; i++){ //繰り返し撮影の処理
if (BrkSW==1){
break;
}

TimeS=millis();
TimeN=millis();
TimeE=TimeS+ShotTime;
LcdOut(ShotNo-SoTN+1, IntTime, ShotTime, “RS”, ShotTime);

ShutterON();
while(TimeN<TimeE){ //撮影中の処理
if (BrkSW==1){
ShutterOFF();
break;
}

//delay(200);
LcdOut(ShotNo-SoTN+1, IntTime, TimeE-TimeN, “RS”, ShotTime);

Kdata = KEYPAD.getKey();
delay(KWaitTime);
if (Kdata==12){
ShutterOFF();
BrkSW=1;
break;
}
TimeN=millis();
}

InTTS=millis();
InTTE=InTTS+IntTime;
InTTN=millis();
ShutterOFF();

while(InTTN<InTTE){
//インターバルタイムの処理
if (BrkSW==1){
break;
}
if (ShotNo==SoTN){ //最後の撮影ではインターバルタイムを止める
break;
}
//delay(200);
LcdOut(ShotNo-SoTN+1, InTTE-InTTN, ShotTime, “RI”, ShotTime);
Kdata = KEYPAD.getKey();
delay(KWaitTime);
if (Kdata==12){
BrkSW=1;
break;
}
InTTN=millis();
}
SoTN=SoTN+1;
}
LcdOut(ShotNo, IntTime, ShotTime, “”, ShotTime);
break;
}

case 3: //shutter time up
BrkSW=0;
if (ShotTime>1 && ShotTime<1000){
ShotTime=1000;
}
else if (ShotTime<10000){
ShotTime=ShotTime+1000;
}
else if (ShotTime<90000){
ShotTime=ShotTime+10000;
}
else{
ShotTime=ShotTime+30000;
}
LcdOut(ShotNo, IntTime, ShotTime, “”, ShotTime);
break;

case 6: //shutter time down
BrkSW=0;
if (ShotTime>1 && ShotTime<1100){
ShotTime=50;
}
else if (ShotTime<11000){
ShotTime=ShotTime-1000;
}
else if (ShotTime<120000){
ShotTime=ShotTime-10000;
}
else{
ShotTime=ShotTime-30000;
}

//if (ShotTime<1000){
// ShotTime=1000;
//}
LcdOut(ShotNo, IntTime, ShotTime, “”, ShotTime);
break;

case 2: //intv up
BrkSW=0;
if (IntTime<20000){
IntTime=IntTime+1000;
}
else
{
IntTime=IntTime+10000;
}

LcdOut(ShotNo, IntTime, ShotTime, “”, ShotTime);
break;

case 5: //intv down
BrkSW=0;
if (IntTime<30000){
IntTime=IntTime-1000;
}
else
{
IntTime=IntTime-10000;
}
if (IntTime<2000){
IntTime=2000;
}
LcdOut(ShotNo, IntTime, ShotTime, “”, ShotTime);
break;

case 1: //count No up
BrkSW=0;
if (ShotNo<20){
ShotNo=ShotNo+1;
}
else
{
ShotNo=ShotNo+10;
}
LcdOut(ShotNo, IntTime, ShotTime, “”, ShotTime);
break;

case 4: //count No down
BrkSW=0;
if (ShotNo<30){
ShotNo=ShotNo-1;
}
else
{
ShotNo=ShotNo-10;
}
if (ShotNo<1){
ShotNo=1;
}
LcdOut(ShotNo, IntTime, ShotTime, “”, ShotTime);
break;

default:
BrkSW=0;
//delay(200);
LcdOut(ShotNo, IntTime, ShotTime, “”, ShotTime);
break;
}
}

void LcdWait(){
//TodaYorozuLEDon();}
}

void LcdOut(int NoS, unsigned long ItT, unsigned long StT, String MD, unsigned long ShotModeT){
int DisRefSW=0;
if (NoS!=SotNoMem){
DisRefSW=DisRefSW+1;
}

if (int(ItT/1000)!=IntTMem){
DisRefSW=DisRefSW+1;
}

if (int(StT/1000)!=SotTMem){
DisRefSW=DisRefSW+1;
}

if (DisRefSW!=0){
//lcd.clear();
lcd.setCursor(0, 0);
lcd.print(“Shot INT Exp MS”);
lcd.setCursor(0, 1);
lcd.print(” “);
lcd.setCursor(0, 1);
lcd.print(NoS);
lcd.setCursor(5, 1);
lcd.print(int(ItT/1000));
lcd.setCursor(9, 1);
if (ShotModeT<1000){
lcd.print(0.05);
}
else{
lcd.print(int(StT/1000));
}
lcd.setCursor(14, 1);
lcd.print(MD);
SotNoMem=NoS;
IntTMem=int(ItT/1000);
SotTMem=int(StT/1000);
}
}

void ShutterON(){
digitalWrite(10,HIGH);
digitalWrite(11,HIGH);
}

void ShutterOFF(){
digitalWrite(10,LOW);
digitalWrite(11,LOW);
}