-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathshutter.ino
673 lines (623 loc) · 26.1 KB
/
shutter.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include <Servo.h>
#include <EEPROM.h>
#define I2C_ADDRESS 0x3C
// Define proper RST_PIN if required.
#define RST_PIN -1
SSD1306AsciiWire oled;
// Create a new servo object:
Servo myservo;
// Output pins:
#define servoPin 9 // for servo
#define FlashSyncPin 10 // for flash sync opto isolator
// Input pins:
#define PlusButtonPin 3 // Plus button pin
#define MinusButtonPin 4 // Minus button pin
#define ShutterButtonPin 5 // shutter button pin
#define MenuButtonPin 6 // menu button pin
#define rotButtonPin 2 // rotary encoder switch
#define rotCLKPin 7 // rotary encoder clock
#define rotDTPin 8 // rotary encoder DT pin
boolean PlusButtonState; // "+" button state
boolean MinusButtonState; // "-" button state
boolean ShutterButtonState; // Metering button state
boolean MenuButtonState; // menu button state
boolean mainscreen = true; // indicates which screen displayed
boolean selftimermenu = false; // indicates self timer menu active
boolean adjustmenu = false; // indicates settings menu active
// EEPROM for memory recording
#define ShutterSpeedAddr 1
#define ShutterOpenAddr 2
#define ShutterCloseAddr 3
#define ShutterReliefAddr 4
#define ButtonDelayAddr 5
#define ServoDelayAddr 6
#define FlashSyncAddr 7
// default values if running for the first time
#define defaultShutterOpen 68 // shutter open angle
#define defaultShutterClose 0 // shutter close angle
#define defaultShutterRelief 4 // angle that servo backs off after opening/closing
#define defaultButtonDelay 200 // button repeat delay
#define defaultShutterSpeedIndex 10 // default shutter speed
#define defaultServoDelay 100 // time it takes to completely open shutter
#define defaultFlashSync 0 // 0 = X, 20 = M, amount to subtract from ServoDelay for flash syne
#define MaxShutterIndex 49 // matches number of items in spvalues
// load values from EEPROM
uint8_t ShutterSpeedIndex = EEPROM.read(ShutterSpeedAddr);
uint8_t ShutterOpen = EEPROM.read(ShutterOpenAddr);
uint8_t ShutterClose = EEPROM.read(ShutterCloseAddr);
uint8_t ShutterRelief = EEPROM.read(ShutterReliefAddr);
uint8_t buttondelay = EEPROM.read(ButtonDelayAddr);
uint8_t ServoDelay = EEPROM.read(ServoDelayAddr);
uint8_t FlashSync = EEPROM.read(FlashSyncAddr);
int ShutterState = 0; // closed
int selftimer = 0; // self time in seconds
int adjustmenuitem = 1; // selected adjust menu item
float voltage = 0; // for storing voltage of battery
int rotcounter = 0; // counter for rotary enocoder
int currentStateCLK; // for rotary encoder
int lastStateCLK; // for rotary encoder
unsigned long lastButtonPress = 0; // for rotary encoder
int btnState; // for rotary encoder
boolean rotaryencoder = false; // for rotary encoder
// Shutter speed values in seconds. 700 = TIME setting. If you add/delete, modify MaxShutterIndex
// shutter speeds faster than the servo speed will not open the shutter completely
float spvalues[] = {.05, .067, .08, .1, .125, .150, .200, .250, .300, .400, .500, .600, .800, 1.000, 1.250, 1.500, 2.000, 2.500, 3.000, 4.000, 5.000, 6.000, 7.000, 8.000, 9, 10, 11, 12, 13, 14, 15.00, 20.00, 25.00, 30.00, 35.00, 40.00, 45.00, 60.00, 90.00, 120.0, 150.0, 180.0, 240.0, 300.0, 360.0, 420.0, 480.0, 540.0, 600.0, 700};
// Store settings
void SaveSettings() {
EEPROM.write(ShutterSpeedAddr, ShutterSpeedIndex);
EEPROM.write(ShutterOpenAddr, ShutterOpen);
EEPROM.write(ShutterCloseAddr, ShutterClose);
EEPROM.write(ShutterReliefAddr, ShutterRelief);
EEPROM.write(ButtonDelayAddr, buttondelay);
EEPROM.write(ServoDelayAddr, ServoDelay);
EEPROM.write(FlashSyncAddr, FlashSync);
}
// read button state
void readButtons() {
PlusButtonState = digitalRead(PlusButtonPin);
MinusButtonState = digitalRead(MinusButtonPin);
ShutterButtonState = digitalRead(ShutterButtonPin);
MenuButtonState = digitalRead(MenuButtonPin);
}
// figure out what to do with button presses
void menu() {
// Menu button is pressed, cycle through menus:
if(MenuButtonState == 0) {
if(mainscreen) {
showtimermenu();
} else if(selftimermenu) {
showadjustmenu();
} else {
refresh();
delay(buttondelay);
}
}
// self timer menu active:
if(selftimermenu) {
if(PlusButtonState == 0) {
selftimer++; // increase self timer by 2 seconds
selftimer++;
} else if (MinusButtonState == 0) {
if (selftimer > 0) {
selftimer--; // decrease self timer by 2 seconds
selftimer--;
}
}
if(PlusButtonState == 0 || MinusButtonState == 0) {
showtimervalue(); // show changes in self timer
}
}
// on main screen and a plus or minus button is pressed:
if (mainscreen) {
if(PlusButtonState == 0) {
if(ShutterSpeedIndex >= MaxShutterIndex) {
ShutterSpeedIndex = 0;
} else {
ShutterSpeedIndex++; // Increase shutter speed time
}
refreshShutter(); // redisplay shutter speed
SaveSettings();
}
if(MinusButtonState == 0) {
if(ShutterSpeedIndex == 0) {
ShutterSpeedIndex = MaxShutterIndex;
} else {
ShutterSpeedIndex--; // decrease shutter speed time
}
refreshShutter(); // display shutter speed
SaveSettings();
}
}
float shutterdelay = spvalues[1];
shutterdelay = shutterdelay * 1000; // time in milliseconds
// Switch...Case statements to handle menu item adjustments -EHM 5.11.23
// First check for adjustmenu & PlusButtonState states.
// var adjustmenu must exist
// int PlusButtonState 0 or 1
if(adjustmenu && PlusButtonState == 0) { // plus button pressed
// Now Switch check on adjustmenuitem
// int adjustmenuitem 1-6
switch(adjustmenuitem) {
case(1): // Servo angle for open shutter
ShutterOpen++;
clearadjustitem(1); // erase value on screen for open angle
oled.print(ShutterOpen); // display new value for open angle
break; // done
case(2): // Servo angle for close shutter
ShutterClose++;
clearadjustitem(2);
oled.print(ShutterClose);
break;
case(3): // servo relief angle
ShutterRelief++;
clearadjustitem(3);
oled.print(ShutterRelief);
break;
case(4): // button delay in milliseconds
buttondelay = buttondelay + 10;
clearadjustitem(4);
oled.print(buttondelay);
break;
case(5): // servo delay (time it takes to fully open shutter)
ServoDelay++;
clearadjustitem(5);
oled.print(ServoDelay);
break;
case(6): // flash sync X or M
clearadjustitem(6);
if (FlashSync == 0) {
FlashSync = 20;
oled.print(F("M"));
} else {
FlashSync = 0;
oled.print(F("X"));
break;
}
}
} else if(adjustmenu && MinusButtonState == 0) { // minus button pressed
// Now Switch check on adjustmenuitem
// int adjustmenuitem 1-6
switch(adjustmenuitem) {
case(1):
ShutterOpen--;
clearadjustitem(1);
oled.print(ShutterOpen);
break;
case(2):
ShutterClose--;
clearadjustitem(2);
oled.print(ShutterClose);
break;
case(3):
ShutterRelief--;
clearadjustitem(3);
oled.print(ShutterRelief);
break;
case(4):
buttondelay = buttondelay - 10;
clearadjustitem(4);
oled.print(buttondelay);
break;
case(5):
if(ServoDelay > 0) {
ServoDelay--;
clearadjustitem(5);
oled.print(ServoDelay);
break;
}
case(6):
clearadjustitem(6);
if (FlashSync == 0) {
FlashSync = 20;
oled.print(F("M"));
} else {
FlashSync = 0;
oled.print(F("X"));
break;
}
}
}
}
// clear and get ready to display adjust value
void clearadjustitem(int adjust) { // erase adjust parameter on screen
oled.setCursor(94, adjust + 1);
oled.print(F(" ")); // display spaces
oled.setCursor(94, adjust + 1); // reset the cursor to print the value
SaveSettings(); // save settings
if(!rotaryencoder){ // if the buttons were used
delay(buttondelay); // wait for button delay time for repeat rate
}
rotaryencoder = false; // reset flag
}
// display self timer menu
void showtimermenu() {
mainscreen = false;
selftimermenu = true;
adjustmenu = false;
oled.clear();
printdivider(1);
oled.setCursor(10, 0);
oled.print(F("Self Timer:"));
showtimervalue();
}
void showtimervalue() { // show self timer value
oled.set2X();
oled.setCursor(25, 3);
oled.print(F(" ")); // clear line
oled.setCursor(25, 3);
if(selftimer == 0) { // self timer not active
oled.print(F("OFF"));
} else {
oled.print(selftimer); // show self timer value
oled.print(F(" sec")); // in seconds
}
if(!rotaryencoder){
delay(buttondelay); // button repeat rate
}
rotaryencoder = false;
}
// display shutter adjust menu
void showadjustmenu() { // settings menu
mainscreen = false;
selftimermenu = false;
adjustmenu = true;
oled.clear();
printdivider(1);
oled.setCursor(10, 0);
oled.print(F("Shutter Adjust:"));
oled.set1X();
oled.setCursor(22, 2); // characters are 6 pixels wide including space
oled.print(F("Open Angle: ")); // display the 5 adjustable items
oled.print(ShutterOpen);
oled.setCursor(16, 3);
oled.print(F("Close Angle: "));
oled.print(ShutterClose);
oled.setCursor(10, 4); // make the titles justified right
oled.print(F("Relief Angle: "));
oled.print(ShutterRelief);
oled.setCursor(10, 5);
oled.print(F("Button Delay: "));
oled.print(buttondelay);
oled.setCursor(16, 6);
oled.print(F("Servo Delay: "));
oled.print(ServoDelay);
oled.setCursor(22, 7);
oled.print(F("Flash Sync: "));
if(FlashSync == 0) {
oled.print(F("X"));
} else {
oled.print(F("M"));
}
oled.setCursor(0, adjustmenuitem + 1); // display an asterisk beside the selected item
oled.print(F("*"));
if(!rotaryencoder){
delay(buttondelay);
}
rotaryencoder = false;
}
void printdivider(int row) { // prints a divider
oled.set1X();
oled.setCursor(0, row);
int count = 1;
while (count < 23) { // 22 characters wide
oled.print(F("-")); // choose your divider character...
count++;
}
}
// Display main screen
void refresh() {
mainscreen = true;
selftimermenu = false;
adjustmenu = false;
// Start main display
oled.clear();
oled.set1X();
oled.setCursor(0, 0);
oled.print(F("Shutter Control |"));
oled.setCursor(105, 0);
oled.print(voltage, 1);
oled.print(F("v"));
printdivider(1);
oled.set1X();
oled.setCursor(40, 2);
oled.print(F("|"));
oled.setCursor(40, 3);
oled.print(F("|"));
oled.setCursor(0, 2);
oled.print(F("Shutter"));
oled.setCursor(0, 3);
oled.print(F("Speed"));
refreshShutter();
showshutterstate(0); // shutter is closed and ready
if(selftimer > 0) { // display self timer value if any
oled.setCursor(40, 4);
oled.print(F("|"));
oled.setCursor(40, 5);
oled.print(F("|"));
oled.setCursor(0, 4);
oled.print(F("Self"));
oled.setCursor(0, 5);
oled.print(F("Timer"));
oled.set2X();
oled.setCursor(50, 4);
oled.print(selftimer);
oled.print(F(" sec"));
}
delay(buttondelay);
}
void refreshShutter(){ // display just shutter speed
float T = spvalues[ShutterSpeedIndex]; // get shutter speed from array
uint8_t Tdisplay = 0; // Flag for shutter speed display style (fractional, seconds, minutes)
double Tfr = 0; // value for shutter speed fraction
float Tmin = 0; // shutter speed in minutes, if over 60 seconds
if (T >= 60 && T <= 600) {
Tdisplay = 0; // Exposure is in minutes
Tmin = T / 60;
} else if (T < 60 && T >= 0.6) { // speed in seconds
Tdisplay = 2; // Exposure in in seconds
} else if (T < 0.6 && T > .01) { // speed in fractions
Tdisplay = 1; // Display is in fractional form
Tfr = round(1 / T);
} else if ( T = 700) {
Tdisplay = 3; // Exposure is TIME
}
oled.set2X();
oled.setCursor(50, 2);
oled.print(F(" ")); // clear old shutter speed
oled.setCursor(50, 2); // reset cursor
if (Tdisplay == 0) { // display shutter speed
oled.print(Tmin, 1); // in minutes
oled.print(F("m"));
}
if (Tdisplay == 1) { // or in fractions
if (T > 0) {
oled.print(F("1/"));
oled.print(Tfr, 0);
}
}
if (Tdisplay == 2) { // or in seconds
oled.print(T, 1);
oled.print(F("s"));
}
if (Tdisplay == 3) { // or TIME
oled.print(("TIME"));
}
if(!rotaryencoder){ // if a button is being used, delay
delay(buttondelay);
}
rotaryencoder = false; // clear rotary encoder use flag
}
// display shutter state on bottom line
void showshutterstate(int expose) {
printdivider(6);
oled.setCursor(0, 7);
oled.print(F("State: "));
if(ShutterState == 0) { // 0 is shutter closed and ready to shoot
oled.print(F("CLOSED--READY "));
} else {
oled.print(F("OPEN--")); // if the shutter is open...
if(expose == 1) {
oled.print(F("EXPOSING")); // 1 = shutter open for exposure
} else {
oled.print(F("FOCUS ")); // any other number is shutter is open for focusing
}
}
if(expose == 2) { // 2 is shutter is closed, but self time counting down
oled.setCursor(0, 7);
oled.print(F("State: COUNTING DOWN "));
}
if(expose == 3) { // 3 is shutter is open for focusing
oled.setCursor(0, 7);
oled.print(F("State: FOCUS "));
}
}
boolean useselftimer(int stimer) { // self timer routine, sends back an abort flag if shutter is pressed
boolean abort = false;
if(stimer > 0) {
showshutterstate(2); // display timer is counting down status
oled.set2X();
while(stimer > 0) { // stimer in seconds
int countdown = 100; // for counting down 1 second
oled.setCursor(0, 4);
oled.print(F(" ")); // clear self timer value row
oled.setCursor(0, 4);
oled.print(stimer); // display self timer value
while(countdown > 0) {
if(stimer > 9) {
oled.print(stimer % 10); // display 10s column, then remainder if over 10 seconds
} else {
oled.print(stimer);
}
countdown = countdown - 10; // reduce counter by 1/10
delay(100); // wait 1/10 second
readButtons(); // read button state
if(ShutterButtonState == 0) { // if the shutter button is pressed
abort = true; // flag abort
countdown = 0; // stop countdown
stimer=0; // stop self timer
}
}
stimer--; // reduce timer by 1 second
}
oled.setCursor(0, 4);
oled.print(F("0000000000")); // last count
}
return(abort); // return the abort flag
}
void setup() {
pinMode(PlusButtonPin, INPUT_PULLUP); // setup buttons to pins
pinMode(MinusButtonPin, INPUT_PULLUP);
pinMode(ShutterButtonPin, INPUT_PULLUP);
pinMode(MenuButtonPin, INPUT_PULLUP);
pinMode(FlashSyncPin, OUTPUT); // setup flash sync output to opto isolator
pinMode(rotCLKPin, INPUT); // setup rotary encoder
pinMode(rotDTPin, INPUT);
pinMode(rotButtonPin, INPUT_PULLUP); // setup rotary encoder switch
lastStateCLK = digitalRead(rotCLKPin); // read last state of CLK on rotary encoder
Wire.begin();
myservo.attach(servoPin); // setup servo output
oled.begin(&Adafruit128x64, I2C_ADDRESS); // setup oled address
oled.setFont(Adafruit5x7); // setup oled font
myservo.write(ShutterOpen); // open shutter for viewing, focusing
delay(200); // wait 200ms
myservo.write(ShutterOpen - ShutterRelief); // back off to relieve stress on servo
ShutterState = 1; // shutter open
// load defaults if first time running
if (ShutterSpeedIndex > MaxShutterIndex) {
ShutterSpeedIndex = defaultShutterSpeedIndex;
}
if (ShutterOpen > 200) {
ShutterOpen = defaultShutterOpen;
}
if (ShutterClose > 90) {
ShutterClose = defaultShutterClose;
}if (ShutterRelief > 20) {
ShutterRelief = defaultShutterRelief;
}if (buttondelay > 250) {
buttondelay = defaultButtonDelay;
}
if (ServoDelay > 250) {
ServoDelay = defaultServoDelay;
}
if (FlashSync > 20) {
FlashSync = defaultFlashSync;
}
// get voltage
const long InternalReferenceVoltage = 1056L; // Adjust this value to your boards specific internal BG voltage x1000
ADMUX = (0 << REFS1) | (1 << REFS0) | (0 << ADLAR) | (1 << MUX3) | (1 << MUX2) | (1 << MUX1) | (0 << MUX0);
delay(100); // Let mux settle a little to get a more stable A/D conversion
ADCSRA |= _BV( ADSC );
while ( ( (ADCSRA & (1 << ADSC)) != 0 ) );
voltage = (((InternalReferenceVoltage * 1024L) / ADC) + 5L) / 10L; // calculates for straight line value
voltage = voltage/100;
refresh(); // display main screen
}
void loop() {
readButtons(); // get button state
currentStateCLK = digitalRead(rotCLKPin); // read current state of rotary encoder
if(lastStateCLK == LOW && currentStateCLK == HIGH){
rotaryencoder = true;
if(digitalRead(rotDTPin) == HIGH ){
MinusButtonState = 0; // translate it to button state
} else {
PlusButtonState = 0;
}
}
lastStateCLK = currentStateCLK; // wait until next event from encoder
btnState = digitalRead(rotButtonPin); // read rotary encoder button
if (btnState == LOW){
if (millis() - lastButtonPress > 50){
MenuButtonState = 0; // translate encoder switcht to menu push
}
lastButtonPress = millis();
}
menu(); // do stuff with button press
// shutter button pressed during self timer menu and the shutter is closed
if(!ShutterButtonState && selftimermenu && ShutterState == 0) {
myservo.write(ShutterOpen); // open the shutter for focus, viewing
while (!ShutterButtonState) { // as long as the shutter button is pressed...
delay(100); // wait another 100 ms
readButtons(); // then read the buttons again
}
delay(200); // wait until shutter opens
myservo.write(ShutterOpen - ShutterRelief);
ShutterState = 1;
showshutterstate(3); // open shutter for focus
}
// shutter button pressed during adjust menu
if(!ShutterButtonState && adjustmenu) {
while (!ShutterButtonState) { // wait until Shutter button is released
delay(100);
readButtons(); // try reading the buttons again
}
oled.setCursor(0, adjustmenuitem + 1);
oled.print(F(" ")); // clear adjust option item
adjustmenuitem++; // go to next adjust menu item
if(adjustmenuitem > 6) { // cycle back to first item
adjustmenuitem = 1;
}
oled.setCursor(0, adjustmenuitem + 1);
oled.print(F("*")); // Item selection indicator
}
// Main routine: shutter button pressed
if(!ShutterButtonState) {
boolean abort = false; // setup self timer abort variable
if(ShutterState == 1) { // If the shutter is open, close it
myservo.write(ShutterClose);
delay(200); // wait .2 sec
myservo.write(ShutterClose + ShutterRelief); // relieve servo stress
ShutterState = 0; // 0 = closed
showshutterstate(ShutterState); // indicate on status line on oLED
} else { // If the shutter is closed
abort = useselftimer(selftimer); // go to self timer routine and count down
if (!abort) { // if self timer hasn't been aborted
float shutterdelay = spvalues[ShutterSpeedIndex]; // get shutter speed in seconds
int shutterseq = 1; // normal flash sync shutter operation (default)
if (shutterdelay > 600){ // if shutter speed is greater than max (10 min)
shutterseq = 4; // TIME, no flash
} else if (shutterdelay > 1 && shutterdelay < 700) { // if shutter speed is slower than 1 second
shutterseq = 2; // shutter sequence with servo relief
}
shutterdelay = shutterdelay * 1000; // convert time in milliseconds
if (shutterdelay > ServoDelay){ // if shutter speed is slower than servo delay
shutterdelay = shutterdelay - ServoDelay; // subtract flashsync time from total
} else {
shutterseq = 3; // shutter speed faster than servo delay: fire the flash after shutter delay
}
ShutterState = 1; // show shutter open
showshutterstate(ShutterState);
// these case statements make shutter operations redundant between cases. Since shutter timing is critical, each shutter sequence is done in its own case, to avoid conditionals and possible delays during shutter operation
switch(shutterseq){ // choose shutter operation based on shutterseq
case(1): // normal shutter operation
myservo.write(ShutterOpen); // open shutter
delay(ServoDelay - FlashSync); // wait until flash sync delay
digitalWrite(FlashSyncPin, HIGH); // activate opto isolator for flash
delay(FlashSync); // delay the rest of the time to add up to ServoDelay
delay(shutterdelay); // keep shutter open for rest of time
digitalWrite(FlashSyncPin, LOW); // turn off flash sync
break; // done
case(2): // shutter longer than 1 second
myservo.write(ShutterOpen); // open shutter
delay(ServoDelay - FlashSync); // wait until blades are open
digitalWrite(FlashSyncPin, HIGH); // activate opto isolator for flash
delay(FlashSync); // wait until the rest of the flash sync time
delay(50); // and an additional 50ms for good measure for flash
digitalWrite(FlashSyncPin, LOW); // turn off flash
myservo.write(ShutterOpen - ShutterRelief); // relieve stress on servo
delay(shutterdelay - 50); // keep shutter open the rest of the duration
break; // done
case(3): // shutter speed faster than servo delay (for high shutter speeds where blades don't completely open)
myservo.write(ShutterOpen); // open shutter
delay(shutterdelay); // wait for duration of shutter time
digitalWrite(FlashSyncPin, HIGH); // fire flash
break; // done
case(4): // TIME
myservo.write(ShutterOpen); // open shutter
delay(200); // wait 200 ms
myservo.write(ShutterOpen - ShutterRelief); // relieve stress on servo
delay(100); // wait 100ms
readButtons(); // clear button state
while(ShutterButtonState) { // as long as shutter button isn't pressed, keep open
readButtons(); // wait here until shutter button pressed.
}
break; // done
} // finished with shutter sequence
myservo.write(ShutterClose); // close shutter
digitalWrite(FlashSyncPin, LOW); // turn off flash
delay(200); // wait 200ms
myservo.write(ShutterClose + ShutterRelief); // relieve stress on shutter
ShutterState=0; // shutter closed
showshutterstate(ShutterState); // show shutter on status line
}
// wait until shutter button is released
while (!ShutterButtonState) { // as long as the shutter button is pressed...
delay(100); // wait another 100 ms
readButtons(); // then read the buttons again
}
refresh(); // refresh the display
}
}
}