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.

Project Help and Ideas » Programmable "limit switch"

February 16, 2011
by SpaceGhost
SpaceGhost's Avatar

Hello all, I am working on what might be described as a programmable "limit switch."

The MCU counts at a rate of 100 ms per increment with the "close" pushbutton held down (input PC3) and lights an LED (output PB1) through the duration of the button closure. The count stops and the LED returns to its off state when this pushbutton is released.

Now, with the count displayed on the LCD's line one, holding down another pushbutton (input PC5) counts at the same rate and stops at the same count that was "set" by the other pushbutton (PC3). This count is displayed on the LCD's line two.

PC5's input also lights an LED (output PC3) for the duration of its button closure, but I want that LED to turn off when it equals input PC3's count - regardless if pushbutton PC5 is still held down. A "reset" button (PC2) resets the count on line two, and allows the second counter to repeat the process of counting up to the "preset limit" set by the first pushbutton.

The program below does this... Output PC3 brightly lights the LED for the duration of the button press (PC5), and when the "limit" is reached the count on line two stops... But the LED faintly flickers if the button is still held down after the limit is reached.

// PIN DEFINITIONS:
// PC3 -- CRIMP-CLOSE PUSHBUTTON (pin 26)
// PC4 -- CRIMP-OPEN PUSHBUTTON (pin 27)
// PC5 -- OPERATE (pin 28)
// PC2 -- OPERATE RESET

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

    // Set output pins
DDRB |= (1<<PB1);
DDRB |= (1<<PB2); // + outputs
DDRB |= (1<<PB3);

// Set pins to input mode - Pushbuttons
  DDRC &= ~(1<<PC3); // set PC3 as input  "close"   |   o   o <
  DDRC &= ~(1<<PC4); // set PC4 as input   "open"   |   ^
  DDRC &= ~(1<<PC5); // set PC5 as input  "operate" | > o   o
  DDRC &= ~(1<<PC2); // set PC2 as input  "operater reset"  ^

// turn on the internal resistors for the pins
  PORTC |= (1<<PC2);
  PORTC |= (1<<PC3); 
  PORTC |= (1<<PC4); 
  PORTC |= (1<<PC5);

// declare the variables to represent each pushbutton input
  uint8_t close;
  uint8_t open;
  uint8_t operate;
  uint8_t reset;

  uint8_t i; // operate
  uint8_t j; // set

  i=0;
  j=0;

    lcd_line_one();
    fprintf_P(&lcd_stream, PSTR("%u "), i); 
    lcd_line_two();
    fprintf_P(&lcd_stream, PSTR("%u "), j);

while(1) {

    close = (PINC & (1<<PC3)) >> PC3;
    if (close == 0) 
    {
           j = 0;

           i = i + 1;   //if "close" button pressed, increase count

            delay_ms(100);

            PORTB |= (1<<PB1); // output ON

        lcd_line_one();
        fprintf_P(&lcd_stream, PSTR("%u "), i);
    }

    if (close == 1) {

    PORTB &= ~(1<<PB1); // Output OFF
    }

    open = (PINC & (1<<PC4)) >> PC4;
    if (open == 0)
    {  
            j = 0;
            if(i==0)
            i=0;
            if(i>0)
            i = i - 1; // if "open" button pressed, lower count
            delay_ms(100);

            PORTB |= (1<<PB2); // output ON

          lcd_line_one();
          fprintf_P(&lcd_stream, PSTR("%u "), i); //leave a space after %i, to cover trailing 0
    }

    if (open == 1) {

    PORTB &= ~(1<<PB2); // output OFF
    }

    operate = (PINC & (1<<PC5)) >> PC5;
    if (operate == 0)   
    {
            j = j + 1;   //if ""operate"" button pressed, increase count
            if (j > i)
            j = i;  
            delay_ms(100);

            PORTB |= (1<<PB3); // output ON

          lcd_line_two();
          fprintf_P(&lcd_stream, PSTR("%u "), j); //leave a space after %i, to cover trailing 0         
    }

            if (j >= i) {

            PORTB &= ~(1<<PB3); // output OFF
            }

    if (operate == 1) {

    PORTB &= ~(1<<PB3); // output OFF
    }

    reset = (PINC & (1<<PC2)) >> PC2;
    if (reset == 0)
    {
            (j = 0);

          lcd_line_two();
          fprintf_P(&lcd_stream, PSTR("%u "), j); //leave a space after %i, to cover trailing 0         
    }

    }

    return 0;

    }

I am pretty sure that the problem lies around line #107 where I try to turn that output off after the limit is reached. The LED dimly flickers instead of turning off completely.

I have tried a number of different things but the results have been pretty much the same...

Any suggestions or hints would be greatly appreciated, as always!

Thanks,

Dave

February 16, 2011
by SpaceGhost
SpaceGhost's Avatar

Sorry, I mean line #104

February 17, 2011
by Rick_S
Rick_S's Avatar

Try changing the line at 98 from this:

PORTB |= (1<<PB3); // output ON

To this:

if (j < i) {

     PORTB |= (1<<PB3); // output ON

}

else {

    PORTB &= ~(1<<PB3); // output OFF
}

That way the LED wil only go on if the value of j is less than i - otherwise it's off.

Rick

February 17, 2011
by SpaceGhost
SpaceGhost's Avatar

Rick your advice has done it again my friend, many thanks!!

Those "else" and "else if" statements still get me confused sometimes... I recall having seen some forum posts that have discussed these functions - I will revisit these posts.

The program now works great, and once again the MCU is doing exactly what I want it to do... And for me that's what makes playing with the kit and browsing these forum so enjoyable.

Thanks again Rick for helping me over another hurdle!

Dave

February 17, 2011
by Rick_S
Rick_S's Avatar

No problem, glad to have helped. :)

Rick

February 17, 2011
by SpaceGhost
SpaceGhost's Avatar

Say Rick, here is something that I just tried a couple minutes ago...

You of course recognize that this program is yet another modification of that counter program you helped me with when I first got my kit.

I have studied the printf and scanf and decided this time to try "%u" to print the unsigned integer value instead of "%i" to represent the integer's value, as you see in the code above...

What I have just now learned, is that we can do away with "leaving a space to cover the trailing 0" in the string by using "%u"... Pretty cool, huh?

Glad that you're out there lurking around,

Dave

February 17, 2011
by Rick_S
Rick_S's Avatar

I'm always "lurking" around :)... I'm on this forum several times a day pretty much every day. I get up around 5AM and normally check in, follow up at lunch at work, then often some more in the evening.

I've just been playing around with a little assembler programming on an attiny85. I was curious how small I could make a program that would read a voltage on the ADC and output a PWM signal based on the ADC reading. I got the program down to 42 Bytes. As I move a potentiometer from GND to VCC, an LED on the PWM output goes from dim to bright. It's neat to know I can make something simple quite compact.

Of course I wouldn't even consider trying to do something major there :D.. I'd be totally lost. But maybe someday.

You can probably tell, I love this stuff. I'm glad to see you are making progress.

Rick

February 17, 2011
by SpaceGhost
SpaceGhost's Avatar

Your project sounds pretty cool.. Just the sort of thing that could start the wheels turning in my own head :).

I've been playing with electronics for years... Even had a ham license back in 70's when I was in middle school. Kinda put it aside for a few years (never got out of my blood completely), but really got back into it when I started a family. Kept me off the streets, ya know. My son has grown up now, but I still keep playing.

I resisted the micro-controller stuff for a long time (too long), but nonetheless thought it was interesting. Guess I was kinda chicken to make the leap. But after taking a second (advanced) course in PLC programming, and with encouragement from an instructor whom I consider about the smartest man I have ever met when it comes to electronics... Here I am now, finally starting to get my feet wet.

I have lots more to learn, and I definitely hope to branch out to other types of devices such as you have. You rock man!

Dave

Post a Reply

Please log in to post a reply.

Did you know that you can build an analog amplifier with one transistor and a few resistors? Learn more...