Serial monitor gives wrong values /Multiple_IRQ_REQUESTS crash

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hello im trying to test an hc-sr04 ultrasonic sensor using this code, what supposed to happen is that i send a pulse on trigger pin of the module wait for rising edge of echo pin which interrupts and sets a flag and timer1 starts counting ,i poll the pin till it becomes low then i save the timer value and stop the timer, turn value of timer to a bunch of characters and send over to serial monitor.

the serial communication works because i've tried to send characters and it worked. but when i run this code i keep getting garbage values and then my laptop crashes MULTIPLE_IRQ_REQUESTS ERROR.

 

code:

 #define F_CPU 8000000UL 
 #define TRIGGER 6
 #define ECHO 2
#include <util/delay.h> 
#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdlib.h>
volatile uint16_t travel_time;
volatile unsigned char count =0xff;
volatile unsigned char rising_edge=0x00;
volatile unsigned char wave_sent=0x00;




void start_timer1(void);
void send_wave(void);




ISR(INT0_vect){
	rising_edge=0xff;
	
}

int main(void)
{
   MCUCSR|=(1<<JTD);
   MCUCSR|=(1<<JTD);
   DDRD|=(1<<4);
   PORTD&=~(1<<TRIGGER);
   DDRD|=(1<<TRIGGER);
   DDRD&=~(1<<ECHO);
   PORTD&=~(1<<ECHO);
   GICR|=(1<<INT0);
   MCUCR=(1<<ISC00)|(1<<ISC01);
   UBRRL=51;
   UCSRB|=(1<<TXEN);
   UCSRC|=(1<<UCSZ0)|(1<<UCSZ1)|(1<<URSEL);
   char to_monitor[8];
    sei();
	
   
   
   while(1){
	   if(!wave_sent){
		   send_wave();
		   wave_sent=0xff;
	   }
	   if(rising_edge){
		   start_timer1();
		   while(1){
			  if(~(PIND&(1<<ECHO))){
				  travel_time=TCNT1;
				  itoa(travel_time,to_monitor,10);
				  TCCR1B=0X00;
				  for(count=0;count<=7;++count){
					  UDR=to_monitor[count];
					  _delay_ms(15);
					  
					  }
					  
				   break;
		   }
		   }
	   
	   
rising_edge=0x00;
wave_sent=0x00;	   
}
   }
}
	   
	   
	   
	   
	   
	   
	   
	   
	   
	   
	   
	   
	   
	    

void start_timer1(void){
	TCNT1H=0X00;
	TCNT1L=0X00;
	TCCR1A=0X00;
	TCCR1B=(1<<CS11);
}

void send_wave(void){
	PORTD|=(1<<TRIGGER);
	_delay_us(15);
	PORTD&=~(1<<TRIGGER);
	}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which processor ? (the AVR models are similar but not identical).
itoa(travel_time,to_monitor,10); will convert the value in travel_time into a string of upto 6 digits with a trailing null.
The loop for(count=0;count<=7;++count){ will always transmit 8 bytes, which means that it will send your value, the null (0x00) and any trailing 'rubbish' in the array to_monitor[]
You should stop transmitting 'strings' when the byte is zero.

Last Edited: Tue. Jul 17, 2018 - 12:42 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   MCUCSR|=(1<<JTD);
   MCUCSR|=(1<<JTD);
   DDRD|=(1<<4);
   PORTD&=~(1<<TRIGGER);
   DDRD|=(1<<TRIGGER);
   DDRD&=~(1<<ECHO);
   PORTD&=~(1<<ECHO);
   GICR|=(1<<INT0);
   MCUCR=(1<<ISC00)|(1<<ISC01);
   UBRRL=51;
   UCSRB|=(1<<TXEN);
   UCSRC|=(1<<UCSZ0)|(1<<UCSZ1)|(1<<URSEL);

You do know that spaces cost nothing in C?

   MCUCSR |=  (1 << JTD);
   MCUCSR |=  (1 << JTD);
   DDRD   |=  (1 << 4);
   PORTD  &= ~(1 << TRIGGER);
   DDRD   |=  (1 << TRIGGER);
   DDRD   &= ~(1 << ECHO);
   PORTD  &= ~(1 << ECHO);
   GICR   |=  (1 << INT0);
   MCUCR  =   (1 << ISC00) | (1 << ISC01);
   UBRRL  =   51;
   UCSRB  |=  (1 << TXEN);
   UCSRC  |=  (1 << UCSZ0) | (1 << UCSZ1) | (1 << URSEL);

Also an interesting lack of comments. Now maybe some of those lines are self documenting but I wouldn't have minded a comment to remind me what ICS00/ICS01 is actually selecting (I'm guessing "rising edge" perhaps?). Similarly what 11 to UCSZ0 actually achieves?

 

In fact for both of those, as they are bit groups you could have done:

   MCUCR  =   (3 << ISC00);
...
   UCSRC  |=  (3 << UCSZ0) | (1 << URSEL);

or possibly more readable still is:

   MCUCR  =   (0b11 << ISC00);
...
   UCSRC  |=  (0b11 << UCSZ0) | (1 << URSEL);

Oh and while we're looking at this the last line will NOT work. Never use |= when UCSRC (with a URSEL bit) is involved because in this kind of AVR the UBRRH and UCSRC registers are at the same address and when you read the location (as |= forces it to do) it's not the existing state of UCSRC you read but the contents of UBRRH. So when URSEL is involved only ever use =.

 

Having said that I am pretty sure UCSZ = 11 is the power on default anyway - so the whole line is superfluous anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
			  if(~(PIND&(1<<ECHO))){

Won't work.

Either use ! instead, or change the parentheses.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Edit: Double post deleted.

Stefan Ernst

Last Edited: Tue. Jul 17, 2018 - 11:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sternst wrote:

			  if(~(PIND&(1<<ECHO))){

Won't work.

Either use ! instead, or change the parentheses.

 

I think changing it to ! fixed it , timer1 was always stopped as this condition was always true that's why i get one digit and then a bunch of garbage values.

i've also tried commenting more and making spaces in my code , i actually found it hard to read my own code sometimes, have also added new line character and detect null character and this is new code and its working thanks all.

#define F_CPU 8000000UL 
 #define TRIGGER 6
 #define ECHO 2
#include <util/delay.h> 
#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdlib.h>
volatile uint16_t travel_time;
volatile unsigned char count =0xff;
volatile unsigned char rising_edge=0x00;
volatile unsigned char wave_sent=0x00;




void start_timer1(void);
void send_wave(void);




ISR(INT0_vect){
	rising_edge=0xff;
	
}

int main(void)

{
	char to_monitor[8];
	
   MCUCSR|=(1<<JTD);                        //disable JTAG >>Free PORTC
   MCUCSR|=(1<<JTD);                        // ....................    
   
   
   PORTD&=~(1<<TRIGGER);                    //TRIGGER PIN OUTPUT .... initial LOW
   DDRD|=(1<<TRIGGER);
   
   DDRD&=~(1<<ECHO);                        //ECHO pin input .... No pullup
   PORTD&=~(1<<ECHO);
   
   
   GICR=(1<<INT0);                            //Enable external interrupt INT0 ;;;; rising edge
   MCUCR=(0b11<<ISC00);
   
   
   UBRRL=51;                //      9600 baud rate
   UCSRB|=(1<<TXEN);          //      UART Transmit enable
   UCSRC=(0b11<<UCSZ0)|(1<<URSEL);             //8 bit data
   sei();
	
   
   
   while(1){
	   
	   
	   if(!wave_sent){
		   send_wave();
		   wave_sent=0xff;
	   }
	   
	   
	   
	   
	   if(rising_edge){
		   
		   
		   start_timer1(); 
		                                                   
		   while(1){
			  if(!(PIND&(1<<ECHO))){                         // POLL echo pin for low
				                                         
				  travel_time=TCNT1;
				  itoa(travel_time,to_monitor,10);
				  TCCR1B=0X00;
				  
				  
				  for(count=0;count<=7;++count){
					  if(to_monitor[count]==0){                                    //transmit timer1 values via UART
						  break;
					  }
					  
					  
					  UDR=to_monitor[count];
					  _delay_ms(100);
					  
					  }
					  UDR='\n';
					   _delay_ms(100);
					  
				   break;
		   }
		   
		   }
	   
	   
rising_edge=0x00;  
                                           //reset wave_sent ;;; rising_edge flags
wave_sent=0x00;	 
  
}

   }
   
}