<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=4&amp;t=9599&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-12-08T22:41:32+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=9599&amp;mode</id>
<entry>
<author><name><![CDATA[piotrek_194]]></name></author>
<updated>2014-12-08T22:41:32+01:00</updated>
<published>2014-12-08T22:41:32+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9599&amp;p=107880#p107880</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9599&amp;p=107880#p107880"/>
<title type="html"><![CDATA[Pomiar odległości HC-SR04 - niedokładność wyników]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9599&amp;p=107880#p107880"><![CDATA[
Witam! Na podstawie kodu użytkownika SunRiver  z tematu:http://forum.atnel.pl/topic2655.html stworzyłem taki oto kod do obsługi czujnika HC_SR04:<br />[syntax=c]/*<br /> * main.c<br /> *<br /> *  Created on: 06-12-2014<br /> *      Author: Piotrek<br /> */<br /><br /><br />#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br /><br />#include &quot;lcd44780.h&quot;<br /><br />#define ECHO_PORT D<br />#define ECHO_NUM 3<br />#define TRIG_PORT C<br />#define TRIG_NUM 1<br />#define DIODA_PORT C<br />#define DIODA_NUM 4<br /><br />#define ICP_PIN (1&lt;&lt;PB0)<br /><br />#define ICP_DIR DDRB<br />#define ICP_PORT PORTB<br /><br />// Makra preprocesora<br />#define PORT(x) SPORT(x)<br />#define SPORT(x) (PORT##x)<br />#define DDR(x) SDDR(x)<br />#define SDDR(x) (DDR##x)<br /><br />#define DELAY_BETWEEN_TESTS_MS 50<br /><br />void trig_on(void);<br /><br />volatile uint8_t trig_processing = 0;<br />volatile uint8_t slope_detection = 0;<br />volatile unsigned long  distance = 0;<br />volatile unsigned long  distance_ICP = 0;<br />volatile uint32_t pulse_width_us = 0;<br />volatile uint32_t counter_ovf = 0;<br />volatile uint16_t PulseWidth;<br /><br />int main(void)<br />{<br />lcd_init();<br />lcd_cls();<br /><br /><br />// Ustawienie kierunków pinów: ECHO (wej.), TRIG(wyj)<br />DDR(ECHO_PORT) &amp;= ~(1&lt;&lt;ECHO_NUM);<br />DDR(TRIG_PORT) |= (1&lt;&lt;TRIG_NUM);<br /><br />DDR(DIODA_PORT) |= (1&lt;&lt;DIODA_NUM);<br />PORT(DIODA_PORT) |= (1&lt;&lt;DIODA_NUM);<br /><br />// Domyślnie 0 na pinie TRIG<br />PORT(TRIG_PORT) &amp;= ~(1&lt;&lt;TRIG_NUM);<br />PORT(ECHO_PORT) &amp;= ~(1&lt;&lt;ECHO_NUM);<br /><br />// Konfiguracja przerwania INT1<br />EICRA |= (0&lt;&lt;ISC11) | (1&lt;&lt;ISC10); // dowolna zmiana na pinie INT1 gen. przerwanie<br />EIMSK |= (1&lt;&lt;INT1); // INT1 - enabled<br /><br />// Konfiguracja Timer0 w trybie NormalMode<br />TCCR0A |= (0&lt;&lt;WGM01) | (0&lt;&lt;WGM00); // wybór trybuNormalMode<br />TCCR0B |= (0&lt;&lt;WGM02); // wybór trybu NormalMode<br />TCCR0B |= (0&lt;&lt;CS02) | (0&lt;&lt;CS01) | (1&lt;&lt;CS00); // preskaler = 1<br />TIMSK0 |= (1&lt;&lt;TOIE0); // odblokowanie przerwania od przepełnienia<br />TCNT0 = 0; // początkowa wartość licznika<br /><br />// Konfiguracja przerwania ICP<br />// KONFIGURACJA PRACY PRZERWANIA ICP I TIMERA1<br />TCCR1B = (1&lt;&lt;CS10);// ustawienie preskalera dla Timer1 = 1<br />TCCR1B &amp;= ~(1&lt;&lt;ICES1);// reakcja na zbocze opadające<br />TIMSK1 |= (1&lt;&lt;ICIE1);// odblokowanie przerwania ICP<br /><br />sei(); // globalne odblokowanie przerwań<br /><br /><br />int numDelays = 0;<br /><br />while(1)<br />{<br />lcd_cls();<br />lcd_locate(0,0);<br />lcd_int(distance);<br />lcd_locate(0,3);<br />lcd_str(&quot;mm&quot;);<br />lcd_locate(0,7);<br />lcd_int(distance_ICP);<br />lcd_locate(0,10);<br />lcd_str(&quot;mm&quot;);<br />lcd_locate(1,0);<br />lcd_int(pulse_width_us);<br />lcd_locate(1,4);<br />lcd_str(&quot;us&quot;);<br />lcd_locate(1,7);<br />lcd_int(PulseWidth);<br />lcd_locate(1,11);<br />lcd_str(&quot;us&quot;);<br />_delay_ms(10);<br /><br />if(slope_detection == 0)<br />{<br /><br />// opóżnienie licznika<br />_delay_ms(1);<br />numDelays++;<br />if (numDelays &gt; DELAY_BETWEEN_TESTS_MS)<br />            {<br /><br /> trig_on(); // pomiar<br /> numDelays = 0;<br />            }<br /><br /><br />}<br />}<br /><br /><br />}<br /><br />// Procedura obsługi przerwania od ICP<br />ISR(TIMER1_CAPT_vect)<br />{<br />static uint16_t LastCapture;<br /><br />    if( !(TCCR1B &amp; (1&lt;&lt;ICES1)) ) PulseWidth = ICR1 - LastCapture;<br />    LastCapture = ICR1;<br /><br />    TCCR1B ^= (1&lt;&lt;ICES1); //zmiana zbocza<br />}<br /><br />// Procedura obsługi przerwania od sygnału ECHO na INT1<br />ISR(INT1_vect)<br />{<br />if(trig_processing) // obsługujemy przerwanie tylko gdy wysłano sygnał wyzwalajacy czujnik<br />{<br />if(slope_detection == 0) // zbocze narastające - START<br />{<br /><br /><br />slope_detection = 1; // kolejne wykryte zbocze będzie oznaczać koniec pomiaru<br />// zerowanie naszych liczników<br />counter_ovf = 0;<br />TCNT0 = 0;<br />}<br />else<br />{<br />slope_detection = 0; // KONIEC pomiaru<br /><br /><br />// obliczanie wyniku<br />                distance = (counter_ovf * 256 + TCNT0) / 58;<br />                distance_ICP = PulseWidth/58;<br />pulse_width_us = (counter_ovf * 256 + TCNT0);<br />trig_processing = 0;<br />}<br />}<br /><br /><br />}<br />// Procedura obsługi przerwania od przepełnienia Timer0<br />ISR(TIMER0_OVF_vect)<br />{<br /> if (slope_detection)<br /> {<br /><br />   counter_ovf++; // zwiekaszanie licznika<br /><br /><br />  }<br /><br />}<br />void trig_on(void)<br />{<br />PORT(TRIG_PORT) &amp;= ~(1&lt;&lt;TRIG_NUM); // stan niski na TRIG<br />_delay_us(1);<br />PORT(TRIG_PORT) |= (1&lt;&lt;TRIG_NUM); // wystawienie stanu wysokiego na TRIG<br />trig_processing = 1; // start pomiaru (wyzwolenie czujnika)<br />_delay_us(10); // odczekaj 10us<br />PORT(TRIG_PORT) &amp;= ~(1&lt;&lt;TRIG_NUM); // stan niski na TRIG<br /><br />}[/syntax]<br />Niestety pomiary są dość niedokładne (dla obiektu oddalonego od czujnika o 150mm wskazanie pomiaru wynosi 125mm, zarówno przy mierzeniu czasu trwania impulsu przy pomocy INT1 jak i ICP), co widać na poniższym zdjęciu. Z tego co wyczytałem w innych tematach tutaj na forum, przy małych odległościach wykrywanego obiektu czujniki charakteryzują się bardzo dobrą dokładnością. Stąd moje pytanie: czy coś z moim kodem jest nie tak, że uzyskuję aż tak dużą niedokładność?<br /><a href="http://forum.atnel.pl/_obrazki/o/3505/04771d8b39a390d7f9d86fdc50f70e08.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/3505/04771d8b39a390d7f9d86fdc50f70e08.jpg" alt="Obrazek" /></a><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3505">piotrek_194</a> — 8 gru 2014, o 22:41</p><hr />
]]></content>
</entry>
</feed>