NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Help with some code?

May 13, 2011
by SpaceGhost
SpaceGhost's Avatar

I've been working on what should be a simple piece of code for several days now, and it's really starting to drive me nuts!

This function of the code works -

When the pushbutton is pressed LEDs 1 & 2 turn on and stay on until the button is released. LED 3 is off for the duration of the button press also.

When the pushbutton is released, LED 1 turns off and LED 3 turns on. LED 2 stays on for a duration of 900 ms., then turns off too...

What isn't working, is that I need LED 3 to turn off when LED 2 turns off.

/////////////////  rbeep03

#define F_CPU 14745600

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"

 int main() {
    // fire up the LCD
    lcd_init();
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
    lcd_home();

  DDRC |= (1<<PC0);   // Set pin 23 as LED 1
  DDRB |= (1<<PB5);   // Set pin 19 as LED 2
  DDRB |= (1<<PB4);   // Set pin 18 as LED 3

  DDRC &= ~(1<<PC5); // set PC5 (pin 28) as TX button (sink input)

  PORTC |= (1<<PC5); // turn on internal pull up resistor (pin 28)

// declare variable to represent pushbutton input

  uint8_t a;

  a = 0;

while(1) {

    lcd_line_one();

    fprintf_P(&lcd_stream, PSTR("%u "), a);

    if (!(PINC & (1<<PC5))) { // pin goes low on push

      PORTC |= (1<<PC0); // LED 1 on

      PORTB |= (1<<PB5); // LED 2 on

      a = 1;

    }

    else {

      PORTC &= ~(1<<PC0); // LED 1 off

      PORTB |= (1<<PB4); // LED 3 on

      a = 0;

    }

    if (a == 0) {

      delay_ms(900); // delay

      PORTB &= ~(1<<PB4); // LED 3 off

      PORTB &= ~(1<<PB5); // LED 2 off

    }

  }

   return 0;

}

I've tried several ways to get this to happen - but that darned LED 3 always stays on! (though at least I get it to turn off when the button is pressed, which is what I want it to do too).

Could someone please explain to me why oh why do these lines -

    if (a == 0) {

      delay_ms(900); // delay

      PORTB &= ~(1<<PB4); // LED 3 off

      PORTB &= ~(1<<PB5); // LED 2 off

    }

work to turn off LED 2, but does not turn off LED 3 at the same time???

Dave

May 13, 2011
by bretm
bretm's Avatar

LED 3 does go off. And then your loop starts over, and because the button is not pushed it turns LED on again and starts the 900ms delay again, etc. You need to do something like this:

while (1)
{
    // do LCD stuff

    while (button isn't pushed)
        ; // do nothing

    // turn on 1 and 2

    delay_ms(50); // for debouncing

    while (button is pushed)
        ; // do nothing

    // turn off 1
    // turn on 3

    delay_ms(900);

    // turn off 2
    // turn off 3
}
May 14, 2011
by SpaceGhost
SpaceGhost's Avatar

On my way to work, I will try this out when I get home this afternoon...

I should have searched the forums for "do nothing", and I might have saved myself a few a hours!

Thanks bretm again, for the point in the right direction.

Dave

May 14, 2011
by SpaceGhost
SpaceGhost's Avatar

Hey, works great - problem solved.

This bit of knowledge will most definitely help me out in future projects. Once I put the while statements where they belonged, it actually made sense for me. Then I got rid of that silly "if (a == 0)" statement and tidied up the code a bit. Had to move the LCD instructions into the button state loops too, of course -

/////////////////  rbeep03

#define F_CPU 14745600

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"

 int main() {
    // fire up the LCD
    lcd_init();
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
    lcd_home();

  DDRC |= (1<<PC0);   // Set pin 23 as LED 1
  DDRB |= (1<<PB5);   // Set pin 19 as LED 2
  DDRB |= (1<<PB4);   // Set pin 18 as LED 3

  DDRC &= ~(1<<PC5); // set PC5 (pin 28) as TX button (sink input)

  PORTC |= (1<<PC5); // turn on internal pull up resistor (pin 28)

// declare variable to represent pushbutton input

  uint8_t a;

  a = 0;

while(1) {

    while ((PINC & (1<<PC5)));

    if (!(PINC & (1<<PC5))) { // pin goes low on push

      PORTC |= (1<<PC0); // LED 1 on

      PORTB |= (1<<PB5); // LED 2 on

      a = 1;

    lcd_line_one();

    fprintf_P(&lcd_stream, PSTR("%u "), a);

    }

    while (!(PINC & (1<<PC5)));

    if ((PINC & (1<<PC5))) { // switch open

      PORTC &= ~(1<<PC0); // LED 1 off

      PORTB |= (1<<PB4); // LED 3 on

      delay_ms(900); // delay

      PORTB &= ~(1<<PB4); // LED 3 off

      PORTB &= ~(1<<PB5); // LED 2 off

      a = 0;

    lcd_line_one();

    fprintf_P(&lcd_stream, PSTR("%u "), a);

    }

  }

   return 0;

}

This was a good lesson for me, hope that it can help someone else out too. Thanks bretm!

Dave

Post a Reply

Please log in to post a reply.

Did you know that you can input numbers in binary via a DIP switch, and output them to the LCD? Learn more...