can't read external input on pins DB101

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I'm new, and have just got a blinky program to work on a DB101 (ATmega1281), and now I would like to get input to control the LED.

Here's what I understand, and have so far.

I have 3 LEDs connected to to D5, D6, and D7. I am able to turn these on and off.

Input pins are set to 1, and therefor the button must be connected to ground to do anything.

I found this bit of code somewhere online to set the desired pins as input/output:

#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)
#define LED_1 PD7
#define BUTTON PB5

set_output(DDRD, LED_1);
set_input(DDRB, BUTTON);

I'm assuming that PD7 and PB5 correspond to D7 and B5 on the PCB. It works for PD7 at least.

Also I'm not exactly sure what "|=" and "&=" mean so if someone could help me out with that I would be grateful.

The macro for set_input seems to set the desired pin to not 1? I'm assuming that's equivalent to setting it to 0 for input. What it doesn't seem to do is activate the pull up resistors for that pin. For that I do this

set_output(PORTB, BUTTON);

which looks like it should put put PORTB's PB5 pin to 1.

When I check the voltage of PB5 with a voltmeter I get 3.45V, instead of the regular 5V of an output, but I assume that's because of the voltage drop across the pull up resistor.

I'm not sure what to put in my if statement though.

I've seen this, but it won't compile for me.

if(PINB.BUTTON == 0)

and this never sees the button pressed.

if(PORTB & BUTTON)

I learned most of this from
http://elecrom.wordpress.com/200...

if there is a better place for me to get more info please let me know

Thanks,

Waspinator

Last Edited: Tue. Jul 28, 2009 - 07:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you combine the techniques in:

if(PINB.BUTTON == 0)

and

if(PORTB & BUTTON)

you might end up with:

if(PINB & BUTTON)

which is more likely to work. (depending on how BUTTON is defined - it needs to be a mask not a bit number)

EDIT: Sorry I now see

#define BUTTON PB5

in which case the solution is either:

if(PINB & (1<<BUTTON))

or

if(PINB & _BV(BUTTON))

where (1<<) or _BV() convert a bit number into a bit mask

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

THANK YOU!

I've been fighting this for 2 days now. I hope things will get easier as I go along.

Both of your solutions worked, but for some reason I had to NOT the if statements.

if(!(PINB & (1<<BUTTON)))

or

if(!(PINB & _BV(BUTTON))) 

Thanks again! I was about to give up for today.

Waspinator

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,
|= or &= are short forms of C. If you write
A = A & B is the same as A &= B and
A |= B is the short form of A = A | B.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Also I'm not exactly sure what "|=" and "&=" mean so if someone could help me out with that I would be grateful.

Then you need to read the "Programming 101" thread in the tutorials forum.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I've seen this, but it won't compile for me.

if(PINB.BUTTON == 0)


This is not a construct available in avr-gcc, at least not in that form.

Quote:
Both of your solutions worked, but for some reason I had to NOT the if statements.

Likely because the switch you are using is active low, not active high.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Likely because the switch you are using is active low, not active high.

I'm not sure what an active low / high switch is.

Here is what I do know.

The button passes current only when depressed.
Since the input pin is set to high ( by pull up resistor to 3.45V) I connected the button to ground. So when pressed the pin goes to 0V.

Is there a way to do this the other way around? Set the input pin to 0 (pull down?), and have the button connected to 5V?

Thanks,

Waspinator

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Hello,
|= or &= are short forms of C. If you write
A = A & B is the same as A &= B and
A |= B is the short form of A = A | B.

Thanks for that.

It's not much of a short cut though. I wish they would just use the 'long' form if it. Much more human readable.

Thanks,

Waspinator

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just one more question that maybe someone can answer here.

Input now works, but I'd like to now make it only recognize the button press if it's held down for a set amount of time. (ex. 1 second) So kind of like debouncing.

I've seen this:

if(!(PINB & (1<<BUTTON))) 
{
  _delay_ms(1000);
  if(!(PINB & (1<<BUTTON))) 
  {
    return true;
  }

but this would still work if the button was pressed, then depressed, and then pressed again in 1 second.

Does anyone have any suggestions of how to do this?

Thanks,

Waspinator

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Since the input pin is set to high ( by pull up resistor to 3.45V) I connected the button to ground. So when pressed the pin goes to 0V.

Which is a description of an active low switch.

Quote:
Does anyone have any suggestions of how to do this?

Start (and clear) a timer when the button press is detected, stop the timer when the button release is detected. If the value of the timer is greater than the minimum value that you want, then it is a valid press.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

waspinator wrote:
Just one more question that maybe someone can answer here.

Input now works, but I'd like to now make it only recognize the button press if it's held down for a set amount of time. (ex. 1 second) So kind of like debouncing.

I've seen this:

if(!(PINB & (1<<BUTTON))) 
{
  _delay_ms(1000);
  if(!(PINB & (1<<BUTTON))) 
  {
    return true;
  }

but this would still work if the button was pressed, then depressed, and then pressed again in 1 second.

Does anyone have any suggestions of how to do this?

Thanks,

Waspinator

Quote:
Do like Koshchi says , or if you haven't yet played with timers ....

How about using the 1000ms of "waste time" to check the button , here you would need to release & press within 1 ms. That's not possible by a human (but is possible from bouncing).



if(!(PINB & (1<<BUTTON)))
{
  uint16_t ms;

  for(ms = 0; ms < 1000; ms++)
  {
    _delay_ms(1);
    if((PINB & (1<<BUTTON)))
    {
      return false;
    }
  } 
  return true;
}

/Bingo