blink without delay example for simultaneous functions

I have been advised time and again to embrace the "blink without delay" example to perform functions independently. This sketch is a failed attempt to program two solenoids to fire randomly, not consecutively. Although they are random, one activates after the other in sequence. Am I asking Arduino to do something it wasn't designed to do?

int solOne =2;
int solTwo =4;
int solState = LOW;            
long previousMillis = 0;
long interval = 10;
long randOn1 = 0;                  // Initialize a variable for the ON time
long randOff1 = 0;
long randOn2 = 0;                  // Initialize a variable for the ON time
long randOff2 = 0;


void setup() {
  randomSeed (analogRead (0));
  pinMode (solOne, OUTPUT);
  pinMode (solTwo, OUTPUT);
}
void loop()
{
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (solState == LOW)
      solState = HIGH;
    else
      solState = LOW;
    OneSol();
    TwoSol();
    delay(1000);
  }
}
void OneSol()
{
  randOn1 = random (100, 1200);    // generate ON time between 0.1 and 1.2 seconds
  randOff1 = random (200, 900);    // generate OFF time between 0.2 and 0.9 seconds
  digitalWrite(solOne, HIGH);   // sets the solenoid on
  delay(randOn1);                // waits for a random time while ON
  digitalWrite(solOne, LOW);    // sets the solenoid off
  delay(randOff1);  
}
void TwoSol()
{
  randOn2 = random (150, 500);    // generate ON time between 0.1 and 1.2 seconds
  randOff2 = random (100, 1900);    // generate OFF time between 0.2 and 0.9 seconds
  digitalWrite(solTwo, HIGH);   // sets the solenoid on
  delay(randOn2);                // waits for a random time while ON
  digitalWrite(solTwo, LOW);    // sets the solenoid off
  delay(randOff2);  
}

http://www.mushclient.com/forum/bbshowpost.php?bbsubject_id=11411

Looking at your code I see that the call to TwoSol() always follows the call to OneSol() so it is no wonder that the solenoids always work in sequence, and you exacerbate that by using delay() in the functions which is exactly what you are trying to avoid.

Your code says:

If 1/100th of a second has passed since the time was last noted:
begin
note the time.
Toggle ‘solState’ which is never used.

Turn on Solenoid One
delay between 100 and 1200 milliseconds
Turn off Solenoid One
delay between 200 and 900 milliseconds

Turn on Solenoid Two
delay between 150 and 500 milliseconds
Turn off Solenoid Two
delay between 100 and 1900 milliseconds

delay 1000 milliseconds
end

Since your IF statement takes at least 1.45 seconds (all those delays) the 1/100th of a second will always have passed before you check again. To do ‘Blink Without Delay’ you have to take out ALL the delays.

Great advise, great because I understand what you are describing, which is not always the case. First time I've actually gotten two of anything to function independently. Now for the random business which I assume is just a matter of editing. Thanks again.

After looking at web examples, I assumed this would generate random solenoids. I am puzzled why it doesn't. The two ignore the random and fire at 1/2 and one second just as before.

const byte solOne = 2; const byte solTwo = 4;

// Time periods of blinks in milliseconds (1000 to a second). unsigned long solOneinterval = 0;//500 unsigned long solTwointerval = 0;//1000

// Variable holding the timer value so far. One for each "Timer" unsigned long solOnetimer; unsigned long solTwotimer;

void setup () { pinMode (solOne, OUTPUT); pinMode (solTwo, OUTPUT); solOnetimer = millis (); solTwotimer = millis (); } // end of setup

void toggleSolOne () { if (digitalRead (solOne) == LOW) digitalWrite (solOne, HIGH); else digitalWrite (solOne, LOW);

// remember when we toggled it solOnetimer = millis (); } // end of toggleGreenLED

void toggleSolTwo () { if (digitalRead (solTwo) == LOW) digitalWrite (solTwo, HIGH); else digitalWrite (solTwo, LOW);

// remember when we toggled it solTwotimer = millis (); } // end of toggleRedLED

void loop () {

// Handling the blink of one LED. solOneinterval = random (100,500); ????????? if ( (millis () - solOnetimer) >= solOneinterval) toggleSolOne (); solTwointerval = random (500,1000); ???????? // The other LED is controlled the same way. Repeat for more LEDs if ( (millis () - solTwotimer) >= solTwointerval) toggleSolTwo ();

/* Other code that needs to execute goes here. It will be called many thousand times per second because the above code does not wait for the LED blink interval to finish. */

} // end of loop

Use code tags.

Looks to me like you are resetting your random value every iteration. Check the timer first, if it has ended call the toggle, and after that reset the random value still within the braces { } that belong to the if statement (you aren't using those yet). Then the random value will not be reset every iteration (which is more than several thousand times per second).

Obviously not resetting the random correctly. Also, what are code tags (dumb question).

const byte solOne = 2;
const byte solTwo = 4;

// Time periods of blinks in milliseconds (1000 to a second).
unsigned long solOneinterval = 0;//500
unsigned long solTwointerval = 0;//1000

// Variable holding the timer value so far. One for each "Timer"
unsigned long solOnetimer;
unsigned long solTwotimer;

void setup () 
{
  pinMode (solOne, OUTPUT);
  pinMode (solTwo, OUTPUT);
  solOnetimer = millis ();
  solTwotimer = millis ();
}  // end of setup

void toggleSolOne ()
{
  if (digitalRead (solOne) == LOW)
    digitalWrite (solOne, HIGH);
  else
    digitalWrite (solOne, LOW);

  // remember when we toggled it
  solOnetimer = millis ();
  solOneinterval = 0; [font=Verdana]//////[/font]
}  // end of toggleGreenLED

void toggleSolTwo ()
{
  if (digitalRead (solTwo) == LOW)
    digitalWrite (solTwo, HIGH);
  else
    digitalWrite (solTwo, LOW);

  // remember when we toggled it
  solTwotimer = millis ();
  solTwointerval = 0;[font=Verdana]///////// [/font] 
}  // end of toggleRedLED

void loop ()
{
  solOneinterval = random (100,500);
  if ( (millis () - solOnetimer) >= solOneinterval)
    toggleSolOne ();

  solTwointerval = random (500,1000);
  
  if ( (millis () - solTwotimer) >= solTwointerval) 
    toggleSolTwo ();

  

}

What did you change, apart from using the code tags this time to show your code and remove some comments ?

Added "solOneinterval = 0;" below else.

Setting that value to 0 doesn't help a lot here.

You are still setting the random interval every time the loop runs. You should only set a new value after the old one had reached its end.

So change this part of your code:

void loop ()
{
  solOneinterval = random (100,500);
  if ( (millis () - solOnetimer) >= solOneinterval)
    toggleSolOne ();

  solTwointerval = random (500,1000);
  
  if ( (millis () - solTwotimer) >= solTwointerval) 
    toggleSolTwo ();

  

}

To:

void loop ()
{
  if ( (millis () - solOnetimer) >= solOneinterval)
    {
     toggleSolOne ();
     solOneinterval = random (100,500);                 // A new value is set after the old value has done it's job
     }
  
  if ( (millis () - solTwotimer) >= solTwointerval) 
    {
     toggleSolTwo ();
     solTwointerval = random (500,1000);                // A new value is set after the old value has done it's job
     }
  

}

You're getting close. This should do what you want:

const unsigned long sloenoidOneMinOnTime = 100;
const unsigned long sloenoidOneMaxOnTime = 1200;
const unsigned long sloenoidOneMinOffTime = 200;
const unsigned long sloenoidOneMaxOffTime = 900;

const unsigned long sloenoidTwoMinOnTime = 100;
const unsigned long sloenoidTwoMaxOnTime = 1200;
const unsigned long sloenoidTwoMinOffTime = 200;
const unsigned long sloenoidTwoMaxOffTime = 900;

const byte solenoidOnePin = 2;
const byte solenoidTwoPin = 4;

// Time periods of blinks in milliseconds (1000 to a second).
unsigned long solenoidOneInterval = 0;
unsigned long solenoidTwoInterval = 0;

// Variable holding the timer value so far. One for each "Timer"
unsigned long solenoidOneTimerStart = 0;
unsigned long solenoidTwoTimerStart = 0;

void setup() {
  pinMode (solenoidOnePin, OUTPUT);
  pinMode (solenoidTwoPin, OUTPUT);
  solenoidOneInterval = random (sloenoidOneMinOnTime,sloenoidOneMaxOnTime);
  solenoidTwoInterval = random (sloenoidTwoMinOnTime,sloenoidTwoMaxOnTime);
}  // end of setup

void solenoidOne () {
  if (millis() - solenoidOneTimerStart >= solenoidOneInterval) {
    solenoidOneTimerStart = millis();
    if (digitalRead (solenoidOnePin)) {  // If HIGH
      // Toggle solenoid off
      digitalWrite (solenoidOnePin, LOW);
      solenoidOneInterval = random (sloenoidOneMinOffTime,sloenoidOneMaxOffTime);
    } 
    else {
      // Toggle solenoid on
      digitalWrite (solenoidOnePin, HIGH);
      solenoidOneInterval = random (sloenoidOneMinOnTime,sloenoidOneMaxOnTime);
    }
  }
} 

void solenoidTwo () {
  if (millis() - solenoidTwoTimerStart >= solenoidTwoInterval) {
    solenoidTwoTimerStart = millis();
    if (digitalRead (solenoidTwoPin)) {  // If HIGH
      // Toggle solenoid off
      digitalWrite (solenoidTwoPin, LOW);
      solenoidTwoInterval = random (sloenoidTwoMinOffTime,sloenoidTwoMaxOffTime);
    } 
    else {
      // Toggle solenoid on
      digitalWrite (solenoidTwoPin, HIGH);
      solenoidTwoInterval = random (sloenoidTwoMinOnTime,sloenoidTwoMaxOnTime);
    }
  }
} 

void loop () {
  solenoidOne();
  solenoidTwo();
}

Perfect! For the ALD (Arduino Learning Disabled), solving this puzzle seems both necessary and impossible. Thanks again.

Also, what are code tags (dumb question).

http://forum.arduino.cc/index.php/topic,148850.0.html