Knight Rider lights with button press

Hi all,

I am new with my Arduino One and the programming language C. I am trying to build the knight rider lights with a button. Everytime I press my button, i would like to change the light to the other light. A little example: 7 lights, light number 1 is on. After the button press, light number 1 is off, number 2 is on.

But when I press the button, there is just nothing. (it is a software problem) I have tried a lot of things, but I can’t fix it. Maybe someone can help me a little bit further.

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

int main()
{
	UCSR0B = 0;
	DDRD = 0b11111111; // ouput pins

	DDRB = 0b00000000;	// input pins

	unsigned char upDown=1;	// start going with the ports up
	unsigned char cylon=0;  // says which LED is on

	for(;;)
	{
		if (PORTB0)
		{
			if(upDown==1){cylon++;if(cylon>=6) upDown=0;}      // Reached the last LED
			else {cylon--;if(cylon==0) upDown=1;}     // Reached min LED
			PORTD = 1 << cylon;
		}
	}
}

How is your switch wired? Are you having a hardware problem or a software problem?

i would like to change the light to the other light.

I have no idea what this means.

PaulS:
How is your switch wired? Are you having a hardware problem or a software problem?

i would like to change the light to the other light.

I have no idea what this means.

Added a little bit more information in my question.

How is the button wired? Are you using a pull-up or pull-down resistor? Are you sure you are connected to pin 14 of the ATmega328 or pin 8 of the Arduino Uno? How are you preventing button bounce?

Some questions.

  1. Is that your whole program ?
  2. What programming environment are you using ?
  3. What is that main() function doing in an Arduino sketch (may be connected to 2 above) ?
  4. Why use an unsigned char ?
  5. Did you put multiple statements on one line to make the program difficult to read ?

But when I press the button, there is just nothing. (it is a software problem)

Or so you assume. Provide some data so that we can confirm that.

Why are you not using setup(), loop(), digitalRead(), pinMode(), digitalWrite(), etc.?

[quote author=James C4S link=topic=189720.msg1403467#msg1403467 date=1380029222] How is the button wired? Are you using a pull-up or pull-down resistor? Are you sure you are connected to pin 14 of the ATmega328 or pin 8 of the Arduino Uno? How are you preventing button bounce? [/quote] Pin 0 to 7 are going to a resistor. After the resistor there is a led. All the leds are going to the GND. Pin 8 is connected to a resistor. After the resistor there is the button. The button goes to the 5V. I am not using the pull-up or pull-down resistor and I am not preventing button bounce.

UKHeliBob: Some questions.

  1. Is that your whole program ?
  2. What programming environment are you using ?
  3. What is that main() function doing in an Arduino sketch (may be connected to 2 above) ?
  4. Why use an unsigned char ?
  5. Did you put multiple statements on one line to make the program difficult to read ?

1: Yes, this is all. 2: I am using Eclipse with the AVR Arduino plugin. (Code isn't working in the Arduino programming environment either) 3: The main() function is a function I use instead of the setup(), loop() etc. 4: Cause the char is never below 0, I used the unsigned char. (unsigned char is: 0 - 255, signed char is: -128 - 127) 5: No, I did that for no reason. That part of the code is running correct when there is now if statement and a little delay of some miliseconds. So there is no problem over there.

PaulS:

But when I press the button, there is just nothing. (it is a software problem)

Or so you assume. Provide some data so that we can confirm that.

Why are you not using setup(), loop(), digitalRead(), pinMode(), digitalWrite(), etc.?

If you delete the if statement (and so the button detection) and add a little delay. You can see the lights turning on and of like the Knight Rider. As you can see in my answer above, the wires are connected correctly.

That is because setup(), loop(), digitalRead() etc. uses more space and is slower. Using the main() method and some portmanupilations makes the program using less space and act faster.

Yamotos: I am not using the pull-up or pull-down resistor and I am not preventing button bounce.

Floating buttons are not reliable. You need to use an external pull-up or pull-down, or use the built-in pull-up. The pull-up will invert your logic.

You'll also need to do some kind of state detection, or bounce detection. When you press the button, your code will execute multiple times before your slow human finger releases it.

[quote author=James C4S link=topic=189720.msg1403579#msg1403579 date=1380033288]

Yamotos: I am not using the pull-up or pull-down resistor and I am not preventing button bounce.

Floating buttons are not reliable. You need to use an external pull-up or pull-down, or use the built-in pull-up. The pull-up will invert your logic.

You'll also need to do some kind of state detection, or bounce detection. When you press the button, your code will execute multiple times before your slow human finger releases it.

[/quote] How is it possible to use the pull-up or pull-down?

I can make a state detection. I am on it now! Thank you for that one.

Yamotos: How is it possible to use the pull-up or pull-down?

From the ATmega datasheet: "If PORTxn is written logic one when the pin is configured as an input pin, the pull-up resistor is activated"

So write a 1 into the PORTx register.

Also, you are reading the port register, which isn't where input values are stored. You need to be reading the PINx register to determine the state of an input pin.

I have changed my code a little bit. I have added (I think I did that) a pull-up resistor and I have added a prevent for the button bounce. But it isn’t working. I think there is still a little bug in my code.

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

int main()
{
	UCSR0B = 0;
	DDRD = 0b11111111; // ouput pins
	DDRB = 0b00000000;	// input pins
	PORTB = 0b00000001; // activate pull-up resistor

	unsigned char upDown=1;	// start going with the ports up
	unsigned char cylon=0;  // says which LED is on
	unsigned char pressed=0;
	int vButtonState = 0;

	for(;;)
	{
		vButtonState = PINB0;
		if (vButtonState == 1)
		{
			pressed = 1;
		}
		if (pressed == 1)
		{
			if(upDown==1){cylon++;if(cylon>=6) upDown=0;}      // Reached the last LED
			else {cylon--;if(cylon==0) upDown=1;}     // Reached min LED
			PORTD = 1 << cylon;
			pressed = 0;
		}
	}
}
  vButtonState = PINB0;
        if (vButtonState == 1)
        {
            pressed = 1;
        }
        if (pressed == 1)

This is redundant. State checking meant:

  1. Store the current state of the button.
  2. Check to see if the button state has [u]changed[/u].

e.g.

for (;;) {
   currentState = PINB0;
   if (previousState == HIGH) && (currentState == LOW) {
     // the button has been pressed down. 
   }
   previousState = currentState;
}

[quote author=James C4S link=topic=189720.msg1403624#msg1403624 date=1380034845]

  vButtonState = PINB0;
        if (vButtonState == 1)
        {
            pressed = 1;
        }
        if (pressed == 1)

This is redundant. State checking meant:

  1. Store the current state of the button.
  2. Check to see if the button state has [u]changed[/u].

e.g.

for (;;) {
   currentState = PINB0;
   if (previousState == HIGH) && (currentState == LOW) {
     // the button has been pressed down. 
   }
   previousState = currentState;
}

[/quote] The code above doesn't work either. I think it is something with my PINB or PORTB or DDRB that cause the problem.

I think it is something with my PINB or PORTB or DDRB that cause the problem.

Write a normal sketch, with setup() and loop() and digitalRead() and digitalWrite() and pinMode() statements.

Use Serial.begin() and Serial.print() to output information. Determine whether you have a hardware problem (which I suspect, as your switch wiring sounds weird) or a software problem.

That is because setup(), loop(), digitalRead() etc. uses more space and is slower. Using the main() method and some portmanupilations makes the program using less space and act faster.

For such a simple piece of code, and one which is supposed to produce an effect visible to humans, why are such optimizations needed?

Yamotos:
The code above doesn’t work either. I think it is something with my PINB or PORTB or DDRB that cause the problem.

The biggest problem is the way you’re tying to read the button state. PINB0 is just 0. The input pins are simply “PINB”. You can AND that with the bit you want.

Try something like this:

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

int main()
{
    UCSR0B = 0;
    DDRD = 0b11111111; // ouput pins
    DDRB = 0b00000000;  // input pins
    PORTB = 0b00000001; // activate pull-up resistor

    uint8_t led = 0x1;
    uint8_t up = 1;
    uint8_t last_btn_state = PINB;

    for(;;)
    {
        PORTD = led;

        if (last_btn_state != PINB)
        {
            last_btn_state = PINB;
            if (!(last_btn_state & 1))
            {
                if (up)
                    led <<= 1;
                else
                    led >>= 1;

                if (led == 0x01 || led == 0x40)
                    up = !up;
            }
        }
    }
}

2: I am using Eclipse with the AVR Arduino plugin. (Code isn't working in the Arduino programming environment either)

To me that points to a hardware problem as others have suggested.

int2str:

Yamotos: The code above doesn't work either. I think it is something with my PINB or PORTB or DDRB that cause the problem.

The biggest problem is the way you're tying to read the button state. PINB0 is just 0. The input pins are simply "PINB". You can AND that with the bit you want.

I've tried it. We are making some real progress now. My first LED is on. But when I press the button, there is just nothing happening at all. I think we are close.

wildbill: For such a simple piece of code, and one which is supposed to produce an effect visible to humans, why are such optimizations needed?

Because I am learning it. I know how to work with the read and write methods. It is easy and it works for me. Even the program above works with it. But using the port manupilation is a little big difficult and I want to understand it.

Yamotos: I've tried it. We are making some real progress now. My first LED is on. But when I press the button, there is just nothing happening at all. I think we are close.

Do you have a button connected to pin 8, which shorts to ground?

int2str:

Yamotos: I've tried it. We are making some real progress now. My first LED is on. But when I press the button, there is just nothing happening at all. I think we are close.

Do you have a button connected to pin 8, which shorts to ground?

pin 8 goes to a resistor. The resistor goes to the button. And the button goes to the 5v.