Count multiple pulse width

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

Hello to all!
I need to connect 4 HC-SR04 sensors to my Atmega 1284P. For doing this, i decided to use the PCINT function of the atmega to measure the echo pulse width from the sensor.
Based on this patten:https://sites.google.com/site/qeewiki/books/avr-guide/external-interrupts-on-the-atmega328 i written a drive, but it doesn't work properly..
I did some test and it seem that some falling edge from the echo signals is not read and some else falling edge is read two times:

ISR(PCINT0_vect)
{
	unsigned char changed_bits = PINA ^ port_history;
	port_history = PINA;
	
	
	if ( changed_bits & (1 << ECHO_1) ) // change on the pin echo_1
	{
		if ( !(PINA & (1<<ECHO_1)) )// rising edge change
		transmit_uchar(0x01);
		else if ( (PINA & (1<<ECHO_1)) )// falling edge change
		{
			transmit_uchar(0x02);
		}
	}
	if ( changed_bits & (1 << ECHO_2) ) // change on the pin echo_2
	{
		if (!(PINA & (1<<ECHO_2)) )// rising edge change
		transmit_uchar(0x03);
		else if ( (PINA & (1<<ECHO_2)) )// falling edge change
		{
			transmit_uchar(0x04);
		}
	}
	if ( changed_bits & (1 << ECHO_3) ) // change on the pin echo_3
	{
		if (!(PINA & (1<<ECHO_3)) )// rising edge change
		transmit_uchar(0x05);
		else if ( (PINA & (1<<ECHO_3)) )// falling edge change
		{
			transmit_uchar(0x06);
		}
	}
	if ( changed_bits & (1 << ECHO_4) ) // change on the pin echo_4
	{
		if ( !(PINA & (1<<ECHO_4)) ) // rising edge change
		transmit_uchar(0x07);
		else if ( (PINA & (1<<ECHO_4)) ) // falling edge change
		{
			transmit_uchar(0x08);
		}
	}
}

This is my ISR routine. In practice and only for testing purpose, i send a trig to all the sensor and i send a uchar if i detect a rising edge or a falling edge for each sensor.
i expect to read this sequence: [1 3 5 7 2 4 6 8] or in similar fashion, but i receive this sequence [1 3 5 7 2 6 8 5] or similar. In practice, in all experiments what did I do, i read correctly only the first part that corresponds to the rising edge of the echo while the last part is wrong, is as if I read twice the rising edge ....

Can anyone give me some advice on how to solve this problem?

 

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

Do you trigger all 4 at the same time? What if the first unit is close to a wall and his echo goes to all of the sensors? This is surely wrong.

 

Imagecraft compiler user

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

Do you trigger the four sensors simultaneously or sequentially? 

 

If simultaneously, then there is a strong probability that multiple echoes will return at or very close to the same time. It is not at all clear to me what will happen if a PCINT edge happens during the latency time between an earlier PCINT edge and the time that it reads the pin change register. I simply would not count on that behavior being predictable. Instead, I would not trigger sensor 2 until the echo from sensor 1 (or a trimeout) happens, and so forth.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

Hi bobgardener, ka7ehk, thank you so much for the reply!

 

Do you trigger all 4 at the same time? What if the first unit is close to a wall and his echo goes to all of the sensors? This is surely wrong.

Yes, i trigger all the sensor at the same time, but they are in a "+" configuration, so i think that the interference for each one is minimum..

 

 

Do you trigger the four sensors simultaneously or sequentially? 

 

If simultaneously, then there is a strong probability that multiple echoes will return at or very close to the same time. It is not at all clear to me what will happen if a PCINT edge happens during the latency time between an earlier PCINT edge and the time that it reads the pin change register. I simply would not count on that behavior being predictable. Instead, I would not trigger sensor 2 until the echo from sensor 1 (or a trimeout) happens, and so forth.

Not even for me it is clear! But i think that if multiple echo will return at or very close to the same time, the next interrupt will bein in wait in the memory and it will  executed after that the first interrupt ends its execution, but maybe i'm wrong.
Your solution is ok, but in this way i need much time for reading all the sensors! I have a timeout for each one that is of about 26 ms, but 26*4 = 104 ms is too much for my control loop!

 

Now i use only the PCINT0, but if i use one pin of PCINT0, one pin of PCINT1 e so on for each echo signals, in yours opinions i solve the problem?

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

You don't show what transmit_uchar() function does, how long does it take? 

You must keep IRQ fuctions as short as possible or you will miss one or more of your echos.

Just set a flag in your IRQ and poll it's status in main() and do your output function there.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

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

Hi ki0bk, thank you so much for the reply! 

The function transmit_uchar is simple

void transmit_uchar( unsigned char data )
{
	while ( !(UCSR0A & (1<<UDRE0)) )
	; /* wait for empty transmit buffer */
	UDR0 = data; /* start transmittion */
}

 

My ISR routine is not long,  the one I have shown is for test, but the "release" version is already short

 

ISR(PCINT0_vect)
{
	unsigned char changed_bits = PINA ^ port_history;
	port_history = PINA;
	
	
	if ( changed_bits & (1 << ECHO_1) ) // change on the pin echo_1
	{
		if (echo_1_rising) // rising edge change
		{
			t0_1 = sonar_counter;
			echo_1_rising = 0;
		}
		else  // falling edge change
		{
			t1_1 = sonar_counter;
			echo_1_complete = 1;     // echo 1 complete
			PCMSK0 &= ~(1<<PCINT3);  // disable pin change interrupt
		}
		
	}
	
	if ( changed_bits & (1 << ECHO_2) ) // change on the pin echo_2
	{
		if (echo_2_rising) // rising edge change
		{
			t0_2 = sonar_counter;
			echo_2_rising = 0;
		}
		else  // falling edge change
		{
			t1_2 = sonar_counter;
			echo_2_complete = 1;     // echo 2 complete
			PCMSK0 &= ~(1<<PCINT4);  // disable pin change interrupt
		}
	}
	//
	if ( changed_bits & (1 << ECHO_3) ) // change on the pin echo_3
	{
		if (echo_3_rising) // rising edge change
		{
			t0_3 = sonar_counter;
			echo_3_rising = 0;
		}
		else  // falling edge change
		{
			t1_3 = sonar_counter;
			echo_3_complete = 1;     // echo 3 complete
			PCMSK0 &= ~(1<<PCINT5);  // disable pin change interrupt
		}
	}
	//
	if ( changed_bits & (1 << ECHO_4) ) // change on the pin echo_4
	{
		if (echo_4_rising) // rising edge change
		{
			t0_4 = sonar_counter;
			echo_4_rising = 0;
		}
		else  // falling edge change
		{
			t1_4 = sonar_counter;
			echo_4_complete = 1;     // echo 4 complete
			PCMSK0 &= ~(1<<PCINT6);  // disable pin change interrupt
		}
	}
}

 

this is the main for the test

int main(void)
{
	init_multi_sonar();
	
	sei();
	
	float measure[4] = {0};
	
	sendMultiPulse();
	
	while (isMultiSonarMeasureReady()) ;
	
	getMultiSonarMeasure(measure);
	
	while(1)
	{
		
	}
}

 

Just set a flag in your IRQ and poll it's status in main() and do your output function there.

I'm sorry, but I do not understand what to do! Please, can you explain me better?

 

However, i tried to using one PCINT for each echo signals, but i obtain the same result.  It is as if an rising echo was read twice by the same interrupt eg.  [7 1 3 5 "7" 2 4 6]. The second "7" is the problem, i expect an even number, because the even number indicate the falling edge. Instead i obtain an odd number that indicate a rising edge. It seem that the function read twice a rising edge on the same echo pin and i not understand why..

Last Edited: Tue. Sep 22, 2015 - 09:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sending a char out the uart takes time. Eg at 9600 baud, each char takes 1ms. That might upset things.
I'd suggest you get a logic analyser to see what is really happening. Something like a salae logic or clone.

Last Edited: Tue. Sep 22, 2015 - 11:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suggest reading each sensor by itself. Sound travels 1ms per foot. If the range of the gizmo is 5 feet, trigger, TCNT1=0; wait for done pulse; tics[chan]=TCNT1; If TCNT1 gets to 10ms, break out. Move to the next sensor. When all 4 have been read (should take 40ms at most), cvt tics to ms and print.

 

Imagecraft compiler user

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

Good morning to all, and thank for the reply! smiley

 

Sending a char out the uart takes time. Eg at 9600 baud, each char takes 1ms. That might upset things.
I'd suggest you get a logic analyser to see what is really happening. Something like a salae logic or clone.

Kartman , thank for the reply!

I use a baud rate of 115200 with 2x enable. So for send each char i need about 43 us.. I don't think that this is the problem. I haven't a logic analyzer, and now is problematic for me to get one.

 

 

I suggest reading each sensor by itself. Sound travels 1ms per foot. If the range of the gizmo is 5 feet, trigger, TCNT1=0; wait for done pulse; tics[chan]=TCNT1; If TCNT1 gets to 10ms, break out. Move to the next sensor. When all 4 have been read (should take 40ms at most), cvt tics to ms and print.

Last night i have adopted a similar solution. I have tried using only one sensor and i obtain a right sequence. I have tried with two sensors and i obtain a right sequence only if I position the hardware perpendicular at the wall. Note that, using the ISR routine posted above, this is not a problem because in this routine i haven't done any kind of control if the echo doesn't return in time. I also tried using three sensors, but with this configuration i obtain a bad sequence although I place the sensors perpendicular of the wall.

 

Today i try using two different PCINT (eg PCINT0 and PCINT1) each for a couple of sensors, and i see what happens, otherwise i try your approach!

Last Edited: Wed. Sep 23, 2015 - 06:03 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you are coming round to one sensor at a time.  Think about how RADAR works - the antenna rotates (physically or via phased array) and so it only 'sees' echo from a narrow field of view.  The longer distance the RADAR the slower it spins to allow the echo to return and the bigger the antenna as the echo is so much smaller - check out RADAR equation. 

 

Active Sonar is different using a single point source however target distances are much greater and local echoes are ignored.

 

David 

 

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

You can use your sound card as an oscilloscope. You can use this to determine if you get multiple echoes.

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

DaFlippers, thank for the advice!

I have clear how to works the sonar. I have done a driver, but it work only for one sonar. Now i need to extend this drive to take into account 4 sonars, this is my problem!

 

You can use your sound card as an oscilloscope. You can use this to determine if you get multiple echoes.

How i do this? Please, can you explain me or give me some reference on how i do?

 

 

However, i tried to using two PCINT (PCINT0 and PCINT1) it work but not in the while loop. In the while loop i obtain again a bad sequence..

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

Google 'soundcard oscilloscope'
You'll find out all about it

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

luca80 wrote:

Last night i have adopted a similar solution. I have tried using only one sensor and i obtain a right sequence. I have tried with two sensors and i obtain a right sequence only if I position the hardware perpendicular at the wall.

 

Sounds like either your sensors are interacting, or your interrupts are.

One way to check which, would be to use a separate MCU for each sensor, and  if that allows you free orientation with no issues, then your software can be tuned.

If that fails, then no matter what you do in SW, the design has fundamental flaws.

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

Try to discover whether you are getting the input you expect.

If you do not have an oscilloscope, you can do the job by writing code so simple you know it is correct.

int main(void)
{
intialize
    while(1) {
        oldbyte=PINA;
        bytes[0]=oldbyte;
        times[0]=0;
        j=1;
        send trigger
        for(t=0; t< 1000000 && j< sizeof bytes; ++t) {
            byte=PINA;
            if(byte != oldbyte) { bytes[j]=byte, times[j]=t, ++j, oldbyte=byte; }
        }  // t

        transmit j;
        for(k=0; k< j; ++k]) { transmit bytes[k] and times[k] }
    }  // forever
} // main

Important details have been left as an exercise for the reader.

 

I noticed PINA used multiple times in the ISR.

Probably a bad idea.

Each instance represents a separate fetch.

They do not have to all yield the same value.

Annoying inconsistencies are possible.

 

Also, "transmit_uchar" suggests a time-consuming function.

Not usually good in an ISR.

 

Edit: fixed loop to avoid array overrun

Iluvatar is the better part of Valar.

Last Edited: Mon. Sep 28, 2015 - 05:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good Morning to all!

 

Google 'soundcard oscilloscope'
You'll find out all about it

Yes, i have found a lot of projects about suondcard oscilloscope, the simplest for me is this: http://www.instructables.com/id/Use-Your-Laptop-as-Oscilloscope/?ALLSTEPS 

 

Hi Who-me, thank you so much for the reply!

Sounds like either your sensors are interacting, or your interrupts are.

One way to check which, would be to use a separate MCU for each sensor, and  if that allows you free orientation with no issues, then your software can be tuned.

If that fails, then no matter what you do in SW, the design has fundamental flaws.

I not have idea what is the problem. Starting of the result of my test, it seem that the sensors, in the while loop, do not read correctly the falling edge of the echo for each loop. 
Most of time they read always only the rising edge, this is strange for me. Now i try with soundcard oscilloscope to try to see what happens, in the negative case i think to use a bobgardner approach.

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

Hi skeeve, thank you so much for the reply!

 

I noticed PINA used multiple times in the ISR.

Probably a bad idea.

Each instance represents a separate fetch.

They do not have to all yield the same value.

Annoying inconsistencies are possible.

 

Also, "transmit_uchar" suggests a time-consuming function.

Not usually good in an ISR.

You are right, but how i can do? I need the PINA to select the pins receiving the echo signals.
However your reasoning make sense for me, because the correct flow of the ISR depend of the value of the PINA. If PINA have a wrong value, then the ISR does not  works well!
From my test, I obtain a sequence on which the falling edge missing sometimes! Probably the incorrect value of PINA creates this inconsistency.

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

Read PINA once into a variable.

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

Hi Kartman, i have try the sound card oscilloscope, but it don't works well.

Now i will try using the software, like advice of skevee and you..

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

Hi to all!

 

I have done some experiments in these days. First of all i have double checked the hardware and it work fine. Using my lib for one HC-SR04, all the sensors work.
 
Second, i have implemented the skevee's methods, maybe i don't see the important details, but the results are difficult to me to understand!
However this is the program that i done, i hope that is correct!

 

int main(void)
{
	//intialize
	InitUART(BAUD_115200_2x_16MHZ,EN_2X);
	
	// set echo pin as input
	DDRA  = 0x00;
	PORTA =  ( (1<<ECHO_1) );//| (1<<ECHO_2) | (1<<ECHO_3)  | (1<<ECHO_4) ); // pull-up on
	
	// set trig pin as output
	DDRC |= (1<<TRIG);
	PORTC &= ~(1<<TRIG);  // pull-up off
	
	//PCMSK0 |= (1<<PCINT3) | (1<<PCINT4) | (1<<PCINT5) | (1<<PCINT6); // enable single pin change interrupt
	//PCICR = (1<<PCIE0);                                              // enable PCINT0 interrupt
	
	unsigned char oldbyte;
	unsigned char bytes[8] = {0};
	unsigned char times[8] = {0};
	
	
	while(1) {
		
		oldbyte=PINA;
		bytes[0]=oldbyte;
		times[0]=0;
		
		//send trigger
		PORTC |= (1<<TRIG);  // low to high
		_delay_us(12);
		PORTC &= ~(1<<TRIG); // high to low		
		
		unsigned char byte;
		unsigned long t;
		unsigned char j=1;
		
		for(t=0; t< 1000000; ++t) {
			
			byte=PINA;          // read PINA
			
			if(byte != oldbyte) // there is a change in PINA?
			{ 
				bytes[j]=byte;  // store the PINA change
				times[j]=t;     // store time
				++j;            // increase number occurrence
				oldbyte=byte;   // new oldbyte 
			}
		}  // t

		//transmit j;
		transmit_uchar(j);
		
		unsigned char k;
		for(k=0; k<j; ++k) 
		{ 
			//transmit bytes[k] and times[k] 
			transmit_uchar(bytes[k]);
			transmit_uchar(times[k]);
		}
		
		_delay_ms(50);
	}  // forever
} // main

 

I have bought a usb soundcard, so the "poor man" oscilloscope now it works!
Using the visual analyzer program i see the echo pulse from the sensor.

 

After some test, i tried to using only one sensor, using the PCINT method and the problem seem to be the recognition of the rising edges and falling edges.
I have done some test, using a couple of ISR routine:

 

ISR(PCINT0_vect)
{
    unsigned char actual_bits = PINA;
    unsigned char changed_bits = actual_bits ^ port_history;
    port_history = actual_bits;
	
		
	if ( changed_bits & (1 << ECHO_1) ) // change on the pin echo_1
	{
		PORTC ^= (1<<1);
	}
}

with this routine i see the led blinking, and using the oscilloscope, I see the pulse come out of the pins of PORTC.

 

However, if i use this routine:

 

ISR(PCINT0_vect)
{
    unsigned char actual_bits = PINA;
    unsigned char changed_bits = actual_bits ^ port_history;
    port_history = actual_bits;
	
		
	if ( changed_bits & (1 << ECHO_1) ) // change on the pin echo_1
	{
		if ( !(actual_bits & (1<<ECHO_1)) )// rising edge change
		{
			PORTC |= (1<<1);
		}
		else if ( (actual_bits & (1<<ECHO_1)) )// falling edge change
		{
			PORTC &= ~(1<<1);
		}
	}
}

the led blink only when i power on the STK500, and after it is off forever.

In this case, the oscilloscope doesn't help, because i don't see anything on the screen.

 

My question is, why this last routine doesn't work? Is the code that is wrong or is something that i don't know?

I have read many times the datasheet and the application note AVR1200 and I seem to have did everything it says, then where am I wrong?

Last Edited: Mon. Sep 28, 2015 - 11:51 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It seems to me that if the first ISR in #20 causes an LED to blink, the second should also.

Are there unshown differences?

 

Also, my code was likely to cause an array overrun.

'Twill be changed shortly.

Iluvatar is the better part of Valar.

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

What happens if you change:

		
	if ( changed_bits & (1 << ECHO_1) ) // change on the pin echo_1
	{
		if ( !(actual_bits & (1<<ECHO_1)) )// rising edge change
		{
			PORTC |= (1<<1);
		}
		else if ( (actual_bits & (1<<ECHO_1)) )// falling edge change
		{
			PORTC &= ~(1<<1);
		}
	}

to

		
	if ( changed_bits & (1 << ECHO_1) ) // change on the pin echo_1
	{
		if ( !(actual_bits & (1<<ECHO_1)) )// rising edge change
		{
			PORTC |= (1<<1);
		}
		else                               // falling edge change
		{
			PORTC &= ~(1<<1);
		}
	}

 

You might want to change the variables to volatile.

 

David

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

Hi skevee, David!

 

It seems to me that if the first ISR in #20 causes an LED to blink, the second should also.

Are there unshown differences?

 

Also, my code was likely to cause an array overrun.

'Twill be changed shortly.

 

After i check how to modify your code. The past few days, I tried it with 4 sensors, but the result isn't what i expect. I read the result using a Matlab script because if i run your code in the normal terminal (eg. bray terminal) is very difficult for me to read the result!

The difference is that in the first ISR, the led blinks forever, while in the second ISR the led blinks once after that i turn on the STK500 and after it turns off forever..
I'm sorry but I don't know why...

 

 What happens if you change:

I have tried, the result is that the led blinks once after i turn on the STK500 and after a few moments it stays on for all time.
The variable port_history it's declared as volatile, and also the others..

 

I have tried to read the PINA value in the main, using the first ISR:

int main(void)
{
    InitUART(BAUD_115200_2x_16MHZ,EN_2X);
    init_multi_sonar();
    
    sei();
    
    
    while(1)
    {
        sendMultiPulse();
        
        transmit_uchar(PINA);
        
        _delay_ms(50);
    }
}

ISR(PCINT0_vect)
{
    unsigned char actual_bit = PINA;
    unsigned char changed_bits = actual_bit ^ port_history;
    port_history = actual_bit;
    
        
    if ( changed_bits & (1 << ECHO_1) ) // change on the pin echo_1
    {
        PORTC ^= (1<<1);
    }
}

ISR(TIMER0_COMPA_vect) // resolution of 29[us]
{	
    if (sonar_counter >= MAX_SONAR_COUNT)
    {
        TCCR0B = 0x00; // stop timer-counter0
        
        invalid_measure = 1;
    }
    else
    {
        sonar_counter++;   // increase the counter of 29[us]
    }	
    
}

void sendMultiPulse(void)
{
    TCCR0B = 0x0; // stop timer
    TCNT0 = 0x0;  // reset timer	
    
    DDRA &= ~(1<<ECHO_1);
    PORTA |=  (1<<ECHO_1);   // pull-up on  --> uscita a 1
    
    PCMSK0 |= (1<<PCINT3);// enable single pin change interrupt
    
    sonar_counter  = 0;
    
    port_history   = 0xFF;
    
    echo_1_rising = 0;
    
    invalid_measure = 0;
    
    echo_1_complete = 0;
    
    // send a pulse of 12us (> 10us) on the pin C4
    PORTC |= (1<<TRIG);
    _delay_us(12);
    PORTC &= ~(1<<TRIG);
    
    PCICR = (1<<PCIE0);                   // enable PCINT0 interrupt
    
    TCCR0B =  (1<<CS01);                  // start timer-counter0 @FCPU/8
    
}

 

but the result confusing me a lot!

 

C0 C0 C0 40 40 40 40 40 40 40 
40 40 40 40 40 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 
....

In this case the led blink, but the value of PINA is not what I expect (0x08 and 0x00). I'm not able to explain why..

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

Hello to all!
I have read some post and articles about this problem, i think there are some serious problem using this way to solve my problem..

 

 

https://github.com/GreyGnome/EnableInterrupt/blob/master/Interrupt%20Timing.pdf

https://www.avrfreaks.net/forum/atmega88-pcint-question

 

I haven't much time, so i think to change my algorithm using another control loop with run using another frequency (8-10 Hz), so i can do one measure at time..

 

Thank you to all for the help! :)

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

Shouldn't the following be in your init_multi_sonar()?

    TCCR0B = 0x0; // stop timer
    TCNT0 = 0x0;  // reset timer 
    
    DDRA &= ~(1<<ECHO_1);
    PORTA |=  (1<<ECHO_1);   // pull-up on  --> uscita a 1
    
    PCMSK0 |= (1<<PCINT3);// enable single pin change interrupt
    
    sonar_counter  = 0;
    
    port_history   = 0xFF;
    
    echo_1_rising = 0;
    
    invalid_measure = 0;
    
    echo_1_complete = 0;

David

 

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

Hi David!

Yes, there is also in my init function. 

I have used the repetition because so have advised me on the forum some time ago, look at this:

https://www.avrfreaks.net/forum/hc-sr04-and-atmega-1284p-problem

 

In this post, I obtained a strange behavior of the sensor and it made me mad for a long time because i could not understand what the problem was. It was a software problem or a hardware problem?

In reality the software worked fine, the problem it was the cable. I done some test using a short ribbon cable, and the sensor it worked well, but when i put the sensor on my system it did not work.
I connected my system with my STK500 using a long cable, but non a ribbon cable, it was a scart cable (i had only this...). 
This cable did not create any problem with a MARG sensor and the ESC, but it created some problem with the sonar.

 

To find where was the problem, i had asked an help to the forum, so i used they advice to make my sonar driver.
At the time I have not solved the problem, I solve it quite by accident recently, and the problem it was the long cable.
Evidently the echo signal is modified in the cable and made me get erroneous measurements.

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

It looks like you are: resetting the port; sending a pulse; immediately sending the state of the port that detects the echo; and, while waiting 50mS,  detecting echoes in the ISR.

 

Is that what you a trying to do?

 

David 

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

Yes, more or less!

My idea is: reset the port, send a pulse, send the state of the port that detect the first edge (rising) of the echo, and after 50 ms repeat this steps.
I assume that the detecting the echo in the ISR is fast than the other operations 

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

Ciao Luca, 

 

As you are transmitting the PINA state immediately after the pulse the echo is unlikely and you won't see it - I presume the state was C0 C0 C0 40 40 ... I don't know what else is on Port A and I presume from your comment you were expecting C0 C0 C8 48 40... or similar.

 

David  

 

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

Ciao David! :)

 

Your comment confuse me! But maybe it's a good thing!

I have this setting on the portA:

 

    #define ECHO_1 3          // pin 3 of the portA is for the echo
    
    DDRA  &= ~(1<<ECHO_1);    // pinA.1 is input          
    PORTA |=  (1<<ECHO_1);    // pull-up on

and on the portA there are only the connector for the echo.

 

So if i read the PINA register i expect this value 0x08 that is the default value of the PINA (because there are the pullup on).
This value correspond to the state low (inverse logic) and the value 0x00 correspond to the state high.  
This is that i know! But this argument is not very clear to me...
Following this logic, if i run this code

 

#define TRIG 4 // pinC.4 is the trigger

int main(void)
{
    InitUART(BAUD_115200_2x_16MHZ,EN_2X);
    init_multi_sonar();
    
    sei();
    
    while(1)
    {
        sendMultiPulse();
        
        transmit_uchar(PINA);
        
    }
}

void init_multi_sonar(void)
{
	
	/***** init IO *****/
	// set pin echo as input
	DDRA &= ~(1<<ECHO_1);              
	PORTA |=  (1<<ECHO_1);   // pull-up on  --> uscita a 1
	// set pin trig as output, pin 1 for the led
	DDRC |= (1<<TRIG) | (1<<1);                
	PORTC &= ~(1<<TRIG);   // pull-up off  --> uscita a zero
	/*******************/

	/***** init External Interrupt *****/
	//see sendMultiPulse()
	/***********************************/
	
	/***** init timer counter *****/
	TCCR0A = (1<<WGM01);    // set timer0 in CTC mode
	OCR0A = 0x39;           // set timer0 resolution @ 29[us]
	TIMSK0 = (1<<OCIE0A);   // abilito il timer0 compare match interrupt
	/******************************/	
}

void sendMultiPulse(void)
{
    TCCR0B = 0x0; // stop timer
    TCNT0 = 0x0;  // reset timer	
    
    DDRA &= ~(1<<ECHO_1);
    PORTA |=  (1<<ECHO_1);   // pull-up on  --> uscita a 1
    
    PCMSK0 |= (1<<PCINT3);// enable single pin change interrupt
    
    sonar_counter  = 0;
    
    port_history   = 0xFF;
    
    echo_1_rising = 0;
    
    invalid_measure = 0;
    
    echo_1_complete = 0;
    
    // send a pulse of 12us (> 10us) on the pin C4
    PORTC |= (1<<TRIG);
    _delay_us(12);
    PORTC &= ~(1<<TRIG);
    
    PCICR = (1<<PCIE0);                   // enable PCINT0 interrupt
    
    TCCR0B =  (1<<CS01);                  // start timer-counter0 @FCPU/8
    
}

I'm expect to read only the value of 0x00, or i'm wrong?

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

Ciao Luca,

 

Are you sure you have nothing else connected to Port A?  Do you have a debugger - that would help if you don't have a logic analyser or 'scope. 

 

David

 

 

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

Ciao David! 

Yes, i'm sure! I think that the problem are the float pin that don't have all the pullup on:

            	PORTA |=  (1<<ECHO_1);  // pull-up on  --> uscita a 1

 

maybe i should use this code:

 

    PORTA =  0xFF;  // pull-up on  --> uscita a 1

 

However, i have changed my algorithm. Now i use one PCINT for each sensor (one trig and one echo for each sensor).  It works!  :)

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

Ciao Luca,

 

Glad to hear you have it working.

 

Gruss vom Zurich,

 

David