0

I have a simple sketch here that should just blink a led once a second or so (approximately):

boolean onOff=true;
int count=0;

void setup() {
  pinMode(13, OUTPUT);
 }

void loop() {
    count++;
    delay(1);

    if (count == 316) { 
    onOff=!onOff;
    digitalWrite(13, onOff);
    count=0;
    }
}

So, if count is 316 it changes the state of led. It works right now, but it does not without delay() function or some other complex ones like digitalWrite() being in the loop() too. If i am deleting delay(), than led is just always on. I can feel it is smth about interrupts, but i am not sure.


What am i trying to do here is to make an alternative to delay() and millis() for my other project. One of the most needed thing for me is to make ASAP (as soon as possible) "timer", so that some code could run every 2(3-4...) iterations of loop(). delay() is bad always, and millis() uses long variable (which is bad for cpu time and ram), and while having problems with ram and cpu time in my project, i want smth lighter for ASAP and other not very precise timing. So, the questions are:

  1. Why does my sketch works only with delay(), but does not work without it?
  2. Why does blinking sketches work with millis(), while they do not use any delay() just like my sketch.
  3. Am i a bad person for trying to make smth like an ASAP timer?:) Is saved ram and cpu time worth of it? Any other possible problems?
  4. Can this sketch be workable without delay() or other complex or ram and cpu costly functions?

Thank you.

So, the sketch up there works indeed, but here is the version that you can can observe with your eyes:

boolean onOff=1;
unsigned int counter=0;
unsigned long time=0;

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(57600);
}

void loop() {
   if (counter==0)  time=micros();
    counter++;
    if (counter == 0) {
        onOff= !onOff;
    digitalWrite(13, onOff);
    Serial.println(micros()-time);
    }
}

With Serial i was checking delay between blinks, and it is 140164 mcs = 140 ms = 0.14s. But to be honest it feels slower, so please correct me if i can benchmark it in a better way.

2 Answers2

1

As majenko answered in the comments, the blinking rate will be so fast you can not see it.
Also it is possible that without the delay the optimizer removes the whole counting. So increasing the number as proposed by majenko may not even work due to compiler optimisations.
Using a method based on counters is a very unreliable way to use timings.

Look at the blinkwithout delay example as proposed by Dirk.
It boils down to using millis() for timing. millis tells you how many millis the arduino is running.

void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink 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:
    digitalWrite(ledPin, ledState);
  }
}
jantje
  • 1,392
  • 1
  • 8
  • 16
0

This sketch blinks an LED on D10 (on a Uno) at one second intervals. It does not use delay, micros, millis or any unsigned long variables (apart from a constant).

const int STROBE_FREQ = 1000;     // sets the period in milliseconds 
const unsigned long countTo = ((float) F_CPU / 1024.0) / (1000.0 / STROBE_FREQ); 

void setup ()
  {
  // D10 to output
  bitSet (DDRB, 2);

  // Fast PWM top at OCR1A
  TCCR1A = bit (WGM10) | bit (WGM11); // fast PWM
  TCCR1B = bit (WGM12) | bit (WGM13) | bit (CS12) | bit (CS10);   // fast PWM, prescaler of 1024
  OCR1A = countTo - 1;                 // zero relative 
  OCR1B = (countTo / 2) - 1;           // 50% duty cycle
  bitSet (TCCR1A, COM1B1);   // clear OC1B on compare
  }  // end of setup

 void loop ()
   {
    // do something useful
   }

It frees up the main loop to do something useful without worrying about time taken to do the blinking.

For more details see my page about timers.

Nick Gammon
  • 38,901
  • 13
  • 69
  • 125