Changing modes with one touch button; on-mode1-mode2-mode3-off-on-mode1, etc.

Hi,

I have made a circuit like the picture is showing. What I want to achieve is when I touch the button once, the LEDs will turn on. If I touch the button the second time I want the LEDs to go on and off in an interval (mode1). If I touch the button the third time, I want the LEDs to turn on and off in a different interval than the previous. I want to have four different modes (including just having the LEDs on), and with the fifth touch on the button, the LEDs will turn off.

I am very new in programming, but this is how I see before me the sequence of the program:

  1. Initialize all variables
  2. Set initial condition
  3. Tell the micro controller to continuously count how many times the touch button is being pressed.
  • If pressed once, this happens: LEDs on.

  • If pressed twice, LEDs on, interval 1

  • If pressed three times; LEDs on, interval 2

  • If pressed four times; LEDs on, interval 3

  • If pressed five times; LEDs off and the counter is being reset.

This is how my program looks like.

/*
*Blink
*This is a prototype for the Aurora scooter jacket.
*Created 17th of September 2012
*By Janniche Aaroen
*/

int ledPin = 13; // the LED on the Lilypad
int shoulder = 11; // Red LEDs
int back = 10; // Red LEDs
int frontdown = 9; // White LEDs
int fronttop = 3; // White LEDs
int pushbutton = 7; // pushbutton
int buttonPushCounter = 0; // counter for the number of button presses
int buttonState = LOW; // current state of the button
int lastButtonState = LOW; // previous state of the button

// The setup() method runs once, when the sketch starts

void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT); // sets the LedPin to be an output
pinMode(shoulder, OUTPUT); // sets the shoulder to be an output
pinMode(back, OUTPUT); // sets the back to be an output
pinMode(frontdown, OUTPUT); // sets the frontdown to be an output
pinMode(fronttop, OUTPUT); // sets the fronttop to be an output
pinMode(pushbutton, INPUT); // sets the button to an input signal
digitalWrite(ledPin, LOW); // sets the ledPin to LOW
digitalWrite(shoulder, LOW); // sets the shoulder pin to LOW
digitalWrite(back, LOW); // sets the back pin to LOW
digitalWrite(frontdown, LOW); // sets the frontdown pin to LOW
digitalWrite(fronttop, LOW); // sets the fronttop pin to LOW

}

void loop(){
{ buttonPushCounter++;
Serial.println("on");
Serial.print("number of button pushes: ");
Serial.println(buttonPushCounter, DEC);

if(buttonPushCounter == 1);
{
digitalWrite(shoulder, HIGH);
digitalWrite(back, HIGH);
digitalWrite(frontdown, HIGH);
digitalWrite(fronttop, HIGH); }

if(buttonPushCounter == 2);
{ void loop();

{

digitalWrite(shoulder, HIGH);
digitalWrite(back, HIGH);
digitalWrite(frontdown, HIGH);
digitalWrite(fronttop, HIGH);
delay(500); // wait for 0,5 second
digitalWrite(shoulder, LOW);
digitalWrite(back, LOW);
digitalWrite(frontdown, LOW);
digitalWrite(fronttop, LOW);
delay(500); } }

}

}

I have only put in the two modes.. Some functions are missing for sure, that is what I need help to to put in.
What is Serial.In? And what does DEC mean? Serial.println(buttonPushCounter, DEC);
Also; how do I put a loop inside another loop?

When I upload the program, nothing happens for a second, then all LEDs goes on once and then off. This happens without me touching the button...

Thank you for any help on my project.

-Janniche

Read this before posting a programming question

Hi Janniche,

First off, looking at your schematic you don't seem to have any resistors to limit current to the LED's and driving 5x LED's from one I/O pin will probably draw to much current and damage your LilyPad.

The code you supplied has a few errors like extra void loop() and spurious extra { and } brackets. You have a button in the schematic but don't read it in your main loop to increment buttonPushCounter, you just continually increment buttonPushCounter so it will quickly go from 0 to 1 and 2 then beyond that you don't check for any more states.
Push buttons become very unresponsive when you use long delays in the code as you have.

void loop(){
    if (digitalRead(pushbutton) == HIGH){
        delay(20); // button debounce
        buttonPushCounter++;
        if (buttonPushCounter > 2){
            buttonPushCounter = 1;
        }
    }
    Serial.println("on");
    Serial.print("number of button pushes:  ");
    Serial.println(buttonPushCounter, DEC);
    
    if(buttonPushCounter == 1) {
        digitalWrite(shoulder, HIGH);
        digitalWrite(back, HIGH);
        digitalWrite(frontdown, HIGH);
        digitalWrite(fronttop, HIGH); 
    }
    
    if(buttonPushCounter == 2) {         
        digitalWrite(shoulder, HIGH);
        digitalWrite(back, HIGH);
        digitalWrite(frontdown, HIGH);
        digitalWrite(fronttop, HIGH);
        delay(500);                // wait for 0,5 second
        digitalWrite(shoulder, LOW);
        digitalWrite(back, LOW);
        digitalWrite(frontdown, LOW);
        digitalWrite(fronttop, LOW);
        delay(500); 
    }
}

Hi Riva,

Thank you for your reply.

I did not mention it, but the LEDs in the circuit are Lilypad LEDs with integrated resistors (tiny boards with both the LED and the resistor)
About the code you sent, is it how it should be or are you highlighting what is wrong? Would you mind explaining what each line of this part does:

if (digitalRead(pushbutton) == HIGH){
delay(20); // button debounce
buttonPushCounter++;
if (buttonPushCounter > 2){
buttonPushCounter = 1;

Thank you again for your assistance.

if (digitalRead(pushbutton) == HIGH){
        delay(20); // button debounce
        buttonPushCounter++;

This will increase the value of the counter every 20 (plus a little) milliseconds, for as long as the switch is held down. That is most likely NOT what you want to do.

You need to compare the current state of the switch to the previous state of the switch, and do something only when the values are not the same (a transition has occurred). Of course, this means that you need to save the current state as the previous state, at the end of loop.

You can tell whether the transition is from pressed to released or from released to pressed by the current state of the switch, so that you don't increment the value when the switch is pressed and again when it is released.

Ah, I see. That makes sense. I will do some research and come up with a suggestion. Not going to bed before I've managed this!

How do I write a "loop" inside the main loop?

How do I write a "loop" inside the main loop?

A for loop? A while loop? There are several ways to loop inside the loop() function. In some cases, though, the best answer is don't.

It really depends on what you are trying to accomplish in your loop.

Not going to bed before I've managed this!

Dead on your feet is not a good way to program/solder/think/function.

Depends on exactly what you want to achieve, but start with these:

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

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

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

I recommend you find a C tutorial.

The reason I am asking for a loop within a loop is that when I touch the touch button, I want the LEDs to go ON and OFF with an interval (like a loop) until I touch the button again and the LEDs go ON and OFF with a different interval. I will check out the like you gave me. Thank you.

The reason I am asking for a loop within a loop is

unnecessary.

The loop() method already loops. On each pass, it should determine what ti do, based on state(s) (switch pressed once, switch pressed twice, LED(s) on, LED(s) off) and time (how long has it been since the LED(s) was/were toggled).

Do NOT create a loop within loop to do this.

Thank you Paul :slight_smile:

I have found this code that I've changed for the touch button and it works very well.

const int buttonPin = 7;
const int ledPin = 13; // the LED on the Lilypad
const int shoulder = 11; // Red LEDs
const int back = 10; // Red LEDs
const int frontdown = 9; // White LEDs
const int fronttop = 3; // White LEDs

int buttonState = 0;
int buttonPressed = 0;
int ledState = 0;

void setup()
{
pinMode(ledPin, OUTPUT);
pinMode(ledPin, OUTPUT); // sets the LedPin to be an output
pinMode(shoulder, OUTPUT); // sets the shoulder to be an output
pinMode(back, OUTPUT); // sets the back to be an output
pinMode(frontdown, OUTPUT); // sets the frontdown to be an output
pinMode(fronttop, OUTPUT); // sets the fronttop to be an output
pinMode(buttonPin, INPUT);
}

void loop()
{
buttonState = digitalRead(buttonPin);

if (buttonState == HIGH && buttonPressed == 0)
{
ledState = 1 - ledState;
buttonPressed = 1;
}
if (buttonState == LOW && buttonPressed == 1)
{
buttonPressed = 0;
}

if (ledState == 1)
{
digitalWrite(ledPin, LOW);
digitalWrite(shoulder, HIGH); // sets the shoulder petal to LOW
digitalWrite(back, HIGH); // sets the back petal to LOW
digitalWrite(frontdown, HIGH); // sets the frontdown petal to LOW
digitalWrite(fronttop, HIGH); // sets the fronttop petal to LOW
}
else
{
digitalWrite(ledPin, LOW);
digitalWrite(shoulder, LOW); // sets the shoulder petal to LOW
digitalWrite(back, LOW); // sets the back petal to LOW
digitalWrite(frontdown, LOW); // sets the frontdown petal to LOW
digitalWrite(fronttop, LOW); // sets the fronttop petal to LOW
}
}

When I turn on the Lilypad, nothing happens before I touch the switch; then all the LEDs come on. When I touch the button again, I turn off all the LEDs.

How can I, in between there, when I touch the button the second time, instead of turning the LEDs off, I want to make the LEDs blink, and then with the third touch of the button I want to turn them off. How can this be achieved? I've been looking for examples that kind of look like what I am trying to do, but I find it difficult to transfer the code when I do not understand the function of that particular sentence/statement.

I will be very thankful for feedback with code examples with description of what the code means.

How can I, in between there, when I touch the button the second time, instead of turning the LEDs off, I want to make the LEDs blink, and then with the third touch of the button I want to turn them off. How can this be achieved?

First, I'd suggest that you re-read all the replies so far. You are incrementing the counter too often/incorrectly.
Separate the need to increment the counter from the actual counter value.

Clearly, you need more valid buttonPressed values (0, 1, and 2), and you need an else if case to handle the (new) buttonPressed == 1 case.

Inside that block, do not even consider putting a call to delay(). Look at the blink without delay example.

Ok, clearly I can not figure this out due to my lack of knowledge and time. I have already spent three days trying to figure this out, I recon it is not in for me, and I now need to solve other issues within my project. Do anyone know of someone I can hire to help me with the programming?

Scenario: 4 LED circuits that does the same at all time. One button. One lilypad (see initial sketch).

Sequence:

  1. Press on button: LEDs on

  2. press on button: LEDs fading on and off

  3. press on button: LEDs blinking with interval 1s

  4. press on button: LEDs blinking with interval 0,5s

  5. press on button: LEDs off

  6. Press on button: LEDs on
    7... etc.

Thank you.

-Janniche

u have to use npn transistor to power your leds i don t thinks lily pad can handle 5 leds per pin, read this post http://lanavajadelgeek.blogspot.com.ar/2011/07/aprende-como-funciona-un-interruptor.html use google traslator :stuck_out_tongue: to traslate all the page

realy is very easy in general a transistor (npn) have 3 leg base, emiter, colector

base: is the pin that recive the signal from the arduino (micro, ect) and let pass voltage from colector to emiter
emiter: conected to comond ground
colector: conected to the ground of the led

and the code u can use raw code, a variable "state"

if (state == 3) { 
           state = 0;
                    }

 if (button1 == HIGH){
           state++;
                             }

if (state == 0) {do something1;}
if (state == 1) {do something2;}
if (state == 2) {do something3;}
if (state == 3) {do something4;}

this is an idea no the actual code you have to add the timer to the button to lock him from been trigger alot of times in 1 push

Here's my attempt. You'll need my SimpleTimer library http://arduino.cc/playground/Code/SimpleTimer

#include <SimpleTimer.h>


// sequence 1: led on
// sequence 2: led fading on and off
// sequence 3: led blinking with interval 1s
// sequence 4: led blinking with interval 0,5s

// pin 3 = pwm output to led
// pin 2 = input, select button (active low)

SimpleTimer timer;


int ledPin = 3;
int btnPin = 2;

int seq_2_timerId;
int seq_3_timerId;
int seq_4_timerId;

int currSequence = 0;        // current running sequence; 0 = no sequence is running, led off
const int NUM_SEQ = 4;       // number of implemented sequences


void ledOn() {
    digitalWrite(ledPin, HIGH);
}

void ledOff() {
    digitalWrite(ledPin, LOW);
}


void ledBlink() {
    static boolean isLedOn = false;

    if (isLedOn) {
        ledOn();
    }
    else {
        ledOff();
    }

    isLedOn = isLedOn ? false : true;
}


void ledPwm(boolean reset = false) {
    static int pwmLevel = 0;
    static int pwmStep = 1;
    static int maxPwmLevel = 255;
    static int pwmDirection = 1;

    if (reset) {
        pwmLevel = 0;
        pwmDirection = 1;
    }

    analogWrite(ledPin, pwmLevel);

    pwmLevel += pwmDirection;

    if (pwmLevel >= maxPwmLevel) {
        pwmLevel = maxPwmLevel;
        pwmDirection = -1;
    }
    else if (pwmLevel <= 0) {
        pwmLevel = 0;
        pwmDirection = 1;
    }
}

void ledPwmTmrCallback() {
    ledPwm();
}


void seq1_start() {
    ledOn();
}

void seq1_stop() {
    ledOff();
}


void seq2_start() {
    ledPwm(true);
    timer.enable(seq_2_timerId);
}

void seq2_stop() {
    timer.disable(seq_2_timerId);
}


void seq3_start() {
    timer.enable(seq_3_timerId);
}

void seq3_stop() {
    timer.disable(seq_3_timerId);
}


void seq4_start() {
    timer.enable(seq_4_timerId);
}

void seq4_stop() {
    timer.disable(seq_4_timerId);
}


void seq1_setup() {
}

void seq2_setup() {
    seq_2_timerId = timer.setInterval(5, ledPwmTmrCallback);
}

void seq3_setup() {
    seq_3_timerId = timer.setInterval(1000, ledBlink);
}

void seq4_setup() {
    seq_4_timerId = timer.setInterval(500, ledBlink);
}


void selectNextSequence() {
    currSequence++;
    if (currSequence > NUM_SEQ) {
        currSequence = 0;
    }

    switch (currSequence) {
    case 0:
        seq1_stop();
        seq2_stop();
        seq3_stop();
        seq4_stop();
        Serial.println("Off");
        break;

    case 1:
        seq1_start();
        seq2_stop();
        seq3_stop();
        seq4_stop();
        Serial.println("Seq 1: led on");
        break;

    case 2:
        seq1_stop();
        seq2_start();
        seq3_stop();
        seq4_stop();
        Serial.println("Seq 2: fading on and off");
        break;

    case 3:
        seq1_stop();
        seq2_stop();
        seq3_start();
        seq4_stop();
        Serial.println("Seq 3: blink 1s");
        break;

    case 4:
        seq1_stop();
        seq2_stop();
        seq3_stop();
        seq4_start();
        Serial.println("Seq 4: blink 0,5s");
        break;
    }
}


void serialEvent() {
    char ch;

    ch = Serial.read();

    if (ch == 'P') {
        selectNextSequence();
    }
}


int btnRead() {
    return digitalRead(btnPin);
    //return (analogRead(btnPin) > 500 ? HIGH : LOW);
}


void btnCheck() {
    static int prevState = 0;
    static int currState = 0;

    currState = btnRead();
    if (currState != prevState) {
        if (currState == LOW) {        // button is active low
            selectNextSequence();
        }
    }

    prevState = currState;
}


void setup() {
    // hw initialization
    Serial.begin(9600);
    pinMode(ledPin, OUTPUT);
    pinMode(btnPin, INPUT);
    digitalWrite(btnPin, HIGH);        // internal pullup
    ledOff();

    // sequence setup
    seq1_setup();
    seq2_setup();
    seq3_setup();
    seq4_setup();

    // stop all sequences
    seq1_stop();
    seq2_stop();
    seq3_stop();
    seq4_stop();

    // button polling routine
    timer.setInterval(20, btnCheck);

    // print usage
    Serial.println("Send P to cycle through sequences.");
}


void loop() {
    timer.run();
}

(Compiled and tested on a Arduino UNO board. To be precise, the board didn't have a pushbutton attached to it, but had a fotoresistor instead, so I used it to simulate a button (see commented line in btnRead). This version digitally reads a button, though.)

Usage: connect the led driver to pin 3 (active high); fire up the serial monitor @9600 and send P char to cycle through sequences.
Otherwise, connect an active low switch to pin 2 to achieve the same effect. Keep the serial monitor open to see what sequence it's running.

Improving the code by using an array of function pointers or an array of objects is left as an exercise for the reader :stuck_out_tongue: