Hi Noah.
Here's a quick draft at what I think you want to do.
Instead of writing pseudo-code in english, I wrote it in a real language (ruby). You should be able to read it as though it were pseudocode, and we have the benefit of knowing I tested it and it works. Your job is to grok it and see if it's what you want, steal ideas from it, or use it to help describe to us what you actually wanted, if it's not this.
On mac os x you should be able to run this program and view the output, to confirm the behaviour is what you want. on other platforms, you'll have to first install ruby. Save the program as solenoids.rb and run ruby solenoids.rb
at the command line. Use ctrl-c to stop the program.
#polyrhythmic solenoids pseudocode (actually, in ruby)
#constants -----
LOW = 0
HIGH = 1
NUMBER_OF_SWITCHES = 4
SLEEP_PERIOD=0.5 #this should be lowest common denominator of all on_durations
#how long (in seconds) each switch should go high for (in your example all are 500ms)
$on_duration=[0.5, 0.5, 0.5, 0.5]
#periodicity (in seconds) with which each solenoid cycles
$period=[2, 5, 8, 13]
#program-maintained info -----
#calculated time at which each solenoid should next change state
$next_time=[0,0,0,0]
#current state of each solenoid (as understood by the program)
$state = [LOW, LOW, LOW, LOW]
def update_switches(current_time)
for i in 0...NUMBER_OF_SWITCHES do
#if it is time to change this switch...
if current_time >= $next_time[i]
#change state and
if $state[i]==LOW
$state[i]=HIGH
#TODO: change your solenoid HIGH here
#set the next_time we should change this switch's state
$next_time[i] = $next_time[i]+$on_duration[i]
else
$state[i]=LOW
#TODO: change your solenoid LOW here
#TODO: Decide if like me you want to subtract on_duration[i] from this...
$next_time[i] = $next_time[i] + $period[i] - $on_duration[i]
end
end
end
end
#just for ruby version.
def show_switches(current_time)
for i in 0...NUMBER_OF_SWITCHES do
print "%s " % $state[i]
end
puts "PERIOD: %s TIME: %.1f NEXT_TIME: %s" % [$period.join(','), current_time, $next_time.join(",")]
end
#just for ruby version - emulate arduino delay(milli)
def delay(ms)
sleep(ms/1000.0)
end
#main stuff here
current_time = 0
#this "while" represents your arduino loop()
while true do
update_switches(current_time)
#show states e.g. on LEDs
show_switches(current_time)
delay(SLEEP_PERIOD * 1000)
current_time = current_time + SLEEP_PERIOD
end
Note that I've incorporated the time each solenoid spent in its HIGH state when calculating the next_time for a state transition. This isn't what you asked for - you asked for 500ms on, 10s off, 500ms on, 10s off. But this gives you a period of 10.5 seconds, instead of 10 seconds as I think you might have meant! It's easily fixed if not.
Problem 1.
I've worked with floating point values. You should NOT do this in arduino, but should move everything to be in integer values. In doing this conversion you'll have to be careful in deciding what type of variable to use to store the "next time" array. Be careful that the next_time[] values don't get too big for their storage type and wrap round to zero.
If you need to work in sub-second periods, decide what's a small enough interval; in your case perhaps 10ths of a second. There are 10 x 60 x 60 x 24 tenths of a second in a day; make sure you can store a value that high, if you want it to run for one day, for example. Just don't think about using floating point values.
Problem 2.
This current version will drift slightly over time, because I haven't used the arduino clock, rather just kept a rough counter (current_time) of what time has elapsed (and this doesn't take into consideration the time spent in the other parts of the loop). In this version, your solenoids WILL stay quantized relative to each other, but their collective idea of 2 seconds might be 2.001 seconds, so they will be like the three hands on a slow-running wall-clock: half a revolution for the minute hand will be exactly a 24th of a revolution of the hour hand as expected, but it WON'T be exactly 30 minutes real time.
It's easy to fix this: Draw current_time in milliseconds from the arduino instead of maintaining it yourself. At the start of the program, get the current time from the arduino and set this as the next_time for each solenoid.
For other readers, I hope it is obvious that this solution has nothing really to do with solenoids and can be used wherever.
hope this helps,
neillzero