I have a very simple circuit, but my program is some what complicated.

Here is the circuit diagram:

enter image description here

Here is the code:

/*
  01 - GND -------- GND
  02 - +5V -------- 5V
  03 - V0  -------- Potentiometer Middle
  04 - Reset ------ 9
  05 - Read/Write - GND
  06 - Enable ----- 8
  07 - Data0 ------ NC
  08 - Data1 ------ NC
  09 - Data2 ------ NC
  10 - Data3 ------ NC
  11 - Data4 ------ 10
  12 - Data5 ------ 11
  13 - Data6 ------ 12
  14 - Data7 ------ 13
  15 - +LCD ------- 5V
  16 - -LCD ------- GND
*/

//include LCD library
#include <LiquidCrystal.h>

//Initialize an LCD object
/*Pins should be mentioned in this order:
  Reset
  Enable
  Data4
  Data5
  Data6
  Data7
*/
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int onTimePin = A0;
int onTime = 0;
int offTimePin = A1;
int offTime = 0;
int ledPin = 13;

void setup()
{

  pinMode(onTimePin, INPUT);
  pinMode(offTimePin, INPUT);

  pinMode(ledPin, OUTPUT);

  //Begin the LCD interface
  lcd.begin(16, 2);

  lcd.print("ON  TIME : ");
  lcd.setCursor(0, 2);
  lcd.print("OFF TIME : ");

}

void loop()
{
  onTime = map(analogRead(onTimePin), 0, 1023, 1, 3);
  lcd.setCursor(11, 0);
  lcd.print(onTime);

  offTime = map(analogRead(offTimePin), 0, 1023, 1, 9);
  lcd.setCursor(11, 1);
  lcd.print(offTime);

  digitalWrite(ledPin, HIGH);
  delay(onTime * 1000);

  digitalWrite(ledPin, LOW);
  delay(offTime * 1000);
}

The above code works. But there is a small problem:

When I turn the potentiometer wiper, there is a delay.

It's obvious because when the loop completes, the changed value of potentiometer is displayed. So, I decided to do the same thing using interrupts. But only digital pins have interrupts.

I would like to know the solution for using interrupts on analog input.

migrated from electronics.stackexchange.com Oct 21 '16 at 13:55

This question came from our site for electronics and electrical engineering professionals, students, and enthusiasts.

  • 5
    There's a delay because you're delaying. – Ignacio Vazquez-Abrams Oct 21 '16 at 14:06
  • I'd put the led blinking inside a timer(-interrupt). Or use the technique described in blink without delay – Gerben Oct 21 '16 at 14:06
  • @IgnacioVazquez-Abrams I know that there is a delay and I get the expected output. In short I want to have an led blinking as per the values given by potentiometer. – Vishal Oct 21 '16 at 14:08
up vote 3 down vote accepted

Avoid delay.

Very simplistic alternative:

unsigned long lastLedToggleTime;
unsigned long currentLedToggleInterval;

void loop() {
  ...

  unsigned long now = millis();

  if ( (now - lastLedToggleTime) > currentLedToggleInterval) {
    lastLedToggleTime = now;
    // We need to toggle the LED now.
    if ( digitalRead( ledPin ) == LOW ) {
      // LED was LOW, so we set it HIGH and setup next toggling after onTime.
      digitalWrite(ledPin, HIGH);
      currentLedToggleInterval = (onTime * 1000);
    } else {
      // LED was HIGH, so we set it LOW and setup next toggling after offTime.
      digitalWrite(ledPin, LOW);
      currentLedToggleInterval = (offTime * 1000);
    }
  } 
  ...
}

Notice that we're dealing with 32 bit unsigned integer values here, which is why this code will work even if/when millis() rolls over to 0. Specifically, not only will now - lastLedToggleTime always return a positive value (because it is cast into the unsigned data type), it will also return the correct value due to two's complement representation and modulo arithmetic base 2^32.

Example: Let's just look at an 8 bit value for simplicity:

Say, lastLedToggleTime was at the last tick of the 8 bit timer value, i.e. lastLedToggleTime == 255. In the next timer tick, now will overflow to 0, so next we have now - lastLedToggleTime = 0 - 255 = -255. In two's complement, this value would need (at least) 9 bits to represent (binary: 1 0000 0001), but because we only have 8 bits of storage, the sign bit (MSB) is just discarded resulting in 0000 0001 binary = 1. We can see that 1 is the correct value for the number of ticks to get from 255 to 0; it's exactly one tick.

  • 2
    Your solution will fail when millis() rolls over. Although this may not be a very serious issue, there is no reason to keep the bug, especially since it is very easy to avoid. See the Blink Without Delay Arduino tutorial for the proper way to write the code. – Edgar Bonet Oct 21 '16 at 14:11
  • 2
    This is why I say “this may not be a very serious issue”. But yet, there is no valid reason to show buggy code in an answer, when it is just so easy to avoid the bug. The pseudo-code in the page you link to is also correct. – Edgar Bonet Oct 21 '16 at 14:16
  • @EdgarBonet You did notice that the OP has both variable and independent on and off times? – JimmyB Oct 21 '16 at 14:18
  • @EdgarBonet Since it seems to be really bugging you as it was, I edited your proposed solution in now. – JimmyB Oct 21 '16 at 14:24

You are looking for the bad solution for a simple problem. As Ignacio Vazquez-Abrams puts it, the problem is you using delay(). The simplest solution is to manage the timings with millis(). See the Blink Without Delay Arduino tutorial.

protected by Juraj Dec 6 at 10:37

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.