PING))) Sensor with ATMega168
davecw
Posts: 2
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
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
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- Stephen
Thank you! I will send my question over to those forums.
Thanks again for the reply!
Dave
Post Edited (mladams03) : 9/21/2009 2:34:51 AM GMT