Cant get my buttons to do anything

Hi,

I wrote some code but for some reason i cant get the buttons to do anything even though I dont see anything wrong in the code. I know that my buttons work. All that my code is supposed to do so far is jump from the menu to the main game when i press A and stop drawing the speaker icon in the menu when I press B. Neither of these things happen.

Thanks in advance.

#include "Arduboy.h"

Arduboy arduboy;

boolean sound = true;
int screen = 0;

void setup() {
  arduboy.begin();
  arduboy.setFrameRate(60);
  arduboy.clear();
  drawStartMenu();
  arduboy.display();
}

void loop() {
  
  //if (!(arduboy.nextFrame()))
    //return;
    
  while (screen = 0) {
    drawStartMenu();
    
    if (arduboy.pressed(B_BUTTON)) {
      sound = false;
    }

    if (arduboy.pressed(A_BUTTON)) {
      screen = 1;
    }
    
  }
  
  while (screen = 1) {
    
    drawRoom();
  }
}

void drawRoom() {
  arduboy.drawFastHLine(0, 0, 128, 1);
  arduboy.drawFastHLine(0, 63, 128, 1);
  arduboy.drawFastVLine(0, 0, 64, 1);
  arduboy.drawFastVLine(127, 0, 64, 1);
  arduboy.drawFastVLine(56, 0, 8, 1);
  arduboy.drawFastVLine(71, 0, 8, 1);
  arduboy.drawFastVLine(56, 56, 8, 1);
  arduboy.drawFastVLine(71, 56, 8, 1);
  arduboy.drawFastHLine(0, 24, 8, 1);
  arduboy.drawFastHLine(0, 39, 8, 1);
  arduboy.drawFastHLine(120, 24, 8, 1);
  arduboy.drawFastHLine(120, 39, 8, 1);
}

void drawDoors(bool dn,bool de,bool ds,bool dw) {
  if (dn) {
    arduboy.drawFastHLine(56, 7, 16, 1);
  }
  if (de) {
    arduboy.drawFastVLine(120, 24, 16, 1);
  }
  if (ds) {
    arduboy.drawFastHLine(56, 56, 16, 1);
  }
  if (dw) {
    arduboy.drawFastVLine(7, 24, 16, 1);
  }
}

void drawStartMenu() {
  arduboy.setCursor(0, 4);
  arduboy.print("A to Start...");
  arduboy.setCursor(0, 20);
  arduboy.print("B to toggle Sound");
  arduboy.drawCircle(56, 52, 8, 1);
  arduboy.drawCircle(72, 41, 8, 1);
  arduboy.setCursor(54, 49);
  arduboy.print ("B");
  arduboy.setCursor(70, 38);
  arduboy.print ("A");
  arduboy.drawTriangle(114, 20, 114, 28, 106, 24, 1);
  if (sound) {
    arduboy.drawFastVLine(116, 23, 3, 1);
    arduboy.drawFastVLine(118, 22, 5, 1);
    arduboy.drawFastVLine(120, 21, 7, 1);
  }
}

Hi Hans,

I didn’t took a deep look to your code, but i immediately noticed you loop conditions are assignments and not comparisons.
So instead of while (screen = 0) you need while(screen == 0) and so on.

Best

2 Likes

After further reading you are also missing arduboy.clear() andarduboy.display() in you loops. You have to call them so the device actually draws something. Similiar for the buttons.

i.e. your first loop should look like this:

while (screen = 0) {

    // Keep this
    if (!arduboy.nextFrame())
       return;

    // You need this so the new button states will be fetched
    arduboy.pollButtons();
    
    if (arduboy.pressed(B_BUTTON)) {
      sound = false;
    }

    if (arduboy.pressed(A_BUTTON)) {
      screen = 1;
    }

    // Do the display stuff
    arduboy.clear();
    drawStartMenu();
    arduboy.display();
  }
2 Likes

@Botisaurus covered the issues you asked about, but I’m going to add two more things.

Firstly (in an attempt to pre-empt MLXXXP), the Arduboy library has been discontinued, Arduboy2 is its replacement.


Secondly you’re using while loops for all your ‘screens’, when you could be using ifs, or even better, switches.

For example:

void loop()
{
	switch(screen)
	{
		case 0:
		{
			drawStartMenu();
			
			if (arduboy.pressed(B_BUTTON))
			{
				sound = false;
			}

			if (arduboy.pressed(A_BUTTON))
			{
				screen = 1;
			}
		}
		break; // break ends the case
		case 1:
		{
			drawRoom();
		}
		break;
	}
}

The loop function is continually executed - when it ends, it begins again.

In fact there’s actually another function hidden away called main that is calling your setup and loop functions, and it looks something like this:

void main()
{
	setup();
	while(true)
	{
		loop();
	}
}

(Not exactly like that, there’s a bit more to it, but the rest isn’t really important, so pretend it’s that.)


Lastly I think the drawDoors thing is going to cause you some issues later (particularly when you get bored of adding new doors). I won’t say anything now in case you want to figure it out on your own, but if you would like to know some better ways to handle the doors, ask away.

2 Likes

Along with what has already been pointed out,

Note that the pressed() function will detect the button being pressed for as long as it’s held down, not only once. For every time through loop() the buttons will be detected, and the same code will be executed, while the button(s) are pressed.

If you want to detect a button only once each time it’s pressed and released, you should used the justPressed() function, along with pollButtons() in the loop. These functions are only available in the Arduboy2 library.

1 Like

Hey thanks for your reply.
I have tried switching to justPressed() but it istn ding anything.
Maybe you can see what I am doing wrong.
Thanks.

#include <Arduboy2.h>

Arduboy2 arduboy;

boolean sound = true;
int screen = 0;

void setup() {
  arduboy.begin();
  arduboy.setFrameRate(30);
  arduboy.clear();
  drawStartMenu();
  arduboy.display();
}

void loop() {
  
  //if (!(arduboy.nextFrame()))
    //return;
    
  while (screen == 0) {
    
    if (!arduboy.nextFrame())
      return;
      
    drawStartMenu();
    arduboy.display();
    arduboy.pollButtons();
    if (arduboy.justPressed(B_BUTTON)) {
      sound = false;
    }

    if (arduboy.pressed(A_BUTTON)) {
      screen = 1;
      arduboy.clear();
    }
  }
  
  while (screen == 1) {

    if (!arduboy.nextFrame())
      return;
    
    drawRoom();
    drawDoors(true, true, true, true);
    arduboy.display();
  }
}

void drawRoom() {
  arduboy.drawFastHLine(0, 0, 128, 1);
  arduboy.drawFastHLine(0, 63, 128, 1);
  arduboy.drawFastVLine(0, 0, 64, 1);
  arduboy.drawFastVLine(127, 0, 64, 1);
  arduboy.drawFastVLine(56, 0, 8, 1);
  arduboy.drawFastVLine(71, 0, 8, 1);
  arduboy.drawFastVLine(56, 56, 8, 1);
  arduboy.drawFastVLine(71, 56, 8, 1);
  arduboy.drawFastHLine(0, 24, 8, 1);
  arduboy.drawFastHLine(0, 39, 8, 1);
  arduboy.drawFastHLine(120, 24, 8, 1);
  arduboy.drawFastHLine(120, 39, 8, 1);
}

void drawDoors(bool dn,bool de,bool ds,bool dw) {
  if (dn) {
    arduboy.drawFastHLine(56, 7, 16, 1);
  }
  if (de) {
    arduboy.drawFastVLine(120, 24, 16, 1);
  }
  if (ds) {
    arduboy.drawFastHLine(56, 56, 16, 1);
  }
  if (dw) {
    arduboy.drawFastVLine(7, 24, 16, 1);
  }
}

void drawStartMenu() {
  arduboy.setCursor(0, 4);
  arduboy.print("A to Start...");
  arduboy.setCursor(0, 20);
  arduboy.print("B to toggle Sound");
  arduboy.drawCircle(56, 52, 8, 1);
  arduboy.drawCircle(72, 41, 8, 1);
  arduboy.setCursor(54, 49);
  arduboy.print ("A");
  arduboy.setCursor(70, 38);
  arduboy.print ("B");
  arduboy.drawTriangle(114, 20, 114, 28, 106, 24, 1);
  if (sound) {
    arduboy.drawFastVLine(116, 23, 3, 1);
    arduboy.drawFastVLine(118, 22, 5, 1);
    arduboy.drawFastVLine(120, 21, 7, 1);
  }
}

arduboy.pollButtons();
should go at the start of loop(), after the nextframe() code that you’ve disabled. It should only be called once per frame.

I dont think I am getting this because its still not working.

Here is my code so far the B button still isnt working

#include <Arduboy2.h>

Arduboy2 arduboy;

boolean sound = true;
int screen = 0;

void setup() {
  arduboy.begin();
  arduboy.setFrameRate(30);
  arduboy.clear();
  drawStartMenu();
  arduboy.display();
}

void loop() {
  
  if (!(arduboy.nextFrame())) {
    return;
  }
  
  arduboy.pollButtons();
    
  while (screen == 0) {
    drawStartMenu();
    arduboy.display();
    if (arduboy.justPressed(B_BUTTON)) {
      if (sound) {
        sound = false;
      } else {
        sound = true;
      }
    }

    if (arduboy.pressed(A_BUTTON)) {
      screen = 1;
      arduboy.clear();
    }
  }
  
  while (screen == 1) {
    
    drawRoom();
    drawDoors(true, true, true, true);
    arduboy.display();
    if (arduboy.pressed(B_BUTTON)) {
      screen = 0;
      arduboy.clear();
    }
  }
}

void drawRoom() {
  arduboy.drawFastHLine(0, 0, 128, 1);
  arduboy.drawFastHLine(0, 63, 128, 1);
  arduboy.drawFastVLine(0, 0, 64, 1);
  arduboy.drawFastVLine(127, 0, 64, 1);
  arduboy.drawFastVLine(56, 0, 8, 1);
  arduboy.drawFastVLine(71, 0, 8, 1);
  arduboy.drawFastVLine(56, 56, 8, 1);
  arduboy.drawFastVLine(71, 56, 8, 1);
  arduboy.drawFastHLine(0, 24, 8, 1);
  arduboy.drawFastHLine(0, 39, 8, 1);
  arduboy.drawFastHLine(120, 24, 8, 1);
  arduboy.drawFastHLine(120, 39, 8, 1);
}

void drawDoors(bool dn,bool de,bool ds,bool dw) {
  if (dn) {
    arduboy.drawFastHLine(56, 7, 16, 1);
  }
  if (de) {
    arduboy.drawFastVLine(120, 24, 16, 1);
  }
  if (ds) {
    arduboy.drawFastHLine(56, 56, 16, 1);
  }
  if (dw) {
    arduboy.drawFastVLine(7, 24, 16, 1);
  }
}

void drawStartMenu() {
  arduboy.setCursor(0, 4);
  arduboy.print("A to Start...");
  arduboy.setCursor(0, 20);
  arduboy.print("B to toggle Sound");
  arduboy.drawCircle(56, 52, 8, 1);
  arduboy.drawCircle(72, 41, 8, 1);
  arduboy.setCursor(54, 49);
  arduboy.print ("A");
  arduboy.setCursor(70, 38);
  arduboy.print ("B");
  arduboy.drawTriangle(114, 20, 114, 28, 106, 24, 1);
  if (sound) {
    arduboy.drawFastVLine(116, 23, 3, 1);
    arduboy.drawFastVLine(118, 22, 5, 1);
    arduboy.drawFastVLine(120, 21, 7, 1);
  }
}

As @Pharap said, you shouldn’t be using while loops for your states. You should be using if or switch

//while (screen == 0) {
if (screen == 0) {
1 Like

Once you get things working:

Don’t keep track of the sound mute state yourself. Use the Arduboy2 library’s audio subclass.

if (arduboy.audio.enabled()) // to test if sound is on or muted
arduboy.audio.on() // to turn sound on
arduboy.audio.off() // to turn sound off
arduboy.audio.toggle() // to toggle sound on or off
arduboy.audio.saveOnOff(); // to save the current state to EEPROM.
2 Likes

You’ve put display and clear in some very odd places there.

Move arduboy.clear() to just after arduboy.pollButtons() and move arduboy.display to the bottom of loop.

clear clears the screen, display displays what’s been drawn to the screen.

Also you can get rid of

  arduboy.clear();
  drawStartMenu();
  arduboy.display();

in setup,
they aren’t needed there because they happen in loop anyway.

1 Like

Everything seems to be working now thanks for your help.

3 Likes

No problem, if you need any more help, more explanation or more resources (e.g. some tutorials to read) then don’t hesitate to ask.

6 posts were split to a new topic: Using display(CLEAR_BUFFER) instead of clear() and display()

Actually there is no fault in constructing something like that since you can only display the sound’s state with another boolean. the arduboy.audio(off) (I could be wrong, haven’t used it in a while) don’t give you a value.

That’s what arduboy.audio.enabled() is for.

arduboy.audio.on() turns the sound on.
arduboy.audio.off() turns the sound off.
arduboy.audio.enabled() returns a bool, which is true if the sound is on and false if the sound is off.
arduboy.audio.toggle() turns the sound on if it is off and turns the sound off if it is on (i.e. it toggles it). (It’s the same as if(arduboy.audio.enabled()) arduboy.audio.off(); else arduboy.audio.on();

The Arduboy2Audio class has its own static variable bool audio_enabled;, so creating another one is redundant.
You can see for yourself by looking at the implementation.

1 Like

Okay.
I guess you cannot just go and use the audio_enabled boolean, nor directly set it.
Arduboy.audio.enabled(); do is handy in this case as it returns you a value.
Are there a list of things in Arduboy2 libary
I guess there is a list of useable Arduboy functions and Arduboy2 functions. Where can I find them?
Found that under MLXXXp’s name. (cool dude)

No, and that’s a good thing.

on and off change the value at the same time they manipulate the hardware, which ensures that the value is accurate.
If you could alter it yourself then the value might not be accurate - you could make it incorrect.

(Technically it is possible, but only through doing hacky things that would take a long time to explain.)

You can look at the source, like I do.
You can use the doxygen pages, as MLXXXp often suggests.
Or you can use this pdf which hardly ever gets used.

3 Likes

And note that you can use audio.enabled() for the purposes of displaying the current sound state (such as with a little speaker icon) but you don’t need to use it to actually determine whether or not to do sound generation. The sound generation functions/libraries will handle muting automatically themselves.

I.e.:

You don’t need to do something like:

if (arduboy.audio.enabled()) {
  sound.tone(1000, 100);
}

You can just do:

sound.tone(1000, 100);

If sound is currently muted by the audio functions, calling
sound.tone(1000, 100)
will result in silence automatically.

1 Like