Delay Trouble

I’m running a loop that waits for an analog reading from a bunch of 4051 pins to turn different 74HC595 pins high. To make it easy I’m using this shifter library bildr You searched for 74hc595 - bildr
My problem is i need the 595 pin to stay high for 2 seconds without slowing down the rest of my loop (which constantly looks for signals from the 4051’s) is there any way to keep the pin high for 2 seconds without delay(2000);?
I tried using a millis timer but couldnt get it to work with the shifter library commands.

heres where i need help

for (int count2=0; count2<=7; count2++) { //SLAVE 4 pin y7 4051

   r3 = bitRead(count2,0);
   r4 = bitRead(count2,1);
   r5 = bitRead(count2,2);

   digitalWrite(5, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(7, HIGH);

if (analogRead(0)>=10)    // if the 4051 pin gets a signal, the reading goes to analog pin 0 and if its greater than or equal to 10
  {                                // it turns pin 1 on my first 595 high
  shifter.setPin(1, HIGH); 
  shifter.write(); //send changes to the chain and display them
  delay(2000);    // stays on for 2 seconds
  }
  else
  shifter.clear();  // turns pin low
  shifter.write(); //send changes to the chain and display them
}

I tried using a millis timer but couldnt get it to work with the shifter library commands.

But that is the method you need to master to be successful. Using multiple delays for unrelated things just doesn't work as it makes everything dependent on the total of all delays within any loop you are working in.

Lefty

The example is here http://arduino.cc/forum/index.php/topic,76140.msg574940.html#msg574940 and a longer explanation here http://arduino.cc/playground/Code/AvoidDelay

TomK: I tried using a millis timer but couldnt get it to work with the shifter library commands.

I dunno what you tried but you should be using millis to set an unsigned long at the start of your interval then in each succeeding loop() check if millis() - start-time is more than or equal to 2000UL. The UL is for unsigned long type, to get it for sure right. If it is >= 2000UL it's been on for 2 seconds and you can let it clear the shifter which will take some re-ordering of that section since as now it only checks the analog state to set or clear the shifter.

TomK: I tried using a millis timer but couldnt get it to work with the shifter library commands.

Show what you tried without using delay.

if (analogRead(0)>=10)    // if the 4051 pin gets a signal, the reading goes to analog pin 0 and if its greater than or equal to 10
  {                                // it turns pin 1 on my first 595 high
  shifter.setPin(1, HIGH); 
  shifter.write(); //send changes to the chain and display them
  delay(2000);    // stays on for 2 seconds
  }
  else
  shifter.clear();  // turns pin low
  shifter.write(); //send changes to the chain and display them

You know that last write is unconditional don't you? Indenting doesn't change how the compiler sees things.

im not sure what you mean nick. heres what i am trying now. my pin does not stay on for 2 seconds. it just flickers for however long i have my sensor on.

// in the setup i declare TimerA as an unsigned long
TimerA= millis();

if (analogRead(0)>400){
    
  shifter.setPin(31, HIGH);
  shifter.write(); 

if (millis()-TimerA >= 2000UL){
  shifter.clear();
  shifter.write(); 

}

else
  shifter.clear();
  shifter.write();
}

TomK: im not sure what you mean nick.

if (analogRead(0)>=10)    // if the 4051 pin gets a signal, the reading goes to analog pin 0 and if its greater than or equal to 10
  {                                // it turns pin 1 on my first 595 high
  shifter.setPin(1, HIGH); 
  shifter.write(); //send changes to the chain and display them
  delay(2000);    // stays on for 2 seconds
  }
else
  shifter.clear();
  shifter.write();

The indentation implies that shifter.clear() and shifter.write() are both within the 'else' clause. Since you haven't put them in a compound statement (enclosed in '{' and '}' ) only shifter.clear() is in the else clause. As you've put it, the actual behaviour is the same as this:

if (analogRead(0)>=10)    // if the 4051 pin gets a signal, the reading goes to analog pin 0 and if its greater than or equal to 10
{                                // it turns pin 1 on my first 595 high
  shifter.setPin(1, HIGH); 
  shifter.write(); //send changes to the chain and display them
  delay(2000);    // stays on for 2 seconds
}
else
{
  shifter.clear();
}
shifter.write();

That's almost certainly not what you intended. To avoid bugs like that, you should always always follow 'if', 'else', 'for', 'do' and 'while' conditions with a '{' and '}'.

You got two principal errors in this code.

Firstly you reset the timer on EVERY pass through this code. (Re)Setting the timer to millis should be done only when triggered.

Scondly Nick has pointed out you have written

if (millis()-TimerA >= 2000UL){
  shifter.clear();   // executed if true
  shifter.write();  // executed if true
}
else
  shifter.clear(); // executed if false
shifter.write();  // always executed

Nicks point is that the compiler counts {-brackets and semi colons, not indentention. So you probaly wanted a braces pair after your else

The small fraction of the code you have shown us is an incorrect usage of the "BlinkWthoutDelay" structure. Check it up again, check up the other references and try again. Maybe even post more of your code.

i have fixed my code (i think) and it works. i have another problem tho. my entire code checks every pin from the 4051 individually for a signal and if there is one, it executes the shifter and the delay for every pin. this means that i need to have a separate Timer ul for each pin thats being checked (since the timer is being updated each time it is checked). this means tho, that the millis is going to be checked quite often and reset quite often for different timers and wont always be >=2000, which means my delay wont always be 2 seconds. is there any way to fix this?
another question i had was, if my sensor is triggered, and the shifter goes on for two seconds, and during those two seconds the sensor gets triggered again, how can i get the shifter to go low then high again (essentially restart the 2 seconds)?
any help would be wonderful and the help i have received already has been great too.
thanks!

here’s a section of my code for checking one pin on the 4051, and turning the shifter high for 2 seconds. i would post the whole thing but it just repeats this for 32 pins.

for (int count2=0; count2<=7; count2++) { //SLAVE 4 pin y7
  // 
   r3 = bitRead(count2,0);
   r4 = bitRead(count2,1);
   r5 = bitRead(count2,2);

   digitalWrite(5, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(7, HIGH);

   
if (analogRead(0)>=300){
  shifter.setPin(31, HIGH);
  shifter.write();  
}

if (millis()-TimerA >= 2000UL){ 
  TimerA= millis();  
  shifter.setPin(31,LOW);
  shifter.write();
} 
}

If by “repeat” you mean copy-n-paste, you’re definitely in need of some arrays, IMHO.

Also, be more careful with indentation. Whenever you open a code block, indent the following lines. Whenever you close a code bloc, decrease the indentation.

This may help:

http://www.gammon.com.au/forum/?id=11094

[quote author=Nick Gammon link=topic=88134.msg666794#msg666794 date=1327521087] This may help:

http://www.gammon.com.au/forum/?id=11094

[/quote]

I like that class. Straight to the point and very easy to use. A pity it's not listed here: http://arduino.cc/playground/Main/LibraryList#Timing :)