Shop OBEX P1 Docs P2 Docs Learn Events
PING))) Sensor with ATMega168 — Parallax Forums

PING))) Sensor with ATMega168

davecwdavecw Posts: 2
edited 2009-09-21 02:30 in Accessories
Hello all,
I hope I'm not beating a topic to death by asking how to interface the PING to yet another microcontroller, but...
I'm hoping to find some help with programming interrupts on an AVR ATMega168
and with programing the ATMega168 to interface with the Parallax PING Ultrasonic
sensor (I'm looking to do collision avoidance for a robot project). I was planning
to use the ICP mode of the ATMega168, and have attempted to write some code that
uses an interrupt service routine for the TIMER1 Capture vector.

And so my troubles began: my first attempt failed to control this sensor. I determined
this failure by connecting the ATMega168 to a PC serial port and reading out the counter values
I was getting from the TIMER/Counter on the ATMega (which should have been counting the
width of the pulses from the PING sensor). I noticed the values displayed had no relation to the distance
between my PING sensor and a wall. I sensed something was fishy with my code.

So, I started debugging and quickly found out that the ATMeg168 was inexplicably resetting.
I immediately suspected the watchdog timer, but then my attempts to turn off the WDT didn't
seem to work, either. I then suspected that the serial port connection to the ATMega168
was causing some sort of ground bounce and thus resetting the ATMega. To test this, I disconnected
the serial port, and to keep track of what parts of the code were running, I arranged to
light LEDs at different points in the code.

After many iterations, I programmed the code below. The problem is, I'm still reseting
unexpectedly and repeatedly (so, the serial port is not apparently the problem). I copied the
WDT_off function code from the Atmel Datasheet for the ATMega168 (I did comment out the __watchdog_reset()
function statement, which was not defined anywhere in the datasheet).

My code:

#define F_CPU 8000000UL

#define FOSC 8000000 //usart clk spd
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1 // sets the baud rate for the serial port

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


void delayus( uint16_t micros ) {
while ( micros ) {
_delay_us( 1 );
micros--;
}
}


void WDT_off(void)
{

cli();
// __watchdog_reset(); // where is this defined??
/* clear WDRF in MCUSR */
MCUSR &= ~(1<<WDRF);
/* Write logical 1 to WDCE and WDE */
/* keep old prescalar setting to prevent unintentional time out */
WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = 0b00100001;

/* turn off the WDT */
WDTCSR = 0x00;

}


////////////////////////////
// Define Iterrupt Service Routines
////////////////////////////


//Timer1 capture interrupt service subroutine

ISR (TIMER1_CAPT_vect)
{

TCCR1B = TCCR1B&0xBF;
TIFR1 = 32;
PORTD = 16; // turn on PORTD Pin 4 to see if I get here
delayus(50000);
delayus(50000);

}
ISR (WDT_vect)
{
PORTD = 0;
}

// main program

int main(void) {

// turn off the Watchdog timer
WDT_off();
SREG = 0x00; //globally disable interrupts
USART_Init(MYUBRR); // I initialize the USART, but currently don't use it
DDRD = 0xFF;
/*Noise canceller, without prescaler, rising edge*/
TCCR1B=0xC1;
TIFR1=0x20;
TIMSK1=0x24; // includes setting ICIE1 to 1; enable this interrupt
PORTD = 8; // turn on PORTD Pin3 to see if I get to this place
delayus(50);
delayus(50);
delayus(50);
DDRB = 0x00;

SREG = 0x80;

while(1)
{

PORTD = 32; // turn on PORTD Pin 5 to see if I get here

}

}

The Fuse settings on the ATMega168 are WDTON set to 0; Brownout detect is disabled.

The results of my experiment are:
The LED on PORTD Pin3 is dimly lit (but steady); this tells me I'm still resetting;
the LED on PORTD Pin5 is brightly lit indicating that I get to the while loop, and stay in there for some time

Whenever I take PIN0 of PORTB high, the LED on PORTD Pin4 lights for a time, then goes out. At this point
the two other LEDs on PORTD are lit as described above. This tells me the ISR functions.

So, I'm stuck in that the ATMega is resetting when I don't want it to. Now, my ultimate goal is to write some
code to use the Parallax PING sensor properly, so if anyone can help me directly with that, I would be most
obliged. If, however, someone could also point out what I'm doing wrong here, I would it appreciate that as well!


BTW: I'm using AVRStudio4 (revision 4.16, build 638) with the gcc compiler for code entry and compile/link/assemble.


Thanks in advance for any help!!

Dave

Comments

  • FranklinFranklin Posts: 4,747
    edited 2009-09-06 01:56
    I'd start by going to AVR Freaks or Arduino.cc to see if the Atmel guys can give you some help. I know the Arduino playground has methods of connecting the ping))) to an Arduino.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - Stephen
  • davecwdavecw Posts: 2
    edited 2009-09-06 20:32
    Hello Stephen,
    Thank you! I will send my question over to those forums.
    Thanks again for the reply!

    Dave
  • mladams03mladams03 Posts: 2
    edited 2009-09-21 02:15
    You're probably resetting due to the fact that you're clearing and setting interrupts unnecessarily. If I were you I wouldn't be using the cli() command at all, it's typically bad practice. Just disable the interrupt you don't want on at that time. Then re-enable it when you need it. And is there any reason for using the watchdog timer? If I've read the documentation on the atmel processors correctly it states that the watchdog timer has something to do with automatic, timed processor resets. That's the most likely cause of your resetting issue. There are timers on that chip for the specific use of timing things. I believe there's two on that chip. That's how the arduino drives the PWM outputs. It seems like you have an idea of what you're doing as you are manipulating registers pretty well but I would take another read through the data sheet for the device. (it's called the preliminary under documentation on Atmels site.) Those are my suggestions, take it or leave it, but it's what I've been through school for and those are some of the things I've learned along the way.

    Post Edited (mladams03) : 9/21/2009 2:34:51 AM GMT
  • mladams03mladams03 Posts: 2
    edited 2009-09-21 02:30
    I just looked over the documentation for that processor and it's definitely a problem with the watchdog timer. That timer is used specifically to reset the device when the timer runs out. My guess is you set it to start running and it overflowed and triggered an internal reset. Use a different timer and you shouldn't have a problem.
Sign In or Register to comment.