Society of Robots - Robot Forum
Software => Software => Topic started by: DTM22 on November 18, 2011, 02:37:03 PM
-
Hi, I'm attempting to use port manipulation for a project I'm working on where the timing is very crucial. Ive read several tutorials about it online but I am still unclear on how to read whether the appropriate INPUT pins read HIGH or LOW. In my case I'm using the digital pins 6 and 7. I was already told by someone to use the following code to check whether the state of either of the pins changes to HIGH and if so, to perform a particular function. Here's the code I was given by joe61:
Code:
int main()
{
DDRD &= ~ ((1 << PD6) | (1 << PD7));
for ( ;; )
{
if (PIND & (1 <<PD6))
handlePD6 ();
if (PIND & (1 <<PD7))
handlePD7 ();
_delay_ms (100);
}
}
Where handlePD[67] are functions you write to do what you want.
This was very helpful but when I add it to my code, I get the error message saying PD6 and PD7 were not declared in this scope, how do I got about declaring them properly?
-
That was just a fragment, you have to #include <avr/io.h> as well. If you're using the Arduino environment I thought it did that for you, but I don't use it so maybe not. If not using the Arduino IDE, just add this to the top of the file
#include <avr/io.h>
Then your makefile (if you're doing it that way) needs to define the processor you're using. Here's an example:
DEVICE = atmega328p
AVRDUDE_DEVICE = m328p
SRCS = main.c
OBJS = $(SRCS:.c=.o)
CFLAGS=-g -Wall -mcall-prologues -mmcu=$(DEVICE) -Os
CC=avr-gcc
OBJ2HEX=avr-objcopy
LDFLAGS=-Wl,-gc-sections -Wl,-relax
PROG = -c usbtiny -P usb
#PROG = -c avrisp2 -P /dev/ttyACM0
AVRDUDE=avrdude
TARGET=main
OBJECT_FILES=$(OBJS)
all: $(TARGET).hex
clean:
rm -f *.o *.hex *.obj *.hex
%.hex: %.obj
$(OBJ2HEX) -R .eeprom -O ihex $< $@
sensors.o: sensors.c
%.obj: $(OBJECT_FILES)
$(CC) $(CFLAGS) $(OBJECT_FILES) $(LDFLAGS) -o $@
program: $(TARGET).hex
$(AVRDUDE) -p $(AVRDUDE_DEVICE) $(PROG) -U flash:w:$(TARGET).hex
I switch back and forth between a Pololu and Adafruit programmer, so that's what the PROG macros are for, substitute a definition that suits your programmer.
Joe
P.S. Lots of people use something like webbotLib to keep from having to mess with makefiles. You might find it very helpful: http://webbot.org.uk/iPoint/30.page (http://webbot.org.uk/iPoint/30.page)
-
Hi, sorry to bother you again about this but I'm using the Arduino IDE and it does not recognize that library. I'm still getting the same error message, any other ideas as to what may be causing the problem?
-
Post the code you're using and I'll take a look. Can't say without seeing that.
Joe
Edit: Are you copying the code I posted into the Arduino environment? That won't work, because it has its own main() routine. Rather than use main() as I did, you need to use the setup() and loop() functions.
Put the 'DDRD &= ~ ((1 << PD6) | (1 << PD7)); ' part in the setup() function, and the code in the for (;;) loop in the loop() function.
-
Hey, thanks for your help, here's what I have so far.
Right now I'm just attempting to have a value sent to the LCD screen when the sensor is tripped(Goes HIGH)
Code:
#include <LiquidCrystal.h> //Liquid Crystal Library
#define pin6 (1 << PD6)
#define pin7 (1 << PD7)
int BPS;
int FPS;
long Inches;
long Time;
unsigned long StartTime;
unsigned long StopTime;
unsigned long Duration;
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
//Initialises the library with the appropriate interface pins
void setup()
{
lcd.begin(16, 2); // Sets up the LCD's number of columns and rows(16x2):
DDRD &= ~ ((1 << PD6) | (1 << PD7)); //Sets Pins 6 and 7 as INPUTS
}
void loop()
{
if (PIND & (1 <<PD6))
{
StartTime=micros();
lcd.print(StartTime, DEC);
delay(3000);
lcd.clear();
}
}
-
I set up an LCD on a breadboard and loaded your code. I think it's doing what the code says to. What are you seeing that is different than what you expect? Can you copy and paste the error messages?
Incidentally. I didn't realize you're using the Arduino environment. You don't need any of the bit-fiddling we've been doing there. You don't have to set pin 6 & 7 as input because that's what they are by default. To read the value of pin 6 you can just say
unsigned char val = digitalRead (6)
Joe
-
Here are the error messages Im getting:
Sensor_Programming_with_LCD_PortMan__.cpp: In function 'void setup()':
Sensor_Programming_with_LCD_PortMan__:36: error: 'PD6' was not declared in this scope
Sensor_Programming_with_LCD_PortMan__:36: error: 'PD7' was not declared in this scope
Sensor_Programming_with_LCD_PortMan__.cpp: In function 'void loop()':
Sensor_Programming_with_LCD_PortMan__:62: error: 'PD6' was not declared in this scope
Sensor_Programming_with_LCD_PortMan__:69: error: 'PD7' was not declared in this scope
And as for using digitalread, I read it is too slow for the time sensitive calculation I will be doing and could cause errors in my end result which is why I was looking into port manipulation to take much faster readings.
-
Weird, it compiles fine for me with PD6 & PD7. Maybe your avr-gcc got messed up somehow. Try removing and reinstalling the Arduino environment. What version are you using? (Help -> About Arduino)
Joe
-
I just removed and reinstalled the Arduino Environment, I was running version 022 and I now have version 023 and Im still getting the same error message
-
There's a thread on the Arduino forums about this ( http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1287285012 (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1287285012) ), it says to use PORTD6 rather than PD6, because of the way things are declared for the 328. So I checked the header file for the 328p and sure enough they are declared like that.
So now I have to figure out why it compiles on my machine, I don't think I've every used PORTDn.
Joe
-
So by rewriting the code and changing PD6 to PORTD6 and PD7 to PORTD7 is should work?
-
I did it and it works! Thanks so much, you were a big help!