Push-button only works once, does not progress in duty cycle

My student has been trying several projects with his push-button, and in each case, the button turns on the music exactly once, but will not repeat the trick and play (or stop) a second time if the button is pressed again. Why isn't this if() statement working, does anyone know?

int cycles;

#define G 1567.98 //telling the arduino that G is 1567.98hz
#define B 1864.66 //telling the arduino that Bb minor is 1864.66hz
#define A 1760.00 //telling the arduino that A is 1760.00hz
#define D 1174.66 //telling the arduino that D is 1174.66hz
#define R 0 //adding a rest 

  int btn = 10; //making btn a global variuable for pin 10
  int bzzr = 11; //making bzzr a global variuable for pin 11
  int notes [] = {G,B,A,D,R};//there sre the notes that i want the speaker to play 
  int dur [] =   {1,1,1,1,2};//this is how long each note will play for

void setup () {
  pinMode(bzzr,OUTPUT);
  pinMode(btn, INPUT);
  Serial.begin(9600);
  cycles=0;
}

void loop () {
  if(digitalRead(btn)==HIGH){
    cycles=cycles+1;    
   }
  
if(cycles==1){
    Serial.print("hi   ");
    Serial.println(cycles);
      for(int i = 0; i < 6; i++){ //playing the music
        tone(11, notes[i], 1000);
        delay(dur[i]*900);//the amount of time in between each note 
  }

  if(cycles==2){
    cycles=0;
  }
}

Show us a good schematic of the circuit.
Show us a good image of your ‘actual’ wiring.

Use CTRL T to format sketches.


Look at ‘when the switch goes HIGH’ NOT while the switch is HIGH.

1 Like

The for loop is missing a closing brace.

1 Like

Hi Seliaser,

when you press the button, cycles become 1, then you have an if statement, but in that statement, you don't check if the button is pressed again.

Also, you should only execute code when the button is pressed and then released, now if I hold the button, cycles will keep increasing.

I always do something like this:

/* Boolean to check if the button is pressed */
uint8_t buttonPressed = 0;
void loop () {
    /* When the button is pressed, set the boolean to true (1) */
    if(digitalRead(button)){
        buttonPressed = 1;
    } 
    /* if the button is released and buttonPressed set true */
    if (!digitalRead(button) && buttonPressed) {
    // Do your thing here
    buttonPressed = 0; // DONT forget to set this low again for next press
    }
}

So also check if btn is high in if(cycles==1){}

You could try this:

int cycles;

#define G 1567.98 //telling the arduino that G is 1567.98hz
#define B 1864.66 //telling the arduino that Bb minor is 1864.66hz
#define A 1760.00 //telling the arduino that A is 1760.00hz
#define D 1174.66 //telling the arduino that D is 1174.66hz
#define R 0 //adding a rest 

int btn = 10; //making btn a global variuable for pin 10
int bzzr = 11; //making bzzr a global variuable for pin 11
int notes [] = {G, B, A, D, R}; //there sre the notes that i want the speaker to play
int dur [] =   {1, 1, 1, 1, 2}; //this is how long each note will play for

/* Boolean to check if the button is pressed */
int buttonPressed = 0;


void setup () {
  pinMode(bzzr, OUTPUT);
  pinMode(btn, INPUT);
  Serial.begin(9600);
  cycles = 0;
}

void loop () {
  if (digitalRead(btn)) {
    buttonPressed = 1;
  }
 // When the button is released, cycles will go up one
  if (!digitalRead(button) && buttonPressed) {
    cycles = cycles + 1;
    buttonPressed = 0;
  }

  if (cycles == 1) {
    // When cycles is 1, we still need to check if the button is pressed. 
    if (digitalRead(btn)) {
      buttonPressed = 1;
    }
    // If pressed and released, cycles goes up one, then `cycles == 1` is false and we leave this part
    if (!digitalRead(button) && buttonPressed) {
      cycles = cycles + 1;
      buttonPressed = 0;
    }
    Serial.print("hi   ");
    Serial.println(cycles);
    for (int i = 0; i < 6; i++) { //playing the music
      tone(11, notes[i], 1000);
      delay(dur[i] * 900); //the amount of time in between each note
    }
  }

  if (cycles == 2) {
    cycles = 0;
  }
}

If I understood the question correctly, this will actually produce the wrong result... my understanding was that the music would play each time that the button is pressed.
(Using your button-pressed-and-released approach):

void loop () {
  if (digitalRead(btn)) {
    buttonPressed = 1;
  }
 // When the button is released, cycles will go up one
  if (!digitalRead(button) && buttonPressed) {
    cycles = cycles + 1;
    buttonPressed = 0;
  }

  if (cycles == 1) {
    Serial.print("hi   ");
    Serial.println(cycles);
    for (int i = 0; i < 6; i++) { //playing the music
      tone(11, notes[i], 1000);
      delay(dur[i] * 900); //the amount of time in between each note
    }
    cycles = 0;
  }

}

... should do the trick I think.

1 Like

I think you are right here! Should play every time the button is pressed.

int cycles;

#define G 1567.98 //telling the arduino that G is 1567.98hz
#define B 1864.66 //telling the arduino that Bb minor is 1864.66hz
#define A 1760.00 //telling the arduino that A is 1760.00hz
#define D 1174.66 //telling the arduino that D is 1174.66hz
#define R 0 //adding a rest 

byte btn = 10; //making btn a global variuable for pin 10
byte bzzr = 11; //making bzzr a global variuable for pin 11
byte notes [] = {G,B,A,D,R};//there sre the notes that i want the speaker to play 
byte dur [] =   {1,1,1,1,2};//this is how long each note will play for

byte poll = 0;

void setup () 
{
  pinMode(bzzr,OUTPUT);
  pinMode(btn, INPUT);
  Serial.begin(9600);
  cycles=0;
}

void loop () 
{
  do
  {
    poll = digitalRead(btn);
  }while (poll == LOW);
  
  playNotes ();
  delay (2000);
  playNotes ();
}

void playNotes ()
{
  Serial.println(cycles);
  for(int i = 0; i < 6; i++)
  { 
    //playing the music
    tone(11, notes[i], 1000);
    delay(dur[i]*900);//the amount of time in between each note 
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.