DanLRC:
Wow...thank you all for the quick and extensive feedback!
I have the mechanical and basic electronics (LEDs, relays, etc) covered, just not at all familiar with boards and programming.
as I see the programming
once you set smoke_Cannon_1 to fire
the heater is turned on
2.5000 seconds later the solenoid is opened
2.600 seconds from start the LED is turned on
2.7 seconds from start, the LED is turned off
2.9 seconds, the LED is turned on
3.2 seconds, it is turned off
3.3 seconds the heater is turned off
3.7 seconds the solenoid is turned off
all the while that this is going on, other cannons are in similar sequences, but at different points in them.
blink without delay is your friend here.
there is a main system clock that you can use to access for timing.
start = millis() will set start to that point in time.
fire1 gets it's value from your switch or other input.
if fire1_active == 0 ; // ready
start1=millis() // keeps start1 at 0 until fire1 command is given
if (fire1 == activated) // this is your command to fire
fire1_active = 1 ; // sets the flag to show it is in the timing cycle
digitalWrite(heater1, HIGH)
see how you set start1 with a system time.
but then it will not change that as long as you are in the active loop after the fire command is given.
fire1_timing = millis()-start1 ; // this would do the stopwatch math function and constantly set the time since start
it would be 0 all the time, until the fire1 command is given and start1=millis() is no longer being set on each loop.
start1=millis() will record the time that the fire1 command was given and not be re-set until after the entire firing sequence is complete.
if fire1_timeing >= 2500 // 2.5 seconds
digitalWrite(solenoid1, HIGH) // after 2.5 seconds open the solenoid
if fire1_timing >= 2600 // 2.6 seconds
digitalWrite(LED1, HIGH)
if fire1_timing >= 2700
digitalWrite(LED1, LOW)
if fire1_timing >= 2900
digitalWrite(LED1, HIGH)
if fire1_timing >= 3300
digitalWrite(LED1, LOW)
if fire1_timing >= 3500
digitalWrite(heater, LOW)
if fire1_timing >= 3700
digitalWrite(solenoid1,LOW)
fire1_active = 0 ; // resets the flag to show it is in the timing cycle
since after 3700 milliseconds have passed, and the entire firing sequence has run it's course, you can re-set the fire1_active flag so that this timing loop will only see a 0 millisecond result.
this is not real code but if you look at it, you can see how you have one running clock time for one cannon as the stopwatch for that cannon.
it allows you to have other cannons have their own times.
if you look at the timing, you can easily set the milliseconds at any stage so you can create the timing effect you want.
this NOT code, but a general idea of only one way you could do this.
this is more for your understanding of one way to use the system clock, millis() for your project.
this is really not working code because it does not prevent the bits to turn on when they should be off, or turn off, when they should be on.
you would want to say
if 2500 milliseconds have passed.... I want to turn on the solenoid and then leave it on
if 3700 milliseconds have passed, turn it off and leave it off
but, since 3700 is greater than 2500, the first 'turn on' will turn it on, but and instant later it would be turned off because it was over 2500, but also over 3700...
you should say, if it is over 2500 and also under 3700, turn it on.
there are other ways, but for a single timing process, I find this easy to follow and understand
or, you can add a flag that knows it is on.
if solenoid1 == LOW
if fire1_timeing >= 2500 // 2.5 seconds
digitalWrite(solenoid1, HIGH) // after 2.5 seconds open the solenoid
this would prevent it from being turned on a second time, but adds more lines (clutter) when discussing the general idea.