Society of Robots - Robot Forum
Software => Software => Topic started by: jonagik 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
-
In order to read a port digital input (high or low) you should use the PINx register, where x is the port letter.
-
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.
-
Thanks for that :)
-
Is this valid?
if( (PIND) & (1 << 2) ) {
//Do something when port D2 input is high.
}
-
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.
-
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.
-
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.
-
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;
}
}
-
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.
-
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.
-
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 ){...}
-
Yea I wondered if that was the problem but it doesn't help.
-
Try this:
if( PIND & (1<<2) ){...}
-
Yea I tried that - same problem.
-
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.
#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
-
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.
#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
-
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.
-
This line:
PORTD &= !(1 << 4);
should be:
PORTB &= ~(1 << 4);
-
Same problem :(
-
This line:
PORTD &= !(1 << 4);
should be:
PORTB &= ~(1 << 4);
Ooops - should have said:-
PORTD &= ~(1 << 4);
ie you should '~' rather than '!'
-
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))
-
@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?
-
Ok, so I tried the experiment myself, and everything worked for me. The code I used is:
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.
-
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?
-
Can you provide a schematic of how your switch is hooked up please? Are you sure you have your switch connected to PD2?
-
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)
-
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.
-
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:
(http://www.ladyada.net/images/arduino/pulldown.png)
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.
-
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.