ATmega328 Camera Controller | |
The Arduino SketchProgramming the ATmega328
Interim - 18 Jan 2013 This sketch was developed while the project was still on the breadboard. It's likely that it will be modified later in the light of experience as the controller is used "for real".
/********************************************************** * Camera / Slave Flash Controller (c) vwlowen.co.uk * **********************************************************/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * modified fonts in Adafruit_GFX library: glcdfont.c * * static unsigned char font[] PROGMEM = { * * 0x00, 0x00, 0x00, 0x00, 0x00, * * 0x3C, 0x22, 0x2A, 0x22, 0x3C, // Camera * * 0x00, 0x0F, 0x78, 0x0E, 0x00, // Spanner * * 0xFC, 0x86, 0x86, 0xFC, 0x00, // Battery * *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ //https://github.com/adafruit/Adafruit-GFX-Library #include <Adafruit_GFX.h> #include <Adafruit_PCD8544.h> //http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/ #include "LowPower.h" #include <EEPROM.h> // Defines for setting and clearing register bits for analog pre-scaler #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif // Assign the Nokia 5110 BoB pins to the Arduino pins. ***Many different versions*** #define RST A3 // Most analog pins are used for OUTPUT #define CE A2 #define DC A1 #define DIN A0 #define CLK 13 #define Vcc 12 #define LED 11 //Assign Arduino pins to the 7-function nav switch. #define DOWN 7 // S2 #define UP 9 // S4 #define LEFT 10 // S5 #define RIGHT 8 // S3 #define OK 4 // S1 #define INT0 2 // A interrupt from thumbwheel rotary encoder #define INT1 3 // B input from rotary encoder #define FOCUS 5 // output to focus opto-isolator #define SHUTTER 6 // output to shutter opto-isolator #define FLASH A4 // output to flash opto-isolator #define DIODE A5 // analog input from photodiode int LEDON = 0; // ON - My display has an 'active low' backlight int LEDOFF = 255; // OFF int LEDHALF = 200;// HALF // use Adafruit LCD controller and graphics libraries Adafruit_PCD8544 lcd = Adafruit_PCD8544(CLK, DIN, DC, CE, RST); // Arrays for menus and sub menus char* camMainItemsNames[3] = {"Sensor", "Timer", "Bulb"}; int camTimerDelayValues[16] = {1,2,4,8,15,30,1,2,4,8,15,30,1,2,4,8}; char* flashMainItemsNames[3] = {"Slave", "Hi-Sp", "*"}; char* flashSlaveModes[6] = {"0", "1", "2", "3", "4", "Auto"}; char* flashHiSpeedUnits[2] = {"u", "m"}; char* setupMainItemsNames[3] = {"Cont", "BkLt", "BkTim"}; int setupBkLtOpt[4] = {48, 171, 49, 65}; char* exitStr ="(OK) to Exit"; //EEPROM locations for saving configuration byte saved_camSelectedTimerRepeat = 0; byte saved_camSelectedTimerDelay = 1; byte saved_camShutterHold = 2; byte saved_camSelectedBulbDelay = 3; byte saved_flashSelectedSlaveMode = 4; byte saved_flashHiSpeedDelay = 5; // TWO bytes byte saved_flashSelectedHiSpeedUnit = 7; byte saved_setupContrast = 8; byte saved_setupSelectedBkLt = 9; byte saved_Delta = 10; // Two bytes byte saved_BkTimer = 12; byte saved_FlashFromCam = 13; byte saved_camFocusGap = 14; // two bytes byte saved_activeMenu = 16; byte saved_testMode = 17; boolean eepromSaved1 = false; // flags for each value to be saved to boolean eepromSaved2 = false; // avoid writing every item to EEPROM boolean eepromSaved3 = false; // every time. Only when a value is boolean eepromSaved4 = false; // changed will that value be written boolean eepromSaved5 = false; // to EEPROM boolean eepromSaved6 = false; boolean eepromSaved7 = false; boolean eepromSaved8 = false; boolean eepromSaved9 = false; boolean eepromSaved10 = false; boolean eepromSaved11 = false; boolean eepromSaved12 = false; boolean eepromSaved13 = false; boolean eepromSaved14 = false; boolean eepromSaved15 = false; unsigned long eepromTimer = 0; // only check for saving every 5 seconds. // This allows quick clicks of buttons without // writing to EEPROM for every click. // end of EEPOM locations and saved flags. // Camera Tab 'Values Column' values int camSelectedMainItem = 0; int camSelectedTimerDelay; int camSelectedTimerRepeat; char* camSelectedTimerUnit = "s"; int camFocusGap; int camShutterHold; int camActualShutterHold; unsigned long camActualTimerDelay; unsigned long camActualBulbDelay; int camSelectedBulbDelay; char* camSelectedBulbUnit = "s"; // Flash Tab 'Values Column' values int flashSelectedMainItem = 0; int flashSelectedSlaveMode; int flashSelectedHiSpeedUnit; unsigned long flashHiSpeedDelay; unsigned long flashActualHiSpeedDelay; int flashFromCam; // Setup tab 'Values Column' values int setupSelectedMainItem = 0; int setupContrast; int setupSelectedBkLtOpt; int testMode = 0; int setupTabLED = 0; // Backlight brightness. 0 = full on. int BkTimer = 5; // backlight timer in seconds unsigned long ledTimer; // and in milliseconds int activeMenu = 0; // 0 = cam, 1 = flash, 2 = setup int activeColumn = 1; // 0 = tabs column, 1 = menu items column, 2 = values column int delta = 50; // Required difference between ambient and actual (photodiode etc) int ambient; int buttonTim = 0; // Counters to time length of time buttons are held down. int buttonTim1 = 0; // This allows 'value column' items with a large range of values int buttonTim2 = 0; // to increase their increment/decrement rate as time increases. int buttonTim3 = 0; int buttonTim4 = 0; int buttonTim5 = 0; boolean adjustAllowed = true; // prevent interrupt adjusting delta when delta isn't displayed int count = 0; unsigned long time, lasttime, firsttime; // timers for Auto Slave flash unsigned long flashWatchdog; boolean oneFlashOnly = false; boolean doSensorIsActive = false; int watchdogTimeout = 1000; int ledCounter = 0; // Timer & Bulb: Flash tell-tale led every 10 seconds if in Test Mode void setup() { // Read last values from EEPROM and check for sensible values rather than assuming EEPROM // is brand new and contains 255 in its unused EEPROM locations. activeMenu = EEPROM.read(saved_activeMenu); if ((activeMenu > 2) || (activeMenu < 0)) activeMenu = 0; camFocusGap = constrain(EEPROMReadInt(saved_camFocusGap), 0, 990); camShutterHold = constrain(EEPROM.read(saved_camShutterHold), 0, 3); camSelectedTimerDelay = constrain(EEPROM.read(saved_camSelectedTimerDelay), 0, 15); camSelectedBulbDelay = constrain(EEPROM.read(saved_camSelectedBulbDelay), 0, 15); flashSelectedSlaveMode = constrain(EEPROM.read(saved_flashSelectedSlaveMode), 0, 5); flashHiSpeedDelay = constrain(EEPROMReadInt(saved_flashHiSpeedDelay), 0, 999); flashSelectedHiSpeedUnit = constrain(EEPROM.read(saved_flashSelectedHiSpeedUnit), 0, 1); flashFromCam = constrain(EEPROM.read(saved_FlashFromCam), 0, 4); setupContrast = constrain(EEPROM.read(saved_setupContrast), 20, 80); setupSelectedBkLtOpt = constrain(EEPROM.read(saved_setupSelectedBkLt), 0, 3); BkTimer = constrain(EEPROM.read(saved_BkTimer), 5, 20); testMode = constrain(EEPROM.read(saved_testMode), 0, 1); lcd.setContrast(setupContrast); switch (setupSelectedBkLtOpt) { case 0: setupTabLED = 255; break; case 1: setupTabLED = 200; break; case 2: setupTabLED = 0; break; case 3: setupTabLED = map(ambient, 0, 400, 100, 255); break; default: setupTabLED = 0; } analogWrite(LED, setupTabLED); delta = EEPROMReadInt(saved_Delta); // Define pinModes and enable internal pullup resistors on INPUTS. pinMode(2, INPUT); pinMode(3, INPUT); pinMode(4, INPUT); pinMode(7, INPUT); pinMode(8, INPUT); pinMode(9, INPUT); pinMode(10, INPUT); digitalWrite(2, HIGH); // Enable internal pullups digitalWrite(3, HIGH); digitalWrite(4, HIGH); digitalWrite(7, HIGH); digitalWrite(8, HIGH); digitalWrite(9, HIGH); digitalWrite(10, HIGH); for (int i = 11; i < 14; i++) // define OUTPUTS 11 to 13 pinMode(i, OUTPUT); pinMode(FOCUS, OUTPUT); // OUTPUT 5 pinMode(SHUTTER, OUTPUT); // OUTPUT 6 digitalWrite(FOCUS, LOW); digitalWrite(SHUTTER, LOW); // Analog pins can be referenced as digital pins 14 to 19 but I've // left them with their analog designations for clarity. pinMode(DIN, OUTPUT); // A0 | pinMode(DC, OUTPUT); // A1 | pinMode(CE, OUTPUT); // A2 |__outputs to Nokia LCD display pinMode(RST, OUTPUT); // A3 | pinMode(FLASH, OUTPUT); // A4 to opto isolator for flash pinMode(DIODE, INPUT); // A5 input from photodiode digitalWrite(Vcc, HIGH); // Vcc to LCD display . Power up display. analogReference(INTERNAL); // set analog reference to 1.1v to increase sensitivity // Set analog prescale to 16 for much faster analog read. sbi(ADCSRA,ADPS2); cbi(ADCSRA,ADPS1); cbi(ADCSRA,ADPS0); ambient = analogRead(DIODE); if (digitalRead(OK) == LOW) { // OK button is held during startup - reset to defaults activeMenu = 2; // setup menu activeColumn = 2; // display will start up with Contrast Value highlighted camFocusGap = 100; // (100ms) camShutterHold = 1; camSelectedTimerDelay = 4; // 15s camSelectedTimerRepeat = 0; // (r)epeat camSelectedBulbDelay = 4; // 15s flashSelectedSlaveMode = 5; // Auto flashHiSpeedDelay = 100; // 100 flashSelectedHiSpeedUnit = 1; // milliseconds flashFromCam = 0; // No linkage between Cam & Flash setupContrast = 55; // LCD contrast 55 setupSelectedBkLtOpt = 2; // LED backlight 'Full' BkTimer = 10; // 10 s delta = 50; // delta 50 testMode = 1; // enable tell-tale LED flashes on LCD saveEeprom(); // save to EEPROM } switch (setupSelectedBkLtOpt) { case 0: setupTabLED = 255; break; case 1: setupTabLED = 200; break; case 2: setupTabLED = 0; break; case 3: setupTabLED = map(ambient, 0, 400, 100, 255); break; default: setupTabLED = 0; } lcd.begin(setupContrast); // set LCD contrast lcd.clearDisplay(); lcd.display(); analogWrite(LED, setupTabLED); // Set PWM value to LED backlight attachInterrupt(0, rotaryEncoder, FALLING); // Attach thumbwheel rotary encoder interrupt } void saveEeprom() { if (!eepromSaved1) {EEPROM.write(saved_activeMenu, activeMenu); eepromSaved1 = true;} if (!eepromSaved2) {EEPROMWriteInt(saved_Delta, delta); eepromSaved2 == true;} if (!eepromSaved3) {EEPROM.write(saved_camShutterHold, camShutterHold); eepromSaved3 == true;} if (!eepromSaved4) {EEPROMWriteInt(saved_camFocusGap, camFocusGap); eepromSaved4 = true;} if (!eepromSaved5) {EEPROM.write(saved_camSelectedTimerRepeat, camSelectedTimerRepeat); eepromSaved5 = true;} if (!eepromSaved6) {EEPROM.write(saved_camSelectedTimerDelay, camSelectedTimerDelay); eepromSaved6 = true;} if (!eepromSaved7) {EEPROM.write(saved_camSelectedBulbDelay, camSelectedBulbDelay); eepromSaved7 = true;} if (!eepromSaved8) {EEPROM.write(saved_flashSelectedSlaveMode, flashSelectedSlaveMode); eepromSaved8 = true;} if (!eepromSaved9) {EEPROMWriteInt(saved_flashHiSpeedDelay, flashHiSpeedDelay); eepromSaved9 = true;} if (!eepromSaved10) {EEPROM.write(saved_flashSelectedHiSpeedUnit, flashSelectedHiSpeedUnit); eepromSaved10 = true;} if (!eepromSaved11) {EEPROM.write(saved_FlashFromCam, flashFromCam); eepromSaved11 = true;} if (!eepromSaved12) {EEPROM.write(saved_setupContrast, setupContrast); eepromSaved12 = true;} if (!eepromSaved13) {EEPROM.write(saved_testMode, testMode); eepromSaved13 = true;} if (!eepromSaved14) {EEPROM.write(saved_setupSelectedBkLt, setupSelectedBkLtOpt); eepromSaved14 = true;} if (!eepromSaved15) {EEPROM.write(saved_BkTimer, BkTimer); eepromSaved15 = true;} eepromTimer = millis(); // start eeprom-saved timer so it won't save again for at least 5 seconds } void showHeader(char* name, int wait) { // Opening screen for most options lcd.clearDisplay(); // except Timer & Bulb. lcd.print(name); lcd.print("..."); lcd.setCursor(2, 38); if (testMode == 1) lcd.write(2); lcd.setCursor(4, 24); lcd.print(exitStr); lcd.drawLine(0, 36, 84, 36, BLACK); lcd.setCursor(2, 38); if (testMode) lcd.write(2); lcd.display(); delay(wait); } void openMessage() { // Opening screen used by Timer & Bulb lcd.setCursor(4, 12); lcd.print("(OK) to Start"); lcd.setCursor(12, 28); lcd.print("Hold (OK)"); lcd.setCursor(15, 38); lcd.print("to Exit"); lcd.display(); } void restoreDisplay() { // Timer & Bulb shut down the display - this routine digitalWrite(Vcc, HIGH); // brings it back to life and sets up the backlight. lcd.begin(setupContrast); digitalWrite(LED, setupTabLED); ledTimer = millis(); } /******************************************************************************** * Main Menu Items - 'Action' routines * ********************************************************************************/ /* Routine waits for rising or falling trigger and fires shutter. */ void doSensor() { doSensorIsActive = true; delay(40); while(digitalRead(OK) == LOW); adjustAllowed = false; showHeader("Sensor", 2000); int ambient = analogRead(DIODE); int oldDelta = delta; unsigned long refresh = millis(); if (delta > 0) { // delta is positive - Rising edge while(1) { restart: refresh = millis(); ambient = analogRead(DIODE); // Refresh ambient baseline while (analogRead(DIODE) < (ambient + abs(delta))) { // wait for rising edge if (millis() - ledTimer > (BkTimer * 1000)) digitalWrite(LED, LEDOFF); if (millis() - refresh > 2000) goto restart; // refresh ambient baseline after 2s if (bitRead(PIND, 4) == 0) { // Allow escape - read OK button delay(40); ledTimer = millis(); doSensorIsActive = false; adjustAllowed = true; while (digitalRead(OK) == LOW); return; } } fireShutter(); while (analogRead(DIODE) > (ambient + abs(delta))){ // wait for possible long trigger to finish but if (millis() - refresh > 2000) break; // wait 2s then quit waiting anyway } // and refresh ambient baseline } } if (delta < 0) { // delta is negative - falling edge. while (1) { restart1: refresh = millis(); ambient = analogRead(DIODE); while (analogRead(DIODE) > (ambient - abs(delta))) { if (millis() - ledTimer > (BkTimer * 1000)) digitalWrite(LED, LEDOFF); if (millis() - refresh > 2000) goto restart1; // refresh ambient baseline after 2s if (bitRead(PIND, 4) == 0) { // Allow escape - read OK button delay(40); ledTimer = millis(); doSensorIsActive = false; adjustAllowed = true; while (digitalRead(OK) == LOW); return; } } fireShutter(); while (analogRead(DIODE) <= (ambient - abs(delta))) { // wait for possible long trigger to finish but if (millis() - refresh > 2000) break; // wait 2s then quit waiting anyway } // and refresh ambient baseline } } adjustAllowed = true; doSensorIsActive = false; } /* Timer routine fires shutter after pre-set delay - repeat indefinitely (if set to do so) */ void doTimer() { delay(70); adjustAllowed = false; ledTimer = millis(); while(digitalRead(OK) == LOW); analogWrite(LED, setupTabLED); boolean repeat = true; lcd.clearDisplay(); lcd.print("Timer "); lcd.print(camTimerDelayValues[camSelectedTimerDelay]); lcd.print(camSelectedTimerUnit); if (camSelectedTimerRepeat == 0) lcd.print(" (r)"); openMessage(); while(digitalRead(OK) == HIGH) { if (millis() - ledTimer > (BkTimer * 1000)) digitalWrite(LED, LEDOFF); } digitalWrite(LED, LEDOFF); // Turn off backlight unsigned long timerCount = 0; int loopCount = 0; delay(80); while(digitalRead(OK) == LOW); digitalWrite(Vcc, LOW); // Shut down LCD display while(repeat) { // repeat if set to do so ledCounter = 0; while(timerCount < camActualTimerDelay) { if (bitRead(PIND, 4) == 0) { // provide escape route delay(20); restoreDisplay(); adjustAllowed = true; while(digitalRead(OK) == LOW); return; } LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); // put ATmega328 to sleep. Wake at timerCount++; // 1s intervals to increment counter. if (testMode && (timerCount % 20 == 0)) timerCount++; // every 20 sec skip 1 sec to counteract if (testMode) ledCounter++; // telltale delay if (ledCounter > 9) { // every 10 seconds flash telltale ledCounter = 0; digitalWrite(Vcc, HIGH); digitalWrite(LED, LEDON); delay(50); digitalWrite(Vcc, LOW); digitalWrite(LED, LEDOFF); } } fireShutter(); timerCount = 0; loopCount++; (camSelectedTimerRepeat == 0 ? repeat = true : repeat = loopCount < camSelectedTimerRepeat); } restoreDisplay(); // bring LCD back to life. adjustAllowed = true; // Allow delta to be adjusted } void doBulb() { adjustAllowed = false; delay(80); while(digitalRead(OK) == LOW); analogWrite(LED, setupTabLED); lcd.clearDisplay(); lcd.print("Bulb... "); lcd.print(camTimerDelayValues[camSelectedBulbDelay]); lcd.print(camSelectedBulbUnit); openMessage(); ledTimer = millis(); while(digitalRead(OK) == HIGH) { if (millis() - ledTimer > (BkTimer * 1000)) digitalWrite(LED, LEDOFF); } digitalWrite(LED, LEDOFF); delay(80); while(digitalRead(OK) == LOW); digitalWrite(Vcc, LOW); digitalWrite(FOCUS, HIGH); delay(camFocusGap); digitalWrite(SHUTTER, HIGH); unsigned long timerCount = 0; ledCounter = 0; while (timerCount < camActualBulbDelay) { if (bitRead(PIND, 4) == 0) { digitalWrite(SHUTTER, LOW); delay(50); digitalWrite(FOCUS, LOW); restoreDisplay(); adjustAllowed = true; while(digitalRead(OK) == LOW); return; } LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); // ATmega328 to Power Down mode timerCount++; // wake at 1s intervals until time is elapsed if (testMode && (timerCount % 20 == 0)) timerCount++; // every 20s skip 1s to counteract telltale delay if (testMode) ledCounter++; if (ledCounter > 9) { ledCounter = 0; digitalWrite(Vcc, HIGH); digitalWrite(LED, LEDON); delay(50); digitalWrite(Vcc, LOW); digitalWrite(LED, LEDOFF); } } digitalWrite(SHUTTER, LOW); delay(50); digitalWrite(FOCUS, LOW); restoreDisplay(); adjustAllowed = true; } /* Slave flash routine. Always looks for rising edge(s) from pre-flash from camera. */ void doSlave() { doSensorIsActive = true; adjustAllowed = false; boolean repeat = true; unsigned long refresh; delay(400); while(digitalRead(OK) == LOW); showHeader("Slave", 2000); digitalWrite(LED, LEDOFF); ambient = analogRead(DIODE); count = 0; if (flashSelectedSlaveMode < 5) { // Not Auto - 'manually' count the pre-flashes while (1) { ambient = analogRead(DIODE); while (analogRead(DIODE) - ambient < abs(delta)) { // Cam flash -to- slave flash with watchdog timer. if (oneFlashOnly && (millis() - flashWatchdog > watchdogTimeout)) { if (flashFromCam == 3) { delay(1000); lcd.setCursor(0, 15); lcd.print("ERROR (* w *)"); lcd.display(); digitalWrite(SHUTTER, LOW); delay(50); digitalWrite(FOCUS, LOW); while(digitalRead(OK) == HIGH); } ledTimer = millis(); doSensorIsActive = false; adjustAllowed = true; while (digitalRead(OK) == LOW); return; } if (bitRead(PIND, 4) == 0) { // Exit early with 'OK' button. Direct Port read delay(40); // makes 'if' conditional check faster. ledTimer = millis(); flashWatchdog = 0; doSensorIsActive = false; adjustAllowed = true; while(digitalRead(OK) == LOW); return; } } count++; if ((count == flashSelectedSlaveMode - 1) || (flashSelectedSlaveMode == 0)){ fireFlash(); } while (analogRead(DIODE) - ambient >= abs(delta)); // make sure pulse has subsided before looping } // or same pulse may be counted more than once. } else { while(1) { // Auto - work out pre-flashes automatically. firsttime = 0; ambient = analogRead(DIODE); time = millis(); while (analogRead(DIODE) - ambient < abs(delta)) { if (oneFlashOnly && (millis() - flashWatchdog > watchdogTimeout)) { if (flashFromCam == 3) { lcd.setCursor(0, 15); lcd.print("ERROR ("); if (flashFromCam == 3) {lcd.print("* ");lcd.print("w"); lcd.print(" *");} lcd.print(")"); lcd.display(); digitalWrite(SHUTTER, LOW); delay(50); digitalWrite(FOCUS, LOW); while(digitalRead(OK) == HIGH); } ledTimer = millis(); flashWatchdog = 0; adjustAllowed = true; doSensorIsActive = false; return; } if (bitRead(PIND, 4) == 0) { // Exit early with 'OK' button delay(40); ledTimer = millis(); adjustAllowed = true; doSensorIsActive = false; while(digitalRead(OK) == LOW); return; } } count++; if (count == 2) firsttime = millis() - time; // If gap betwen 1st and 2nd pulse is > 250ms, assume 2nd pulse is main flash so Fire! if (firsttime > 250) { fireFlash(); if (oneFlashOnly) { doSensorIsActive = false; return; } } else { if ((count > 1) && (millis() - time < 3 * firsttime)) lasttime = millis() - time; // If gap between previous pulse and current pulse is > (7 * previous gap) assume // current pulse is main flash and Fire! if (count > 1 && millis() - time > (lasttime * 7)) { fireFlash(); if (oneFlashOnly) { doSensorIsActive = false; return; } } } while (analogRead(DIODE) - ambient >= abs(delta)); // make sure pulse has subsided before looping } // or same pulse may be counted more than once. } doSensorIsActive = false; } /* Hi-Speed routine opens shutter and waits for rising or falling trigger */ void doHiSpeed() { adjustAllowed = false; delay(40); while(digitalRead(OK) == LOW); unsigned long now; switch (camShutterHold) { case 0: camActualShutterHold = 250; break; case 1: camActualShutterHold = 500; break; case 2: camActualShutterHold = 1000; break; case 3: camActualShutterHold = 2000; break; default: camActualShutterHold = 500; } lcd.clearDisplay(); lcd.print("Hi-Speed.."); lcd.setCursor(0, 12); lcd.print(flashHiSpeedDelay); (flashSelectedHiSpeedUnit == 0 ? lcd.print(" usec") : lcd.print(" msec")); lcd.setCursor(9, 32); lcd.print(exitStr); lcd.display(); digitalWrite(LED, LEDOFF); digitalWrite(FOCUS, HIGH); delay(camFocusGap); digitalWrite(SHUTTER, HIGH); int ambient = analogRead(DIODE); if (delta > 0) { // wait forrising edge ambient = analogRead(DIODE); while (analogRead(DIODE) <= (ambient + abs(delta))) { if (bitRead(PIND, 4) == 0) { digitalWrite(SHUTTER, LOW); // Exit early. Don't leave shutter open delay(50); digitalWrite(FOCUS, LOW); adjustAllowed = true; ledTimer = millis(); return; } } } else { ambient = analogRead(DIODE); // wait for falling edge while (analogRead(DIODE) >= (ambient + abs(delta))) { if (bitRead(PIND, 4) == 0) { digitalWrite(SHUTTER, LOW); // Exit early. Don't leave shutter open delay(50); digitalWrite(FOCUS, LOW); adjustAllowed = true; ledTimer = millis(); return; } } } now = micros(); while ((micros() - now) < flashActualHiSpeedDelay); // delay for set microseconds fireFlash(); // fire flash delay(camActualShutterHold); // wait for Shutter Hold time (just to make sure) digitalWrite(SHUTTER, LOW); // close shutter and release focus. delay(50); digitalWrite(FOCUS, LOW); ledTimer = millis(); adjustAllowed = true; } /* fire flash - easy */ void fireFlash() { digitalWrite(FLASH, HIGH); delay(250); digitalWrite(FLASH, LOW); count = 0; // reset auto pre-flash counters and timers firsttime = 0; lasttime = 0; if ((testMode == 1) && doSensorIsActive) { digitalWrite(LED, LEDON); delay(10); digitalWrite(LED, LEDOFF); } } /* Fire shutter */ void fireShutter() { digitalWrite(FOCUS, HIGH); delay(camFocusGap); digitalWrite(SHUTTER, HIGH); if (flashFromCam == 1) { // flash to flash no watchdog flashWatchdog = millis(); oneFlashOnly = true; doSlave(); // normal 'Slave' settings apply oneFlashOnly = false; } if (flashFromCam == 2) { // shutter to flash no watchdog unsigned long now; now = micros(); while((micros() - now) < flashActualHiSpeedDelay); fireFlash(); } if (flashFromCam == 3) { // flash to flash with watchdog oneFlashOnly = true; flashWatchdog = millis(); doSlave(); oneFlashOnly = false; } if (flashFromCam == 4) { // shutter to flash with watchdog unsigned long now; now = micros(); while((micros() - now) < flashActualHiSpeedDelay); while(analogRead(DIODE) - ambient > abs(delta)) ; fireFlash(); flashWatchdog = millis(); // wait for flash from slave while (analogRead(DIODE) - ambient < abs(delta)) { if (millis() - ledTimer > (BkTimer * 1000)) analogWrite(LED, LEDOFF); if ((millis() - flashWatchdog > watchdogTimeout)) { digitalWrite(SHUTTER, LOW); delay(50); digitalWrite(FOCUS, LOW); lcd.setCursor(0, 15); lcd.print("ERROR ("); lcd.write(175); lcd.print(" w *)"); lcd.display(); if (digitalRead(OK) == LOW) { ledTimer = millis(); flashWatchdog = 0; adjustAllowed = true; return; } } } // end of waiting for flash from slave } // end shutter to flash with watchdog switch (camShutterHold) { case 0: camActualShutterHold = 250; break; case 1: camActualShutterHold = 500; break; case 2: camActualShutterHold = 1000; break; case 3: camActualShutterHold = 2000; break; default: camActualShutterHold = 500; } delay(camActualShutterHold); if (testMode && doSensorIsActive) { digitalWrite(LED, LEDON); delay(20); digitalWrite(LED, LEDOFF); delay(50); digitalWrite(LED, LEDON); delay(20); digitalWrite(LED, LEDOFF); } digitalWrite(SHUTTER, LOW); delay(50); digitalWrite(FOCUS, LOW); } /* main loop scans round buttons setting menus and values as requested */ void loop() { if (millis() - ledTimer > (BkTimer * 1000)) { analogWrite(LED, LEDOFF); } else if (setupSelectedBkLtOpt == 3) { analogWrite(LED, map(analogRead(DIODE), 0, 400, 100, 255)); } else analogWrite(LED, setupTabLED); // Set display column that cursor is active in if ((digitalRead(RIGHT) == LOW) ) { delay(40); if (activeColumn < 2) activeColumn++; while (digitalRead(RIGHT) == LOW); ledTimer = millis(); } if ((digitalRead(LEFT) == LOW) ) { delay(40); if (activeColumn > 0) activeColumn--; while (digitalRead(LEFT) == LOW); ledTimer = millis(); } // If cursor is in column 0 switch through Tabs (active menu) if (activeColumn == 0) { if (digitalRead(DOWN) == LOW) { delay(40); activeMenu++; if (activeMenu > 2) activeMenu = 2; while (digitalRead(DOWN) == LOW); eepromSaved1 = false; ledTimer = millis(); } } if (activeColumn == 0) { if (digitalRead(UP) == LOW) { delay(40); activeMenu--; if (activeMenu < 0) activeMenu = 0; while (digitalRead(UP) == LOW); eepromSaved1 = false; ledTimer = millis(); } } // Display appropriate Tab. if (activeMenu == 0) showTab1(); if (activeMenu == 1) showTab2(); if (activeMenu == 2) showTab3(); // If cursor is in middle column, scan UP/DOWN Tab1 items if ((activeMenu == 0) &&(activeColumn == 1)) { if (digitalRead(DOWN) == LOW) { delay(40); if (camSelectedMainItem < 2) camSelectedMainItem++; while(digitalRead(DOWN) == LOW); ledTimer = millis(); } if (digitalRead(UP) == LOW) { delay(40); if (camSelectedMainItem > 0) camSelectedMainItem--; while(digitalRead(UP) == LOW); ledTimer = millis(); } // +++++++ Actions for Camera menu Items +++++++++++ if (digitalRead(OK) == LOW) { delay(40); if (setupSelectedBkLtOpt == 3) { analogWrite(LED, map(analogRead(DIODE), 0, 400, 100, 255)); } else analogWrite(LED, setupTabLED); ledTimer = millis(); if (camSelectedMainItem == 0) doSensor(); if (camSelectedMainItem == 1) doTimer(); if (camSelectedMainItem == 2) doBulb(); while(digitalRead(OK) == LOW); } } // If cursor is in middle column, scan UP/DOWN Tab2 items if ((activeMenu == 1) &&(activeColumn == 1)) { if (digitalRead(DOWN) == LOW) { delay(40); if (flashSelectedMainItem < 2) flashSelectedMainItem++; while(digitalRead(DOWN) == LOW); ledTimer = millis(); } if (digitalRead(UP) == LOW) { delay(40); if (flashSelectedMainItem > 0) flashSelectedMainItem--; while(digitalRead(UP) == LOW); ledTimer = millis(); } // +++++++ Actions for Flash menu Items +++++++++++ if (digitalRead(OK) == LOW) { delay(40); if (flashSelectedMainItem == 0) doSlave(); if (flashSelectedMainItem == 1) doHiSpeed(); while(digitalRead(OK) == LOW); } } // If cursor is in middlew column, scan UP/DOWN Tab3 items if ((activeMenu == 2) &&(activeColumn == 1)) { if (digitalRead(OK) == LOW) { ledTimer = millis(); } if (digitalRead(DOWN) == LOW) { delay(40); if (setupSelectedMainItem < 2) setupSelectedMainItem++; while(digitalRead(DOWN) == LOW); ledTimer = millis(); } if (digitalRead(UP) == LOW) { delay(40); if (setupSelectedMainItem > 0) setupSelectedMainItem--; while(digitalRead(UP) == LOW); ledTimer = millis(); } } /**************************************************************************** Cursor in right-hand column - adjustments take place here. ****************************************************************************/ // Camera Tab setting routines // =========================== // If cursor in right-most column, allow UP/DOWN to change focusing time and // OK button to change Shutter Hold time. if ((activeMenu == 0) && (activeColumn == 2)&& (camSelectedMainItem == 0)) { if (digitalRead(OK) == LOW) { delay(30); camShutterHold++; if (camShutterHold > 3) camShutterHold = 0; eepromSaved3 = false; while(digitalRead(OK) == LOW); ledTimer = millis(); } if (digitalRead(UP) == LOW) { delay(50); camFocusGap += 10; if (camFocusGap > 990) camFocusGap = 0; showTab1(); delay(160); eepromSaved4 = false; ledTimer = millis(); } if (digitalRead(DOWN) == LOW) { delay(50); camFocusGap -= 10; if (camFocusGap < 0) camFocusGap = 990; showTab1(); delay(160); eepromSaved4 = false; ledTimer = millis(); } } // If cursor is in right-most column use UP/DOWN to set Timer delay if ((activeMenu == 0) && (activeColumn == 2)&& (camSelectedMainItem == 1)) { if (digitalRead(OK) == LOW) { delay(40); camSelectedTimerRepeat++; if (camSelectedTimerRepeat > 5) camSelectedTimerRepeat = 0; while (digitalRead(OK) == LOW); eepromSaved5 = false; ledTimer = millis(); } if ((digitalRead(UP) == LOW)) { camSelectedTimerDelay++; if (camSelectedTimerDelay > 15) camSelectedTimerDelay = 0; showTab1(); delay(350); eepromSaved6 = false; ledTimer = millis(); } if ((digitalRead(DOWN) == LOW)) { camSelectedTimerDelay--; if (camSelectedTimerDelay < 0) camSelectedTimerDelay = 15; showTab1(); delay(350); eepromSaved6 = false; ledTimer = millis(); } } // If cursor is in right-most colum, use UP/DOWN to set Bulb delay if ((activeMenu == 0) && (activeColumn == 2)&& (camSelectedMainItem == 2)) { if (digitalRead(OK) == LOW) { ledTimer = millis(); } if ((digitalRead(UP) == LOW)) { camSelectedBulbDelay++; if (camSelectedBulbDelay > 15) camSelectedBulbDelay = 0; showTab1(); delay(350); eepromSaved7 = false; ledTimer = millis(); } if ((digitalRead(DOWN) == LOW)) { camSelectedBulbDelay--; if (camSelectedBulbDelay < 0) camSelectedBulbDelay = 15; showTab1(); delay(350); eepromSaved7 = false; ledTimer = millis(); } } // Flash Tab setting routines. //============================ // Use UP/DOWN to set Slave pre-flash mode if ((activeMenu == 1) && (activeColumn == 2)&& (flashSelectedMainItem == 0)) { if (digitalRead(OK) == LOW) { flashSelectedSlaveMode = 5; ledTimer = millis(); } if ((digitalRead(UP) == LOW)) { delay(10); flashSelectedSlaveMode++; if (flashSelectedSlaveMode > 5) flashSelectedSlaveMode = 0; showTab2(); delay(350); eepromSaved8 = false; ledTimer = millis(); } if ((digitalRead(DOWN) == LOW)) { delay(10); flashSelectedSlaveMode--; if (flashSelectedSlaveMode < 0) flashSelectedSlaveMode = 5; showTab2(); delay(350); eepromSaved8 = false; ledTimer = millis(); } } // Flash hi-speed - set delay if ((activeMenu == 1) && (activeColumn == 2)&& (flashSelectedMainItem == 1)) { if (digitalRead(OK) == LOW) { delay(40); (flashSelectedHiSpeedUnit == 0 ? flashSelectedHiSpeedUnit = 1 : flashSelectedHiSpeedUnit = 0); showTab2(); while (digitalRead(OK) == LOW); eepromSaved10 = false; ledTimer = millis(); } if ((digitalRead(UP) == LOW)) { buttonTim++; int inc; delay(50); if (buttonTim < 10) inc = 1; if ((buttonTim > 10) && (buttonTim < 20)) inc = 5; if ((buttonTim > 20) && (buttonTim < 30)) inc = 10; if (buttonTim > 30) inc = 50; flashHiSpeedDelay += inc ; if (flashHiSpeedDelay > 999) flashHiSpeedDelay = 0; showTab2(); delay(350); eepromSaved9 = false; ledTimer = millis(); } else { buttonTim = 0; } if ((digitalRead(DOWN) == LOW)) { buttonTim1++; int inc; delay(50); if (buttonTim1 < 10) inc = 1; if ((buttonTim1 > 10) && (buttonTim1 < 20)) inc = 5; if ((buttonTim1 > 20) && (buttonTim1 < 30)) inc = 10; if (buttonTim1 > 30) inc = 50; flashHiSpeedDelay -= inc ; if ((flashHiSpeedDelay < 0) || (flashHiSpeedDelay > 999)) flashHiSpeedDelay = 999; showTab2(); delay(350); eepromSaved9 = false; ledTimer = millis(); }else { buttonTim1 = 0; } } // select Flash From Cam timeout if ((activeMenu == 1) && (activeColumn == 2)&& (flashSelectedMainItem == 2)) { if ((digitalRead(OK) == LOW)) { flashFromCam = 0; eepromSaved11 = false; ledTimer = millis(); } if ((digitalRead(UP) == LOW)) { delay(10); flashFromCam++; if (flashFromCam > 4) flashFromCam = 0; showTab2(); delay(350); eepromSaved11 = false; ledTimer = millis(); } if ((digitalRead(DOWN) == LOW)) { delay(10); flashFromCam--; if (flashFromCam < 0) flashFromCam = 4; showTab2(); delay(350); eepromSaved11 = false; ledTimer = millis(); } } // SetupTab setting routines //========================== if ((activeMenu == 2) && (activeColumn == 2)&& (setupSelectedMainItem == 0)) { if ((digitalRead(UP) == LOW)) { delay(10); if (setupContrast < 100) setupContrast++; lcd.setContrast(setupContrast); delay(150); eepromSaved12 = false; ledTimer = millis(); } if ((digitalRead(DOWN) == LOW)) { delay(40); if (setupContrast > 10) setupContrast--; lcd.setContrast(setupContrast); delay(150); eepromSaved12 = false; ledTimer = millis(); } } if ((activeMenu == 2) && (activeColumn == 2)&& (setupSelectedMainItem == 1)) { if (digitalRead(OK) == LOW) { delay(40); (testMode == 0 ? testMode = 1 : testMode = 0); showTab3(); while (digitalRead(OK) == LOW); eepromSaved13 = false; ledTimer = millis(); } if ((digitalRead(UP) == LOW)) { delay(10); setupSelectedBkLtOpt++; if (setupSelectedBkLtOpt > 3) setupSelectedBkLtOpt = 0; delay(350); eepromSaved14 = false; ledTimer = millis(); } if ((digitalRead(DOWN) == LOW)) { delay(10); setupSelectedBkLtOpt--; if (setupSelectedBkLtOpt < 0) setupSelectedBkLtOpt = 3; delay(350); eepromSaved14 = false; ledTimer = millis(); } switch (setupSelectedBkLtOpt) { case 0: setupTabLED = LEDOFF; break; case 1: setupTabLED = LEDHALF; break; case 2: setupTabLED = LEDON; break; case 3: setupTabLED = map(ambient, 0, 400, 100, 255); break; default: setupTabLED = 0; } } if ((activeMenu == 2) && (activeColumn == 2)&& (setupSelectedMainItem == 2)) { if ((digitalRead(UP) == LOW)) { delay(10); if (BkTimer < 20) BkTimer++; delay(150); eepromSaved15 = false; ledTimer = millis(); } if ((digitalRead(DOWN) == LOW)) { delay(40); if (BkTimer > 5) BkTimer--; delay(150); eepromSaved15 = false; ledTimer = millis(); } } if (millis() - eepromTimer > 5000) saveEeprom(); } /***************************************************************************************** Tab Drawing and updating routines ******************************************************************************************/ // Camera menu void showTab1() { camSelectedTimerUnit = getUnits(camSelectedTimerDelay); camSelectedBulbUnit = getUnits(camSelectedBulbDelay); drawTabs(); lcd.drawRect(0, 0, 10, 10, BLACK); // Draw Tab. lcd.drawLine(9, 1, 9, 8, WHITE); // Remove rectangle edge for Tab to blend into Tab Page. // Print Menu Item Names - highlight if it is the selected item for (int i = 0; i < 3; i++) { lcd.setCursor(12, 10 * i +2); ((activeColumn == 1) && (camSelectedMainItem == i) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); lcd.print(camMainItemsNames[i]); } // If cursor is in 'Values' column , print values for 'Sensor' lcd.setCursor(52, 2); ((activeColumn == 2) && (camSelectedMainItem == 0) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); if (camFocusGap < 10) lcd.print(" "); if (camFocusGap < 100) lcd.print(" "); lcd.print(camFocusGap); lcd.print(":"); if (camShutterHold == 0) lcd.write(172); if (camShutterHold == 1) lcd.write(171); if (camShutterHold == 2) lcd.print("1"); if (camShutterHold == 3) lcd.print("2"); // If cursor is in 'Values' column , print values for 'Timer' lcd.setCursor(52, 12); ((activeColumn == 2) && (camSelectedMainItem == 1) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); if (camTimerDelayValues[camSelectedTimerDelay] < 10) lcd.print(" "); lcd.print(camTimerDelayValues[camSelectedTimerDelay]); lcd.print(camSelectedTimerUnit); lcd.print(" "); (camSelectedTimerRepeat == 0 ? lcd.print("r") : lcd.print(camSelectedTimerRepeat)); camActualTimerDelay = multiply(camSelectedTimerUnit, camSelectedTimerDelay); // If cursor is in 'Values' column , print values for 'Bulb' lcd.setCursor(52, 22); ((activeColumn == 2) && (camSelectedMainItem == 2) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); if (camTimerDelayValues[camSelectedBulbDelay] < 10) lcd.print(" "); lcd.print(camTimerDelayValues[camSelectedBulbDelay]); lcd.print(camSelectedBulbUnit); camActualBulbDelay = multiply(camSelectedBulbUnit, camSelectedBulbDelay); lcd.display(); } // Flash Menu void showTab2() { drawTabs(); lcd.drawRect(0, 11, 10, 10, BLACK); // Draw Tab. lcd.drawLine(9, 12, 9, 19, WHITE); // Remove rectangle edge for Tab to blend into Tab Page. // Print Menu Item Names - highlight if it is the selected item for (int i = 0; i < 3; i++) { lcd.setCursor(12, 10 * i +2); ((activeColumn == 1) && (flashSelectedMainItem == i) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); if (i == 2) { lcd.write(1);lcd.print(" "); lcd.write(26);lcd.print(" *"); } else { lcd.print(flashMainItemsNames[i]); } } // If cursor is in 'Values' column , print values for 'Slave' lcd.setCursor(52, 2); ((activeColumn == 2) && (flashSelectedMainItem == 0) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); lcd.print(flashSlaveModes[flashSelectedSlaveMode]); // Auto, or 0, 1, 2, 3, 4 pre-flashes. // If cursor is in 'Values' column , print values for 'Hi-Speed' lcd.setCursor(52, 12); ((activeColumn == 2) && (flashSelectedMainItem == 1) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); if (flashHiSpeedDelay < 10) lcd.print(" "); if (flashHiSpeedDelay < 100) lcd.print(" "); lcd.print(flashHiSpeedDelay); lcd.print(" "); lcd.print(flashHiSpeedUnits[flashSelectedHiSpeedUnit]); (flashSelectedHiSpeedUnit == 1 ? flashActualHiSpeedDelay = flashHiSpeedDelay * 1000 : flashActualHiSpeedDelay = flashHiSpeedDelay); // If cursor is in 'Values' column , print values for 'Cam -to- Flash' lcd.setCursor(52, 22); ((activeColumn == 2) && (flashSelectedMainItem == 2) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); if (flashFromCam == 0) lcd.print("Off "); if (flashFromCam == 1) {lcd.print("* "); lcd.write(26); lcd.print(" *");} if (flashFromCam == 2) {lcd.write(175); lcd.print(" ");lcd.write(26); lcd.print(" *");} if (flashFromCam == 3) {lcd.print("* ");lcd.print("w"); lcd.print(" *");} if (flashFromCam == 4) {lcd.write(175);lcd.print(" ");lcd.print("w"); lcd.print(" *");} lcd.display(); } // Setup menu void showTab3() { drawTabs(); lcd.drawRect(0, 21, 10, 10, BLACK); // Draw Tab. lcd.drawLine(9, 22, 9, 29, WHITE); // Remove rectangle edge for Tab to blend into Tab Page. // Print Menu Item Names - highlight if it is the selected item for (int i = 0; i < 3; i++) { lcd.setCursor(12, 10 * i +2); ((activeColumn == 1) && (setupSelectedMainItem == i) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); lcd.print(setupMainItemsNames[i]); } // If cursor is in 'Values' column , print value for 'Contrast' lcd.setCursor(52, 2); ((activeColumn == 2) && (setupSelectedMainItem == 0) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); lcd.print(setupContrast); // If cursor is in 'Values' column , print values for 'Backlight Brightness and TestMode' lcd.setCursor(52, 12); ((activeColumn == 2) && (setupSelectedMainItem == 1) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); lcd.print(" "); lcd.write(setupBkLtOpt[setupSelectedBkLtOpt]); lcd.print(" "); (testMode == 0 ? lcd.print(" ") : lcd.write(2)); lcd.setTextColor(BLACK); // If cursor is in 'Values' column , print values for 'Backlight timer' lcd.setCursor(52, 22); ((activeColumn == 2) && (setupSelectedMainItem == 2) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); lcd.print(BkTimer); lcd.print("s"); lcd.display(); } // Draw common framework for Tab1, Tab2 and Tab3 void drawTabs() { lcd.clearDisplay(); lcd.setTextColor(BLACK); // May have been left WHITE // Draw main Tab Page and Icons in left column. lcd.drawRect(9, 0, 75, 48, BLACK); lcd.drawLine(9, 35, 82, 35, BLACK); lcd.drawLine(48, 0, 48, 48, BLACK); lcd.setCursor(2, 2); ((activeMenu == 0) && (activeColumn == 0) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); lcd.write(1); // camera symbol lcd.setCursor(2, 12); ((activeMenu == 1) && (activeColumn == 0) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); lcd.print("*"); lcd.setCursor(2, 22); ((activeMenu == 2) && (activeColumn == 0) ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); lcd.write(2); // spanner symbol lcd.setTextColor(BLACK); lcd.setCursor(3, 37); lcd.write(3); // battery symbol lcd.setCursor(12, 38); float volts = readVcc(); if ((volts < 3100) || (volts > 4300)) { digitalWrite(Vcc, LOW); LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); } int v; if (volts >= 3600) { v = 40; } else if ((v < 3600) && (v >= 3200)) { } else v = 44; lcd.drawLine(4, v, 4, 44, BLACK); (volts < 3200 ? lcd.setTextColor(WHITE, BLACK) : lcd.setTextColor(BLACK)); lcd.print(volts/1000); lcd.print("v"); lcd.setCursor(54, 38); lcd.setTextColor(BLACK); (delta >0 ? lcd.write(24) : lcd.write(25)); lcd.print(abs(delta)); } /***************************************************************************************** Utility routines *****************************************************************************************/ // Interrupt handler for rotary encoder void rotaryEncoder() { if (!adjustAllowed) return; if ((activeMenu == 0) &&(camSelectedMainItem == 0) && (activeColumn == 2)) { if ((digitalRead(INT0) == digitalRead(INT1)) && (camFocusGap > 10)) camFocusGap-=10 ; if ((digitalRead(INT0) != digitalRead(INT1)) && (camFocusGap < 990)) camFocusGap+=10 ; eepromSaved4 = false; return; } if ((activeMenu == 1) && (flashSelectedMainItem == 1) && activeColumn == 2) { if ((digitalRead(INT0) == digitalRead(INT1)) && (flashHiSpeedDelay > 10)) flashHiSpeedDelay -= 10 ; if ((digitalRead(INT0) != digitalRead(INT1)) && (flashHiSpeedDelay < 990)) flashHiSpeedDelay += 10 ; eepromSaved9 = false; return; } analogWrite(LED, setupTabLED); ledTimer = millis(); (digitalRead(INT0) == digitalRead(INT1) ? delta-= 1 : delta+= 1); delta = constrain(delta, -250, 250); eepromSaved2 = false; } // Determine 'units' from value's position in Timer and Bulb arrays char* getUnits(int value) { char* result = "s"; if (value < 6) result = "s"; if ((value > 5) && (value < 12)) result = "m"; if (value > 11) result = "h"; return result; } // Calculate actual timer value from units unsigned long multiply(char* unit, int value) { unsigned long result = 1000; if (unit == "s") result = camTimerDelayValues[value]; if (unit == "m") result = camTimerDelayValues[value] * 60; if (unit == "h") result = camTimerDelayValues[value] * 3600; return result; } // Get Battery Voltage long readVcc() { long result; // Read 1.1V reference against AVcc ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Convert while (bit_is_set(ADCSRA,ADSC)); result = ADCL; result |= ADCH<<8; result = 1113000L / result; // Back-calculate AVcc in mV return result; } // Integer EEPROM routines (two bytes) Required for Hi-Sppeed Timer and delta void EEPROMWriteInt(int p_address, int p_value) { byte lowByte = ((p_value >> 0) & 0xFF); byte highByte = ((p_value >> 8) & 0xFF); EEPROM.write(p_address, lowByte); EEPROM.write(p_address + 1, highByte); } unsigned int EEPROMReadInt(int p_address) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); }
|