Go Down

Topic: blink without delay example for simultaneous functions (Read 683 times) previous topic - next topic

ifugaopapercraft

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? 

Code: [Select]

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); 
}



Arrch

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

UKHeliBob

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.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

johnwasser

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.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

ifugaopapercraft

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.

ifugaopapercraft

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

MAS3

#6
Aug 17, 2013, 11:08 pm Last Edit: Aug 17, 2013, 11:10 pm by MAS3 Reason: 1
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).

Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

ifugaopapercraft

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

Code: [Select]


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 ();

 



MAS3

What did you change, apart from using the code tags this time to show your code and remove some comments ?
Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

ifugaopapercraft


MAS3

#10
Aug 18, 2013, 12:50 am Last Edit: Aug 18, 2013, 12:52 am by MAS3 Reason: 1
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:
Code: [Select]

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

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

 

}  


To:
Code: [Select]

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
    }
 

}  
Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

johnwasser

You're getting close.  This should do what you want:
Code: [Select]


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();

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

ifugaopapercraft

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

Grumpy_Mike


Go Up