Reading Input From Button

I have an LED (PORTD5) that's flashing with a 200ms delay. When I press a button (PINB1) I want it to flash faster with a 50ms delay. The button doesn't seem to do anything when I press it. I'm using an atmega328p with the Arduino Uno R3 shield.

#include <avr/io.h>
#include <avr/delay.h>
#include <stdint.h>

#define F_CPU 16000000


int main(void) {
	
	DDRB &= ~(1 << PINB1);  // Button to input
	
	DDRD |= (1 << DDD5);  // LED to output
	
	PORTB |= (1 << PINB1);  // Turn Button on
	
		
	while(1) {
		
		PORTD ^= 1 << PORTD5;  // Toggle light on/off every cycle
		
		if ((PINB1 & (1 << PINB1)) != 0) {  // Check if PINB1 is on
			_delay_ms(50);
		} else {
			_delay_ms(200);
		}
		
	}	
	
}

If I switch this code to check if equal to 0, it flashes with a 50ms delay, yet the button still does nothing:

if ((PINB1 & (1 << PINB1)) == 0)

What am I doing wrong?

Thanks!

Perhaps if you told us about the hardware you are iusing and included a schematic and a photo of your setup it would help?

My bad! Just added the picture.

I'm using an atmega328p with the Arduino Uno R3 shield.

If you need a CAD (Computer Aided Design) software package look into KiCad, it is well supported, popular, works great and it is free.

Button is wired incorrectly. Move the blue wire to the other side

As I suspected switch is wired wrong. A common fault

Is there any reason to use these instructions rather than the self-explanatory ones?

DDRB &= ~(1 << PINB1);  // Button to input
DDRD |= (1 << DDD5);  // LED to output
PORTB |= (1 << PINB1);  // Turn Button on

or

pinMode(ledPin, OUTPUT);  
pinMode(inPin, INPUT);   
val = digitalRead(inPin);   
digitalWrite(ledPin, val); 

Buttons always tricky as pairs of pins are joined.

They typically are joined along the axis of the pins internally


(source)

if you don't know how the pairs are setup then you have 50% chances of having picked the two pins that are interconnected. One way to be 100% sure is to wire in diagonal across the button, this way you can't get it wrong.

As it's wired seems to be fine if the blue wire goes to an INPUT_PULLUP pin.

+1 on using

pinMode(ledPin, OUTPUT);  
pinMode(inPin, INPUT_PULLUP);

@kgover25
the PIN register could be used fo flip the state if you want to keep playing with PORT registers

here is a wokwi simulation with either PORTs or arduino's helper functions

details
void setup() {
  // Set the LED pin (D5) as an output Using DDRD register
  DDRD |= (1 << DDD5);

  // Set the button pin (D9) as an input with internal pull-up resistor Using DDRB register
  DDRB &= ~(1 << DDB1); // Clear the 1st bit to configure it as input
  PORTB |= (1 << PORTB1); // Set the 1st bit to enable the pull-up resistor
}

void loop() {
  // Flip the state of the LED pin Using PIN register to toggle the state
  PIND |= (1 << PIND5);

  // Delay based on the button state
  delay((PINB & (1 << PINB1)) ? 300 : 100);
}

/*

  const byte ledPin = 5;
  const byte buttonPin = 9;

  void setup() {
    pinMode(ledPin, OUTPUT);
    pinMode(buttonPin, INPUT_PULLUP);
  }

  void loop() {
    digitalWrite(ledPin, digitalRead(ledPin) == LOW ? HIGH : LOW); // flip pin state
    delay(digitalRead(buttonPin) == LOW ? 100 : 300); // if button is pressed wait less (but keep it visible)
  }

*/

the source code using Arduino's functions is way more readable and portable to all Arduino compatible's board.

Thank you!

I want to learn the registers/hardware first before I start using the higher-level functions. I'd rather learn exactly what those functions are doing at a low level.

This was helpful! I definitely should have looked into exactly how the buttons works before I tried to do this :slight_smile:

I moved the blue wire to the opposite side, as well as changed my if condition:

if ((PINB1 & (1 << PINB1)) != 0) // FROM THIS

if ((PINB & (1 << PINB1)) == 0) // TO THIS

I'm not exactly sure why, but when looking at other examples (someone in the replies also wrote it this way) they used "PINB" instead of "PINB1" when comparing the state of PINB1. I assume I have to compare it with the 8-bits of the register and not only the individual pin?

Once I made those changes, it worked!

Also, I used bit_is_clear() for the condition and it worked. I assume what I changed it to is what that function is doing.

Thank you! This helped.

Glad it helped

When dealing with human interaction for buttons you rarely need the efficiency of using PORT registers. Using the higher level functions from Arduino will make your code more readable and portable - I would suggest to go for that version (which is also in the wokwi as comment).

As Jackson pointed out, you save some cycles using port manipulation but what mystifies me is the part where then you use delay().

delay(1) completely wastes 16000 cpu cycles.
When delay is in effect the sketch can't read a pin without using an interrupt and can't use interrupt info outside of the IRQ which if too long will likely cause a very hard to nail down Bug.

To blink a led AND read the button IS doing two things at once.
A very good tutorial on do multiple things at once.

When I add a single delay(1) to loop() in a non-blocking sketch that counts the number of times that loop() did run every second...
the loop count drops from 50KHz or more to less than 1000.

When you ditch the delays, your code will run incredibly faster and a 100 button matrix in a box can be read in about 1 ms.

That tutorial was written by Nick Gammon for beginners with some experience and IMO newer coders may be more open to learning new ideas.