If you can write down all the required timings, it becomes much easier to figure out what you need to do inside the loop.
Start off defining what you want to do:
- blink this LED for 0.2s every 1.5s, initially off (i.e.: 1.3s off, 0.2s on)
- blink the other LED for 0.5s every 2.1s, initially on (i.e.: 0.5s on, 1.6s off)
Now you write a loop something like this (I'm at work, no Arduino here, can't test):
#define LED1 0
#define LED2 1
int LED1_state;
int LED2_state;
void setup () {
LED1_state = LOW;
LED2_state = HIGH;
digitalWrite( LED2, LED2_state );
digitalWrite( LED1, LED1_state );
}
void loop () {
int current_millis = millis();
int elapsed_millis;
# Handle LED1
if ((current_millis % 1500) < 1300 and (LED1_state == HIGH)) {
LED1_state = LOW;
digitalWrite( LED1, LED1_state );
}
if ((current_millis % 1500) >= 1300 and (LED1_state == LOW)) {
LED1_state = HIGH;
digitalWrite( LED1, LED1_state );
}
# Handle LED2
if ((current_millis % 2100) < 500 and (LED2_state == LOW)) {
LED2_state = HIGH;
digitalWrite( LED2, LED2_state );
}
if ((current_millis % 2100) >= 500 and (LED2_state == HIGH)) {
LED2_state = LOW;
digitalWrite( LED2, LED2_state );
}
# For debugging purposes, report how long these instructions took to execute.
elapsed_millis = millis() - current_millis;
Serial.println( elapsed_millis );
}
What I'm doing here is simply dividing mills into chunks the same length as the cycle time of the thing in question - in this case I'm blinking two LEDs. One cycle time is 1.5s or 1500ms, so find the "remainder" of "number of milliseconds the Arduino has been running" by the cycle time (to forget about completed cycles) and the remainder will tell us how far through this cycle we are.
In the comparisons, I use "greater than" or "less than" rather than checking for equality, since you can never guarantee that the Arduino will start the cycle on the exact millisecond that you're interested in.
Thus we start at 0 with LED1 turned off and LED2 turned on, in the setup function.
Once millis() returns a value that is greater than or equal to 500, LED2 will be turned off. Then when millis() is greater than 1300 LED1 will be turned on, then shortly after 2100ms (when mills() % 2100 is between 0 and 500) LED2 will be turned on again. I save the state of the LED because any reads or writes take a lot of time and you want to avoid them if possible. There are probably other reasons to avoid setting a high pin to high again, or a low pin to low - I don't know how the guts of the system work so I'll just avoid doing pointless work. You can verify how long a digitalWrite takes by taking the relevant tests out of the if statements and seeing how the elapsed time per loop changes.
So back to the original problem:
if (active == 1)
{ digitalWrite (motorPin, 0);
digitalWrite (wake, HIGH);
delay (200);
digitalWrite (wake, LOW);
delay(800);
digitalWrite (shutter, HIGH);
delay(100);
digitalWrite (shutter, LOW);
delay(900);
{motorVal = analogRead (AnalogmotorPin);
if (motorVal/4 <65) analogWrite (motorPin, 0);
if (motorVal/4 >66) analogWrite (motorPin, motorVal/4);}
delay(ShotSpacing-2000);}
It appears that there is a sequence of waking (the camera?), activating (the shutter?), then doing other stuff, and finally waiting a period of time to ensure the cycle is completed on a predefined interval.
- At 0ms, wake the camera
- At 200ms, no longer wake the camera
- At 1000ms, trigger the shutter
- At 1100ms, turn off shutter trigger
- At 2000ms, fiddle with stuff
Translated roughly, this will become:
int camera_state = 0;
int shot_spacing = 4000;
void loop () {
int current_millis = millis();
int elapsed_millis;
# Handle LED1
if ((current_millis % 1500) < 1300 and (LED1_state == HIGH)) {
LED1_state = LOW;
digitalWrite( LED1, LED1_state );
}
if ((current_millis % 1500) >= 1300 and (LED1_state == LOW)) {
LED1_state = HIGH;
digitalWrite( LED1, LED1_state );
}
int time_in_cycle = current_millis % shot_spacing;
if ((camera_state ==0) and (time_in_cycle < 200)) {
camera_state = 1;
digitalWrite( wake, HIGH );
}
if ((camera_state==1) and (time_in_cycle >= 200)) {
camera_state = 2;
digitalWrite( wake, LOW );
}
if ((camera_state==2) and (time_in_cycle >= 1000)) {
camera_state = 3;
digitalWrite( shutter, HIGH );
}
if ((camera_state==3) and (time_in_cycle >= 1100)) {
camera_state = 4;
digitalWrite( shutter, LOW );
}
if ((camera_state==4) and (time_in_cycle >= 2000)) {
camera_state = 0;
# fiddle with stuff
}
}
But as I've said, I haven't tested that code. Also, this code is incompatible with interrupts since millis will not be tracked when the Arduino is handling interrupts.