/* Copyright (c) 2016 Mike Sterzer. https://hackaday.io/AfroSpock. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include // Load the LiquidCrystal library LiquidCrystal lcd (A1, A2, A3, 10, 9, 8); // initialize the lcd library with the numbers of the interface pins byte playSymbol[8] = { 0x18, 0x1C, 0x1E, 0x1F, 0x1F, 0x1E, 0x1C, 0x18 }; byte pauseSymbol[8] = { 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B }; int shutterPin = A4; // Output pin to trigger the shutter int focusPin = A5; // Output pin to trigger the focus int lcdPin = A0; // Output pin to set the back-light brightness int shutterState = LOW; // state used to set the shutter int focusState = LOW; // state used to set the focus long previousMillis = 0; // will store the last time shutter was updated int taken = 0; // used to count the pictures taken // these are for controlling the buttons const int increaseButton = 7; // Input pin to increase the interval const int decreaseButton = 6; // input pin to decrease the interval const int modePin = 5; // this sets the input pin for the mode button const int startPin = 4; // this is the pin for the start button int buttonStateUp = 0; int buttonStateDown = 0; int lastButtonUp = 0; int lastButtonDown = 0; // when switched into mode 0 this will trigger the first time through the loop, every time it gets brought back to mode 0 int timelapseCount = 0; int interval = 1; //this section contains the variables for astro-photography unsigned long astroInt = 1; unsigned long astroMillis = 0; int astroMessage = 0; // these are for the mode button int modeState = LOW; // this holds the current state of the mode button int lastMode = LOW; // this holds the previous one for comparison int modeCount = 0; // this is used to set the mode into switch-case argument // these are for the start/stop button int startState = LOW; // this holds the current state of the start button int lastStart = LOW; // this holds the last state of the start button for comparison int startCount = 0; //these assist in controlling the lcd int screenResetCounter = 0; unsigned long fadeMillis = 0; //these are used in debouncing inputs unsigned long lastDebounce = 0; unsigned long debounceDelay = 20; //sets the debounce delay int lastInterval = 0; int takenDisplay = 0; void setup() { pinMode(shutterPin, OUTPUT); pinMode(focusPin, OUTPUT); pinMode(lcdPin, OUTPUT); pinMode(increaseButton, INPUT); pinMode(decreaseButton, INPUT); pinMode(modePin, INPUT); pinMode(startPin, INPUT); lcd.begin(20, 4); lcd.createChar(1, playSymbol); lcd.createChar(2, pauseSymbol); } void loop() { //this section controls the button state counter int readUp = digitalRead(increaseButton); int readDown = digitalRead(decreaseButton); int readMode = digitalRead(modePin); int readStart = digitalRead(startPin); if (readMode != lastMode) { lastDebounce = millis(); } if ((millis() - lastDebounce) > debounceDelay) { if (readMode != modeState) { modeState = readMode; if (modeState == HIGH) { modeCount++; } } } lastMode = readMode; // if mode count gets to 2 set it equal to 0. With subsequent button presses it always turns over back to 0 if (modeCount == 2) { modeCount = 0; } //this section determines the function of the start button if (readStart != lastStart) { lastDebounce = millis(); } if ((millis() - lastDebounce) > debounceDelay) { if (readStart != startState) { startState = readStart; if (startState == HIGH) { startCount++; }}} lastStart = readStart; if (startCount == 2) { startCount = 0; } interval = max(interval, 1); unsigned long finInt = interval * 5000; // multiplies newPosition by 1000 for the variable interval. unsigned long currentMillis = millis(); //equates it to the variable currentMillis if (currentMillis < 3000) { digitalWrite(lcdPin, HIGH); delay(500); lcd.setCursor(0,0); lcd.print(" INTERVALO-THINGY "); lcd.setCursor(0,1); lcd.print("Push buttons."); lcd.setCursor(0,2); lcd.print("Enjoy!"); lcd.setCursor(0,3); lcd.print(" -Mike Sterzer"); delay(5000); lcd.clear(); fadeMillis = currentMillis; } //fade the back-light if there hasn't been a button press for 15 seconds if (buttonStateUp == HIGH || buttonStateDown == HIGH || modeState == HIGH || startState == HIGH) { fadeMillis = currentMillis; digitalWrite(lcdPin, HIGH); } if (currentMillis - fadeMillis > 15000) { digitalWrite(lcdPin, LOW); } /*____________________________________ _______TIME LAPSE MODE SECTION_____!!! ____________________________________*/ if (modeCount == 0) { astroMessage = 0; timelapseCount++; if (timelapseCount == 1) { startCount = 0; lcd.clear(); } if (timelapseCount == 3){ timelapseCount = 2; } if ((millis() - lastDebounce) > debounceDelay) { if (readUp != buttonStateUp) { buttonStateUp = readUp; if (buttonStateUp == HIGH) { interval++; }}} lastButtonUp = readUp; if (readDown != lastButtonDown) { lastDebounce = millis(); } if ((millis() - lastDebounce) > debounceDelay) { if (readDown != buttonStateDown) { buttonStateDown = readDown; if (buttonStateDown == HIGH) { interval--; }}} lastButtonDown = readDown; lcd.setCursor(0,0); lcd.print(" TIME-LAPSE MODE "); lcd.setCursor(0,1); lcd.print("Int(sec): "); lcd.print(interval * 5); lcd.setCursor(0,3); lcd.print("# Taken: "); lcd.print(takenDisplay); lcd.setCursor(0,2); lcd.print("Run: "); if (startCount == 0) { lcd.write(2); shutterState = LOW; digitalWrite(shutterPin, shutterState); } if (startCount == 1) { lcd.write(1); } //taken = max(taken, 0); //int takenCount; if (currentMillis - previousMillis > finInt && startCount == 1) { shutterState = HIGH; digitalWrite(shutterPin, shutterState); } if (currentMillis - previousMillis > finInt + 500 && startCount == 1) { shutterState = LOW; digitalWrite(shutterPin, shutterState); focusState = LOW; digitalWrite(focusPin, focusState); previousMillis = currentMillis; taken++; takenDisplay = taken - 1; } if (currentMillis - previousMillis > finInt - 1000 && startCount == 1 && taken % 10 == 0) { focusState = HIGH; digitalWrite(focusPin, focusState); } if (lastInterval != interval) { lcd.setCursor(15,1); lcd.print(" "); lastInterval = interval; } //screenResetCounter++; //if (screenResetCounter % 6 == 0) { //lcd.setCursor(16,1); //lcd.print(" "); //screenResetCounter = 0; //} } /*_______________________________ _______ASTRO MODE SECTION_____!!! _______________________________*/ if(modeCount == 1) { astroMessage++; if (astroMessage == 1) { //astroMillis = millis(); startCount = 0; taken = 0; lcd.clear(); timelapseCount = 0; } if (astroMessage == 3) { astroMessage = 2; } if ((millis() - lastDebounce) > debounceDelay) { if (readUp != buttonStateUp) { buttonStateUp = readUp; if (buttonStateUp == HIGH) { astroInt++; }}} lastButtonUp = readUp; if (readDown != lastButtonDown) { lastDebounce = millis(); } if ((millis() - lastDebounce) > debounceDelay) { if (readDown != buttonStateDown) { buttonStateDown = readDown; if (buttonStateDown == HIGH) { astroInt--; }}} lastButtonDown = readDown; unsigned long astroMid = astroInt * 30000; lcd.setCursor(0,1); lcd.print("Period(x30s): "); lcd.print(astroInt); astroInt = max(astroInt, 1); if (shutterState == HIGH) { lcd.setCursor(0,3); lcd.print("Lapsed Time: "); lcd.print((millis() - astroMillis) / 1000); if ((millis() - astroMillis) > astroMid) { startCount = 0; }} if (shutterState == LOW) { lcd.setCursor(0,0); lcd.print(" ASTRO MODE "); lcd.setCursor(0,2); lcd.print("Run: "); lcd.write(2); lcd.setCursor(0,3); lcd.print(" "); astroMillis = millis(); } if (startCount == 0) { shutterState = LOW; digitalWrite(shutterPin, shutterState); } if (startCount == 1) { shutterState = HIGH; digitalWrite(shutterPin, shutterState); lcd.setCursor(0,0); lcd.print(" ASTRO MODE "); lcd.setCursor(0,2); lcd.print("Run: "); lcd.write(1); } screenResetCounter++; if (screenResetCounter % 8 == 0) { lcd.setCursor(14,1); lcd.print(" "); screenResetCounter = 0; } } }