Go Down

Topic: Program stops after button press (Read 1 time) previous topic - next topic

Thanatos

Dear all

As this is my first post, I will try to explain my problem thoroughly.
I looked around with the search function a bit but couldn't find anything specific that could help me.

I am completely new to Arduino and bought myself a Starter Kit and had a lot of fun with this.
After a day of fooling around I decided to create something useful for myself, a light metronome.

I have 1 display (and a pot meter) which shows the current BPM. Then I have put 2 buttons and 1 LED in between there.
1 button is designed to augment the value of the beat by 1, the other button diminishes it by 1.
Whenever I press 1 of the 2 buttons, the program stops working (also the traces in the monitor stop being printed).

I have basically followed the tutorial here to attach the display, and then I have added the 2 buttons and 1 LED along with that display on my bread board.
Basically we can look at it like this:

Code: [Select]

________
|arduino|-----screen----button-----LED

Basically, I have no clue if my "chain" is series or parallel. I have almost 0 electrical knowledge.
I take a "branch" from the 5V for the 2 buttons. For the - on the buttons, I have put them directly to the arduino inputs and also put a resistor towards the ground (as a "branch").
For the LED, I +, I led it to the input and for the -, I took a resistor and put it to the ground as a "branch".

My code:
Code: [Select]

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int BPM = 120;
int minSwitchState;
int plusSwitchState;
float toDelay;
long previousMillis = 0;

void setup() {
 Serial.begin(9600);
 lcd.begin(16, 2);
 updateDisplay();

 //output LED
 pinMode(6, OUTPUT);

 //input buttons
 pinMode(7, INPUT);
 pinMode(8, INPUT);
}

void loop() {
 
 minSwitchState = digitalRead(8);
 plusSwitchState = digitalRead(7);
 
 if(minSwitchState == HIGH) {
   BPM++;
   updateDisplay();
 }
 if(plusSwitchState == HIGH) {
   BPM--;
   updateDisplay();
 }
 unsigned long currentMillis = millis();
 
 if(currentMillis - previousMillis == toDelay) {
   digitalWrite(6, HIGH);
   previousMillis = currentMillis;
   Serial.println(millis() / 100.0);
 }else{
   digitalWrite(6, LOW);
 }
}

void updateDisplay() {
 toDelay = 60000.0 / (float) BPM;
 lcd.clear();
 lcd.print("Kies BPM: ");
 lcd.setCursor(0, 1);
 lcd.print(BPM);
 delay(100);
}


The delay(100) at the end is to give the display time enough to refresh. I know 100 is too much, but else, when I keep pressing the buttons, the numbers go up soooooo rapidly.
I have used a part of code I found here to have no delay for bling LED's. Later on I will propably make the bling longer than 1 milli :).

Thanks in advance!!

Nick Gammon

Loop is executed very frequently. Instead of incrementing the counter when the switch is HIGH, you need to increment if it is HIGH and was LOW. In other words, a transition.

HazardsMind

Don't do "== todelay", just do "> todelay"
Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

Thanatos

Thanks all for your replies.
Doing > or >= indeed works perfectly.
However, I noticed that my LED blings really really poorly (like at 10% light emitting).
Whenever I hold 1 of the buttons, the LED seems to emit at pretty much 90%, which is good.
Would that be because I only lit it for 1 millisecond when the buttons are not pressed, or is there another explanation?

@Nick Gammon
Thanks for the reply. I don't really understand exactly what you mean, but it seems to alost work perfectly now :).

Nick Gammon

Your schematic is hard to follow. You should have a resistor in series with the LED.

For better help you need to draw what you have actually done.

Thanatos

#5
Feb 04, 2013, 01:00 pm Last Edit: Feb 04, 2013, 01:07 pm by Thanatos Reason: 1
Since I have no clue how to draw this correctly, I took a picture.
The picture is about 1 mega byte, so it could take a while to load.

Nick Gammon

The wiring for the switch doesn't look correct to me. Typically people wire like this, relying on the internal pull-up which you can enable:



This example code enables the pull-up and also detects the transition between the switch being up (and HIGH because of the pull-up) and pressed (thus, LOW).

Code: [Select]

const byte mySwitch = 8;

byte oldMySwitch = HIGH;

void setup ()
  {
  pinMode (mySwitch, INPUT_PULLUP);
  }  // end of setup

void loop ()
  {
  byte switchReading = digitalRead (mySwitch);
 
  if (switchReading != oldMySwitch)
    {
    if (switchReading == LOW)
      {
      delay (15);  // debounce
     
      // handle switch press here
       
      }  // end of switch down
     
    oldMySwitch = switchReading;
    } // end of switch changed
  }  // end of loop
 

HazardsMind

@Nick Gammon
He has a resistor in there, I just can't tell if it is pull up or down though. You have to look very closely to see the connections, but it's there.
Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

Nick Gammon

OK, but he still needs to detect the state change.

HazardsMind

@Nick Gammon
Right, otherwise he'll go through 50 or so numbers (depending on size of program) with just one press.

OP, study Nick's sketch! It looks for when the switch/button's state changes from HIGH to LOW, (or vice versa), and only when it see that the state did change, it does an action.
Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

Thanatos

Hi

Thanks for the replies!
To prevent the program going 50 numbers with 1 press, I have put the delay(100) there.
With trial and error, I concluded that 100 is perfect speed and I can still go up with only 1 when pressing and releasing quickly.

I will however study the code put above. Thanks a lot!

Nick Gammon

Er, yes, but if you hold the button down it will still slowly creep up (maybe you want that, eh?).

Thanatos

Indeed, the slow increments are exactly what I wanted :).
This is because if you want to set the BPM from 90 to 150, I don't want to push the button 60 times :).
I have tried some things in the meantime for the weird led behaviour, but it didn't work, I'll keep things posted.

PaulS

Quote
Indeed, the slow increments are exactly what I wanted smiley.
This is because if you want to set the BPM from 90 to 150, I don't want to push the button 60 times

So, measure the time between discrete presses. A relatively long time means increment by 1. A medium amount of time means increment by 3. A very short time means increment by 5.

Thanatos


Quote
Indeed, the slow increments are exactly what I wanted smiley.
This is because if you want to set the BPM from 90 to 150, I don't want to push the button 60 times

So, measure the time between discrete presses. A relatively long time means increment by 1. A medium amount of time means increment by 3. A very short time means increment by 5.

No, it is now as I like it. Press 1 time, increase by 1. Keep pressing, keep going up rapidly. Why would you want to go up by 5 when you press short time and only by 1 if you keep it pressed in? I can't see a logical use for that :D.

Go Up