Timer with delay- Art student

Hi, I am an art student, kinda new in this thing.

For my upcoming school project I need to build a button that would activate a bunch of LED lights on a board with a delay option.

So basically, the longer I press the button (5,10,20,30 seconds and so on), the more LED lights will turn on respectively (1 light, 3 lights, 5 lights, etc.)- until the board is full with lights and remains like that as long as I keep on pressing the button (No LED flashing required).

Any ideas?

Thanks a lot

Yancha

How many is a “bunch” ? Do you want to learn to program a microcontroller (MCU) like a PIC or perhaps Arduino ? Or would you rather it be just hardware (no coding, this can be done !) ? What is the rate of LEDs turned on per second of button push ? Do you need this to be variable or just a constant, once you know what it is ? How much do you expect this to cost ?

A simple design might be to have power applied, and an oscillator run when you push the button. It clocks a shift register which drives the LEDs. The longer you push, the more clocks and the higher the count and the more LEDs … in a nice linear fashion. At some point the count max’s out and all the LEDs are on. The button removes power when released. Using a 556 (dual 555s) would allow one to be the oscillator and another to do a power on reset (clear) for the shift register.

https://www.sparkfun.com/products/9273

https://www.sparkfun.com/products/10680

https://www.sparkfun.com/products/734

Hi Mee_n_Mac,

I would like to try it with Arduino.

A “Bunch” could be 5-10 LEDs per digital output (depends on the LED colour, right?).

The rate of LEDs per second can be variable (I will need to test the result), but for now I will keep it constant (i.e. per 1 second).

It would be much appreciated if you could help me with below code. It’s my first time using arduino, so I’m not sure if got it right.

Thanks

int ledPins = {2,3,4,5,6,7,8,9};

int buttonPin = 11;

int val = 0;

int sequence = 1;

void setup()

{

for(int i = 0; i < 8; i ++){

pinMode(ledPins*,OUTPUT);*

  • pinMode(buttonPin, INPUT);*
    *} *
    *void loop() { *
    {
    oneAfterAnotherNoLoop();
    val = digitalRead(buttonPin);
    if(val == HIGH) {
  • if(sequence != 1)*
  • {*
  • sequence = 1;*
  • }*
  • delay(100);*
    }
    else {
    buttonPin = 0;
    }
    }
    }
    void oneAfterAnotherNoLoop(){
  • int delayTime = 1000;*
    for(int ledPins = 0; ledPins <= 7; ledPins++){
  • digitalWrite(ledPins, HIGH);*
  • button_delay(delayTime, buttonPin);*
    }
    }
    void button_delay(int msec, int btnpin){
    int btnstate = 0;
  • btnstate = digitalRead(btnpin);*
    if(btnstate == HIGH){
    delay(msec);
    }
    }

Yancha:
Hi Mee_n_Mac,

I would like to try it with Arduino.

A “Bunch” could be 5-10 LEDs per digital output (depends on the LED colour, right?).

You can drive 1 normal (20-30 mA) LED with each Arduino digital output pin. This is typically done by connecting a resistor in between the LED and the pin. The resistor sets the current through the LED. Any single output pin can supply or sink 40 mA max. There's also a max current spec, for all the pins summed together, that you need to stay under. I forget what that is, perhaps 200 mA total ? That may limit the number of LEDs that can be driven directly off the Arduino.

The color of the LED doesn’t affect how much current the LED will draw but does affect the voltage needed to achieve that current. So different colors will need different values for the resistor mentioned above. There are other ways to drive LEDs but let’s keep this simple for now. You may want to look at the wiring used here (I suspect you’ve already seen it though :mrgreen: ) …

http://oomlout.com/a/products/ardx/circ-02/

Yancha:
It would be much appreciated if you could help me with below code. It’s my first time using arduino, so I’m not sure if got it right. Thanks

I see a few problems right off the bat but I'll look at it in detail tomorrow. For now let me point those few out.
int ledPins[] = {2,3,4,5,6,7,8,9}; 	 
int buttonPin = 11;

void setup(){
   for(int i = 0; i < 8; i ++){    
      pinMode(ledPins[i],OUTPUT);
      pinMode(buttonPin, INPUT); 
}

I believe your intent is to have pins 2 - 9 be the output pins used to drive the LEDs. You declare and then initialize them above. First, to save RAM usage, things that are constants and won’t ever change when the code runs, should be declared as constants. You do this by using the const instruction as part of the declaration. Second, and this is a small issue, it’ll work as written, the buttonPin initialization could be outside of the loop. It only needs to be done once. Lastly you were missing a }. So you get the following instead of the above …

const int ledPins[] = {2,3,4,5,6,7,8,9}; 	 
const int buttonPin = 11;  

void setup(){
   for(int i = 0; i < 8; i ++){    
      pinMode(ledPins[i],OUTPUT);
   }
   pinMode(buttonPin, INPUT);
}

I’ll also add that if pin 11 is an input used with a simple connect/no-connect switch (SP-NO or SP-NC) then it’s common practice to use the Arduino’s internal pull-up resistor. Depending on which version of the Arduino environment you’re using, there are different ways to initialize this pin to make this happen. Which Arduino (board and environment) are you using ?

Lastly (for now) … while you can use any name for the index in a for loop, using what you used below is confusing. Also when referencing the array ledPins[] you need to specify which pin is being used by using 's with the index into the array in the 's. So this …

for(int ledPins = 0; ledPins <= 7; ledPins++){
   digitalWrite(ledPins, HIGH);  
   button_delay(delayTime, buttonPin);
}

… should be this (not to say that the result below necessarily does what you need/want). What the above would try to do is set pins 0 through 7 to a logic high. It might have compiled but it’s not what I think you intended.

for(int i= 0; i <= 7; i++){
   digitalWrite(ledPins[i], HIGH);  
   button_delay(delayTime, buttonPin); // does this line want to be here ??????
}

Lastly you’ll note the code above is in “code boxes” and so retains the indentations you see in the Arduino editor and thus is easier to read. The pic below should explain how to use the code tags (you need to be using the “full” forum editor.

[/quote]

I looked at your code and my guess is you tried to adapt the code at the URL I provided to suit your needs. I found another syntax error but moreover I found that it was far more complex than it needed to be. I don’t know (after fixing the simple errors) if it would have worked or not, I just figured there had to be a simpler way to do it. So, below, is my version of that simpler way. See if you think it does what you want.

Here’s what I thought you wanted. When the run/stop button is not pushed, all the LEDs go off and stay off. When the button is pushed :

  • the code times how long the button has been pushed

  • the code calculates how many time increments (user settable) it has been pushed

  • the code turns on, and keeps on, 1 LED for each time increment … up to 8 LEDs

// declare constants
const int ledPins[] = {2,3,4,5,6,7,8,9}; //output pins connected to LEDs
const int buttonPin = 11;                //input pin for button
const unsigned long timeConst = 1000;    //time increment (msec) to turn on each LED

//declare variables
unsigned long startTime = 0; //time when button was pushed
unsigned long onTime = 0;    //amount of time button has been pushed
int numOn = 0;               //integer number of time increments since button pushed

void setup()
{
  for(int i = 0; i < 8; i ++)
  {
    pinMode(ledPins[i],OUTPUT);
  }
  pinMode(buttonPin, INPUT);
}

void loop()
{
  if(digitalRead(buttonPin) == HIGH) //is button pushed ?
  {
    //yes, button is pushed
    onTime = millis() - startTime;     //how long has button been pushed ?
    if(onTime > timeConst)             //pushed longer than 1 time increment ?
    {
      //yes, compute how many LEDs should be on
      numOn = max(onTime/timeConst, 8); //use integer math, how many time increments
      //turn on that number of LEDs, 8 max
      for(int i = 0; i < numOn; i++)
      {
        digitalWrite(ledPins[i], HIGH);
      }
    }
  }
  else
  {
    //no, button is not pushed
    startTime = millis();            //keep resetting time until button is pushed
    //turn off all LEDs
    for(int i = 0; i < 8; i++)
    {
      digitalWrite(ledPins[i], LOW);
    }
  }
}

The above compiles (for an Uno) but I’ve not checked that it does what I hope it does. You can check that. :mrgreen: If it doesn’t quite work (likely IMO) then we can add some debug print instructions to send data to the PC to see what’s going on. I’m also quite sure there’s a few more optimizations that can be made but i wanted to keep it so you could easily follow the logic. When you ‘grok’ the above, I’ll suggest those optimizations as I think you’ll find the process informative. Usually I try to get something working first and then go back to optimize/simplify as much as possible.

I followed your code, but maybe the wiring or the resistors are wrong.

Also, when I tried to upload, this sentence came at the bottom:

“avrdude: stk500_getsync(): not in sync: resp=0x30”

Any idea where the problem might be? :?

could it be…voltage issue?

Some questions.

  • What value resistors ?

  • What can you tell me about the LEDs used ? Do you have a part number or ??

  • What kind of button/switch ? Is is normally open (NO) or normally closed (NC) when not pushed ?

I’d like to calculate the resistors needed but if you’re using something you got from an Inventors kit you’re likely OK. The button, as you had the code originally (and I kept that sense) needed to provide a logic high when pushed and a low when not. That means the button contacts should go to ground and the input pin (11). Then (if you don’t enable the internal pull-ups, which you should do), there should be an external resistor from the pin to Vcc (5v). It should be something between 2k and 20k. The button/switch needs to be a NC type. That way when not pushed it’s closure is providing a short to ground (logic low). When pushed the switch opens and the pull-up provides a logic high (5V). Right now I think you have this wrong but that’s not likely to be the AVR error message cause.

As for that … have you had the Arduino plugged into the PC and working before ? Have you told the Arduino environment what kind of Arduino will be plugged in and on what COM port ? See the links below (Google is your friend). You might wish to unplug the breadboard, at least the ground and any Vcc (5V) connections and try again.

http://arduino.cc/forum/index.php?topic=132645.0

http://www.me.umn.edu/courses/me2011/ar … debug.html

http://www.instructables.com/id/A-solut … ot-in-syn/

Answers:

  1. I tried both 220 and 330om resistors for the LEDs, and 10k for the button

  2. The shop couldn’t tell me the specification of the LEDs, but they are 8mm long (without the pins) and according to the plastic bag they are between 1.8v to 2.2v (Red)

  3. I tried both 2 and 4 pins push buttons- photos attached

  4. As for the port I’ll try to fix it as soon as I can

You should be OK with even the 220 ohm resistors and LEDs with a Vf of 1.8V. The current(s) will be under the Arduino limit(s).

I = (5 - 1.8)/220 = 14.5 mA < 40 mA. 14.5 mA * 8 = 116 mA < 200 mA.

I couldn’t tell what kind of switch you have. The software can be changed to accommodate anything. You might have to know what revision of Arduino you have on your PC though. Enabling the internal pull-up for the input switch pin can be done this (old) way. I suspect this should work no matter what rev of Arduino you have … but you never know.

http://www.arduino.cc/en/Tutorial/DigitalPins

There are also convenient 20K pullup resistors built into the Atmega chip that can be accessed from software. These built-in pullup resistors are accessed in the following manner.
pinMode(pin, INPUT); // set pin to input
digitalWrite(pin, HIGH); // turn on pullup resistors

But I read that rev 1.1 (?only?) now allows the use of the INPUT_PULLUP argument …

http://arduino.cc/en/Reference/Constants

Pins Configured as INPUT_PULLUP
A pin may also be configured as an INPUT with pinMode, and subsequently made HIGH with digitalWrite, this will set the internal 20K pullup resistors, which will steer the input pin to a HIGH reading unless it is pulled LOW by external circuitry. This is how INPUT_PULLUP works as well

The Atmega chip on the Arduino has internal pull-up resistors (resistors that connect to power internally) that you can access. If you prefer to use these instead of external pull-down resistors, you can use the INPUT_PULLUP argument in pinMode(). This effectively inverts the behavior, where HIGH means the sensor is off, and LOW means the sensor is on. See the Input Pullup Serial tutorial for an example of this in use.

I tried this in my 1.0.1 version of Arduino and it compiled so perhaps it will work no matter what rev you have.

void setup()
{
  for(int i = 0; i < 8; i ++)
  {
    pinMode(ledPins[i],OUTPUT);
  }
  pinMode(buttonPin, INPUT_PULLUP);
}

In any case using the internal pull-up for pin 11 means you can just wire the switch to the pin and ground. I note you have a pull-down resistor right now. That’s not needed (shouldn’t hurt so long as the internal pull-up is disabled). Do you know what kind of switch/button you have ? Is is normally open (NO) when not pushed or normally closed (NC) ? If you don’t know you can measure it with an ohmmeter or use one of your resistor+LED to find out.

ok, I tested the button (followed arduino’s “button” tutorial), and I think it is nc because only when I pushed the button did the light turn on.

The port issue has been fixed as well.

After completing above then I tried again the 8LEDs code, but it didn’t work out.

I also tried with and without the 10k resistor

Yancha:
ok, I tested the button (followed arduino’s “button” tutorial), and I think it is nc because only when I pushed the button did the light turn on.

The port issue has been fixed as well.

After completing above then I tried again the 8LEDs code, but it didn’t work out.

OK then, it’s time to do some debugging. First, when you say “button tutorial” can I assume you mean this one ?

http://arduino.cc/en/Tutorial/Button

If so, when you say the light came on when the button was pressed were you using the original wiring configuration in that tutorial ? (see below) This is the same as you had your picture above, a switch to 5V and a pulldown resistor to ground. I’ll assume you accounted for the different wiring below, as it’s input is to pin2 and yours was to pin11; either in code or by swapping wiring.

http://arduino.cc/en/uploads/Tutorial/button_schem.png

If so then the switch is a NO type (more common). The contacts of the switch above are open when the button is not pushed. I’ll assume this is the case unless you tell me otherwise and will modify the new “8LED” code to use that switch type as well as to use the wiring arrangement previously mentioned (w/ the internal pullup) in this thread. I will also add some debug print statements so you can see what’s happening (or not happening) when that new 8LED code runs.

For the latter to work you’ll need to setup your PC so that the Arduino serial monitor can receive and display the print data coming from the Arduino. Look at this tutorial and see if you can get it running on your setup.

http://arduino.cc/en/Tutorial/DigitalReadSerial

You’ll note it uses the same switch wiring as the above. As a result you shouldn’t need to rewire anything on your breadboard, just load the tutorial code (changing the input pin from 2 to your 11). It will certainly tell you what kind of switch you have and will work with that wiring scheme and also with the scheme that has the switch between ground and the input pin, and with a pullup resistor to 5V. Feel free to experiment with either switch wiring using the “DigitalReadSerial” tutorial code.

Then you may want to look at this tutorial as it’s wiring is what everyone does normally (switch to ground, internal pullup).

http://arduino.cc/en/Tutorial/InputPullupSerial

That is the switch wiring (but using pin 11) I’ll assume you will have for the redone code with the debug prints in it. (see below) It’s the simplest (less wires) and thus the more common usage, one you’ll want to use if you continue to use the Arduino for more than this project.

http://arduino.cc/en/uploads/Tutorial/i … al_sch.png

http://arduino.cc/en/uploads/Tutorial/i … Button.png

Give me 30 mins and I’ll post the redone code.

OK, here’s the new “8LED” code with debugging print commands in it and assuming an NO switch to ground, no external resistor, using internal pull-up resistor. To prevent the code from filling up your serial monitor window with print statements 1000 times/second I’ve added a delay in the code so it only reads the button 4 times/second. I don’t see this as a big deal for this code. That said, assuming this code works and the problem can be solved, you can turn off the delay and all the print statements simply by changing 1 line of code. Here’s the new code …

// declare constants
const int debug = 1;                     //debug enabled = 1
const int ledPins[] = {2,3,4,5,6,7,8,9}; //output pins connected to LEDs
const int buttonPin = 11;                //input pin for button
const unsigned long timeConst = 1000;    //time increment (msec) to turn on each LED

//declare variables
unsigned long startTime = 0; //time when button was pushed
unsigned long onTime = 0;    //amount of time button has been pushed
int numOn = 0;               //integer number of time increments since button pushed

void setup()
{
  //initialize the serial port 9600 baud
  Serial.begin(9600);
  // set all the LEDs to off
  for(int i = 0; i < 8; i ++)
  {
    pinMode(ledPins[i],OUTPUT);
  }
  // use the internal pullup, assume NO switch to gnd
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  // add delay so loop runs slowly for debug print purposes
  if(debug)
  {
    delay(250);
  }
  if(digitalRead(buttonPin) == LOW) //is button pushed ?
  {
    //yes, button is pushed
    if(debug)
    {
      Serial.println("Button is pushed = LOW");
    }
    onTime = millis() - startTime;     //how long has button been pushed ?
    if(debug)
    {
      Serial.print("Time since button pushed is  ");
      Serial.println(onTime);
    }
    if(onTime > timeConst)             //pushed longer than 1 time increment ?
    {
      //yes, compute how many LEDs should be on
      numOn = max(onTime/timeConst, 8); //use integer math, how many time increments
      if(debug)
      {
        Serial.print("Number of time constants is  ");
        Serial.println(numOn);
      }
      //turn on that number of LEDs, 8 max
      for(int i = 0; i < numOn; i++)
      {
        digitalWrite(ledPins[i], HIGH);
      }
    }
  }
  else
  {
    //no, button is not pushed
    if(debug)
    {
      Serial.println("Button is not pushed = HIGH");
    }
    startTime = millis();            //keep resetting time until button is pushed
    //turn off all LEDs
    for(int i = 0; i < 8; i++)
    {
      digitalWrite(ledPins[i], LOW);
    }
  }
}

The one line to change is …

const int debug = 1; //debug enabled = 1

To disable the debug stuff set the debug constant to 0

const int debug = 0; //debug enabled = 1

The one questionable (to me) thing in the code is this line.

numOn = max(onTime/timeConst, 8); //use integer math, how many time increments

If it looks like the button “sense” is correct and time since button push is correct but no LEDs are coming on, the above line is likely the reason. Both “onTime” and “timeConst” are unsigned long integer types. I want the result of the above line to be an integer type but I didn’t explicitly force it to be so. Usually the compiler is smart enough to either warn you about such an error of just fix it. Perhaps that didn’t happen and I need to be explicit (this is why I don’t do coding !).

So if everything seems to be working (per the print statements) and yet no LEDs are coming on, then I think it’s 1 of 2 things. Either the line above needs to be …

numOn = max(int(onTime/timeConst), 8); //use integer math, how many time increments

or you have the LEDs in backwards. If nothing is coming on and you didn’t know LEDs have a directionality, reverse a few and see it they then light up. No harm comes from having them in reversed, they just won’t light up. Also try the line above. If neither of those work and no LEDs are on … hmmm

http://arduino.cc/en/Reference/IntCast

Did the reverse LED, they certainly didn’t light up :slight_smile:

I changed the wiring a bit (attached), and tried all previous codes- but nada.

And then, I went back to basics and tried below command just to see if anything works at all:

boolean t = false;

int i = 1;

void setup()

{

pinMode(2,OUTPUT);

pinMode(3,OUTPUT);

pinMode(4,OUTPUT);

pinMode(5,OUTPUT);

pinMode(6,OUTPUT);

pinMode(7,OUTPUT);

pinMode(8,OUTPUT);

pinMode(9,OUTPUT);

pinMode(11,INPUT);

}

void loop()

{

t = digitalRead(11);

if(t == true){

digitalWrite(1, HIGH);{

delay(1000);}

digitalWrite(2, HIGH);{

delay(1000);}

digitalWrite(3, HIGH);{

delay(1000);}

digitalWrite(4, HIGH);{

delay(1000);}

digitalWrite(5, HIGH);{

delay(1000);}

digitalWrite(6, HIGH);{

delay(1000);}

digitalWrite(7, HIGH);{

delay(1000);}

digitalWrite(8, HIGH);{

delay(1000);}

digitalWrite(8, LOW);{

delay(1000);}

digitalWrite(7, LOW);{

delay(1000);}

digitalWrite(6, LOW);{

delay(1000);}

digitalWrite(5, LOW);{

delay(1000);}

digitalWrite(4, LOW);{

delay(1000);}

digitalWrite(3, LOW);{

delay(1000);}

digitalWrite(2, LOW);{

delay(1000);}

digitalWrite(1, LOW);{

delay(1000);}

}

else {if(t == false);

{

(i = 0);}}

}

[u]So this very basic loop works ok, except for[/u]:
  1. the first LED didn’t turn on

  2. couldn’t figure out how to exit the loop when the button is not pressed (tried “While” and “Break” commends, but arduino kept popping up errors…)

  3. also tried to do a short cut with “ForLoop” but again, no results

Is it possible to do it in the “boring” way and ask it to check the Button status after the writing of each LED within the loop?

Maybe this way it will “know” when to exit…?

Yes but that’s what the loop I had was (supposed) to do.

What did the printouts on the serial monitor say with the button not pushed and then with the button pushed ?

I could verify and upload both of the full codes that you provided, but the first one had no response, and the second- all lights turned on/off at the same time when I pushed/released the button

Dare I ask again ?

What did the printouts on the serial monitor say with the button not pushed and then with the button pushed ?

OK, I went and dragged my Arduino out of the closet. Two minutes and looking at the debug prints I figured out what was wrong. It’s consistent with your observation that when the switch is pushed all the LEDs come on and then go out when the switch isn’t pushed. This is good as it indicates the switch is being read correctly. I goofed with the statement that limited the index into the array “ledPin” to 8 max. It said “max(blahblahblah)” and it should have said “min(blahblhblah)”. I fixed that and it should now work. I don’t have 8 LEDs but printouts look good now and the one LED I do have goes on a the right time.

Here’s the fixed code:

// declare constants
const int debug = 1;                     //debug enabled = 1
const int ledPins[] = {2,3,4,5,6,7,8,9}; //output pins connected to LEDs
const int buttonPin = 11;                //input pin for button
const unsigned long timeConst = 1000;    //time increment (msec) to turn on each LED

//declare variables
unsigned long startTime = 0; //time when button was pushed
unsigned long onTime = 0;    //amount of time button has been pushed
int numOn = 0;               //integer number of time increments since button pushed

void setup()
{
  //initialize the serial port 9600 baud
  Serial.begin(9600);
  // set all the LEDs to off
  for(int i = 0; i < 8; i ++)
  {
    pinMode(ledPins[i],OUTPUT);
  }
  // use the internal pullup, assume NO switch to gnd
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  // add delay so loop runs slowly for debug print purposes
  if(debug)
  {
    delay(250);
  }
  if(digitalRead(buttonPin) == LOW) //is button pushed ?
  {
    //yes, button is pushed
    if(debug)
    {
      Serial.println("Button is pushed = LOW");
    }
    onTime = millis() - startTime;     //how long has button been pushed ?
    if(debug)
    {
      Serial.print("Time since button pushed is  ");
      Serial.println(onTime);
    }
    if(onTime > timeConst)             //pushed longer than 1 time increment ?
    {
      //yes, compute how many LEDs should be on
      numOn = min(int(onTime/timeConst), 8); //use integer math, how many time increments
      if(debug)
      {
        Serial.print("Number of time constants is  ");
        Serial.println(numOn);
      }
      //turn on that number of LEDs, 8 max
      for(int i = 0; i < numOn; i++)
      {
        digitalWrite(ledPins[i], HIGH);
      }
    }
  }
  else
  {
    //no, button is not pushed
    if(debug)
    {
      Serial.println("Button is not pushed = HIGH");
    }
    startTime = millis();            //keep resetting time until button is pushed
    //turn off all LEDs
    for(int i = 0; i < 8; i++)
    {
      digitalWrite(ledPins[i], LOW);
    }
  }
}

Here’s a printout of what the serial monitor should look like.