Author Topic: How to tell if an input port is high  (Read 1577 times)

0 Members and 1 Guest are viewing this topic.

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
How to tell if an input port is high
« on: August 19, 2011, 06:44:03 PM »
Do these lines in the Photovore_v1 code return true if the port is high/low (i.e. input) or do they return true if we've set them high/low (i.e. output)?

#define PORT_IS_ON( port_letter, number )      ( port_letter & (1<<number) )
#define PORT_IS_OFF( port_letter, number )      !( port_letter & (1<<number) )

Thanks

Offline adanvasco

  • Full Member
  • ***
  • Posts: 107
  • Helpful? 6
  • Necessity is the mother of invention.
Re: How to tell if an input port is high
« Reply #1 on: August 19, 2011, 08:05:42 PM »
In order to read a port digital input (high or low) you should use the PINx register, where x is the port letter.
Knowledge does not weigh.

Offline rbtying

  • Supreme Robot
  • *****
  • Posts: 452
  • Helpful? 31
Re: How to tell if an input port is high
« Reply #2 on: August 19, 2011, 09:31:55 PM »
If you pass in the PINx register for the port_letter parameter, it will tell you the value it reads from the pin - that is to say, input; however, the pin may not be in high-impedance mode.

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #3 on: August 19, 2011, 09:33:28 PM »
Thanks for that :)

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #4 on: August 19, 2011, 10:19:09 PM »
Is this valid?

if( (PIND) & (1 << 2) ) {
    //Do something when port D2 input is high.
}

Offline Metal Slug 2

  • Supreme Robot
  • *****
  • Posts: 333
  • Helpful? 11
Re: How to tell if an input port is high
« Reply #5 on: August 19, 2011, 10:44:40 PM »
Is this valid?

if( (PIND) & (1 << 2) ) {
    //Do something when port D2 input is high.
}
Yep. :)
When you read PIND, an 8-bit binary number will result, with a 0 representing LOW and 1 representing HIGH.  Then, when you AND (&) the reading with (1<<2), you are checking to see if port D2 is HIGH.

So for example, lets assume in whatever circuit you have setup only the portD2 pin is attached to some sensor, and that sensor is outputting a HIGH signal.  When the microcontroller reads PORTD, the resulting binary number is: 00000100
When you then AND that number with (1<<2), which is 100 in binary, the result is TRUE, and therefore the microcontroller knows that pinD2 is HIGH.



Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #6 on: August 19, 2011, 10:57:52 PM »
I've got a switch attached from VCC to PD2 and an LED from VCC to PD4.

My code is:
DDRD = 0x10;
while(1) {
     if ((PIND) & (0x03)) {
          PORTD = 0x00;
     }
     else {
          PORTD = 0x10;
     }
}

However, when I execute this on my ATMEGA8515, the LED remains lit regardless of the switch position (which implies that D2 is HIGH regardless of the switch position). What's going wrong?

Thanks in advance.

Offline rbtying

  • Supreme Robot
  • *****
  • Posts: 452
  • Helpful? 31
Re: How to tell if an input port is high
« Reply #7 on: August 19, 2011, 11:05:00 PM »
If the switch is attached from VCC to PD2, you'll need a pulldown resistor to pull it down to ground when the switch is not depressed.

What you could do instead, however, is to enable the internal pullup on PD2 (PORTD |= 1 << 2) and set it as an input, and then connect the switch between PD2 and ground. It'll read an inverted signal (true when switch is not pressed, false when switch is pressed), but it's simpler to set up, and easy to account for in the code.

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #8 on: August 19, 2011, 11:35:21 PM »
I've attached the switch from PD2 to GND and used the following code but it still doesn't work (LED remains on):

   DDRD = 0x10;
   while (1) {
      PORTD |= (1 << 2);
      if ((PIND) & (0x03))  {
         PORTD = 0x00;
      }
      else {
         PORTD = 0x10;
      }
   }   

Offline rbtying

  • Supreme Robot
  • *****
  • Posts: 452
  • Helpful? 31
Re: How to tell if an input port is high
« Reply #9 on: August 19, 2011, 11:37:42 PM »
You need to use Read-Modify-Write on the PORTD operations - you're removing the pullup on the switch when you set PORTD to 0x00 and 0x10.

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #10 on: August 20, 2011, 12:08:51 AM »
Shouldn't this work?

              DDRD = 0x14;
   while (1) {
      if (PIND2)  {
         PORTD = 0x04;
      }
      else {
         PORTD = 0x14;      
      }
   }

However, it doesn't.

If someone could post some code which works which I could reverse-engineer it would be much appreciated.

Thanks in advance.
« Last Edit: August 20, 2011, 12:13:09 AM by jonagik »

Offline Metal Slug 2

  • Supreme Robot
  • *****
  • Posts: 333
  • Helpful? 11
Re: How to tell if an input port is high
« Reply #11 on: August 20, 2011, 12:52:23 AM »
Shouldn't this work?

              DDRD = 0x14;
   while (1) {
      if (PIND2)  {
         PORTD = 0x04;
      }
      else {
         PORTD = 0x14;      
      }
   }

However, it doesn't.

If someone could post some code which works which I could reverse-engineer it would be much appreciated.

Thanks in advance.

I think your if statement is written incorrectly.  Just referencing PIND2 returns a 1 or a 0, so try changing
if(PIND2){...}
to
if( PIND2 == 1 ){...}

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #12 on: August 20, 2011, 12:58:37 AM »
Yea I wondered if that was the problem but it doesn't help.

Offline Metal Slug 2

  • Supreme Robot
  • *****
  • Posts: 333
  • Helpful? 11
Re: How to tell if an input port is high
« Reply #13 on: August 20, 2011, 01:15:22 AM »
Try this:
if( PIND & (1<<2) ){...}

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #14 on: August 20, 2011, 01:36:21 AM »
Yea I tried that - same problem.

Offline joe61

  • Supreme Robot
  • *****
  • Posts: 417
  • Helpful? 16
Re: How to tell if an input port is high
« Reply #15 on: August 20, 2011, 06:45:01 AM »
I've got a switch attached from VCC to PD2 and an LED from VCC to PD4.

My code is:
DDRD = 0x10;
while(1) {
     if ((PIND) & (0x03)) {
          PORTD = 0x00;
     }
     else {
          PORTD = 0x10;
     }
}

You need to test for a specific pin. When you say "((PIND) & (0x03))" you're testing to see if both pin 0 and pin 1 are on, which they won't be. 

This is for a tiny85 but the idea is the same.

Code: [Select]
#include <avr/io.h>
#include <util/delay.h>

#define led PB2
#define sw  PB0

int main()
{
    DDRB |= (1 << led);
    for (;;)
    {
if (PINB & (1 << sw))
    PORTB |= (1 <<led);
else
    PORTB &= ~(1 << led);
_delay_ms (100);
    }
}

Joe

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #16 on: August 20, 2011, 07:06:37 PM »
Isn't ((PIND) & (0x03)) the same as ((PIND) & (1 << 2))?

I've got a switch attached from VCC to PD2 and an LED from VCC to PD4.

My code is:
DDRD = 0x10;
while(1) {
     if ((PIND) & (0x03)) {
          PORTD = 0x00;
     }
     else {
          PORTD = 0x10;
     }
}

You need to test for a specific pin. When you say "((PIND) & (0x03))" you're testing to see if both pin 0 and pin 1 are on, which they won't be. 

This is for a tiny85 but the idea is the same.

Code: [Select]
#include <avr/io.h>
#include <util/delay.h>

#define led PB2
#define sw  PB0

int main()
{
    DDRB |= (1 << led);
    for (;;)
    {
if (PINB & (1 << sw))
    PORTB |= (1 <<led);
else
    PORTB &= ~(1 << led);
_delay_ms (100);
    }
}

Joe

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #17 on: August 20, 2011, 07:08:25 PM »
My current code (which isn't working) is as follows. My switch is connected from VCC to PD2 and my LED from VCC to PD4.

DDRD |= (1 << 4);
while (1) {
      if (PIND & (1 << 2))  {
         PORTD |= (1 << 4);
      }
      else {
         PORTD &= !(1 << 4);
      }
}

Where is the error? The LED remains lit.

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,150
  • Helpful? 110
Re: How to tell if an input port is high
« Reply #18 on: August 20, 2011, 07:17:09 PM »
This line:
Code: [Select]
PORTD &= !(1 << 4);
should be:
Code: [Select]
PORTB &= ~(1 << 4);
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #19 on: August 20, 2011, 08:13:51 PM »
Same problem :(

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,150
  • Helpful? 110
Re: How to tell if an input port is high
« Reply #20 on: August 20, 2011, 08:34:08 PM »
This line:
Code: [Select]
PORTD &= !(1 << 4);
should be:
Code: [Select]
PORTB &= ~(1 << 4);

Ooops - should have said:-

Code: [Select]
PORTD &= ~(1 << 4);
ie you should '~' rather than '!'
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline Metal Slug 2

  • Supreme Robot
  • *****
  • Posts: 333
  • Helpful? 11
Re: How to tell if an input port is high
« Reply #21 on: August 20, 2011, 08:41:33 PM »
I've got a switch attached from VCC to PD2 and an LED from VCC to PD4.
If you have the LED connected directly from Vcc to PD4, then you may have burnt out your LED.  If you have another LED, try hooking that up in series with a 220, 240, or 270 Ohm resistor.

Isn't ((PIND) & (0x03)) the same as ((PIND) & (1 << 2))?
Not quite, but your close.  As I mentioned before, (1<<2) in binary is 100.  When we convert 0x03 (a hexadecimal number) into binary we get 11.  To correct this mistake, we must find the hex equivalent of (1<<2) which is 0x04.
Therefore (PIND & 0x04) is the same as (PIND & (1<<2))

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #22 on: August 20, 2011, 08:54:07 PM »
@Webbot: I assumed as much - doesn't work with the tilde rather than the exclamation mark.

@MetalSlug2: I can get the LED to turn on/off by itself and flash and everything. I'm just having trouble with input.

Regarding the 0x03 it was a typo on my part. I meant 0x04.

So, why is my code not working?

Offline Metal Slug 2

  • Supreme Robot
  • *****
  • Posts: 333
  • Helpful? 11
Re: How to tell if an input port is high
« Reply #23 on: August 20, 2011, 09:53:27 PM »
Ok, so I tried the experiment myself, and everything worked for me.  The code I used is:
Code: [Select]
DDRD |= 0x10; //or DDRD |= (1<<4) or  DDRD |= 0b00010000 --> PD4 used for LED, so make it output.
for(;;){
   if( PIND & (1<<2) ){
       PORTD |= (1<<4);
   }else{
       PORTD &= ~(1<<4);
   }
}
This will turn the LED OFF when PD2 is HIGH and ON when PD2 is LOW.

The only other thing I can think of that may be causing you problems is you have the LED mounted backwards. If this is true, and the anode of the LED is attached to PD4 and cathode to Vcc, then the LED can never be lit.  Double check that the anode of your LED (longer lead) is attached to Vcc, and the cathode to PD4.

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #24 on: August 20, 2011, 10:18:37 PM »
I tried using that exact code and it doesn't work.

I can light the LED by itself and make it blink. I can't seem to make the switch work though.

Any ideas?

Offline Metal Slug 2

  • Supreme Robot
  • *****
  • Posts: 333
  • Helpful? 11
Re: How to tell if an input port is high
« Reply #25 on: August 20, 2011, 10:26:24 PM »
Can you provide a schematic of how your switch is hooked up please?  Are you sure you have your switch connected to PD2?

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #26 on: August 20, 2011, 10:39:28 PM »
I'll give you the whole layout (nb: using ATMEGA8515):

Power supply (+ve) to 5V regulator.
Power supply (-ve) to GND regulator.
Other leg of 5V regulator to VCC (Pin 40)
GND of 5V regulator to GND (pin 20)
[Programmer connection is working so won't bother with that]
PD4 (Pin 14) to LED.
LED to VCC (pin 40)
VCC to switch to PD2 (pin 12)

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #27 on: August 20, 2011, 10:42:02 PM »
Is it possible that at some stage I've damaged the uC with a short circuit or something?

However, I would have though that if I had, the whole uC would stop working.

Offline Metal Slug 2

  • Supreme Robot
  • *****
  • Posts: 333
  • Helpful? 11
Re: How to tell if an input port is high
« Reply #28 on: August 20, 2011, 10:59:20 PM »
VCC to switch to PD2 (pin 12)

Ahh ok, this might be the problem then.  PD2 is not tied to ground, therefore when the switch is not pressed (assuming it is NO (normally open) i.e. off) the readings coming from PD2 are "floating" between 0 and 1, i.e. On and Off at random, and not necessarily off as you may may have assumed.  Given the circumstances of your problem, it may very well be that PD2 is returning a HIGH signal, for whatever reason.

To solve this problem, follow the schematic below:

This will ensure that if the button is not being pressed, a reading from PD2 will always be LOW.
Note: since you are not using PD2 as an output pin, you do not have to worry about the 100 Ohm resistor.

Offline jonagikTopic starter

  • Full Member
  • ***
  • Posts: 63
  • Helpful? 1
Re: How to tell if an input port is high
« Reply #29 on: August 20, 2011, 11:36:46 PM »
Thanks everyone - it's working now. The error was that I needed to attach the pin permanently to GND via a resistor and via a switch to VCC.

 


Get Your Ad Here