Go Down

Topic: control 8 digital outs at same time??? (Read 1 time) previous topic - next topic


I am trying to control 8 solenoids from digital outs all with independent on / off times

for example...

solenoid1 on for 500ms then off for 20 seconds.
solenoid2 on for 500ms then off for 30 seconds.
solenoid3 on for 500ms then off for 35 seconds.
solenoid4 on for 500ms then off for 40 seconds.
solenoid5 on for 500ms then off for 50 seconds.
solenoid6 on for 500ms then off for 55 seconds.
solenoid7 on for 500ms then off for 62 seconds.
solenoid8 on for 500ms then off for 70 seconds.

all cycles going at the same time for ever and ever... (mabye 9 1/2 hours will have to do.)

I have the circuits working but I can't figure out how to write the code to make them work all at the same time poly-rhythmically.

What don't am I doing wrong?

I am on a tight deadline and any help would be greatly appreciated.




Feb 04, 2007, 09:50 am Last Edit: Feb 04, 2007, 09:54 am by Daniel Reason: 1
what have you written for code so far? You'll need to be a bit more specific about what goes first.. is it a sequence or do they all trigger simultaneously?


I want them all to be cycling at the same time. They should all start at the same time then get off from each other via there time.

Not a sequence - they all trigger simultaneously.

Any examples of code would be great to look at.

Thanks again,


Feb 04, 2007, 02:04 pm Last Edit: Feb 04, 2007, 02:24 pm by neillzero Reason: 1
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.

Code: [Select]
#polyrhythmic solenoids pseudocode (actually, in ruby)

#constants -----
LOW = 0
HIGH = 1

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

#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
       #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]
       #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]

#just for ruby version.  
def show_switches(current_time)
 for i in 0...NUMBER_OF_SWITCHES do
   print "%s " % $state[i]

 puts "PERIOD: %s  TIME: %.1f  NEXT_TIME: %s" % [$period.join(','), current_time, $next_time.join(",")]

#just for ruby version - emulate arduino delay(milli)
def delay(ms)

#main stuff here
current_time = 0

#this "while" represents your arduino loop()
while true do


 #show states e.g. on LEDs

 delay(SLEEP_PERIOD * 1000)

 current_time = current_time + SLEEP_PERIOD

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,


Noah, here's a bit of the (tidied) output from the program above, to allow you to check quickly if it's what you want.

(4 solenoids, with periods of 2, 5, 8, 13)

Code: [Select]

1 1 1 1 TIME:  0.0  NEXT_TIME: 0.5,0.5,0.5,0.5
0 0 0 0 TIME:  0.5  NEXT_TIME: 2.0,5.0,8.0,13.0
0 0 0 0 TIME:  1.0  NEXT_TIME: 2.0,5.0,8.0,13.0
0 0 0 0 TIME:  1.5  NEXT_TIME: 2.0,5.0,8.0,13.0
1 0 0 0 TIME:  2.0  NEXT_TIME: 2.5,5.0,8.0,13.0
0 0 0 0 TIME:  2.5  NEXT_TIME: 4.0,5.0,8.0,13.0
0 0 0 0 TIME:  3.0  NEXT_TIME: 4.0,5.0,8.0,13.0
0 0 0 0 TIME:  3.5  NEXT_TIME: 4.0,5.0,8.0,13.0
1 0 0 0 TIME:  4.0  NEXT_TIME: 4.5,5.0,8.0,13.0
0 0 0 0 TIME:  4.5  NEXT_TIME: 6.0,5.0,8.0,13.0
0 1 0 0 TIME:  5.0  NEXT_TIME: 6.0,5.5,8.0,13.0
0 0 0 0 TIME:  5.5  NEXT_TIME: 6.0,10.0,8.0,13.0
1 0 0 0 TIME:  6.0  NEXT_TIME: 6.5,10.0,8.0,13.0
0 0 0 0 TIME:  6.5  NEXT_TIME: 8.0,10.0,8.0,13.0
0 0 0 0 TIME:  7.0  NEXT_TIME: 8.0,10.0,8.0,13.0
0 0 0 0 TIME:  7.5  NEXT_TIME: 8.0,10.0,8.0,13.0
1 0 1 0 TIME:  8.0  NEXT_TIME: 8.5,10.0,8.5,13.0
0 0 0 0 TIME:  8.5  NEXT_TIME: 10.0,10.0,16.0,13.0


Feb 04, 2007, 07:10 pm Last Edit: Feb 04, 2007, 07:25 pm by Daniel Reason: 1
Any examples of code would be great to look at.

Have you tried to code it yourself?

It is just a matter of using digital.write to turn them all on, and then keeping track of the time so that you can turn off solenoids if they exeed a certain time value. Actually, if you were to write out what has to happen on paper, in grpahical timeline fashion, you would have a list of the commands needed.

Try coding it yourself first and we will lend you a hand with the probelms.

Go Up