<?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=58&amp;t=9299&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-11-23T17:48:31+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=58&amp;t=9299&amp;mode</id>
<entry>
<author><name><![CDATA[apollo1412]]></name></author>
<updated>2014-11-23T17:48:31+01:00</updated>
<published>2014-11-23T17:48:31+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=105618#p105618</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=105618#p105618"/>
<title type="html"><![CDATA[Re: ATMEGA328p-pu błędny pomiar ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=105618#p105618"><![CDATA[
Problem z piszczeniem ustąpił po przeniesieniu funkcji pomiar z przerwania do głównej pętli - może procek nie wyrabiał.<br /><br />Co to potencjometru to chyba źle się wyraziłem. Silnik przestaję się kręcić przy poniżej wypełnienia 150 (przy podzieleniu wyniku ADC na 4, tak żeby dostosować do zakresu PWM od 0-255) przy pomiarze z potencjometru, natomiast przy ustawieniu na sztywno PWM_akt = 30 kręci się. Dodatkowo jeżeli wyniki pomiarów podzielę np. nie na 4 jak tu:<br />[syntax=cpp]wynik = pomiar ( PC5 );<br />wynik=wynik/4;[/syntax]<br />a na 16 tak aby wynik był z przedziału 0-63 to silnik przestaje działać przy wartości 12. <br />Może sposób pomiaru jest jednak nie właściwy? Nie zależnie jak ustawię skalowanie wyniku potencjometru, silnik przestaje się kręcić jeżeli skręcę potencjometr mniej więcej od 1/3 zakresu w dół.<br /><br />Dlatego myślę że to nie chodzi o częstotliwość PWM, bo ustawienie na sztywno wartości w PWM_akt działa.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5890">apollo1412</a> — 23 lis 2014, o 17:48</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[ryba84]]></name></author>
<updated>2014-11-21T09:36:17+01:00</updated>
<published>2014-11-21T09:36:17+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=105266#p105266</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=105266#p105266"/>
<title type="html"><![CDATA[Re: ATMEGA328p-pu błędny pomiar ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=105266#p105266"><![CDATA[
Na piszczenie pomoże podniesienie częstotliwości PWM poza pasmo akustyczne, ale silnik nie będzie Ci się kręcił przy niskim wypełnieniu i wysokiej częstotliwości PWM. Tutaj jeśli chcesz, żeby pracował w szerszym zakresie wypełnienia to zmniejsz częstotliwość PWM, no i znów silnik będzie się odzywał(im niższa częstotliwość tym grubszym głosem). Musisz wybrać co bardziej Ci odpowiada.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3170">ryba84</a> — 21 lis 2014, o 09:36</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[apollo1412]]></name></author>
<updated>2014-11-19T19:03:43+01:00</updated>
<published>2014-11-19T19:03:43+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104966#p104966</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104966#p104966"/>
<title type="html"><![CDATA[Re: ATMEGA328p-pu błędny pomiar ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104966#p104966"><![CDATA[
coś znalazłem:<br />zamieniłem te dwie linijki:<br />[syntax=cpp]DDRC|= (1&lt;&lt;PC5) | (1&lt;&lt;PC4);//wyjście LED<br />PORTC|= (1&lt;&lt;PC5) | (1&lt;&lt;PC4);//zgaś diody, bo są zapalane zerem[/syntax]<br /><br />na te:<br />[syntax=cpp]DDRC&amp;= ~(1&lt;&lt;PC5); //wyjcie potencjometru<br />DDRC |= (1&lt;&lt;PC4);//wyjście LED<br />PORTC&amp;= ~(1&lt;&lt;PC5);<br />PORTC |= (1&lt;&lt;PC4);//zgaś diody, bo są zapalane zerem[/syntax]<br /><br />i pomiar jest ok. Pod PC5 mam potencjomert właśnie.<br />Ale pojawił się inny. Silnik działa dobrze pomiędzy wartościami 130-255, poniżej takich się nie kręci, ale uwaga ! nawet jak nie używam zmiennej wynik jako wypełnienie PWM (!)<br />Do tego jest teraz nieco głośniejszy - troszkę piszczy, można temu zaradzić?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5890">apollo1412</a> — 19 lis 2014, o 19:03</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[apollo1412]]></name></author>
<updated>2014-11-19T13:40:32+01:00</updated>
<published>2014-11-19T13:40:32+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104882#p104882</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104882#p104882"/>
<title type="html"><![CDATA[Re: ATMEGA328p-pu błędny pomiar ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104882#p104882"><![CDATA[
Funkcja<br />[syntax=cpp]uint16_t pomiar (uint8_t kanal)[/syntax]<br />zapewnia jednokkrotny pomiar ADC.<br />ponowne przywrócenie multipleksera było zrealizowane za pomocą<br />[syntax=cpp]ADCSRA &amp;= ~(1&lt;&lt;ADEN); //wyłącz ADC[/syntax]<br />silnik się kręcił dalej, więc przerwania działały dobrze.<br /><br />No dobrze, poprawiłem kod i zmieniłem trochę koncepcję. Teraz pomiar nie będzie realizowany w przerwaniu, ale w pętli głównej, zaraz po tym jak nastąpi przerwanie od pierwszej komutacji o czym inforumuje<br />[syntax=cpp]bldc_polozenie_wirnika == KOMUT_1[/syntax] <br /><br />Tera program main w którym odbywa się pomiar:<br />[syntax=cpp]/*<br /><br />Sterownik silnika BLDC.<br />Sterowanie silnikiem z wykorzystaniem Back-EMF.<br /><br />Częstotliwość F_CPU: 8MHz (ustaw w opcjach projektu)<br /><br />Szczegóły: http://mikrokontrolery.blogspot.com/2011/03/silnik-bldc-sterownik-back-emf.html<br /><br />2013 Dondu<br /><br />*/<br /><br /><br />#include &quot;avr/io.h&quot;<br />#include &lt;util/delay.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &quot;bldc.h&quot;<br />#include &quot;myuart.h&quot;<br /><br />#define SR 8<br /><br />typedef struct vol {<br />uint16_t adc_mid;<br />uint16_t ref_adc;<br />uint16_t ref_v;<br />char v1&#91;3&#93;;<br />char v2&#91;3&#93;;<br />}TVOL;<br /><br />TVOL accu1_vol;<br /><br />#define REF_VCC (1&lt;&lt;REFS0)<br /><br />uint16_t pomiar (uint8_t kanal);<br />void get_vol (uint16_t adc, TVOL * voltage);<br />volatile uint16_t  wynik=0;<br /><br />//------------------------------------------------------------------<br /><br />int main (void)<br />{<br />uart_init ( __UBRR );<br />uart_puts(&quot;gthfhfth&quot;);<br />//zmienne potrzebne do przykładu zmiany prędkości<br />//patrz pętla główna while() poniżej<br />unsigned char PWM_akt;<br />//unsigned char PWM_kier = 1;   //kierunek zmiany prędkości<br />//0 - zmniejszanie<br />//1 - zwiększanie<br /><br /><br />//diody testowe<br />DDRC|= (1&lt;&lt;PC5) | (1&lt;&lt;PC4);//wyjście LED<br />PORTC|= (1&lt;&lt;PC5) | (1&lt;&lt;PC4);//zgaś diody, bo są zapalane zerem<br /><br /><br />//opóźnienie na ustabilizowanie zasilania (można usunąć)<br />//_delay_ms(1000);<br /><br />//inicjujemy sterownik<br />bldc_inicjuj_sterownik();<br /><br /><br />//Przerwania globalne włącz<br />sei();<br /><br />//Start silnika<br />bldc_start();<br /><br />//odczytaj aktualnie ustawione PWM (dla potrzeb przykładu poniżej)<br />PWM_akt = 100;<br />tr_cls(0); //czyszczenie ekranu do UART<br />//pętla główna<br />while(1){<br /><br /><br />//... tutaj dowolny Twój program<br /><br /><br />//--- PRZYKŁAD ------------------------<br />//Przykład funkcji zmieniającej prędkość obrotów silnika<br />//tylko wtedy, gdy sterownik już rozkręcił silnik i przeszedł<br />//w tyb pracy<br /><br />//Aby przykład działał usuń na początku main() komentarze<br />//dla deklaracji zmiennych PWM_akt oraz PWM_kier<br /><br />if(bldc_tryb_pracy== TRYB_PRACA){<br /><br />//PWM_akt += skok_PWM;<br /><br />//if(PWM_kier) PWM_akt++;<br />//else PWM_akt--;<br /><br /><br />//sprawdzamy, czy osiągnęliśmy próg prędkości maksymalnej<br />//if(PWM_akt &gt;254) PWM_kier = 0; //od teraz zmniejszamy obroty<br /><br />//sprawdzamy, czy osiągnęliśmy próg prędkości minimalnej<br />//if(PWM_akt &lt;40)PWM_kier = 1; //od teraz zwiększamy obroty<br />//PWM_akt=30;<br />//OCR0A=PWM_akt;<br /><br />PWM_akt=150; // z góry ustalam wypełnienie PWM<br />       //ustaw aktualne PWM w celu regulacji prędkości<br />OCR0B=PWM_akt;<br />OCR1A=PWM_akt;<br />OCR1B=PWM_akt;<br />OCR2A=PWM_akt;<br />OCR2B=PWM_akt;<br />//dla testów, opóźnienie zmian prędkości<br /><br />//POMIAR ADC Z POTENCJOMETRU przeprowadzany przy pierwszej komutacji<br />if(bldc_polozenie_wirnika == KOMUT_1){<br />//inicjalizacja ADC<br />ADCSRA |= (1&lt;&lt;ADPS2)|(1&lt;&lt;ADPS1)|(1&lt;&lt;ADPS0); //preskaler 128 8000000/168<br />ADMUX |= REF_VCC; //ust. źródło odniesienia 5 V<br />ADCSRA |= (1&lt;&lt;ADEN); //włącz ADC<br />accu1_vol.ref_adc = 548;<br />accu1_vol.ref_v = 141;<br /><br />wynik = pomiar ( PC5 );<br />wynik=wynik/4;<br /><br />tr_locate(3,3);<br />uart_putlong(wynik,10); //wywietlanie wyniu z pomiaru<br /><br />ADCSRA &amp;= ~(1&lt;&lt;ADEN); //wyącz ADC<br />}<br />_delay_ms(100);<br /><br />}<br />//--- PRZYKŁAD - Koniec -------------<br /><br /><br />//... tutaj dowolny Twój program<br /><br /><br />}<br />}<br /><br />uint16_t pomiar (uint8_t kanal) {<br />ADMUX = (ADMUX &amp; 0b11111000) | kanal;<br />ADCSRA |= (1&lt;&lt;ADSC); //start konwersji<br />while ( ADCSRA &amp; (1&lt;&lt;ADSC) ) ;<br />return ADCW;<br />}<br /><br />void get_vol (uint16_t adc, TVOL * voltage) {<br /><br />static uint16_t sr&#91;SR&#93;;<br />static uint8_t idx;<br />uint32_t sr1=0;<br />uint8_t i;<br /><br />sr&#91; idx++ &amp; (SR-1) &#93; = adc;<br />//sr&#91;idx&#93;=adc;<br />//idx++;<br />//if(idx&gt;7) idx=0;<br />//if( idx &amp; (SR-1) ) return;<br />for ( i=0; i&lt;SR; i++) sr1+=sr&#91;i&#93;;<br />sr1 /=SR;<br /><br />voltage-&gt;adc_mid =sr1;<br /><br /><br />uint16_t wynik = (sr1 * (uint32_t) voltage-&gt;ref_v ) / voltage-&gt;ref_adc;<br />div_t divmod = div(wynik,100 );<br />itoa( divmod.quot, voltage-&gt;v1, 10 );<br />itoa( divmod.rem, voltage-&gt;v2, 10 );<br />if (divmod.rem &lt;10) {<br />voltage-&gt;v2&#91;0&#93;='0';<br />voltage-&gt;v2&#91;1&#93;=divmod.rem+'0';<br />}<br /><br />}[/syntax]<br /><br />Program bldc.c gdzie są przerwania <br />[syntax=cpp]/*<br /><br />Sterownik silnika BLDC.<br />Sterowanie silnikiem z wykorzystaniem Back-EMF.<br /><br />Częstotliwość F_CPU: 8MHz (ustaw w opcjach projektu)<br /><br />Szczegóły: http://mikrokontrolery.blogspot.com/2011/03/silnik-bldc-sterownik-back-emf.html<br /><br />2013 Dondu<br /><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 />#include &lt;stdlib.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &quot;bldc.h&quot;<br /><br />volatile unsigned charbldc_polozenie_wirnika = KOMUT_1;<br />volatile unsigned char bldc_tryb_pracy;   //aktualny tryb pracy<br />volatile unsigned int  bldc_komp_licznik; //licznik przerwań komparatora<br /><br /><br /><br />//--------------------------------------------------------------------<br /><br />void bldc_bezpiecznik_stop(void){<br /><br />//Funkcja wyłącza wszelkie tranzystory oraz przechodzi w stan sygnalizacji<br />//błędu komutacji. Funkcja ta razem z funkcją bezpiecznik() pełni rolę<br />//zabezpieczenia przeciwzwarciowego dla błędnie działającego algorytmu<br />//komutacji w czasie pisania i testów programu.<br /><br />//wyłącz przerwania<br />cli();<br /><br />//natychmiast wyłącz tranzystory<br />WYLACZ_TRANZYSTORY<br /><br />//i ustaw stany niskie na pinach sterujących<br />U_TR_G_USTAW_DDR<br />V_TR_G_USTAW_DDR<br />W_TR_G_USTAW_DDR<br />U_TR_D_USTAW_DDR<br />V_TR_D_USTAW_DDR<br />W_TR_D_USTAW_DDR<br />U_TR_G_PIN_L<br />V_TR_G_PIN_L<br />W_TR_G_PIN_L<br />U_TR_D_PIN_L<br />V_TR_D_PIN_L<br />W_TR_D_PIN_L<br /><br />//ustaw pin LED jako wyjście<br />BEZP_LED_DDR|=(1&lt;&lt;BEZP_LED_PIN);<br /><br />//zatrzymaj program w pętli nieskończonej sygnalizując błąd<br />while(1){<br /><br />//zmień stan LED na przeciwny<br />BEZP_LED_PORT  ^= (1&lt;&lt;BEZP_LED_PIN);<br /><br />//co 100ms<br />_delay_ms(100);<br /><br />}<br />}<br /><br /><br />//------------------------------------------------------------------<br /><br />void bldc_bezpiecznik(void){<br /><br />//Sprawdzamy, czy nie występuje konflikt sterowania, powodujący<br />//jednoczene otwarcie tranzystora górnego i dolnego w tej samej fazie,<br />//co oznacza wystąpienie zwarcia !!!<br /><br />if(U_TR_G_SPRAW_STAN &amp;&amp; U_TR_D_SPRAW_STAN){<br /><br />//Faza U - oba tranzystory są włączone - sytuacja niedopuszczalna!!!<br />bldc_bezpiecznik_stop();<br /><br /><br />}else if(V_TR_G_SPRAW_STAN &amp;&amp; V_TR_D_SPRAW_STAN){<br /><br />//Faza V - oba tranzystory są włączone - sytuacja niedopuszczalna!!!<br />bldc_bezpiecznik_stop();<br /><br /><br />}else if(W_TR_G_SPRAW_STAN &amp;&amp; W_TR_D_SPRAW_STAN){<br /><br />//Faza W - oba tranzystory są włączone - sytuacja niedopuszczalna!!!<br />bldc_bezpiecznik_stop();<br /><br />}<br /><br />}<br /><br /><br /><br />//-----------------------------------------------------------<br /><br /><br />void bldc_inicjuj_sterownik(void){<br /><br />//Funkcja inicjująca pracę sterownika.<br />//-konfiguruje wszystkie wykorzystywane moduły mikrokontrolera<br />//-ustawia piny mikrokontrolera tak, by wszystkie tranzystory<br />// były wyłączone<br />//-ustawia licznikia PWM na początkową wartość DutyCycle<br /><br />//ustaw stan początkowy wyjść sterujących tranzystorami<br />U_TR_G_USTAW_DDR<br />V_TR_G_USTAW_DDR<br />W_TR_G_USTAW_DDR<br />U_TR_D_USTAW_DDR<br />V_TR_D_USTAW_DDR<br />W_TR_D_USTAW_DDR<br />U_TR_G_PIN_L<br />V_TR_G_PIN_L<br />W_TR_G_PIN_L<br />U_TR_D_PIN_L<br />V_TR_D_PIN_L<br />W_TR_D_PIN_L<br /><br /><br /><br />//sprawdzamy, czy nie ma stanu zabronionego na tranzystorach<br />//ZAWSZE WYWOŁUJ TĘ FUNKCJĘ, GDY ZMIENIASZ STAN TRANZYSTORÓW!!!<br />bldc_bezpiecznik();<br /><br /><br /><br />//--- T I M E R Y    P W M   -------------------<br />//Timer0<br />//Obsługa PWM dla wyjść !!! BEZ OC0A !!! oraz OC0B<br />//Mode 5 (Fast PWM, 8bit)<br />//Clear OC0A/OC0B on Compare Match, set OC0A/OC0B at BOTTOM,<br />//(non-inverting mode)<br />//preskaler 1<br />TCCR0A|=(1&lt;&lt;WGM01) | (1&lt;&lt;WGM00) | (1&lt;&lt;COM0B1);<br />TCCR0B|=(1&lt;&lt;CS00);<br />//Timer1<br />//Obsługa PWM dla wyjść OC1A oraz OC1B<br />//Mode 5 (Fast PWM, 8bit)<br />//Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM,<br />//(non-inverting mode)<br />//preskaler 1<br />TCCR1A|=(1&lt;&lt;WGM12) | (1&lt;&lt;WGM10) | (1&lt;&lt;COM1A1) | (1&lt;&lt;COM1B1);<br />TCCR1B|=(1&lt;&lt;WGM12) | (1&lt;&lt;WGM10) | (1&lt;&lt;CS10);<br /><br /><br />//Timer2<br />//Obsługa PWM  dla wyjścia OC2<br />//Mode 3 (Fast PWM, 8bit)<br />//Clear OC2 on Compare Match, set OC2 at BOTTOM, (non-inverting mode)<br />//preskaler 1<br />TCCR2A|=(1&lt;&lt;WGM21) | (1&lt;&lt;WGM20)| (1&lt;&lt;COM2A1) | (0&lt;&lt;COM2B1);<br />TCCR2B  |=(1&lt;&lt;CS20) ;<br /><br />//--- K O M P A R A T O R ---<br />//Obsługuje wykrywanie położenia wirnika poprzez BEMF,<br />//czyli ustalanie momentów przejścia przez zero sygnałów sterujących<br />//przerwanie dla każdej zmiany wyjścia komparatora<br />//Przerwanie jest włączane w funkcji startującej silnik.<br />ADCSRB|= (1&lt;&lt;ACME);//włącz multiplekser wejść ujemnych komparatora<br /><br /><br />//ustaw wartość początkową PWM<br />OCR0B = PWM_MIN;<br />OCR1A = PWM_MIN;<br />OCR1B = PWM_MIN;<br />OCR2A = PWM_MIN;<br />OCR2B = PWM_MIN;<br />//na wszelki wypadek<br />WYLACZ_TRANZYSTORY<br />bldc_bezpiecznik();<br /><br />}<br /><br /><br /><br />//------------------------------------------------------------------<br /><br /><br /><br /><br />void bldc_start_delay_ms(unsigned char il_ms){<br /><br />//Funkcja opóźnienia o zmiennej wartości czasu<br /><br />while(il_ms){<br />_delay_ms(1);<br />il_ms--;<br />}<br />}<br /><br /><br />//-----------------------------------------------------------<br /><br />void bldc_start_komutacja(void){<br /><br />//Funkcja komutacji w czasie rozruchu silnika.<br />//nie zawiera obsługi BackEMF<br /><br />//zależnie od numeru aktualnej komutacji przełącza na następną<br />switch (bldc_polozenie_wirnika++){<br /><br />case (KOMUT_1)://komutacja 1<br />W_TR_G_OFF<br />U_TR_G_ON<br />break;<br /><br />case (KOMUT_2)://komutacja 2<br />V_TR_D_OFF<br />W_TR_D_ON<br />break;<br /><br />case (KOMUT_3)://komutacja 3<br />U_TR_G_OFF<br />V_TR_G_ON<br />break;<br /><br />case (KOMUT_4)://komutacja 4<br />W_TR_D_OFF<br />U_TR_D_ON<br />break;<br /><br />case (KOMUT_5)://komutacja 5<br />V_TR_G_OFF<br />W_TR_G_ON<br />break;<br /><br />case (KOMUT_6)://komutacja 6<br />U_TR_D_OFF<br />bldc_polozenie_wirnika = KOMUT_1; //komutacja od początku<br />V_TR_D_ON<br />break;<br /><br />}<br /><br />//sprawdzamy konflikty sterowania<br />bldc_bezpiecznik();<br />}<br /><br /><br /><br />//-----------------------------------------------------------<br /><br />void bldc_start(void){<br /><br />//Funkcja odpowiedzialna za:<br />//- ustawienie wirnika w pozycji początkowej<br />//- rozkręcenie silnika do momentu uzyskania odczytów BackMEF<br /><br />signed int i; //zmienna pomocnicza<br /><br />//wartości początkowe<br />bldc_tryb_pracy= TRYB_START;<br /><br /><br /><br />////RUSZAMY SILNIK<br />////Poniżej przykład kolejnych kroków, mających na celu ruszenie silnika<br />////z miejsca oraz rozkręcenie go do momentu w którym uzyskamy sygnał<br />////BackEMF. Po osiągnięciu odpowiedniej ilości przerwań z komparatora,<br />////uznajemy, że nadszedł moment w którym należy się przełączyć na<br />////sterowanie komutacjami z wykorzystaniem przerwań BackEMF (komparatora).<br />//<br />////UWAGA!<br />////W zależności od silnika należy dobrać doświadczalnie procedurę startu<br />//<br />//<br />//<br />////KROK 1<br />////Ustaw wirnik w pozycji startowej<br />//bldc_polozenie_wirnika= KOMUT_1;<br />U_TR_G_ON//włączamy wybraną parę tranzystorów<br />W_TR_D_ON<br />_delay_ms(300);<br />bldc_bezpiecznik();//sprawdzamy konflikty sterowania<br /><br />//<br />////odczekujemy oscylacje wirnika zmniejszając wypełnienie PWM<br />////tutaj możesz dostosować doświadczalnie parametry pozycjonowania silnika<br />////do bezwładności wirnika<br />for(i=100; i&gt;0; i-=5){<br /><br />//ustaw nowe PWM wykorzystując jawne rzutowanie http://mikrokontrolery.blogspot.com/2011/02/kurs-jezyka-c-rzutowanie-promocja-typow.html<br />OCR0B  = (unsigned char) i;<br />OCR1A = (unsigned char) i;<br />OCR1B = (unsigned char) i;<br />OCR2A  = (unsigned char) i;<br />OCR2B  = (unsigned char) i;<br />//opóźnienie<br />_delay_ms(100);<br />}<br />//<br />//<br />////KROK 2<br />////ruszamy silnik z miejsca<br />//<br />//początkowa wartość PWM dla startu silnika (regulacja prądu)<br />OCR0A = 254;<br />OCR1A = 254;<br />OCR1B = 254;<br />OCR2A = 254;<br />OCR2B = 254;<br />//<br />////rusz silnik z miejsca przełączając komutacje ze zmienjszającym się<br />////opóźnieniem, by osiągnąć początkową prędkość<br />for(i=40; i&gt;0; i-=1){<br />bldc_start_komutacja();//kolejna komutacja<br />bldc_start_delay_ms(50);//opóźnienie<br />}<br />for(i=80; i&gt;0; i-=1){<br />bldc_start_komutacja();//kolejna komutacja<br />bldc_start_delay_ms(30);//opóźnienie<br />}<br />//<br />////KROK 3<br />////zwiększaj dalej prędkość, ale mniejszymi krokami PWM<br />//for(i=60; i&gt;=10; i-=1){<br />//bldc_start_komutacja();//kolejna komutacja<br />//bldc_start_delay_ms(i);//opóźnienie<br />//<br />//}<br /><br />//<br />////KROK 4<br />////włącz przerwania z komparatora ponieważ już mogą być prawidłowe<br />////sygnały BEMF.<br />ACSR|= (1&lt;&lt;ACIE);<br />//<br />for(i=200; i&gt;0; i-=1){<br />bldc_start_komutacja();//kolejna komutacja<br />bldc_start_delay_ms(20);//opóźnienie<br /><br />////ustabilizuj obroty i czekaj na wykrycie odpowiedniej ilości przerwań<br />//for(i=0; i&lt;200; i++){<br />//<br />//bldc_start_komutacja(); //kolejna komutacja<br />//bldc_start_delay_ms(10); //opóźnienie<br /><br />//Przerwij, gdy wykryto już wystarczającą ilość przerwań z komparatora<br />//ilość impulsów zależy tylko od Ciebie - ja wybrałem 40<br />if(bldc_komp_licznik &gt; 80){<br /><br />//Wykryto odpowiednią ilość przerwań z sygnałów BackEMF<br />//uznajemy więc, że możemy przejść na sterowanie za pomocą<br />//przerwań z sygnałów BackEMF<br /><br />//ustaw tryb pracy i wróć do main()<br />bldc_tryb_pracy= TRYB_PRACA;<br />WYLACZ_TRANZYSTORY<br />DDRD |=(1&lt;&lt;PD2);<br />PORTD ^=(1&lt;&lt;PD2);<br />break;<br />}<br /><br />}<br /><br /><br />//KROK 5<br />//sprawdzamy, czy sterownik przełączył się na tryb pracy<br />if(bldc_tryb_pracy!= TRYB_PRACA){<br /><br />//Sterownik nie przełączył się, ponieważ pomimo wielu obrotów wirnika<br />//komparator nie wykrył założonej ilości impulsów sygnału BackEMF,<br />//stąd przerywamy procedurę startu.<br /><br />//Jeżeli sytuacja będzie się powtarzać, powinieneś zmienić parametry<br />//kroków 2, 3 i 4<br /><br />//wyłącz przerwania z komparatora<br />ACSR&amp;= ~(1&lt;&lt;ACIE);<br /><br />//wyłącz tranzystory<br />WYLACZ_TRANZYSTORY<br />bldc_bezpiecznik();<br /><br />}<br /><br />//wróć do main()<br /><br />}<br /><br /><br /><br />//-----------------------------------------------------------<br /><br /><br />ISR (ANALOG_COMP_vect)<br />{<br /><br />//Funkcja obsługi przerwania z komparatora wykrywającego punkty ZC<br />//funkcja zajmuje się wykryciem właściwego położenia wirnika<br />//oraz przełączeniem następnej komutacji<br /><br /><br />//DLA TESTÓW ZC możesz podłączyć do pinu PB0 oscyloskop i obserwować<br />//moment wykonania się przerwania. Wcześniej musisz ustawić<br />//pin PBO jako wyjście<br />//PORTB^=(1&lt;&lt;PB0);//zmień stan pinu na przeciwny<br /><br />//w zależności od trybu pracy sterownika<br />switch (bldc_tryb_pracy){<br /><br />//-------------------------------------------------<br /><br />case TRYB_START:<br />//Podczas trybu startu jedynie zliczaj wykryte przerwania<br />//z komparatora, czyli punkty ZC sygnału BackEMF<br />bldc_komp_licznik++;<br />break;<br /><br />//-------------------------------------------------<br /><br />case TRYB_PRACA:<br /><br />//tryb normalnej pracy czyli kręcenia silnikiem na podstawie<br />//wykrytych punktów ZC sygnałów BackEMF<br /><br />//w zależności od położenia wirnika (fakt wystąpienia przerwania<br />//oraz sprawdzenie stanu wyjścia komparatora)<br />switch (bldc_polozenie_wirnika)<br />{<br />case (KOMUT_1)://kąt 0 stopni<br />if(!KOMP_STAN_AKT)//gdy komparator = 0<br />{<br />W_TR_G_OFF//wyłącz tranzystor górny W<br />KOMP_KANAL_W;//włącz kanał fazy W<br />bldc_polozenie_wirnika = KOMUT_2; //następna komutacja<br />U_TR_G_ON//włącz tranzystor górny U<br />}<br />break;<br /><br />case (KOMUT_2)://kąt 60 stopni<br />if(KOMP_STAN_AKT)//gdy komparator = 1<br />{<br />V_TR_D_OFF//wyłącz tranzystor dolny V<br />KOMP_KANAL_V;//włącz kanał fazy V<br />bldc_polozenie_wirnika = KOMUT_3; //następna komutacja<br />W_TR_D_ON//włącz tranzystor dolny W<br />}<br />break;<br /><br />case (KOMUT_3)://kąt 120 stopni<br />if(!KOMP_STAN_AKT)//gdy komparator = 0<br />{<br />U_TR_G_OFF//wyłącz tranzystor górny U<br />KOMP_KANAL_U;//włącz kanał fazy U<br />bldc_polozenie_wirnika = KOMUT_4; //następna komutacja<br />V_TR_G_ON//włącz tranzystor górny V<br />}<br />break;<br /><br />case (KOMUT_4)://kąt 180 stopni<br />if(KOMP_STAN_AKT)//gdy komparator = 1<br />{<br />W_TR_D_OFF//wyłącz tranzystor dolny W<br />KOMP_KANAL_W;//włącz kanał fazy W<br />bldc_polozenie_wirnika = KOMUT_5; //następna komutacja<br />U_TR_D_ON//włącz tranzystor dolny U<br />}<br />break;<br /><br />case (KOMUT_5)://kąt 240 stopni<br />if(!KOMP_STAN_AKT)//gdy komparator = 0<br />{<br />V_TR_G_OFF//wyłącz tranzystor górny V<br />KOMP_KANAL_V;//włącz kanał fazy V<br />bldc_polozenie_wirnika = KOMUT_6; //następna komutacja<br />W_TR_G_ON//włącz tranzystor górny W<br />}<br />break;<br /><br />case (KOMUT_6)://kąt 300 stopni<br />if(KOMP_STAN_AKT)//komparator = 1<br />{<br />U_TR_D_OFF  //wyłącz tranzystor dolny U<br />KOMP_KANAL_U;//włącz kanał fazy U<br />bldc_polozenie_wirnika = KOMUT_1; //komut. od początku<br />V_TR_D_ON//włącz tranzystor dolny V<br />}<br />break;<br />}<br />break;<br />}<br />}[/syntax]<br /><br />i biblioteka bldc.h<br />[syntax=cpp]/*<br /><br />Sterownik silnika BLDC.<br />Sterowanie silnikiem z wykorzystaniem Back-EMF.<br /><br />Częstotliwość F_CPU: 8MHz (ustaw w opcjach projektu)<br /><br />Szczegóły: http://mikrokontrolery.blogspot.com/2011/03/silnik-bldc-sterownik-back-emf.html<br /><br />2013 Dondu<br /><br />*/<br /><br /><br /><br />//--- D E F I N I C J E   D O T.  B E Z P I E C Z N I K A  ------<br /><br />//LED bezpiecznika<br />#define BEZP_LED_DDRDDRD<br />#define BEZP_LED_PORTPORTD<br />#define BEZP_LED_PINPD3<br /><br />//--- D E F I N I C J E   D O T.  S I L N I K A  ------<br /><br />//Faza U<br />//tranzystor górny<br />#define U_TR_G_PORTxPORTB<br />#define U_TR_G_DDRxDDRB<br />#define U_TR_G_PINxPINB<br />#define U_TR_G_PINPB1<br />#define U_TR_G_USTAW_DDRU_TR_G_DDRx  |=  (1&lt;&lt;U_TR_G_PIN); //ustaw port<br />#define U_TR_G_PIN_LU_TR_G_PORTx &amp;= ~(1&lt;&lt;U_TR_G_PIN); //ustaw niski<br />#define U_TR_G_ON TCCR1A |= (1&lt;&lt;COM1A1);//włącz tranzystor<br />#define U_TR_G_OFFTCCR1A &amp;=~(1&lt;&lt;COM1A1);//wyłącz tranzystor<br />#define U_TR_G_SPRAW_STAN   (TCCR1A &amp; (1&lt;&lt;COM1A1))//warunek stanu<br />//tranzystor dolny<br />#define U_TR_D_PORTxPORTD<br />#define U_TR_D_DDRxDDRD<br />#define U_TR_D_PINxPIND<br />#define U_TR_D_PINPD3<br />#define U_TR_D_USTAW_DDRU_TR_D_DDRx  |=  (1&lt;&lt;U_TR_D_PIN); //ustaw port<br />#define U_TR_D_PIN_LU_TR_D_PORTx &amp;= ~(1&lt;&lt;U_TR_D_PIN); //ustaw niski<br />//#define U_TR_D_ON U_TR_D_PORTx |=  (1&lt;&lt;U_TR_D_PIN); //włącz tranz.<br />//#define U_TR_D_OFFU_TR_D_PORTx &amp;= ~(1&lt;&lt;U_TR_D_PIN); //wyłącz tranz.<br />//#define U_TR_D_SPRAW_STAN(U_TR_D_PINx &amp;   (1&lt;&lt;U_TR_D_PIN)) //warunek stanu<br />#define U_TR_D_ON TCCR2A |=  (1&lt;&lt;COM2B1); //włącz tranz.<br />#define U_TR_D_OFFTCCR2A &amp;= ~(1&lt;&lt;COM2B1); //wyłącz tranz.<br />#define U_TR_D_SPRAW_STAN(TCCR2A &amp; (1&lt;&lt;COM2B1)) //warunek stanu<br /><br />//Faza V<br />//tranzystor górny<br />#define V_TR_G_PORTxPORTB<br />#define V_TR_G_DDRxDDRB<br />#define V_TR_G_PINxPINB<br />#define V_TR_G_PINPB3<br />#define V_TR_G_USTAW_DDRV_TR_G_DDRx  |=  (1&lt;&lt;V_TR_G_PIN); //ustaw port<br />#define V_TR_G_PIN_LV_TR_G_PORTx &amp;= ~(1&lt;&lt;V_TR_G_PIN); //ustaw niski<br />#define V_TR_G_ON TCCR2A |=  (1&lt;&lt;COM2A1);//włącz tranzystor<br />#define V_TR_G_OFFTCCR2A &amp;= ~(1&lt;&lt;COM2A1);//wyłącz tranzystor<br />#define V_TR_G_SPRAW_STAN(TCCR2A &amp; (1&lt;&lt;COM2A1))//warunek stanu<br />//tranzystor dolny<br />#define V_TR_D_PORTxPORTD<br />#define V_TR_D_DDRxDDRD<br />#define V_TR_D_PINxPIND<br />#define V_TR_D_PINPD5<br />#define V_TR_D_USTAW_DDRV_TR_D_DDRx  |=  (1&lt;&lt;V_TR_D_PIN); //ustaw port<br />#define V_TR_D_PIN_LV_TR_D_PORTx &amp;= ~(1&lt;&lt;V_TR_D_PIN); //ustaw niski<br />//#define V_TR_D_ON V_TR_D_PORTx |=  (1&lt;&lt;V_TR_D_PIN); //włącz tranz.<br />//#define V_TR_D_OFFV_TR_D_PORTx &amp;= ~(1&lt;&lt;V_TR_D_PIN); //wyłącz tranz.<br />//#define V_TR_D_SPRAW_STAN(V_TR_D_PINx &amp;   (1&lt;&lt;V_TR_D_PIN)) //warunek stanu<br />#define V_TR_D_ON TCCR0A |= (1&lt;&lt;COM0B1); //włącz tranz.<br />#define V_TR_D_OFFTCCR0A &amp;=~(1&lt;&lt;COM0B1); //wyłącz tranz.<br />#define V_TR_D_SPRAW_STAN(TCCR0A &amp; (1&lt;&lt;COM0B1)) //warunek stanu<br /><br /><br />//Faza W<br />//tranzystor górny<br />#define W_TR_G_PORTxPORTB<br />#define W_TR_G_DDRxDDRB<br />#define W_TR_G_PINxPINB<br />#define W_TR_G_PINPB2<br />#define W_TR_G_USTAW_DDRW_TR_G_DDRx  |=  (1&lt;&lt;W_TR_G_PIN); //ustaw port<br />#define W_TR_G_PIN_LW_TR_G_PORTx &amp;= ~(1&lt;&lt;W_TR_G_PIN); //ustaw niski<br />#define W_TR_G_ON TCCR1A |= (1&lt;&lt;COM1B1);//włącz tranzystor<br />#define W_TR_G_OFFTCCR1A &amp;=~(1&lt;&lt;COM1B1);//wyłącz tranzystor<br />#define W_TR_G_SPRAW_STAN(TCCR1A &amp; (1&lt;&lt;COM1B1))//warunek stanu<br />//tranzystor dolny<br />#define W_TR_D_PORTxPORTD<br />#define W_TR_D_DDRxDDRD<br />#define W_TR_D_PINxPIND<br />#define W_TR_D_PINPD7<br />#define W_TR_D_USTAW_DDRW_TR_D_DDRx  |=  (1&lt;&lt;W_TR_D_PIN); //ustaw port<br />#define W_TR_D_PIN_LW_TR_D_PORTx &amp;= ~(1&lt;&lt;W_TR_D_PIN); //ustaw niski<br />#define W_TR_D_ON W_TR_D_PORTx |=  (1&lt;&lt;W_TR_D_PIN); //włącz tranz.<br />#define W_TR_D_OFFW_TR_D_PORTx &amp;= ~(1&lt;&lt;W_TR_D_PIN); //wyłącz tranz.<br />#define W_TR_D_SPRAW_STAN(W_TR_D_PINx &amp;   (1&lt;&lt;W_TR_D_PIN)) //warunek stanu<br /><br /><br />//Kąty położenia wirnika<br />#define KOMUT_11<br />#define KOMUT_22<br />#define KOMUT_33<br />#define KOMUT_44<br />#define KOMUT_55<br />#define KOMUT_66<br />#define KOMUT_7 7<br />#define KOMUT_8 8<br /><br />//Wspólna definicja wyłączająca wszystkie tranzystory<br />#define WYLACZ_TRANZYSTORYU_TR_G_OFF; U_TR_D_OFF; V_TR_G_OFF; V_TR_D_OFF; W_TR_G_OFF; W_TR_D_OFF;<br /><br /><br />//--- D E F I N I C J E   P W M ---<br />#define PWM_MIN   240//początkowa wartość wypełnienia PWM<br /><br /><br />//Tryb pracy<br />#defineTRYB_START0<br />#defineTRYB_PRACA1<br /><br /><br />//--- D E F I N I C J E   K O M P A R A T O R A ----<br />#define KOMP_STAN_AKT(ACSR &amp; (1&lt;&lt;ACO))//aktualny stan wyjścia<br />//komparatora<br />#define KOMP_KANAL_UADMUX = 0;//kanał U do pomiaru BEMF<br />#define KOMP_KANAL_VADMUX = 1;//kanał V do pomiaru BEMF<br />#define KOMP_KANAL_WADMUX = 2;//kanał W do pomiaru BEMF<br /><br /><br />extern volatile unsigned charbldc_polozenie_wirnika;<br /><br /><br />extern void bldc_bezpiecznik(void);<br />extern void bldc_bezpiecznik_stop(void);<br />extern void bldc_start_komutacja(void);<br />extern void bldc_inicjuj_sterownik(void);<br />extern void bldc_start_delay_ms(unsigned char il_ms);<br />extern void bldc_start(void);<br /><br />extern volatile unsigned char bldc_tryb_pracy;   //aktualny tryb pracy<br />extern volatile unsigned int  bldc_komp_licznik; //licz. przerwań komparatora[/syntax]<br /><br />Bibliotek do UARTA nie wrzucam do są na pewno dobrze, robione ze stronki mirekk36.blogspot.com, tam wszystko działa.<br />No i na koniec program o który się opierwałem z pomiarem ADC który <strong>DZIAŁA</strong><br />[syntax=cpp]//Data utworzenie: 20-09-2014<br /><br /><br /><br />#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &quot;MYUART/myuart.h&quot;<br />#include &quot;MK_TERMINAL/mk_term.h&quot;<br /><br />#define REF_256 (1&lt;&lt;REFS1)|(1&lt;&lt;REFS0)<br />#define REF_VCC (0&lt;&lt;REFS1)|(1&lt;&lt;REFS0)<br /><br /><br /><br />#define SR 8<br /><br />typedef struct vol {<br />uint16_t adc_mid;<br />uint16_t ref_adc;<br />uint16_t ref_v;<br />char v1&#91;3&#93;;<br />char v2&#91;3&#93;;<br />}TVOL;<br /><br />TVOL accu1_vol;<br /><br />uint16_t pomiar (uint8_t kanal);<br />void get_vol (uint16_t adc, TVOL * voltage);<br /><br />int main ( void ) {<br /><br />//inicjalizacja ADC<br />ADCSRA |= (1&lt;&lt;ADPS2)|(1&lt;&lt;ADPS1)|(1&lt;&lt;ADPS0); //preskaler 128 8000000/168<br />ADMUX |= REF_VCC; //ust. źródło odniesienia 2.56 V<br />ADCSRA |= (1&lt;&lt;ADEN); //włącz ADC<br /><br />accu1_vol.ref_adc = 548;<br />accu1_vol.ref_v = 141;<br /><br />uart_init ( __UBRR );<br /><br />uint16_t wynik=0;<br />tr_cls(0);<br />while(1) {<br />tr_cls(0);<br />wynik = pomiar ( PC5 );<br />wynik=wynik/4;<br />get_vol( wynik, &amp;accu1_vol );<br /><br />tr_locate(3,3);<br />tr_pen_color(RED);<br />uart_putlong(wynik,10);<br />uart_puts(&quot;/&quot;);<br />uart_putlong(accu1_vol.adc_mid,10);<br /><br />}<br />}<br /><br />uint16_t pomiar (uint8_t kanal) {<br />ADMUX = (ADMUX &amp; 0b11111000) | kanal;<br />ADCSRA |= (1&lt;&lt;ADSC); //start konwersji<br />while ( ADCSRA &amp; (1&lt;&lt;ADSC) ) ;<br />return ADCW;<br />}<br /><br />void get_vol (uint16_t adc, TVOL * voltage) {<br /><br />static uint16_t sr&#91;SR&#93;;<br />static uint8_t idx;<br />uint32_t sr1=0;<br />uint8_t i;<br /><br />sr&#91; idx++ &amp; (SR-1) &#93; = adc;<br />//sr&#91;idx&#93;=adc;<br />//idx++;<br />//if(idx&gt;7) idx=0;<br />//if( idx &amp; (SR-1) ) return;<br />for ( i=0; i&lt;SR; i++) sr1+=sr&#91;i&#93;;<br />sr1 /=SR;<br /><br />voltage-&gt;adc_mid =sr1;<br /><br /><br />uint16_t wynik = (sr1 * (uint32_t) voltage-&gt;ref_v ) / voltage-&gt;ref_adc;<br />div_t divmod = div(wynik,100 );<br />itoa( divmod.quot, voltage-&gt;v1, 10 );<br />itoa( divmod.rem, voltage-&gt;v2, 10 );<br />if (divmod.rem &lt;10) {<br />voltage-&gt;v2&#91;0&#93;='0';<br />voltage-&gt;v2&#91;1&#93;=divmod.rem+'0';<br />}<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5890">apollo1412</a> — 19 lis 2014, o 13:40</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[apollo1412]]></name></author>
<updated>2014-11-18T17:15:37+01:00</updated>
<published>2014-11-18T17:15:37+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104728#p104728</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104728#p104728"/>
<title type="html"><![CDATA[Re: ATMEGA328p-pu błędny pomiar ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104728#p104728"><![CDATA[
Dobra. Kod prezentuje się następująco:<br /><br />to jest program w którym wszystko działa jak potrzeba:<br />[syntax=cpp]//Data utworzenie: 20-09-2014<br /><br /><br /><br />#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &quot;MYUART/myuart.h&quot;<br />#include &quot;MK_TERMINAL/mk_term.h&quot;<br /><br />#define REF_256 (1&lt;&lt;REFS1)|(1&lt;&lt;REFS0)<br />#define REF_VCC (0&lt;&lt;REFS1)|(1&lt;&lt;REFS0)<br /><br />#define SR 8<br /><br />typedef struct vol {<br />uint16_t adc_mid;<br />uint16_t ref_adc;<br />uint16_t ref_v;<br />char v1&#91;3&#93;;<br />char v2&#91;3&#93;;<br />}TVOL;<br /><br />TVOL accu1_vol;<br /><br />uint16_t pomiar (uint8_t kanal);<br />void get_vol (uint16_t adc, TVOL * voltage);<br /><br />int main ( void ) {<br /><br />//inicjalizacja ADC<br />ADCSRA |= (1&lt;&lt;ADPS2)|(1&lt;&lt;ADPS1)|(1&lt;&lt;ADPS0); //preskaler 128 8000000/168<br />ADMUX |= REF_VCC; //ust. źródło odniesienia 2.56 V<br />ADCSRA |= (1&lt;&lt;ADEN); //włącz ADC<br /><br />accu1_vol.ref_adc = 548;<br />accu1_vol.ref_v = 141;<br /><br />uart_init ( __UBRR );<br /><br />uint16_t wynik=0;<br />tr_cls(0);<br />while(1) {<br />tr_cls(0);<br />wynik = pomiar ( PC5 );<br />wynik=wynik/4;<br />get_vol( wynik, &amp;accu1_vol );<br /><br />tr_locate(3,3);<br />tr_pen_color(RED);<br />uart_putlong(wynik,10);<br />uart_puts(&quot;/&quot;);<br />uart_putlong(accu1_vol.adc_mid,10);<br /><br />}<br />}<br /><br />uint16_t pomiar (uint8_t kanal) {<br />ADMUX = (ADMUX &amp; 0b11111000) | kanal;<br />ADCSRA |= (1&lt;&lt;ADSC); //start konwersji<br />while ( ADCSRA &amp; (1&lt;&lt;ADSC) ) ;<br />return ADCW;<br />}<br /><br />void get_vol (uint16_t adc, TVOL * voltage) {<br /><br />static uint16_t sr&#91;SR&#93;;<br />static uint8_t idx;<br />uint32_t sr1=0;<br />uint8_t i;<br /><br />sr&#91; idx++ &amp; (SR-1) &#93; = adc;<br />//sr&#91;idx&#93;=adc;<br />//idx++;<br />//if(idx&gt;7) idx=0;<br />//if( idx &amp; (SR-1) ) return;<br />for ( i=0; i&lt;SR; i++) sr1+=sr&#91;i&#93;;<br />sr1 /=SR;<br /><br />voltage-&gt;adc_mid =sr1;<br /><br /><br />uint16_t wynik = (sr1 * (uint32_t) voltage-&gt;ref_v ) / voltage-&gt;ref_adc;<br />div_t divmod = div(wynik,100 );<br />itoa( divmod.quot, voltage-&gt;v1, 10 );<br />itoa( divmod.rem, voltage-&gt;v2, 10 );<br />if (divmod.rem &lt;10) {<br />voltage-&gt;v2&#91;0&#93;='0';<br />voltage-&gt;v2&#91;1&#93;=divmod.rem+'0';<br />}<br />}[/syntax]<br /><br />Teraz drugi program i w nim jest problem z działaniem potencjometru. Tutaj program główny:<br />[syntax=cpp]/*<br /><br />Sterownik silnika BLDC.<br />Sterowanie silnikiem z wykorzystaniem Back-EMF.<br /><br />Częstotliwość F_CPU: 8MHz (ustaw w opcjach projektu)<br /><br /><br />*/<br /><br /><br />#include &quot;avr/io.h&quot;<br />#include &lt;util/delay.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &quot;bldc.h&quot;<br />#include &quot;myuart.h&quot;<br /><br /><br />//------------------------------------------------------------------<br /><br />int main (void)<br />{<br />uart_init ( __UBRR );<br />uart_puts(&quot;gthfhfth&quot;);<br />//zmienne potrzebne do przykładu zmiany prędkości<br />//patrz pętla główna while() poniżej<br />unsigned char PWM_akt;<br />//unsigned char PWM_kier = 1;   //kierunek zmiany prędkości<br />//0 - zmniejszanie<br />//1 - zwiększanie<br /><br /><br />//diody testowe<br />DDRC|= (1&lt;&lt;PC5) | (1&lt;&lt;PC4);//wyjście LED<br />PORTC|= (1&lt;&lt;PC5) | (1&lt;&lt;PC4);//zgaś diody, bo są zapalane zerem<br /><br /><br />//opóźnienie na ustabilizowanie zasilania (można usunąć)<br />//_delay_ms(1000);<br /><br />//inicjujemy sterownik<br />bldc_inicjuj_sterownik();<br /><br /><br />//Przerwania globalne włącz<br />sei();<br /><br />//Start silnika<br />bldc_start();<br /><br />//odczytaj aktualnie ustawione PWM (dla potrzeb przykładu poniżej)<br />PWM_akt = 100;<br />tr_cls(0);<br />//pętla główna<br />while(1){<br /><br /><br />//... tutaj dowolny Twój program<br /><br /><br />//--- PRZYKŁAD ------------------------<br />//Przykład funkcji zmieniającej prędkość obrotów silnika<br />//tylko wtedy, gdy sterownik już rozkręcił silnik i przeszedł<br />//w tyb pracy<br /><br />//Aby przykład działał usuń na początku main() komentarze<br />//dla deklaracji zmiennych PWM_akt oraz PWM_kier<br /><br />if(bldc_tryb_pracy== TRYB_PRACA){<br /><br />//PWM_akt += skok_PWM;<br /><br />//if(PWM_kier) PWM_akt++;<br />//else PWM_akt--;<br /><br /><br />//sprawdzamy, czy osiągnęliśmy próg prędkości maksymalnej<br />//if(PWM_akt &gt;254) PWM_kier = 0; //od teraz zmniejszamy obroty<br /><br />//sprawdzamy, czy osiągnęliśmy próg prędkości minimalnej<br />//if(PWM_akt &lt;40)PWM_kier = 1; //od teraz zwiększamy obroty<br />//PWM_akt=30;<br />//OCR0A=PWM_akt;<br />PWM_akt=50;<br />//ustaw aktualne PWM w celu regulacji prędkości<br />OCR0B=PWM_akt;<br />OCR1A=PWM_akt;<br />OCR1B=PWM_akt;<br />OCR2A=PWM_akt;<br />OCR2B=PWM_akt;<br />//dla testów, opóźnienie zmian prędkości<br />_delay_ms(100);<br /><br />}<br />//--- PRZYKŁAD - Koniec -------------<br /><br /><br />//... tutaj dowolny Twój program<br /><br /><br />}<br />}[/syntax]<br /><br />tutaj program bldc.c gdzie wykonuje pomiar ADC (w przerwaniu na samym końcu - case komut_7)<br />[syntax=cpp]/*<br /><br />Sterownik silnika BLDC.<br />Sterowanie silnikiem z wykorzystaniem Back-EMF.<br /><br />Częstotliwość F_CPU: 8MHz (ustaw w opcjach projektu)<br /><br /><br /><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 />#include &lt;stdlib.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &quot;bldc.h&quot;<br />#include &quot;myuart.h&quot;<br />#include &quot;mk_term.h&quot;<br /><br />#define SR 8<br /><br />typedef struct vol {<br />uint16_t adc_mid;<br />uint16_t ref_adc;<br />uint16_t ref_v;<br />char v1&#91;3&#93;;<br />char v2&#91;3&#93;;<br />}TVOL;<br /><br />TVOL accu1_vol;<br /><br />#define REF_VCC (1&lt;&lt;REFS0)<br /><br />uint16_t pomiar (uint8_t kanal);<br />void get_vol (uint16_t adc, TVOL * voltage);<br /><br />volatile unsigned charbldc_polozenie_wirnika = KOMUT_1;<br />volatile uint8_t l=0;<br />//volatile unsigned int wynik=0;<br />volatile int  wynik=0;<br /><br /><br /><br /><br /><br />volatile unsigned char bldc_tryb_pracy;   //aktualny tryb pracy<br />volatile unsigned int  bldc_komp_licznik; //licznik przerwań komparatora<br /><br /><br /><br />//--------------------------------------------------------------------<br /><br />void bldc_bezpiecznik_stop(void){<br /><br />//Funkcja wyłącza wszelkie tranzystory oraz przechodzi w stan sygnalizacji<br />//błędu komutacji. Funkcja ta razem z funkcją bezpiecznik() pełni rolę<br />//zabezpieczenia przeciwzwarciowego dla błędnie działającego algorytmu<br />//komutacji w czasie pisania i testów programu.<br /><br />//wyłącz przerwania<br />cli();<br /><br />//natychmiast wyłącz tranzystory<br />WYLACZ_TRANZYSTORY<br /><br />//i ustaw stany niskie na pinach sterujących<br />U_TR_G_USTAW_DDR<br />V_TR_G_USTAW_DDR<br />W_TR_G_USTAW_DDR<br />U_TR_D_USTAW_DDR<br />V_TR_D_USTAW_DDR<br />W_TR_D_USTAW_DDR<br />U_TR_G_PIN_L<br />V_TR_G_PIN_L<br />W_TR_G_PIN_L<br />U_TR_D_PIN_L<br />V_TR_D_PIN_L<br />W_TR_D_PIN_L<br /><br />//ustaw pin LED jako wyjście<br />BEZP_LED_DDR|=(1&lt;&lt;BEZP_LED_PIN);<br /><br />//zatrzymaj program w pętli nieskończonej sygnalizując błąd<br />while(1){<br /><br />//zmień stan LED na przeciwny<br />BEZP_LED_PORT  ^= (1&lt;&lt;BEZP_LED_PIN);<br /><br />//co 100ms<br />_delay_ms(100);<br /><br />}<br />}<br /><br /><br />//------------------------------------------------------------------<br /><br />void bldc_bezpiecznik(void){<br /><br />//Sprawdzamy, czy nie występuje konflikt sterowania, powodujący<br />//jednoczene otwarcie tranzystora górnego i dolnego w tej samej fazie,<br />//co oznacza wystąpienie zwarcia !!!<br /><br />if(U_TR_G_SPRAW_STAN &amp;&amp; U_TR_D_SPRAW_STAN){<br /><br />//Faza U - oba tranzystory są włączone - sytuacja niedopuszczalna!!!<br />bldc_bezpiecznik_stop();<br /><br /><br />}else if(V_TR_G_SPRAW_STAN &amp;&amp; V_TR_D_SPRAW_STAN){<br /><br />//Faza V - oba tranzystory są włączone - sytuacja niedopuszczalna!!!<br />bldc_bezpiecznik_stop();<br /><br /><br />}else if(W_TR_G_SPRAW_STAN &amp;&amp; W_TR_D_SPRAW_STAN){<br /><br />//Faza W - oba tranzystory są włączone - sytuacja niedopuszczalna!!!<br />bldc_bezpiecznik_stop();<br /><br />}<br /><br />}<br /><br /><br /><br />//-----------------------------------------------------------<br /><br /><br />void bldc_inicjuj_sterownik(void){<br /><br />//Funkcja inicjująca pracę sterownika.<br />//-konfiguruje wszystkie wykorzystywane moduły mikrokontrolera<br />//-ustawia piny mikrokontrolera tak, by wszystkie tranzystory<br />// były wyłączone<br />//-ustawia licznikia PWM na początkową wartość DutyCycle<br /><br />//ustaw stan początkowy wyjść sterujących tranzystorami<br />U_TR_G_USTAW_DDR<br />V_TR_G_USTAW_DDR<br />W_TR_G_USTAW_DDR<br />U_TR_D_USTAW_DDR<br />V_TR_D_USTAW_DDR<br />W_TR_D_USTAW_DDR<br />U_TR_G_PIN_L<br />V_TR_G_PIN_L<br />W_TR_G_PIN_L<br />U_TR_D_PIN_L<br />V_TR_D_PIN_L<br />W_TR_D_PIN_L<br /><br /><br /><br />//sprawdzamy, czy nie ma stanu zabronionego na tranzystorach<br />//ZAWSZE WYWOŁUJ TĘ FUNKCJĘ, GDY ZMIENIASZ STAN TRANZYSTORÓW!!!<br />bldc_bezpiecznik();<br /><br /><br /><br />//--- T I M E R Y    P W M   -------------------<br />//Timer0<br />//Obsługa PWM dla wyjść !!! BEZ OC0A !!! oraz OC0B<br />//Mode 5 (Fast PWM, 8bit)<br />//Clear OC0A/OC0B on Compare Match, set OC0A/OC0B at BOTTOM,<br />//(non-inverting mode)<br />//preskaler 1<br />TCCR0A|=(1&lt;&lt;WGM01) | (1&lt;&lt;WGM00) | (1&lt;&lt;COM0B1);<br />TCCR0B|=(1&lt;&lt;CS00);<br />//Timer1<br />//Obsługa PWM dla wyjść OC1A oraz OC1B<br />//Mode 5 (Fast PWM, 8bit)<br />//Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM,<br />//(non-inverting mode)<br />//preskaler 1<br />TCCR1A|=(1&lt;&lt;WGM12) | (1&lt;&lt;WGM10) | (1&lt;&lt;COM1A1) | (1&lt;&lt;COM1B1);<br />TCCR1B|=(1&lt;&lt;WGM12) | (1&lt;&lt;WGM10) | (1&lt;&lt;CS10);<br /><br /><br />//Timer2<br />//Obsługa PWM  dla wyjścia OC2<br />//Mode 3 (Fast PWM, 8bit)<br />//Clear OC2 on Compare Match, set OC2 at BOTTOM, (non-inverting mode)<br />//preskaler 1<br />TCCR2A|=(1&lt;&lt;WGM21) | (1&lt;&lt;WGM20)| (1&lt;&lt;COM2A1) | (0&lt;&lt;COM2B1);<br />TCCR2B  |=(1&lt;&lt;CS20) ;<br /><br />//--- K O M P A R A T O R ---<br />//Obsługuje wykrywanie położenia wirnika poprzez BEMF,<br />//czyli ustalanie momentów przejścia przez zero sygnałów sterujących<br />//przerwanie dla każdej zmiany wyjścia komparatora<br />//Przerwanie jest włączane w funkcji startującej silnik.<br />ADCSRB|= (1&lt;&lt;ACME);//włącz multiplekser wejść ujemnych komparatora<br /><br /><br />//ustaw wartość początkową PWM<br />OCR0B = PWM_MIN;<br />OCR1A = PWM_MIN;<br />OCR1B = PWM_MIN;<br />OCR2A = PWM_MIN;<br />OCR2B = PWM_MIN;<br />//na wszelki wypadek<br />WYLACZ_TRANZYSTORY<br />bldc_bezpiecznik();<br /><br />}<br /><br /><br /><br />//------------------------------------------------------------------<br /><br /><br /><br /><br />void bldc_start_delay_ms(unsigned char il_ms){<br /><br />//Funkcja opóźnienia o zmiennej wartości czasu<br /><br />while(il_ms){<br />_delay_ms(1);<br />il_ms--;<br />}<br />}<br /><br /><br />//-----------------------------------------------------------<br /><br />void bldc_start_komutacja(void){<br /><br />//Funkcja komutacji w czasie rozruchu silnika.<br />//nie zawiera obsługi BackEMF<br /><br />//zależnie od numeru aktualnej komutacji przełącza na następną<br />switch (bldc_polozenie_wirnika++){<br /><br />case (KOMUT_1)://komutacja 1<br />W_TR_G_OFF<br />U_TR_G_ON<br />break;<br /><br />case (KOMUT_2)://komutacja 2<br />V_TR_D_OFF<br />W_TR_D_ON<br />break;<br /><br />case (KOMUT_3)://komutacja 3<br />U_TR_G_OFF<br />V_TR_G_ON<br />break;<br /><br />case (KOMUT_4)://komutacja 4<br />W_TR_D_OFF<br />U_TR_D_ON<br />break;<br /><br />case (KOMUT_5)://komutacja 5<br />V_TR_G_OFF<br />W_TR_G_ON<br />break;<br /><br />case (KOMUT_6)://komutacja 6<br />U_TR_D_OFF<br />bldc_polozenie_wirnika = KOMUT_1; //komutacja od początku<br />V_TR_D_ON<br />break;<br /><br />}<br /><br />//sprawdzamy konflikty sterowania<br />bldc_bezpiecznik();<br />}<br /><br /><br /><br />//-----------------------------------------------------------<br /><br />void bldc_start(void){<br /><br />//Funkcja odpowiedzialna za:<br />//- ustawienie wirnika w pozycji początkowej<br />//- rozkręcenie silnika do momentu uzyskania odczytów BackMEF<br /><br />signed int i; //zmienna pomocnicza<br /><br />//wartości początkowe<br />bldc_tryb_pracy= TRYB_START;<br /><br /><br /><br />////RUSZAMY SILNIK<br />////Poniżej przykład kolejnych kroków, mających na celu ruszenie silnika<br />////z miejsca oraz rozkręcenie go do momentu w którym uzyskamy sygnał<br />////BackEMF. Po osiągnięciu odpowiedniej ilości przerwań z komparatora,<br />////uznajemy, że nadszedł moment w którym należy się przełączyć na<br />////sterowanie komutacjami z wykorzystaniem przerwań BackEMF (komparatora).<br />//<br />////UWAGA!<br />////W zależności od silnika należy dobrać doświadczalnie procedurę startu<br />//<br />//<br />//<br />////KROK 1<br />////Ustaw wirnik w pozycji startowej<br />//bldc_polozenie_wirnika= KOMUT_1;<br />U_TR_G_ON//włączamy wybraną parę tranzystorów<br />W_TR_D_ON<br />_delay_ms(300);<br />bldc_bezpiecznik();//sprawdzamy konflikty sterowania<br /><br />//<br />////odczekujemy oscylacje wirnika zmniejszając wypełnienie PWM<br />////tutaj możesz dostosować doświadczalnie parametry pozycjonowania silnika<br />////do bezwładności wirnika<br />for(i=100; i&gt;0; i-=5){<br /><br /><br />OCR0B  = (unsigned char) i;<br />OCR1A = (unsigned char) i;<br />OCR1B = (unsigned char) i;<br />OCR2A  = (unsigned char) i;<br />OCR2B  = (unsigned char) i;<br />//opóźnienie<br />_delay_ms(100);<br />}<br />//<br />//<br />////KROK 2<br />////ruszamy silnik z miejsca<br />//<br />//początkowa wartość PWM dla startu silnika (regulacja prądu)<br />OCR0A = 254;<br />OCR1A = 254;<br />OCR1B = 254;<br />OCR2A = 254;<br />OCR2B = 254;<br />//<br />////rusz silnik z miejsca przełączając komutacje ze zmienjszającym się<br />////opóźnieniem, by osiągnąć początkową prędkość<br />for(i=40; i&gt;0; i-=1){<br />bldc_start_komutacja();//kolejna komutacja<br />bldc_start_delay_ms(50);//opóźnienie<br />}<br />for(i=80; i&gt;0; i-=1){<br />bldc_start_komutacja();//kolejna komutacja<br />bldc_start_delay_ms(30);//opóźnienie<br />}<br />//<br />////KROK 3<br />////zwiększaj dalej prędkość, ale mniejszymi krokami PWM<br />//for(i=60; i&gt;=10; i-=1){<br />//bldc_start_komutacja();//kolejna komutacja<br />//bldc_start_delay_ms(i);//opóźnienie<br />//<br />//}<br /><br />//<br />////KROK 4<br />////włącz przerwania z komparatora ponieważ już mogą być prawidłowe<br />////sygnały BEMF.<br />ACSR|= (1&lt;&lt;ACIE);<br />//<br />for(i=200; i&gt;0; i-=1){<br />bldc_start_komutacja();//kolejna komutacja<br />bldc_start_delay_ms(20);//opóźnienie<br /><br />////ustabilizuj obroty i czekaj na wykrycie odpowiedniej ilości przerwań<br />//for(i=0; i&lt;200; i++){<br />//<br />//bldc_start_komutacja(); //kolejna komutacja<br />//bldc_start_delay_ms(10); //opóźnienie<br /><br />//Przerwij, gdy wykryto już wystarczającą ilość przerwań z komparatora<br />//ilość impulsów zależy tylko od Ciebie - ja wybrałem 40<br />if(bldc_komp_licznik &gt; 80){<br /><br />//Wykryto odpowiednią ilość przerwań z sygnałów BackEMF<br />//uznajemy więc, że możemy przejść na sterowanie za pomocą<br />//przerwań z sygnałów BackEMF<br /><br />//ustaw tryb pracy i wróć do main()<br />bldc_tryb_pracy= TRYB_PRACA;<br />WYLACZ_TRANZYSTORY<br />DDRD |=(1&lt;&lt;PD2);<br />PORTD ^=(1&lt;&lt;PD2);<br />break;<br />}<br /><br />}<br /><br /><br />//KROK 5<br />//sprawdzamy, czy sterownik przełączył się na tryb pracy<br />if(bldc_tryb_pracy!= TRYB_PRACA){<br /><br />//Sterownik nie przełączył się, ponieważ pomimo wielu obrotów wirnika<br />//komparator nie wykrył założonej ilości impulsów sygnału BackEMF,<br />//stąd przerywamy procedurę startu.<br /><br />//Jeżeli sytuacja będzie się powtarzać, powinieneś zmienić parametry<br />//kroków 2, 3 i 4<br /><br />//wyłącz przerwania z komparatora<br />ACSR&amp;= ~(1&lt;&lt;ACIE);<br /><br />//wyłącz tranzystory<br />WYLACZ_TRANZYSTORY<br />bldc_bezpiecznik();<br /><br />}<br /><br />//wróć do main()<br /><br />}<br /><br /><br /><br />//-----------------------------------------------------------<br /><br /><br />ISR (ANALOG_COMP_vect)<br />{<br /><br />//Funkcja obsługi przerwania z komparatora wykrywającego punkty ZC<br />//funkcja zajmuje się wykryciem właściwego położenia wirnika<br />//oraz przełączeniem następnej komutacji<br /><br /><br />//DLA TESTÓW ZC możesz podłączyć do pinu PB0 oscyloskop i obserwować<br />//moment wykonania się przerwania. Wcześniej musisz ustawić<br />//pin PBO jako wyjście<br />//PORTB^=(1&lt;&lt;PB0);//zmień stan pinu na przeciwny<br /><br />//w zależności od trybu pracy sterownika<br />switch (bldc_tryb_pracy){<br /><br />//-------------------------------------------------<br /><br />case TRYB_START:<br />//Podczas trybu startu jedynie zliczaj wykryte przerwania<br />//z komparatora, czyli punkty ZC sygnału BackEMF<br />bldc_komp_licznik++;<br />break;<br /><br />//-------------------------------------------------<br /><br />case TRYB_PRACA:<br /><br />//tryb normalnej pracy czyli kręcenia silnikiem na podstawie<br />//wykrytych punktów ZC sygnałów BackEMF<br /><br />//w zależności od położenia wirnika (fakt wystąpienia przerwania<br />//oraz sprawdzenie stanu wyjścia komparatora)<br />switch (bldc_polozenie_wirnika)<br />{<br />case (KOMUT_1)://kąt 0 stopni<br />if(!KOMP_STAN_AKT)//gdy komparator = 0<br />{<br />l++;<br />W_TR_G_OFF//wyłącz tranzystor górny W<br />KOMP_KANAL_W;//włącz kanał fazy W<br />bldc_polozenie_wirnika = KOMUT_2; //następna komutacja<br />U_TR_G_ON//włącz tranzystor górny U<br />}<br />break;<br /><br />case (KOMUT_2)://kąt 60 stopni<br />if(KOMP_STAN_AKT)//gdy komparator = 1<br />{<br />l++;<br />V_TR_D_OFF//wyłącz tranzystor dolny V<br />KOMP_KANAL_V;//włącz kanał fazy V<br />bldc_polozenie_wirnika = KOMUT_3; //następna komutacja<br />W_TR_D_ON//włącz tranzystor dolny W<br />}<br />break;<br /><br />case (KOMUT_3)://kąt 120 stopni<br />if(!KOMP_STAN_AKT)//gdy komparator = 0<br />{<br />l++;<br />U_TR_G_OFF//wyłącz tranzystor górny U<br />KOMP_KANAL_U;//włącz kanał fazy U<br />bldc_polozenie_wirnika = KOMUT_4; //następna komutacja<br />V_TR_G_ON//włącz tranzystor górny V<br />}<br />break;<br /><br />case (KOMUT_4)://kąt 180 stopni<br />if(KOMP_STAN_AKT)//gdy komparator = 1<br />{<br />l++;<br />W_TR_D_OFF//wyłącz tranzystor dolny W<br />KOMP_KANAL_W;//włącz kanał fazy W<br />bldc_polozenie_wirnika = KOMUT_5; //następna komutacja<br />U_TR_D_ON//włącz tranzystor dolny U<br />}<br />break;<br /><br />case (KOMUT_5)://kąt 240 stopni<br />if(!KOMP_STAN_AKT)//gdy komparator = 0<br />{<br />l++;<br />V_TR_G_OFF//wyłącz tranzystor górny V<br />KOMP_KANAL_V;//włącz kanał fazy V<br />bldc_polozenie_wirnika = KOMUT_6; //następna komutacja<br />W_TR_G_ON//włącz tranzystor górny W<br />}<br />break;<br /><br />case (KOMUT_6)://kąt 300 stopni<br />if(KOMP_STAN_AKT)//komparator = 1<br />{<br />l++;<br />U_TR_D_OFF  //wyłącz tranzystor dolny U<br />KOMP_KANAL_U;//włącz kanał fazy U<br />bldc_polozenie_wirnika = KOMUT_7; //komut. od początku<br />V_TR_D_ON//włącz tranzystor dolny V<br />}<br />break;<br /><br />case (KOMUT_7)://kąt 300 stopni<br />if(KOMP_STAN_AKT)//komparator = 1<br />{<br />if(l==255) l=0;<br />l++;<br />//DDRC|=(1&lt;&lt;PC5);<br />//inicjalizacja ADC<br />ADCSRA |= (1&lt;&lt;ADPS2)|(1&lt;&lt;ADPS1)|(1&lt;&lt;ADPS0); //preskaler 128 8000000/168<br />ADMUX |= REF_VCC; //ust. źródło odniesienia 5 V<br />ADCSRA |= (1&lt;&lt;ADEN); //włącz ADC<br />//wynik=0;<br />accu1_vol.ref_adc = 548;<br />accu1_vol.ref_v = 141;<br /><br />wynik = pomiar ( PC5 );<br />wynik=wynik/4;<br />//get_vol( wynik, &amp;accu1_vol );<br />//tr_cls(0);<br />tr_locate(3,3);<br />uart_putlong(wynik,10);<br />//tr_locate(5,5);<br />//uart_putlong(l,10);<br />//ADCSRA &amp;= ~(1&lt;&lt;ADPS2)|(1&lt;&lt;ADPS1)|(1&lt;&lt;ADPS0);//preskaler 128 8000000/168<br />ADCSRA &amp;= ~(1&lt;&lt;ADEN); //włącz ADC<br />bldc_bezpiecznik();<br />bldc_polozenie_wirnika = KOMUT_1; //komut. od początku<br />//włącz tranzystor dolny V<br />}<br />break;<br />}<br />break;<br />}<br />}<br /><br />uint16_t pomiar (uint8_t kanal) {<br />ADMUX = (ADMUX &amp; 0b11111000) | kanal;<br />ADCSRA |= (1&lt;&lt;ADSC); //start konwersji<br />while ( ADCSRA &amp; (1&lt;&lt;ADSC) ) ;<br />return ADCW;<br />}<br /><br />void get_vol (uint16_t adc, TVOL * voltage) {<br /><br />static uint16_t sr&#91;SR&#93;;<br />static uint8_t idx;<br />uint32_t sr1=0;<br />uint8_t i;<br /><br />sr&#91; idx++ &amp; (SR-1) &#93; = adc;<br />//sr&#91;idx&#93;=adc;<br />//idx++;<br />//if(idx&gt;7) idx=0;<br />//if( idx &amp; (SR-1) ) return;<br />for ( i=0; i&lt;SR; i++) sr1+=sr&#91;i&#93;;<br />sr1 /=SR;<br /><br />voltage-&gt;adc_mid =sr1;<br /><br /><br />uint16_t wynik = (sr1 * (uint32_t) voltage-&gt;ref_v ) / voltage-&gt;ref_adc;<br />div_t divmod = div(wynik,100 );<br />itoa( divmod.quot, voltage-&gt;v1, 10 );<br />itoa( divmod.rem, voltage-&gt;v2, 10 );<br />if (divmod.rem &lt;10) {<br />voltage-&gt;v2&#91;0&#93;='0';<br />voltage-&gt;v2&#91;1&#93;=divmod.rem+'0';<br />}<br /><br />}[/syntax]<br /><br />no i biblioteka do programu<br />[syntax=cpp]/*<br /><br />Sterownik silnika BLDC.<br />Sterowanie silnikiem z wykorzystaniem Back-EMF.<br /><br />Częstotliwość F_CPU: 8MHz (ustaw w opcjach projektu)<br /><br /><br /><br />*/<br /><br /><br /><br />//--- D E F I N I C J E   D O T.  B E Z P I E C Z N I K A  ------<br /><br />//LED bezpiecznika<br />#define BEZP_LED_DDRDDRD<br />#define BEZP_LED_PORTPORTD<br />#define BEZP_LED_PINPD3<br /><br />//--- D E F I N I C J E   D O T.  S I L N I K A  ------<br /><br />//Faza U<br />//tranzystor górny<br />#define U_TR_G_PORTxPORTB<br />#define U_TR_G_DDRxDDRB<br />#define U_TR_G_PINxPINB<br />#define U_TR_G_PINPB1<br />#define U_TR_G_USTAW_DDRU_TR_G_DDRx  |=  (1&lt;&lt;U_TR_G_PIN); //ustaw port<br />#define U_TR_G_PIN_LU_TR_G_PORTx &amp;= ~(1&lt;&lt;U_TR_G_PIN); //ustaw niski<br />#define U_TR_G_ON TCCR1A |= (1&lt;&lt;COM1A1);//włącz tranzystor<br />#define U_TR_G_OFFTCCR1A &amp;=~(1&lt;&lt;COM1A1);//wyłącz tranzystor<br />#define U_TR_G_SPRAW_STAN   (TCCR1A &amp; (1&lt;&lt;COM1A1))//warunek stanu<br />//tranzystor dolny<br />#define U_TR_D_PORTxPORTD<br />#define U_TR_D_DDRxDDRD<br />#define U_TR_D_PINxPIND<br />#define U_TR_D_PINPD3<br />#define U_TR_D_USTAW_DDRU_TR_D_DDRx  |=  (1&lt;&lt;U_TR_D_PIN); //ustaw port<br />#define U_TR_D_PIN_LU_TR_D_PORTx &amp;= ~(1&lt;&lt;U_TR_D_PIN); //ustaw niski<br />//#define U_TR_D_ON U_TR_D_PORTx |=  (1&lt;&lt;U_TR_D_PIN); //włącz tranz.<br />//#define U_TR_D_OFFU_TR_D_PORTx &amp;= ~(1&lt;&lt;U_TR_D_PIN); //wyłącz tranz.<br />//#define U_TR_D_SPRAW_STAN(U_TR_D_PINx &amp;   (1&lt;&lt;U_TR_D_PIN)) //warunek stanu<br />#define U_TR_D_ON TCCR2A |=  (1&lt;&lt;COM2B1); //włącz tranz.<br />#define U_TR_D_OFFTCCR2A &amp;= ~(1&lt;&lt;COM2B1); //wyłącz tranz.<br />#define U_TR_D_SPRAW_STAN(TCCR2A &amp; (1&lt;&lt;COM2B1)) //warunek stanu<br /><br />//Faza V<br />//tranzystor górny<br />#define V_TR_G_PORTxPORTB<br />#define V_TR_G_DDRxDDRB<br />#define V_TR_G_PINxPINB<br />#define V_TR_G_PINPB3<br />#define V_TR_G_USTAW_DDRV_TR_G_DDRx  |=  (1&lt;&lt;V_TR_G_PIN); //ustaw port<br />#define V_TR_G_PIN_LV_TR_G_PORTx &amp;= ~(1&lt;&lt;V_TR_G_PIN); //ustaw niski<br />#define V_TR_G_ON TCCR2A |=  (1&lt;&lt;COM2A1);//włącz tranzystor<br />#define V_TR_G_OFFTCCR2A &amp;= ~(1&lt;&lt;COM2A1);//wyłącz tranzystor<br />#define V_TR_G_SPRAW_STAN(TCCR2A &amp; (1&lt;&lt;COM2A1))//warunek stanu<br />//tranzystor dolny<br />#define V_TR_D_PORTxPORTD<br />#define V_TR_D_DDRxDDRD<br />#define V_TR_D_PINxPIND<br />#define V_TR_D_PINPD5<br />#define V_TR_D_USTAW_DDRV_TR_D_DDRx  |=  (1&lt;&lt;V_TR_D_PIN); //ustaw port<br />#define V_TR_D_PIN_LV_TR_D_PORTx &amp;= ~(1&lt;&lt;V_TR_D_PIN); //ustaw niski<br />//#define V_TR_D_ON V_TR_D_PORTx |=  (1&lt;&lt;V_TR_D_PIN); //włącz tranz.<br />//#define V_TR_D_OFFV_TR_D_PORTx &amp;= ~(1&lt;&lt;V_TR_D_PIN); //wyłącz tranz.<br />//#define V_TR_D_SPRAW_STAN(V_TR_D_PINx &amp;   (1&lt;&lt;V_TR_D_PIN)) //warunek stanu<br />#define V_TR_D_ON TCCR0A |= (1&lt;&lt;COM0B1); //włącz tranz.<br />#define V_TR_D_OFFTCCR0A &amp;=~(1&lt;&lt;COM0B1); //wyłącz tranz.<br />#define V_TR_D_SPRAW_STAN(TCCR0A &amp; (1&lt;&lt;COM0B1)) //warunek stanu<br /><br /><br />//Faza W<br />//tranzystor górny<br />#define W_TR_G_PORTxPORTB<br />#define W_TR_G_DDRxDDRB<br />#define W_TR_G_PINxPINB<br />#define W_TR_G_PINPB2<br />#define W_TR_G_USTAW_DDRW_TR_G_DDRx  |=  (1&lt;&lt;W_TR_G_PIN); //ustaw port<br />#define W_TR_G_PIN_LW_TR_G_PORTx &amp;= ~(1&lt;&lt;W_TR_G_PIN); //ustaw niski<br />#define W_TR_G_ON TCCR1A |= (1&lt;&lt;COM1B1);//włącz tranzystor<br />#define W_TR_G_OFFTCCR1A &amp;=~(1&lt;&lt;COM1B1);//wyłącz tranzystor<br />#define W_TR_G_SPRAW_STAN(TCCR1A &amp; (1&lt;&lt;COM1B1))//warunek stanu<br />//tranzystor dolny<br />#define W_TR_D_PORTxPORTD<br />#define W_TR_D_DDRxDDRD<br />#define W_TR_D_PINxPIND<br />#define W_TR_D_PINPD7<br />#define W_TR_D_USTAW_DDRW_TR_D_DDRx  |=  (1&lt;&lt;W_TR_D_PIN); //ustaw port<br />#define W_TR_D_PIN_LW_TR_D_PORTx &amp;= ~(1&lt;&lt;W_TR_D_PIN); //ustaw niski<br />#define W_TR_D_ON W_TR_D_PORTx |=  (1&lt;&lt;W_TR_D_PIN); //włącz tranz.<br />#define W_TR_D_OFFW_TR_D_PORTx &amp;= ~(1&lt;&lt;W_TR_D_PIN); //wyłącz tranz.<br />#define W_TR_D_SPRAW_STAN(W_TR_D_PINx &amp;   (1&lt;&lt;W_TR_D_PIN)) //warunek stanu<br /><br /><br />//Kąty położenia wirnika<br />#define KOMUT_11<br />#define KOMUT_22<br />#define KOMUT_33<br />#define KOMUT_44<br />#define KOMUT_55<br />#define KOMUT_66<br />#define KOMUT_7 7<br />#define KOMUT_8 8<br /><br />//Wspólna definicja wyłączająca wszystkie tranzystory<br />#define WYLACZ_TRANZYSTORYU_TR_G_OFF; U_TR_D_OFF; V_TR_G_OFF; V_TR_D_OFF; W_TR_G_OFF; W_TR_D_OFF;<br /><br /><br />//--- D E F I N I C J E   P W M ---<br />#define PWM_MIN   240//początkowa wartość wypełnienia PWM<br /><br /><br />//Tryb pracy<br />#defineTRYB_START0<br />#defineTRYB_PRACA1<br /><br /><br />//--- D E F I N I C J E   K O M P A R A T O R A ----<br />#define KOMP_STAN_AKT(ACSR &amp; (1&lt;&lt;ACO))//aktualny stan wyjścia<br />//komparatora<br />#define KOMP_KANAL_UADMUX = 0;//kanał U do pomiaru BEMF<br />#define KOMP_KANAL_VADMUX = 1;//kanał V do pomiaru BEMF<br />#define KOMP_KANAL_WADMUX = 2;//kanał W do pomiaru BEMF<br /><br /><br />extern volatile unsigned charbldc_polozenie_wirnika;<br /><br /><br />extern void bldc_bezpiecznik(void);<br />extern void bldc_bezpiecznik_stop(void);<br />extern void bldc_start_komutacja(void);<br />extern void bldc_inicjuj_sterownik(void);<br />extern void bldc_start_delay_ms(unsigned char il_ms);<br />extern void bldc_start(void);<br /><br />extern volatile unsigned char bldc_tryb_pracy;   //aktualny tryb pracy<br />extern volatile unsigned int  bldc_komp_licznik; //licz. przerwań komparatora<br /><br />//extern volatile uint16_t wynik;[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5890">apollo1412</a> — 18 lis 2014, o 17:15</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[kicajek]]></name></author>
<updated>2014-11-17T17:31:55+01:00</updated>
<published>2014-11-17T17:31:55+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104556#p104556</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104556#p104556"/>
<title type="html"><![CDATA[Re: ATMEGA328p-pu błędny pomiar ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104556#p104556"><![CDATA[
Witam<br />Tu masz niespójność:[syntax=c]#define REF_VCC (0&lt;&lt;REFS1)|(1&lt;&lt;REFS0)....<br />...<br />...<br />ADMUX |= REF_VCC; //ust. źródło odniesienia 2.56 V[/syntax]<br />...no i to przesuwanie zera (0&lt;&lt;REFS1)?<br />Może zamieść swój kod oficjalnie to wtedy więcej osób go obejrzy.<br /><br />Pozdr.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=826">kicajek</a> — 17 lis 2014, o 17:31</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[apollo1412]]></name></author>
<updated>2014-11-17T16:08:23+01:00</updated>
<published>2014-11-17T16:08:23+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104533#p104533</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104533#p104533"/>
<title type="html"><![CDATA[Re: ATMEGA328p-pu błędny pomiar ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104533#p104533"><![CDATA[
100% liniowy, bo <br />- taki kupiłem<br />- działa dobrze (tzn. jak liniowy) w tym drugim programie co wrzuciłem - ADC328p<br />- problem występuje na 4 liniowych potencjometrach 1k, 10k, 110k i 240k<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5890">apollo1412</a> — 17 lis 2014, o 16:08</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[icer_cmg]]></name></author>
<updated>2014-11-17T15:54:19+01:00</updated>
<published>2014-11-17T15:54:19+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104531#p104531</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104531#p104531"/>
<title type="html"><![CDATA[Re: ATMEGA328p-pu błędny pomiar ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104531#p104531"><![CDATA[
A może masz potencjometr logarytmiczny a nie liniowy? Sprawdź miernikiem<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1636">icer_cmg</a> — 17 lis 2014, o 15:54</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[apollo1412]]></name></author>
<updated>2014-11-17T12:02:29+01:00</updated>
<published>2014-11-17T12:02:29+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104468#p104468</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104468#p104468"/>
<title type="html"><![CDATA[ATMEGA328p-pu błędny pomiar ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9299&amp;p=104468#p104468"><![CDATA[
Witajcie koledzy.<br />Robię mały projekcik gdzie potrzebny mi jest pomiar ADC z potencjometru. W moim głównym programie potencjometr działa jakbybył logarytmiczny, a ja potrzebuję żeby działał normalnie. W innym programie testowym ADC potencjometr działa poprawinie.<br />Wstawiam program ADC i mój z projektu BLDC. Kod z wykorzystaniem przetwornika który działa źle jest w pliku bldc.c, w funkcji przewrwania. <br />[syntax=cpp]case (KOMUT_7)://kąt 300 stopni<br />if(KOMP_STAN_AKT)//komparator = 1<br />{<br />if(l==255) l=0;<br />l++;<br />//DDRC|=(1&lt;&lt;PC5);<br />//inicjalizacja ADC<br />ADCSRA |= (1&lt;&lt;ADPS2)|(1&lt;&lt;ADPS1)|(1&lt;&lt;ADPS0); //preskaler 128 8000000/168<br />ADMUX |= REF_VCC; //ust. źródło odniesienia 2.56 V<br />ADCSRA |= (1&lt;&lt;ADEN); //włącz ADC<br />//wynik=0;<br />accu1_vol.ref_adc = 548;<br />accu1_vol.ref_v = 141;<br /><br />wynik = pomiar ( PC5 );<br />wynik=wynik/4;<br />//get_vol( wynik, &amp;accu1_vol );<br />//tr_cls(0);<br />tr_locate(3,3);<br />uart_putlong(wynik,10);<br />//tr_locate(5,5);<br />//uart_putlong(l,10);<br />//ADCSRA &amp;= ~(1&lt;&lt;ADPS2)|(1&lt;&lt;ADPS1)|(1&lt;&lt;ADPS0);//preskaler 128 8000000/168<br />ADCSRA &amp;= ~(1&lt;&lt;ADEN); //włącz ADC<br />bldc_bezpiecznik();<br />bldc_polozenie_wirnika = KOMUT_1; //komut. od początku<br />//włącz tranzystor dolny V<br />}<br />break;[/syntax]<br /><br />Dodam że przetwornik musi być włączony tylko na chwilę, bo w całym procesie działania programu potrzebny jest też komparator dlatego też na końcu case'a wyłączam ADC.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5890">apollo1412</a> — 17 lis 2014, o 12:02</p><hr />
]]></content>
</entry>
</feed>