Blink led twice then fade in without using delay().

Hi!!

I hope some of you can help me.
I have been programming with arduino for about a month now and have built a sketch that meets most of my requirements.
I used the arduino IDE to program the sketch on to my Attiny45.
However the sketch uses delay(), i want replace delay()s with millis()s.

Here is the sketch i built using delay()

const int switchPin =2; // "arduino Switch" connected to digital pin 2
const int switchPin1 =3; // "faceplate Switch" connected to digital pin 3
const int ledPin = 0;  // Led pins
const int ledPin2 = 1;
const int ledPin3 = 4;

int val; // variable for reading the pin status
int val2; // variable for reading the delayed/debounced status
int buttonState = 0;         // variable for reading if button state is changed
int lastButtonState = 0;     // previous state of the button
int buttonPushCounter = 0;   // counter for the number of button presses
int i = 0;



void setup() // run once, when the sketch starts
{
pinMode(switchPin, INPUT);
pinMode(switchPin1, INPUT);
buttonState = digitalRead(switchPin); 
buttonState = digitalRead(switchPin1); 
pinMode(ledPin, OUTPUT); 
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);


 GTCCR |= 0b01010000;  //setup pwm on pin 4
  GTCCR &= 0b11011111;

}

void loop(){  // run over and over again


val = (digitalRead(switchPin) || digitalRead(switchPin1));     // read input from switchPin1&2 and store it in val
delay(20);                       // 20 milliseconds is a good amount of time
val2 = (digitalRead(switchPin) || digitalRead(switchPin1));   // read the input again to check for bounces

if (val == val2) {               // make sure we got 2 consistant readings!               Form of button debouncing

if (val != buttonState) {        // the button state has changed!
if (val == LOW) {               // check if the button is pressed
    buttonPushCounter++;        // adds +1 to int buttonPushCounter


if (buttonPushCounter == 1) { 
  blinkon();    //call void blinkon
  } 


else if(buttonPushCounter == 2){  
  turntobattlemode();   //call void turntobattlemode
  }


else {
   pushbuttonoff();     //call void pushbuttonoff  
  }
  
}
}
 
buttonState = val; // save the new state in our variable
} 
}


//------------------------------------------------------------------------------------------------------------------
void blinkon(){

 // blinking routine
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
delay(00);
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
delay(00);


// fading in
for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {     // sets the value (range from 0 to 255):
analogWrite(ledPin, fadeValue); 
OCR1B = fadeValue;    // same as analogWrite.. 
delay(30); 
  } 
}

//------------------------------------------------------------------------------------------------------------------
void turntobattlemode(){

digitalWrite(ledPin, HIGH);

// fading blue out
for (int i = 255; i > 0; i--){ //descrease i with 1
    OCR1B = i;   // same as analogWrite.. 
    delay(2); 
  }
OCR1B = LOW;


// fading red in
for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {    // sets the value (range from 0 to 255):
analogWrite(ledPin2, fadeValue); 
delay(20); 
  }      
}

//------------------------------------------------------------------------------------------------------------------
void pushbuttonoff(){

for (int i = 255; i > 0; i--){ //descrease i with 1
    analogWrite(ledPin, i);
    analogWrite(ledPin2, i);
    delay(5); 
  }
digitalWrite(ledPin, LOW);
digitalWrite(ledPin2, LOW);

buttonPushCounter = 0;     
}
//------------------------------------------------------------------------------------------------------------------

Every time i push a button i have to wait for the piece of code to end before i can press it again and toggle the next piece of code.

What i want to do is push the button, toggle the piece of code but not have to wait until the piece of code is finishes before i can press te button again to toggle the next piece of code.

As i understand it this can be done by using the blink/fade without delay principles. So the sketch is not interrupted and can look for another buttonpress.

Now, I think i understand the principles of blinking or fading without delay and how to run a loop a set number of times.

I have googled and tried more sketches than i can remember however i cant seem to combine the two to make a led blink twice and then fade in.

I hope you guys understand, and can help me.

Hope im posting this in the appropriate section and sorry if my English is incorrect, im from the Netherlands.

Greets

Hey, I didn't go through all your code, but whenever I need to add some delay for something w/o using the delay() function I usually do something like this:

 long start_time = millis();

 while( millis() - start_time < 3000 ) {
    // do nothing, just wait
  }

The above will just spin in the while loop for 3000 ms to give my code a 3s delay. Hope this helps

That might not actually be using delay but it might just as well use it. It is still blocking code and has no advantage at all over delay.

To answer the question you can do one of two things

  1. use a state machine to keep track of where you are in the sequence
  2. write your own delay, like above but include a line to look at the push button and exit the loop early if it is pressed.

Thanks for the replies guys!!

I will have a look at the options Grumpy_Mike gave me, hopefully i can get one or the other to work!!
If not i'll ask for your help again haha :wink:

keep on coding!

It helps if you draw a graph for the led. The intensity on the left and the time at the bottom.
Create a state machine with the time, or use only the time.
When the led is fading, calculate the intensity at that time. That way the loop() can run slow or fast, the time that the led is faded will be the same.

So i've looked at the state machine function/library and i think this is what i should use.
But i am not quit sure how it works en how to implement it in my code.
Should i use it for the blinking and fading of the leds or for the buttonpushes, or both.

Please help.

If you must use a libary then use it for all the outputs. However it is much simpler to just write it yourself.
There are lots of examples and links if you search the forum for "doing more than one thing at once"

A state machine can be a simple flag, indicating that you are doing the led fading thing. Just a flag and the time.
You can also use the state machine for every step in the sequence for the led.
A "state machine" sounds very sophisticated, but it is mostly just a simple integer. The integer value = 0 means doing nothing. Value 1, first step in the sequence, and so on.

The goal is to know in which part of the sequence you are in. Normally that would be in the program code with delays. Now you have to rely on variables.

When you make a sketch, can you use the system led at pin 13 for the fading ? So we can test your sketch on our own Arduino board.

It is important that you understand your own code, so make a start with what you think is best, and we guide you from there.

Have a look at this page on state machines :-
http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html

I think im going mad!!

I looked at the page Grumpy_Mike gave me and i think i understand the principles.

A state machine is just a integer that tells if the led is on or of.

For example:

digitalWrite (ledPin, HIGH);
Ledstate = HIGH;

The state machine(ledstate) now tells me the led is HIGH.

And the time when the next blink should occur is simply calculated.

But i cant seem to get the led blinking just twice.

But i cant seem to get the led blinking just twice.

You have another variable that counts how many times the LED has been turned off.

You use that variable in the if statement to decide if you are going to turn the LED on.

So, if it is time and the LED is OFF and the number of times it has been turned off is less than two then turn on the LED and set the time for the next off. Otherwise you never turn on the LED again unless you reset that turn off count variable.

Grumpy_Mike would you be so kind as to give me a example piece of code?

I know this is not the best way to learn but ive been at this for almost a month now and i still cant get it to work.

By giving me an expample and comparing it to my code i hope i can finally understand what i am doing wrong.

I'll be in your deth :wink:

whoeeehoeee finally got it to work, the blinking part that is!

Its kind of how Grumpy_Mike described how i should do it, i think?!

int counter = 0;
int state = HIGH;      // the current state of the output pin

long previousMillis = 0;        // will store last time LED was updated
long interval = 50;           // interval at which to blink (milliseconds)
int ledState = LOW;             // ledState used to set the LED




{
   
      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 (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    counter++;
  }

        if (counter <4){
    digitalWrite(ledPin, ledState);
  }
  else
    digitalWrite(ledPin, LOW);
  }

Thanks for all the help!

Now for the fading part

finally got it to work

Good :slight_smile: well done.

Do you know you can compound if statements, that is put several conditions that can themselves be logically linked like:-

if( (currentMillis - previousMillis > interval) && (counter <4) ) {

That says if both those conditions apply do what follows the brace.

Nope, i did not know that.
I will change my code accordingly when inget back home. :slight_smile:

How should i go about making my fade in effect?

How should i go about making my fade in effect?

In exactly the same way as a blink. But instead of changing the state of the LED you increment or decrement ( depending on if you are fading up or down ) the variable that defines the brightness. Then you only stop changing this variable when it has reached its desired value. Note you will have another time variable to keep track of how often the LEDs brightness needs to be nudged.

Hi,
why you don't design the code using interrupts?
so you can design the code to read the button values not related to time (delay or millis) but on the actual keypress event.

ciao

Gianpaolo

why you don't design the code using interrupts?

Because there is absolutely no need to.

so you can design the code to read the button values not related to time (delay or millis) but on the actual keypress event.

Are you reading a different thread to me?

//fade
long previousMillis1 = 0;        // will store last time LED was updated
long interval1 = 50;           // interval at which to blink (milliseconds)
int fadeValue;             // ledState used to set the LED





void fade (){
  
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis1 > interval1) {
  
    previousMillis = currentMillis;   

    fadeValue = constrain(fadeValue, 0, 255); // limits range of sensor values to between 0 and 255
    if (fadeValue == 0)
    fadeValue += 5;

    // set the LED with the ledState of the variable:
    
  }

    analogWrite(ledPin, fadeValue);   
   
}

Grumpy_Mike, this is what i came up with for the fading part but.. surprise it doesnt work haha.
Is this going the right way or am i missing something?

With that code, does the LED fade up at all? It looks like it will only fade up by 5 once.

The "if (fadeValue == 0)" check means you'll only ever increment the brightness of the LED when its value is 0. Once you increment it up to 5, you'll never increment it again.

If you are trying to fade it up from zero to some limit, say 150, the IF statement would be something like this:

if ( fadeValue < 150 ) fadeValue += 5;

That will ensure that it'll increase the brightness each time though the interval until the value gets up to 150.