I have posted some code below which may work for you.
Caveat:
The code compiles for an Uno using the Arduino IDE version 1.8.1. That does not mean that it will compile for an ATTiny, and that does not mean that it will execute correctly.
I salute you for working with an ATTiny. I have never tried to compile for an ATTiny.
An ATTiny does not have a Serial port, so I should not have mentioned pins 0 and 1. Sorry.
I do not have your hardware, so I have not tested this code.
Furthermore, some of my questions were never answered.
Furthermore, the requirements had some ambiguities in them.
Furthermore, the requirements had some contradictions in them.
Furthermore, I may have made mistakes.
This code is a starting point. You may have to adjust it for your purposes, but it may show you how to get from requirements to code.
There are some "else" statements that are empty (except for a comment). They could be omitted but I kept them to make it more clear what is happening.
A "switch/case" statement is just an advanced way of doing a series of "if/else if" statements.
Some of the variables and some of the states should have better names based on what the system does rather than how the system does something, but I did not have more information.
There are some things that I could have done to save space or save time, but I did not want to get too tricky... yet.
Is this code more complex than the original interrupt-based register-based code? Yes, but it will be easier to debug and the use of digitalRead(...), digitalWrite(...), and pinMode(...) makes the code more easily transferred to other types of Arduinos.
Good Luck!
const int CAMERA_PIN = 3;
const int SHUTTER_PIN = 4;
const int IN_PIN = 2;
// These are times, specified in milliseconds. Adjust as necessary.
const unsigned long ARMED = 120000 ;
const unsigned long DISARMED = 500 ; // Not specified, adjust as
// necessary.
const unsigned long SHUTTER_HOLD = 100 ;
const unsigned long CAMERA_HOLD = 1000 ;
// End of times.
/*
Here is code for defining the states and making use of them,
but there is a better way using enum that is shown lower down
in a comment.
*/
const int SET_SHUTTER_LOW = 100 ;
const int SET_CAMERA_HIGH = 200 ;
const int WAIT_CAMERA_HIGH = 300 ;
const int SET_CAMERA_LOW = 400 ;
const int WAIT_CAMERA_LOW = 500 ;
const int MAKE_CAMERA_HIGH = 1000 ;
const int MAKE_SHUTTER_HIGH = 2000 ;
const int TIME_SHUTTER_HIGH = 3000 ;
const int MAKE_SHUTTER_LOW = 4000 ;
const int MAKE_CAMERA_LOW = 5000 ;
const int TIME_CAMERA_LOW = 6000 ;
const int NO_INTERRUPTION_YET = 7000 ;
int loopState = SET_SHUTTER_LOW ;
int interruptionState = NO_INTERRUPTION_YET ;
/*
End of code for defining the states and making use of them.
*/
/*
Here is better code for defining the states and making use of them,
and it has some advantages, but this code is more advanced and is
therefore commented out.
enum LoopStates {
SET_SHUTTER_LOW,
SET_CAMERA_HIGH, WAIT_CAMERA_HIGH,
SET_CAMERA_LOW, WAIT_CAMERA_LOW
} ;
enum InterruptionStates {
MAKE_CAMERA_HIGH, MAKE_SHUTTER_HIGH, TIME_SHUTTER_HIGH,
MAKE_SHUTTER_LOW, MAKE_CAMERA_LOW, TIME_CAMERA_LOW,
NO_INTERRUPTION_YET
};
LoopStates loopState = SET_SHUTTER_LOW ;
InterruptionStates interruptionState = NO_INTERRUPTION_YET ;
End of better code for defining the states and making use of them.
*/
unsigned long loopStartMillis ;
unsigned long interruptionStartMillis ;
void setup()
{
pinMode(CAMERA_PIN, OUTPUT) ;
pinMode(SHUTTER_PIN, OUTPUT) ;
digitalWrite(CAMERA_PIN, LOW) ;
digitalWrite(SHUTTER_PIN, LOW) ;
pinMode(IN_PIN, INPUT);
// I am going to assume that there is a
// normally open (NO) pushbutton
// switch connected from this pin to the Vcc of the
// Arduino, and a pulldown resistor connected from
// this pin to ground (GND).
// Thus, there is an assumption that when the
// pushbutton is NOT pressed, this pin is LOW,
// and when the pushbutton is pressed,
// this pin is HIGH.
// Serial.begin(115200) ;
}
void loop()
{
unsigned long currentMillis = millis() ; // This variable is
// local to this function.
switch (loopState) {
case SET_SHUTTER_LOW:
digitalWrite(SHUTTER_PIN, LOW) ;
loopState = SET_CAMERA_HIGH ;
break ;
case SET_CAMERA_HIGH:
digitalWrite(CAMERA_PIN, HIGH) ;
loopStartMillis = currentMillis ;
loopState = WAIT_CAMERA_HIGH ;
break ;
case WAIT_CAMERA_HIGH:
if (currentMillis - loopStartMillis >= ARMED) {
loopState = SET_CAMERA_LOW ;
} else {
while (triggered()) ;
}
break ;
case SET_CAMERA_LOW:
digitalWrite(CAMERA_PIN, LOW) ;
loopStartMillis = currentMillis ;
loopState = WAIT_CAMERA_LOW ;
break ;
case WAIT_CAMERA_LOW:
if (currentMillis - loopStartMillis >= DISARMED) {
loopState = SET_SHUTTER_LOW ;
} else {
// Do nothing... Keep waiting.
}
break ;
default:
// Serial.print("***** BAD loopState=") ;
// Serial.println(loopState) ;
while (true) ; // Hang here forever, intentionally.
break ;
}
}
bool triggered() {
unsigned long currentMillis = millis() ; // This variable is
// local to this function.
bool result = false ;
if ((interruptionState == NO_INTERRUPTION_YET) && (digitalRead(IN_PIN) == HIGH)) {
interruptionState = MAKE_CAMERA_HIGH ;
return true ;
} else {
switch (interruptionState) {
case MAKE_CAMERA_HIGH:
digitalWrite(CAMERA_PIN, HIGH) ; // Unnecessary but harmless.
interruptionState = MAKE_SHUTTER_HIGH ;
result = true ;
break ;
case MAKE_SHUTTER_HIGH:
digitalWrite(SHUTTER_PIN, HIGH) ;
interruptionStartMillis = currentMillis ;
interruptionState = TIME_SHUTTER_HIGH ;
result = true ;
break ;
case TIME_SHUTTER_HIGH:
if (currentMillis - interruptionStartMillis >= SHUTTER_HOLD) {
interruptionState = MAKE_SHUTTER_LOW ;
} else {
// Do nothing... Keep waiting.
}
result = true ;
break ;
case MAKE_SHUTTER_LOW:
digitalWrite(SHUTTER_PIN, LOW) ;
interruptionState = MAKE_CAMERA_LOW ;
result = true ;
break ;
case MAKE_CAMERA_LOW:
digitalWrite(CAMERA_PIN, LOW) ;
// Requirements say to do
// this but it is
// in opposition to what the loop()
// function did ;
interruptionStartMillis = currentMillis ;
interruptionState = TIME_CAMERA_LOW ;
result = true ;
break ;
case TIME_CAMERA_LOW:
if (currentMillis - interruptionStartMillis >= CAMERA_HOLD) {
digitalWrite(CAMERA_PIN, HIGH) ;
interruptionState = NO_INTERRUPTION_YET ;
} else {
// Do nothing... Keep waiting.
}
result = true ;
break ;
case NO_INTERRUPTION_YET:
result = false ;
break ;
default:
// Serial.print("***** BAD interruptionState=") ;
// Serial.println(interruptionState) ;
while (true) ; // Hang here forever, intentionally.
break ;
}
}
return result ;
}