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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2016-09-14T07:17:41+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=16198&amp;mode</id>
<entry>
<author><name><![CDATA[maverick_as]]></name></author>
<updated>2016-09-14T07:17:41+01:00</updated>
<published>2016-09-14T07:17:41+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168704#p168704</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168704#p168704"/>
<title type="html"><![CDATA[Re: Sterowanie serwami- jak zrobić?]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168704#p168704"><![CDATA[
Przy 6 serwach ,rozważ zastosowanie układu PCA9685 firmy NXP. Jest to 16 kanałowy, 12 bitowy kontroler PWM sterowany magistralą I2C.<br />Pozdr.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=9169">maverick_as</a> — 14 wrz 2016, o 07:17</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[czarekgr]]></name></author>
<updated>2016-09-13T17:48:42+01:00</updated>
<published>2016-09-13T17:48:42+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168670#p168670</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168670#p168670"/>
<title type="html"><![CDATA[Re: Sterowanie serwami- jak zrobić?]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168670#p168670"><![CDATA[
<div class="quotetitle">Mario17 napisał(a):</div><div class="quotecontent"><br />Lepszym sposobem było by sterowanie serwami jedno po drugim (zwłaszcza kiedy ma być ich 6) tzn. kiedy ustawisz wyjście serwa w stan wysoki i czekasz 1,5 - 2,5ms, to wtedy ustawiasz stan niski dla tego serwa, a dla kolejnego dopiero w tym momencie ustawiasz stan wysoki i tak po kolei dla wszystkich serw.<br />Sygnał sterujący jednym serwem trwa 20ms, więc dzieląc go przez 2,5ms (maksymalny czas trwania stanu wysokiego), wychodzi że w tym czasie można po kolei wysterować do 8 serw.<br /></div><br /><br />Nie wiem jak teraz, ale drzewiej to standardowo impuls sterujący był co 20 ms, więc to chyba bardzo dobra rada.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=14311">czarekgr</a> — 13 wrz 2016, o 17:48</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Mario17]]></name></author>
<updated>2016-09-13T16:48:21+01:00</updated>
<published>2016-09-13T16:48:21+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168669#p168669</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168669#p168669"/>
<title type="html"><![CDATA[Re: Sterowanie serwami- jak zrobić?]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168669#p168669"><![CDATA[
Lepszym sposobem było by sterowanie serwami jedno po drugim (zwłaszcza kiedy ma być ich 6) tzn. kiedy ustawisz wyjście serwa w stan wysoki i czekasz 1,5 - 2,5ms, to wtedy ustawiasz stan niski dla tego serwa, a dla kolejnego dopiero w tym momencie ustawiasz stan wysoki i tak po kolei dla wszystkich serw.<br />Sygnał sterujący jednym serwem trwa 20ms, więc dzieląc go przez 2,5ms (maksymalny czas trwania stanu wysokiego), wychodzi że w tym czasie można po kolei wysterować do 8 serw.<br /><br />Wygląda to mniej więcej tak (przykład dla 2 serw, atmega8, taktowanie 8MHz):<br />Inicjalizacja timera:<br />[syntax=c]TCCR1B |= (1&lt;&lt;WGM12) | (1&lt;&lt;CS11); // 1us<br />TIMSK |= (1&lt;&lt;OCIE1A) | (1&lt;&lt;OCIE1B);<br />OCR1A = 2500; // 2,5ms<br />OCR1B = 2500+1;// pierwsze przerwanie -&gt; COMP1A[/syntax]<br /><br />Obsługa przerwania:<br /><br />[syntax=c]ISR(TIMER1_COMPA_vect){<br />if(servo_cnt == 0) SERWO_1_ON;<br />if(servo_cnt == 1) SERWO_2_ON;<br />OCR1B = signal_ram&#91;servo_cnt&#93;;<br />}<br /><br />ISR(TIMER1_COMPB_vect){<br />if(servo_cnt == 0) SERWO_1_OFF;<br />if(servo_cnt == 1) SERWO_2_OFF;<br />servo_cnt++;<br />if(servo_cnt == 8) servo_cnt = 0;<br />}[/syntax]<br /><br />Wartość OCRA oznacz czas po jakim włączane są kolejne serwa, a do OCRB wpisujesz wartość w zależności od położenia serwa od 1500 do 2500 ale tak żeby nie przekroczyć wartość w OCRA (wtedy nie wykona się przerwanie COMPB).<br />W ten sposób można zrealizować to na jednym timerze, z precyzją do 1000 pozycji serw (teoretycznie <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> ), a przerwania od timera nie obciążają zbytnio mikrokontrolera, bo przerwanie wywoływane jest co ok 1ms (w zależności od położenia danego serwa), a nie jak w twoim przypadku co kilkanaście us.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3695">Mario17</a> — 13 wrz 2016, o 16:48</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[arek3572]]></name></author>
<updated>2016-09-13T13:17:21+01:00</updated>
<published>2016-09-13T13:17:21+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168658#p168658</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168658#p168658"/>
<title type="html"><![CDATA[Sterowanie serwami- jak zrobić?]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=16198&amp;p=168658#p168658"><![CDATA[
Witam wszystkich!!<br />Mam problem z wysterowaniem serwomechanizmów. Korzystam z ATmegi32, 16MHz. Wykorzystuję programowe pwm, wbudowany przetwornik ADC. Do sterowania służy joystick. <br />O ile jedno serwo udało mi się wysterować i działa stabilnie, bez żadnych niechcianych drgnięć o tyle przy dwóch serwach mój sposób się już nie sprawdza, ponieważ działają one niestabilnie (a co dopiero bedzie przy 6). Proszę o pomoc, jakiś pomysł, nakierowanie mnie na właściwą ścieżkę <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" />  <br /><br />Kod programu:<br />[syntax=c]// definicje zmiennych do sterowania 3 kanałami programowych PWM<br />// zmienne typu uint8_t, rozdzielczość 8-bitowa<br />volatile uint8_t  pwm1, pwm2, pwm3;<br /><br /><br />//********************  główna funckja programu ******************<br />int main( void ) {<br /><br /><br /><br /><br />DDRC |= (1&lt;&lt;WE_A);<br />DDRD |= (1&lt;&lt;WE_B);<br /><br />// ustawienie pinów kanałów programowych PWM jako WYJŚCIA<br /><br />DDRC |= (1&lt;&lt;PC3)|(1&lt;&lt;PC4)|(1&lt;&lt;PC5);<br /><br /><br /><br /><br /><br /><br /><br />// ustawienia TIMER2 w tryb CTC<br />TCCR2 |= (1&lt;&lt;WGM21);// tryb  CTC<br />TCCR2 |= (1&lt;&lt;CS21);// preskaler = 8<br />OCR2 = 156;// dodatkowy podział częsttotliwości przez 156<br />TIMSK |= (1&lt;&lt;OCIE2);// zezwolenie na przerwanie CompareMatch<br /><br /><br /><br /><br />// inicjalizacja ADC<br />ADCSRA |= (1&lt;&lt;ADEN); // włącz ADC<br />ADCSRA |= (1&lt;&lt;ADPS2)|(1&lt;&lt;ADPS1)|(1&lt;&lt;ADPS0); // preskaler = 128<br />ADMUX |= REF_256;// ustawiamy wewn. źr odn. 2,56V<br /><br /><br /><br /><br />USART_Init( __UBRR ); //inicjalizacja UARTA<br /><br /><br /><br />uint16_t wynik2 = 0;<br /><br /><br />sei();<br />//******* główna pętla programu<br />while(1) {<br /><br /><br />// ADC<br />wynik2 = pomiar(2);<br /><br /><br /><br />   if(wynik2 &gt; 425 &amp;&amp; wynik2 &lt; 439){     //joystick w pozycji środkowej<br />   pwm1 = 20;<br />     }<br />   else<br /><br />   if(wynik2  &gt; 439  &amp;&amp; wynik2 &lt; 540){   //joystick wysunięty w lewo<br />    pwm1 = 20 +( (wynik2 - 439)/9);<br /> }<br />   else<br /><br />   if(wynik2 &gt;= 540) pwm1 = 31; //pozycja skrajna<br />   else<br /><br />if(wynik2 &lt; 425 &amp;&amp; wynik2 &gt;305 ){       //joystick wysunięty w prawo<br />pwm1 = 20 - ((425 - wynik2)/11);<br /> }<br /><br /><br />}<br /><br />}<br /><br /><br /><br /><br /><br /><br />// pomiar napięcia<br />uint16_t pomiar( uint8_t kanal ) {<br /><br />ADMUX = (ADMUX &amp; 0b11111000) | kanal;<br /><br />ADCSRA |= (1&lt;&lt;ADSC);  // start konwersji<br /><br />while( ADCSRA &amp; (1&lt;&lt;ADSC) );<br /><br />return ADCW;<br />}<br /><br />// ciało procedury obsługi przerwania Compare Match Timera2<br />ISR( TIMER2_COMP_vect )<br />{<br />static uint8_t cnt; // definicja naszego licznika PWM<br /><br />// bezpośrednie sterowanie wyjściami kanałów PWM<br /><br />if(cnt&gt;=pwm1) PORTC &amp;= ~(1&lt;&lt;PC3); else PORTC |= (1&lt;&lt;PC3);<br />if(cnt&gt;=pwm2) PORTC &amp;= ~(1&lt;&lt;PC4); else PORTC |= (1&lt;&lt;PC4);<br />if(cnt&gt;=pwm3) PORTC &amp;= ~(1&lt;&lt;PC5); else PORTC |= (1&lt;&lt;PC5);<br /><br />cnt++;// zwiększanie licznika o 1<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=7988">arek3572</a> — 13 wrz 2016, o 13:17</p><hr />
]]></content>
</entry>
</feed>