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.

Basic Electronics » Not meeting input Voltage Threshold, amplify? and Do I need a buffer? (Button input, LED output)

April 12, 2011
by Ever25
Ever25's Avatar

Same project two issues that I'm trying to resolve and understand.

1) I have been trying to use a button debounce circuit using a tacile pushbutton connected to a Hex inverter w/ Schmitt triger input (DM74ALS14) to input a HIGH to an input on the 168 micro. According to the data sheet (if I'm understanding this correctly) the Voh Min value is Vcc-2 (I am using a VCC of +5V, so my Voh Min "should be" ~3.0V) and when I actually measure the output of the inverter IC I get about 2.1V. From the 168 data sheet it says that the input threshold is ~3.0V (Vih ~ 0.6Vcc = 3.0V, assuming a Vcc of +5V). So i'm assuming that if I am understanding this correctly then my IC output to my micro is just too low for it to recognize the input as a HIGH (Logic 1). Please feel free to correct me if I am not following the right path/thought process here. So if this is my problem would I be able to use a BJT to boost the output of the IC to the input of the micro to get my desired threshold voltage? Or would that be an incorrect way to approach this problem?

2) Omitting the inverter IC and just using the output from the tact button I can get micro to read the single pushbutton as an input and my LED will light. Problem occurs if I attach more than one pushbutton as an input on PORTB (PB4 and PB5) then neither button will activate the code for the pushbutton to light the LED (I'll try to put up the code but basically PORTB is looking for any input to go LOW, which will trigger a LED on PORTC (PC5) to turn on). Do I need to buffer the outputs of the pushbuttons with an opamp/BJT/MOS? Or do I really need to be looking at Interrupts for this type of process

April 12, 2011
by bretm
bretm's Avatar

Can you step back a level and give us the bigger picture? Making an LED light up when you push either of two buttons doesn't require any signal conditioning or debouncing, so it seems like we're missing part of the picture.

#define BUTTONS ((1<<PB4) | (1<<PB5))
#define LED (1<<PC5)

int main()
{
    PORTB = BUTTONS; // enable pull-up resistors

    while ((PINB & BUTTONS) == BUTTONS)
        ;   // while buttons are not pulled to ground, do nothing

    DDRC = LED;    // set LED pin for output
    PORTC = LED;   // and turn on LED (assuming active-high)

    while (1)      // stop
       ;

    return 0;
}
April 12, 2011
by mongo
mongo's Avatar

If you are having trouble driving an input, there may be the chance that it is still configured as an output... Just a thought, as I don't know what you have at the moment.

If it is actually an input, yes, a BJT will do the job. Keep in mind though, that a transistor alone typically inverts the signal when used in the switching configuration.

If you want to drive the input with an active high, it would require a PNP BJT like a 2n 2907 or 3906. The transistor would take an active low through a resistor. If you want to drive the input like a TTL signal, an NPN transistor like a 2N2222 or 3904 will do. Same conventions, only the opposite polarities. You might need a 4.7K resistor from v+ to the collector and the junction of the two is the signal out to the MCU input.

April 12, 2011
by Ever25
Ever25's Avatar

Here's what I have code wise. I'm sure there are better ways to do this, but I'm still trying to learn. This is the code if I dont use the debounce circuit, since I wasent getting the output voltage that was high enough for the MCU to read a HIGH value.

// led_blink.c
// for NerdKits with ATmega168

#define F_CPU 14745600

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

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

// PIN DEFINITIONS:
//
// PC4 -- LED anode

int main() {
    // Configure input PINS on PORT B
    // Inputs - PB5, PB4, PB3 : 0 represents INPUT
        // Configure output PINS on PORTC
    // Output - PC5, PC4, PB : 1 represents OUTPUT
    DDRB = 0x07;    // 0bXX000111  ( X - dont care )
    DDRC = 0x30;    // 0b00110000

    // Configure internal Pull-Up resistors on PORTB
    // 1 activates pull-up resistor
    // 0 deactivates pull-up resistor
    //PORTB = 0x3F; // turn on Pull-up resistors for involved pins
    //PORTC = 0x00;

    // Initialize PORTB to all zero's
    //PORTB = 0x00;

    // Declare variable 'count' and Initialize it to a value of zero
    int count;
    count = 0;

  // loop keeps looking forever
  while(1) {

    // Initialize PORTB to all zero's
    PORTB |= (1<<PB3);
    PORTC = 0x10;   // Initialize LED_1 connected to PC5 to ON state

    // Wait for a PushButton on PortB
    while(PINB & ~(1<<PB3))
    {
        // do nothing until Button is pushed then continue with code after while() loop
    }   // end of while() loop

    PORTC = 0x00;   // clear PORTC
    count = 0;      // reset 'count' variable
    // Blink LED_2 connected to PC4
    do 
    {
        PORTC |= (1<<PC5);      // LED_2 ON
        delay_ms(500);          // delay 0.5 sec
        PORTC = 0x00;   //|= ~(1<<PC5);     // LED_2 OFF
        delay_ms(500);          // delay 0.5 sec
        count++;    // increment 'count' variable
    } while(count < 10);        // Repeat until a PushButton is pressed

    /*
    // Check to see if button connected to Input PB5 is pressed
    if((PINB & (1<<PB5)) != 0)
    {
        PORTB |= (1<<PB0);      // If button is pressed light LED connected to PB0
    }   // end of if() statement

    // Check to see if button connected to Input PB4 is pressed
    if((PINB & (1<<PB4)) != 0)
    {
        PORTB |= (1<<PB1);      // If button is pressed light LED connected to PB1
    }   //end of if() statement

    // Check to see if button connected to Input PB3 is pressed
    if((PINB & (1<<PB3)) != 0)
    {
        PORTB |= (1<<PB2);      // If button is pressed light LED connected to PB2
    }   //end of if() statement
    */

  }     // end of while(1) statement

  return 0;
}
April 13, 2011
by bretm
bretm's Avatar
while (PINB & ~(1 << PB3))

This waits until all PINB bits except PB3 go to zero. If you want to wait until PB3 goes to zero, remove the ~

How are you buttons connected? Usually you just connect a switch to ground and to the pin, and voltage levels are not an issue. Or is it not a button?

April 13, 2011
by Ever25
Ever25's Avatar

@ Bretm

Yes, sorry the way I last was playing with the code I only had the code reacting to a logic LOW from PB3 although I have tried having the code respond to any input on PORTB

while(PINB == 0)

Yet in both instances of code, if I have only one push button attached to PORTB (say PB3) then the code runs fine and my LED's react as I expect them to. But if I attach a second button to PORTB (say PB3 & PB4, with either version of the code) then the MCU doesnt recognize a logic LOW to either input pin, even if it is coded to only look for an input from PB3. I hope I'm explaining it clearly, im not always good at that.

For the push button connection I have a +5 Vcc source connected to one side of a tact pushbutton switch through a 10k resistor, which is holding it to a static HIGH (+5V) value. The other side of the button is connected to GND with a 0.1uF cap in parallel with the button (http://www.ikalogic.com/debouncing.php look at figure 2A this is how I currently have it on my breadboard)

April 13, 2011
by bretm
bretm's Avatar

In your code you're enabling the MCU's pull-up resistor. Since you have your own external pull-up resistor you shouldn't use the MCU's. Leave PORTB at zero.

You've said what the output levels of the inverter are, but what are the on and off voltage levels at the button output without any inverter or transistor connected? Are you seeing those same voltage levels when you connect that circuit to the MCU pin? If they're not pretty close then the pin isn't configured for floating input.

With the button circuit you pointed to, there should be no problem with intermediate voltages. You should be getting a clean +5V or 0V unless the capacitor is broken or the switch doesn't have a low enough "closed" resistance. Try a different capacitor, and measure the switch's resistance when open (should be megaohms) and closed (should be fractional ohms).

April 13, 2011
by bretm
bretm's Avatar

while(PINB == 0) isn't right either. That will wait any input goes high, i.e. until any button is not pressed.

If you want to wait until any of PB3, PB4, or PB5 are pressed (go low), you want

while ((PINB & BUTTONS) == BUTTONS) 
    ;

where BUTTONS is defined as ((1<<PB3)|(1<<PB4)|(1<<PB5))

April 13, 2011
by Ever25
Ever25's Avatar

@Bretm

ok I get what you mean by needing

while(PINB & (1<<PB3))

had to rewrite out the math but I see that PB3 on PORTB is looking for the pin to go to a logic zero no button pressed PINB sees 00001000 (assuming no other connections are HIGH) button pressed PINB sees 00000000

PINB     00001000      PINB    00000000 
1<<PB3  &00001000      1<<PB3 &00001000
        ----------           -----------
         00001000              00000000

So not using the circuit with the inverter piece just the pushbutton connected as in the previous link I have an output when not pressed of ~4.8V (so effectivly Vcc (+5V)) connected to PB3, and when the button is pressed ~0V connected to PB3

When the button/switch is open (+5V to PB3) measuring in parallel with the button (I think this is what you were asking about) I have ~1.8M-Ohms and with the button/switch closed (0V to PB3) I measure about 0.5 Ohms. So this looks as you were saying it should be.

So I added the code for deactivating the pull-up resistors on the inputs of PORTB

PORTB = 0x00;  // disable pull-up resistors

and I'm not sure but that may have helped the issue I was having where if you have two buttons connected then the MCU won't recognize a logic LOW from either input. However I ran into a different problem that maybe I'm not understanding the logic on. I added the following in line with your suggestion

// Declare 'BUTTON' variable and assign attributes
int BUTTON;
BUTTON = ((1<<PB3)|(1<<PB4));  // button PB3 OR PB4 is pressed

//wait for pushbutton on PORTB
while(PINB & BUTTON)
{
}

Now with this code uploaded I only get the rest of the code to run when both buttons connected to PB3 and PB4 are pressed but not one or the other as I think the code should be running

April 13, 2011
by bretm
bretm's Avatar

With

while(PINB & BUTTON)

I would it expect it to require both buttons to be pressed, just like you said it's doing. What you want is

while ((PINB & BUTTONS) == BUTTONS)

which will loop until either button is pressed.

April 14, 2011
by Ever25
Ever25's Avatar

Thanks for your help Bretm, your right that works just the way it should now. I guess I'm just not totally getting how the MCU reads inputs.

so I understand (at least I think I do) that with the code

while((PINB & BUTTON) == BUTTON)

the loop reads what is on the inputs connected to PORTB because of the PINB command, compares it with the mask value ( & BUTTON : where BUTTON = ((1<<PB3)|(1<<PB4)) ) then checks to see if it is equivilent to the value stored in the 'BUTTON' variable. I hope i'm getting this right.

so for

while(PINB & BUTTON)

I am not getting the correct function i'm expecting because it is looking for a boolean value to be compared (maybe made equivilent to is a better description) but doesnt see one. Or is that line of code looking for a different logic pattern that I guess I'm not seeing?

April 14, 2011
by Ever25
Ever25's Avatar

@ mongo

I'm going to try use an amplifer today and see if I can get it to work (and understand what its doing, and how its doing it) but I have a question. If I'm looking to amplfy a DC voltage signal then would it make a difference which transistor type I use (PNP vs NPN) since a DC signal has zero frequency it shouldn't be inverted anyway. If I use it in a basic switching mode could I not use an NPN Trans with a Vsource of my desired output level (+5V) to be output to the MCU input pin(s)? Obviously I would have to change my code to respond to logic HIGHs and not logic LOWs.

I'll work on that today and see what I find.

April 14, 2011
by Noter
Noter's Avatar

Here is a good explaination of transistor circuits -

http://www.kpsec.freeuk.com/trancirc.htm

April 14, 2011
by bretm
bretm's Avatar

The expression in while(...) is just compared against zero and the loop happens as long as the expression is non-zero. When you use a boolean expression it's equal to 0 for false and 1 for true. When you don't use a boolean expression, such as when you do while(PINB & BUTTON) it's equivalent to while ((PINB & BUTTON) != 0) which means it will loop as long as either of the two input pins are not zero. They are not zero when they are not pressed, so it loops as long as either of them is not pressed, which is the same as saying that both of them must be pressed to exit the loop.

Post a Reply

Please log in to post a reply.

Did you know that reading a double floating point variable with scanf requires "%lf" for "long float"? Learn more...