Baby Orangutan External interrupt from sensor

[b]Hi,
recently I bought Baby Orangutan B-328 robot controller and I created a small robot which goes forward and stop if it detects an obstacle. To detect an obstacle I use Pololu 38 kHz IR Proximity Sensor (Pololu item #: 2460).

I Successfully code it in #C. Here is my code:[/b]

[code]#include <avr/io.h>
void M1_forward(unsigned char pwm) {
OCR0A = 0;
OCR0B = pwm;
}
void M1_reverse(unsigned char pwm) {
OCR0B = 0;
OCR0A = pwm;
}
void M2_forward(unsigned char pwm) {
OCR2A = 0;
OCR2B = pwm;
}
void M2_reverse(unsigned char pwm) {
OCR2B = 0;
OCR2A = pwm;
}
void motors_init() {
TCCR0A = TCCR2A = 0xF3;
TCCR0B = TCCR2B = 0x02;
OCR0A = OCR0B = OCR2A = OCR2B = 0;
DDRD |= (1 << PORTD3) | (1 << PORTD5) | (1 << PORTD6);
DDRB |= (1 << PORTB3);
}
int main(void){
motors_init();
DDRB &= ~(1 << PINB4); //set PINB4 as input = obstacle sensor

while(1){
if(bit_is_clear(PINB,4)){ //Obstacle detected
M1_forward(0);
M2_forward(0);
}
else { //Obstacle not detected
M1_forward(180);
M2_forward(180);
}
}
}[/code]

The problem is that I don’t know how to change the code, that the sensor will have a function of external interrupt (it means, that if the sensor detects an obstacle, it will interrupt and stop the robot). I am a newbie in programming and I have already tried many tutorials, but I can’t do it. Please can you help me to solve my problem?

Hi.

If you are not planning on having your robot do more than just detecting obstacles, you probably don’t need to use interrupts. However, if you are going to add more features or want to learn about interrupts, you could start by looking through this guide to AVR interrupts that was posted on the AVR Freaks forum. You might also try looking at the source code for our OrangutanPulseIn library to get an example of how the pin-change interrupts are used. In addition, it would probably be helpful to look through the interrupt section of the ATmega328P datasheet.

By the way, I put your code into code tags, so it is easier to look at. You can use code tags by typing “[ code ]your code here[ /code ]” without the extra spaces. Please use code tags instead of just reducing the size of the font used in the future.

-Claire

Thank you for your answer. :wink:
I would like to use the interrupts, because I want more than just detecting obstacles. I have already read lot of tutorials and I ve also visited the websites which you had proposed me, but I don’t know how to do it :frowning: . Please can You help me? I modified my code the best I could. Here is my code:

[code]#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
void M1_forward(unsigned char pwm) {
OCR0A = 0;
OCR0B = pwm;
}
void M1_reverse(unsigned char pwm) {
OCR0B = 0;
OCR0A = pwm;
}
void M2_forward(unsigned char pwm) {
OCR2A = 0;
OCR2B = pwm;
}
void M2_reverse(unsigned char pwm) {
OCR2B = 0;
OCR2A = pwm;
}
void motors_init() {
TCCR0A = TCCR2A = 0xF3;
TCCR0B = TCCR2B = 0x02;
OCR0A = OCR0B = OCR2A = OCR2B = 0;
DDRD |= (1 << PORTD3) | (1 << PORTD5) | (1 << PORTD6);
DDRB |= (1 << PORTB3);
}
int main(void){
motors_init(); //intialise motors
DDRB &= ~(1 << PINB4); //set PINB4 as input = obstacle sensor

GICR = 1<<INT0; // enable INT0
MCUCR = ~(1 <<ISC01) | ~(1 <<ISC00); // The low level of INT0 generates an interrupt request.
sei(); //Enable Global Interrupt

while(1){
M1_forward(180);
M2_forward(180);
}
}

ISR(INT0_vect) //if it detects an obstacle it will stop for a few ms
{
M1_forward(0);
M2_forward(0);
_delay_ms(200);
}

[/code]

The error box shows me this:

[code]Compiling C: main.c
avr-gcc -c -mmcu=atmega328p -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./main.lst -std=gnu99 -MMD -MP -MF .dep/main.o.d main.c -o main.o
main.c:21: warning: function declaration isn’t a prototype
main.c: In function ‘main’:
main.c:32: error: ‘GICR’ undeclared (first use in this function)
main.c:32: error: (Each undeclared identifier is reported only once
main.c:32: error: for each function it appears in.)
make.exe: *** [main.o] Error 1

Process Exit Code: 2
Time Taken: 00:00[/code]

I program in Programmers Notepad (WinAVR). I think the only error is that I can’t enable INT0 interrupt. Please can you help me?

From the error you are getting, it looks like the compiler doesn’t recognize GICR. That term is also not in the datasheet for the ATmega328P. From your comment it looks like you want that line to enable INT0. If that is the case, you should probably be using the EIMSK and SREG registers instead. The line after that looks like it also will not do what you want, since ISC01 and ISC00 are not part of the MCUCR register.

Note that different AVRs will have different sets of registers and methods to enable interrupts, so the guide I linked to earlier is more intended as a general introduction; you will have to figure out the specifics of your particular AVR yourself. I recommend reading through section 13 External Interrupts in the ATmega328P datasheet carefully to determine which registers you need to use. You might also try searching for tutorials specific to the ATmega328P.

-Claire

Thank You for your advice,
I modified my code using the EIMSK and SREG registers and it works :smiley: . I’ve never heard that different AVRs have different sets of registers and methods to enable interrupts.

Here is my working code:

[code]#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

void M1_forward(unsigned char pwm) {
OCR0A = 0;
OCR0B = pwm;
}
void M1_reverse(unsigned char pwm) {
OCR0B = 0;
OCR0A = pwm;
}
void M2_forward(unsigned char pwm) {
OCR2A = 0;
OCR2B = pwm;
}
void M2_reverse(unsigned char pwm) {
OCR2B = 0;
OCR2A = pwm;
}
void motors_init(void) {
TCCR0A = TCCR2A = 0xF3;
TCCR0B = TCCR2B = 0x02;
OCR0A = OCR0B = OCR2A = OCR2B = 0;
DDRD |= (1 << PORTD3) | (1 << PORTD5) | (1 << PORTD6);
DDRB |= (1 << PORTB3);
}
int main(void){
motors_init(); //intialise motors
DDRD &= ~(1 << PIND2); //set PIND2 as input = obstacle sensor
SREG = ~(1 <<ISC01) | ~(1 <<ISC00); // The low level of INT0 generates an interrupt request.
EIMSK = 1<<INT0; // enable INT0
sei(); //Enable Global Interrupt
M1_forward(180);
M2_forward(180);
while(1){ //infinite loop
}
}

ISR(INT0_vect) //if it detects an obstacle it will stop
{
M1_forward(0);
M2_forward(0);
_delay_ms(200);
M1_forward(150);
M2_forward(150);

[/code]