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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-02-03T15:15:03+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=22&amp;t=4339&amp;mode</id>
<entry>
<author><name><![CDATA[pawel89]]></name></author>
<updated>2014-02-03T15:15:03+01:00</updated>
<published>2014-02-03T15:15:03+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=68193#p68193</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=68193#p68193"/>
<title type="html"><![CDATA[Re: [ATmega88PA] Generator 20 kanałów PWM]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=68193#p68193"><![CDATA[
Świetny pomysł czasem sam też chciałbym coś przetestować i brakuje mi wolnego PWM-a a naraz jest 20 PWM <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" /> Gratulacje<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=2578">pawel89</a> — 3 lut 2014, o 15:15</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mopsiok]]></name></author>
<updated>2013-10-01T14:32:48+01:00</updated>
<published>2013-10-01T14:32:48+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51495#p51495</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51495#p51495"/>
<title type="html"><![CDATA[Re: [ATmega88PA] Generator 20 kanałów PWM]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51495#p51495"><![CDATA[
Dzięki za odpowiedź Mirku, teraz już wiem dlaczego robić tak a nie inaczej. Staram się pisać zgodnie z &quot;dobrym stylem programowania&quot;, po prostu nie zdawałem sobie sprawy że to co robię jest &quot;złe&quot; <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" />.<br />Zawsze wychodziłem z założenia że najwięcej się człowiek uczy na własnych błędach - prosty projekt, a ile ciekawostek się dowiedziałem. Zmienne globalne, odpowiednie typowanie, BADISR a nawet flagi przerwań (za tę informację szczególnie dziękuję, doceniam jej znaczenie ^^).<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1371">mopsiok</a> — 1 paź 2013, o 14:32</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2013-10-01T11:25:17+01:00</updated>
<published>2013-10-01T11:25:17+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51481#p51481</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51481#p51481"/>
<title type="html"><![CDATA[Re: [ATmega88PA] Generator 20 kanałów PWM]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51481#p51481"><![CDATA[
<div class="quotetitle">stachu napisał(a):</div><div class="quotecontent"><br />Przepraszam za wprowadzanie w błąd, przykład podałem w czystym GCC dla PC<br /></div><br /><br />Ale nie ma za co przepraszać - wszyscy razem się tu uczymy, a przykład podałeś dobry tyle że dla zmiennych lokalnych. Przyznam, że ja nawet nie pamiętałem o tym że jak się wpisze do tablicy przy inicjalizacji pierwszą wartość w takiej zmiennej lokalnej to kolejne zostaną już uzupełnione zerami a sprawdzić też jakoś mi się nie chciało.<br /><br />Więc jak widać - z takiej dyskusji zawsze można się czegoś dowiedzieć <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 1 paź 2013, o 11:25</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[stachu]]></name></author>
<updated>2013-10-01T11:22:14+01:00</updated>
<published>2013-10-01T11:22:14+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51480#p51480</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51480#p51480"/>
<title type="html"><![CDATA[Re: [ATmega88PA] Generator 20 kanałów PWM]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51480#p51480"><![CDATA[
No cóż myliłem się późno było ale dowiedziałem się przy okazji parę ciekawych rzeczy.<br /><br />Przepraszam za wprowadzanie w błąd, przykład podałem w czystym GCC dla PC<br /><br />Pozdrawiam.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=72">stachu</a> — 1 paź 2013, o 11:22</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2013-10-01T10:46:32+01:00</updated>
<published>2013-10-01T10:46:32+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51471#p51471</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51471#p51471"/>
<title type="html"><![CDATA[Re: [ATmega88PA] Generator 20 kanałów PWM]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51471#p51471"><![CDATA[
<div class="quotetitle">mopsiok napisał(a):</div><div class="quotecontent"><br />Dzięki za zainteresowanie, cieszę się że projekt nie został jakoś szczególnie skrytykowany<br /></div><br /><br />Projekt działa <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> ... pokazałeś nawet dość fajne efekty. A reszta to tylko uwagi właśnie, które mogą się przyczynić do podniesienia własnego skill'a w dalszym programowaniu.<br /><br />Dodam więc, tak jak mówił Antystatyczny, że akurat taką obsługę PWMów programowych też bym zrobił w przerwaniu. Flagi owszem są potrzebne no ale nie należy przesadnie do tego podchodzić bo gdyby tak miało być jak u ciebie to można byłoby JESZCZE BARDZIEJ skrócić kod i w ogóle wywalić procedurę obsługi przerwania skoro w nim jest ustawiana tylko flaga. Dlaczego ? już tłumaczę - zresztą nie pierwszy raz na tym forum <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> .... ano dlatego że masz flagę sprzętową przerwania i z niej można korzystać dokładnie tak samo jak z tej programowej tyle tylko że tracisz O WIELE mniej czasu no i kodu we flashu robi się mniej <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> ... jak ? o tak: (twoja pętla główna)<br /><br />[syntax=c]for (;;) {<br />                if ( TIFR0 &amp; (1&lt;&lt;OCF0A ) {  // sprawdzamy czy wystąpiła flaga przerwania<br />                        compare();<br />                        TIFR0 |= (1&lt;&lt;OCF0A); // kasujemy tę flagę przerwania ale UWAGA! przez wpisanie JEDYNKI!<br />                }<br />        }[/syntax]<br />(a oczywiście wywalasz całego ISR'a <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> no i przy inicjalizacji nie włączasz przerwań w tym timerze0 <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />  )<br /><br />Widzisz jak prosto .... ? ... dlatego twój przykład jest można powiedzieć troszkę nawet (ale nie odbierz tego źle - żartobliwie mówię) wynaturzeniem wręcz korzystania z flag. Ja wprawdzie w niebieskiej książce podaję podobny przykład przy obsłudze RTC i ustawianiu w ten sposób flagi ... ale to TYLKO po to żeby zrozumieć w ogóle o co chodzi w tych mechanizmach flag. Warto ich używać gdy coś jeszcze się dzieje w przerwaniu i niejako przy okazji wtedy można machać flagą <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> albo flagami do innych celów. <br /><br />Do tego dodam, że u ciebie to działa bo w pętli głównej nic innego nie robisz poza obsługą tych PWM'ów .... ale gdybyś tam miał jeszcze kawał innego programu to sam byś zobaczył że nastąpiłaby MASAKRAAAA .... wtedy jedynym znowu ratunkiem byłoby przeniesienie tych porównań bezpośrednio do procedury obsługi przerwania ... a program główny robiłby swoje w pętli głównej .... taką drogą warto iść<br /><br />Kolejna sprawa, to ten dziwoląg mały w kodzie <img src="https://forum.atnel.pl/images/smilies/icon_e_sad.gif" alt=":(" title="Smutny" /><br /><br />[syntax=c]ISR (BADISR_vect) {} //obsluga pozostalych przerwan[/syntax]<br /><br />w ogóle niepotrzebny bo domyślnie kompilator sam to robi - to DOKŁADNIE tak samo jak z tą inicjalizacją zerami przez ciebie - niepotrzebną zresztą jak już wiesz.<br /><br />--------------<br /><br />unsigned char vs uint8_t<br /><br />tu nie chodzi o różnicę pomiędzy typami ... bo jest to DOKŁADNIE  to samo ale ... ale jest pewne ale ... o którym rzadko kto wspomina a potem początkujący tacy jak ty, którzy mówią z uporem że im się to podoba a programują w AVR GCC później mają rwanie włosów z głowy gdy przyjdzie wchodzić w dalsze bardziej zaawansowane techniki programowania - gdzie szczególnie wtedy początki są trudne ....<br /><br />Po części wyjaśniam to także w swoim Bluebooku<br /><br /><!-- m --><a class="postlink" href="http://atnel.pl/mikrokontrolery-avr-jezyk-c.html" >http://atnel.pl/mikrokontrolery-avr-jezyk-c.html</a><!-- m --><br /><br />i także już niejednokrotnie pisałem o tym na forum ale co tam <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> jeszcze raz<br /><br />1. char - jest DOMYŚLNIE w opcjach kompilacji w AVR GCC zamieniany i tak na unsigned char - więc już chociażby z tego powodu nie ma w ogóle sensu pisać unsigned char (znowu to coś jak z tymi inicjalizacjami zerem) <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> ... Oczywiście można sobie wyłączyć w opcjach kompilatora tą automatyczną zamianę tylko po co panie? po co ?<br /><br />A tymczasem taki początkujący jak ty - sporo piszący w AVR GCC dość szybko się przyzwyczaja do kociego unsigned char i jeszcze mówi że mu się to podoba <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> (matko! TYLE pisaniny <img src="https://forum.atnel.pl/images/smilies/icon_lol.gif" alt=":lol:" title="Śmieje się" /> zamiast krótkiego uint8_t)<br />Ale ok pierwsza zaleta jak widać to mniej pisania, ok ktoś powie czochra mnie to, Druga w takim razie zaleta - jak widać typ uint8_t to dla oka od razu jasne jest że chodzi o unsigned int short (8-bit) .... <br /><br />No i NAJWAŻNIEJSZE - uważaj teraz dobrze - przede wszystkim twórcy C stworzyli typ char jak myślisz dlaczego ? zadałeś sobie kiedyś to pytanie ? ... ja tak i poszukałem , odpowiedź jest prosta char to skrót od character, czyli znak. I właśnie ten typ zwyczajowo służył do trzymania zmiennych które związane były z trzymaniem w nich np kodów ASCII znaków .... natomiast wszelkiego rodzaju liczby trzyma się w typach wszelkiej maści int, short int, long int itp<br /><br />Tyle że z kolei stwórcy AVR GCC (mądrzy ludzie zresztą) postanowili znacząco uprościć życie programistom procków i żeby nikt się nie zastanawiał za długo ile bajtów/bitów ma np typ int czy long int czy short int w AVR GCC to stworzono (i słusznie)<br /><br />uint8_t<br />int8_t<br /><br />uint16_t (odpowiednik unsigned int)<br />int16_t (odpowiednik int)<br /><br />uint32_t <br /><br />.... i tak dalej<br /><br />i teraz UWAGA .... przyjdzie ci w swojej dalszej karierze AVR GCC korzystać z wbudowanych funkcji w AVR GCC szczególnie operujących na wskaźnikach do char , wskaźnikach do uintX_t itp ....<br /><br />i SZLAG cię będzie trafiał gdy zaczną się pojawiać kocie warningi no bo np do jakiejś tam funkcji przekazać chcesz wskaźnik do tablicy znaków ASCII np twoja zmienna:<br /><br />unsigned char tab[]=&quot;test&quot;;<br /><br />funkcja( tab );<br /><br />a tu warning i warning - że typy się nie zgadzają <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> I dobrze ci tak <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> powiedziałbym - a po co stosujesz KOCI unsigned char zamiast char panie ? Bo z punktu widzenia kompilatora to już jest RÓŻNICA którą trzeba owarningować .... <br /><br />więc gdybyś szedł za poradami tych ludzi którzy stworzyli kompilator z którego korzystasz - to nie pisałbyś właśnie unsigned char tylko char (bo domyślnie kompilator i tak zamieni to na unsigned) i masz z głowy<br /><br />ale jak się uprzesz to możesz zostać przy swoim kocim unsigned i funkcję wołać tak <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br />funkcja( (char*) tab );<br /><br />czyli robiąc jawne rzutowanie na typ char* ... ale skoro lubisz tyle pisania to może przy tym zostaniesz <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> do czasu aż kiedyś i tak cię to wkurzy - tak samo jak (wciąż wracam - zerowanie zmiennych globalnych) <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br />jak to mówią - wystarczy tylko poczytać instrukcję<br /><br />------------------------<br /><br />i ostatni argument dlaczego uint8_t zamiast unsigned char czy też zamiast char.<br /><br />bo oczywiście taka forma syntaktycznie jest w pełni poprawna, np:<br /><br />[syntax=c]char i;<br />for( i=0; i&lt;10; i++ ) rób_coś_tam();[/syntax]<br /><br />ale styl dobrego programowania w C a nie jakieś tam wymogi formalne mówi nam że warto to zrobić tak:<br /><br />[syntax=c]uint8_t i;<br />for( i=0; i&lt;10; i++ ) rób_coś_tam();[/syntax]<br /><br />mniej więcej z takiego samego powodu jak ten poniżej, bo np jak widzisz takie zmienne w kodzie gdzie masz akurat tysiąc różnych zmiennych a pomiędzy nimi widać:<br /><br />[syntax=c]char buf&#91;20&#93;;<br />char i,z,k;<br />char p,m;[/syntax]<br /><br />dla mnie - jak widzę taki kod - to widzę od razu niedbalstwo o typy o ich nazewnictwo, bo gdyby to napisać tak:<br /><br />[syntax=c]char buf&#91;20&#93;;<br />char zn;<br />uint8_t i,z,k;<br />uint8_t p,m;[/syntax]<br /><br />to ja od razu na pierwszy rzut oka widzę, że O! gościu używa zmiennej tablicowej buf na jakiś bufor znaków ASCII, tak samo zmiennej zn. A pozostałe zmienne to typowe numeryczne do jakichś tam obliczeń.<br /><br />Czyli NAWET z tak trywialnego kawałka kodu coś widać dla oka - na pierwszy RZUT ... a wiadomo że im dłuższy kod tym ważniejsza jest jego CZYTELNOŚĆ i PRZEJRZYSTOŚĆ. A to był jeden z NAJWAŻNIEJSZYCH celów jaki przyświecał stwórcom języka C. Tyle że ma on tak dużo możliwości i można go używać na milion sposobów, że bardzo szybko tam gdzie wkrada się niedbałość o styl dobrego programowania to kody są o wiele trudniejsze do analizy nawet dla samego siebie po kilku latach ....<br /><br />Popytaj ludzi - ci którzy używają char zgodnie z tą zasadą - powiedzą ci , że jak tylko człowiek to zrozumie i się przyzwyczai to później samemu inaczej wręcz czyta się własne nawet kody programów.<br /><br />O to chodzi <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br /><strong><span style="color: #808000">------------------------ [ Dodano po: 1 minucie ]</span></strong><br /><br /><div class="quotetitle">mopsiok napisał(a):</div><div class="quotecontent"><br />2. Przyzwyczajenia . Staram się nie pakować dłuższego kodu w obsługę przerwania, a stosować raczej flagi.<br /></div><br /><br />I sam widzisz - już masz przyzwyczajenia ale wcale nie najlepsze bo nie chodzi o długość <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> ale o jakość <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> ... to taki żarcik - ale nawiązujący też do tego co napisałem wyżej.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 1 paź 2013, o 10:46</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mopsiok]]></name></author>
<updated>2013-10-01T09:46:37+01:00</updated>
<published>2013-10-01T09:46:37+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51469#p51469</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51469#p51469"/>
<title type="html"><![CDATA[Re: [ATmega88PA] Generator 20 kanałów PWM]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51469#p51469"><![CDATA[
Cześć!<br /><br />Miło mi że rozwinęła się dyskusja w związku z moim tworem, a raczej w związku z moimi błędami programowymi <img src="https://forum.atnel.pl/images/smilies/icon_lol.gif" alt=":lol:" title="Śmieje się" />. Dzięki za rady, bardzo fajnie że nie trzeba ustawiać tablic i zmiennych globalnych, doprowadzało mnie to do szału <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" />. Odpowiadając po kolei:<br /><br /><div class="quotetitle">Antystatyczny napisał(a):</div><div class="quotecontent"><br />1. W jakim celu obsługujesz skok w złe przerwanie?<br />2. Co zadecydowało o tym, że compare() jest funkcją w pętli głównej zamiast w przerwaniu?<br /></div><br />1. Przyznam że nie wiem, C uczyłem się z jakiejś tam książki i we wszystkich przykładach była ta obsługa. Pewnie nie ma to sensu, ale wolę dmuchać na zimne, bo to i tak tylko dwie linijki kodu.<br />2. Przyzwyczajenia <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />. Staram się nie pakować dłuższego kodu w obsługę przerwania, a stosować raczej flagi.<br /><br /><div class="quotetitle">mirekk36 napisał(a):</div><div class="quotecontent"><br />no i te paskudne typy [...]<br /></div><br />Przyznam że nie bardzo rozumiem różnicę między unsigned char a uint8_t. Dla mnie to pierwsze wygląda ładniej, dlatego go używam <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />. Poszukałem na szybko różnicy między tymi dwoma typami, ale znalazłem tylko coś o tym że to drugie informuje kompilator o tym że przechowujemy liczbę a nie znak, ale... co za różnica? Byłbym wdzięczny gdyby ktoś obeznany mi to wytłumaczył.<br /><br />Dzięki za zainteresowanie, cieszę się że projekt nie został jakoś szczególnie skrytykowany <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" />.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1371">mopsiok</a> — 1 paź 2013, o 09:46</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2013-10-01T04:51:22+01:00</updated>
<published>2013-10-01T04:51:22+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51465#p51465</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51465#p51465"/>
<title type="html"><![CDATA[Re: [ATmega88PA] Generator 20 kanałów PWM]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51465#p51465"><![CDATA[
<div class="quotetitle">stachu napisał(a):</div><div class="quotecontent"><br />Tylko skopiowałem <img src="https://forum.atnel.pl/images/smilies/icon_razz.gif" alt=":P" title="Pokazuje język" /> ale dzięki za info <br /><br />To prawda przynajmniej dla czystego GCC i PC <img src="https://forum.atnel.pl/images/smilies/icon_razz.gif" alt=":P" title="Pokazuje język" /> bo o tym mówi standard C <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /></div><br /><br />Stachu nie chcę się kłócić ale ....<br /><br />standard C mówi co innego wg mnie<br /><br />przykłady które pokazałeś pięknie pokazują co się dzieje ze zmiennymi które inicjalizujemy jako zmienne lokalne czyli wewnątrz funkcji. <br /><br />Ba! nawet w pierwszym przypadku na fotce po lewej kompilator KRZYCZY i wymiotuje warningami że tablica jest niezainicjalizowana ale że używasz kociego Atmel Studio to pewnie nawet tego nie widzisz bo domyślnie te warningi są wyłączone - a to jest właśnie jeden z wielu kamyczków z mojej strony do tego że atmel studio jest KOCIE niestety <img src="https://forum.atnel.pl/images/smilies/icon_e_sad.gif" alt=":(" title="Smutny" /> Poza tym wyjaśniam w Bluebooku co się dzieje ze zmiennymi inicjalizowanymi wewnątrz funkcji - że tworzą się na stosie i może się zdarzyć choć nie musi, że nie nie będą one miały zerowych wartości. To jest NORMALNE ... i o tym mówi standard C<br /><br />ale mówi też jeszcze o czymś innym .... otóż o tym, że jeśli zmienne definiujemy jako GLOBALNE, to czy tego chcesz czy nie chcesz będą one miały ZEROWE wartości i nie ma sensu w ogóle ich inicjalizować zerem ani tak:<br /><br />[syntax=c]volatile unsigned char OCR_&#91;20&#93; = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //wartosci programowych PWM[/syntax]<br /><br />ani tak<br /><br />[syntax=c]volatile unsigned char OCR_&#91;20&#93; = {0}; //wartosci programowych PWM[/syntax]<br /><br />bo pojawią się w sekcji zmiennych globalnych gdzie wszystkie są ZEROWANE automatycznie przy starcie ... i nawet nie ma sensu ich inicjalizować wtedy zerami &quot;tak na wszelki wypadek&quot; <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> bo i tak kompilator będzie miał to głęboko gdzieś <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> Zresztą zrób sobie taki sam test jak na obrazku po lewej tylko że definicję tablicy daj w obszarze zmiennych globalnych czyli przed main ok ?<br /><br />--------------------------------------------<br /><br />oczywiście, że specyfikator volatile jest tu absolutnie niepotrzebny przy tej tablicy i to z dwóch powodów:<br /><br />1. bo nie jest to zmienna używana w przerwaniu<br />2. nawet gdyby była używana w przerwaniu i programie głównym - to w przypadku tablic volatile można pominąć bo i tak dostęp do nich jeśli odwołujemy się oczywiście przez indeks do całej tablicy jest także w asemblerze w ten sam sposób obsługiwany i nie może być zoptymalizowany. Ale gdyby gdzieś w kodzie programu ktoś chciał użyć jednego elementu tablicy np &amp;tab[3] przez wrzucenie go do zmiennej trzeba byłoby sprawdzić bo teraz nie pamiętam.<br /><br />--------------------------------<br /><br />mopsiok - z tego co wyżej napisałem widać, że w ogóle niepotrzebnie próbujesz inicjalizować zerem wszystkie zmienne globalne - po prostu musisz na przyszłość zapamiętać co robi standardowo kompilator <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> będziesz miał mniej pisania<br /><br />no i te paskudne typy<br /><br />[syntax=c]unsigned char[/syntax]<br /><br /><img src="https://forum.atnel.pl/images/smilies/icon_e_sad.gif" alt=":(" title="Smutny" /> doprowadzą cię kiedyś do rozpaczy w AVR GCC zobaczysz - po to wymyślono typ<br /><br />[syntax=c]uint8_t[/syntax]<br /><br />żeby go stosować w takich przypadkach....<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 1 paź 2013, o 04:51</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[stachu]]></name></author>
<updated>2013-09-30T23:35:46+01:00</updated>
<published>2013-09-30T23:35:46+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51461#p51461</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51461#p51461"/>
<title type="html"><![CDATA[Re: [ATmega88PA] Generator 20 kanałów PWM]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51461#p51461"><![CDATA[
Tylko skopiowałem <img src="https://forum.atnel.pl/images/smilies/icon_razz.gif" alt=":P" title="Pokazuje język" /> ale dzięki za info <br /><br /><a href="http://forum.atnel.pl/_obrazki/o/72/61af20cc854a2b9457e4abbafb8b014a.png"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/72/61af20cc854a2b9457e4abbafb8b014a.png" alt="Obrazek" /></a><a href="http://forum.atnel.pl/_obrazki/o/72/5d174a4d71fd0d644f45fee0d1a5dc5d.png"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/72/5d174a4d71fd0d644f45fee0d1a5dc5d.png" alt="Obrazek" /></a><br /><br />To prawda przynajmniej dla czystego GCC i PC <img src="https://forum.atnel.pl/images/smilies/icon_razz.gif" alt=":P" title="Pokazuje język" /> bo o tym mówi standard C <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=72">stachu</a> — 30 wrz 2013, o 23:35</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[stachu]]></name></author>
<updated>2013-09-30T22:45:19+01:00</updated>
<published>2013-09-30T22:45:19+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51458#p51458</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51458#p51458"/>
<title type="html"><![CDATA[Re: [ATmega88PA] Generator 20 kanałów PWM]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51458#p51458"><![CDATA[
Witam super <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />Może się czepiam ale warto wiedzieć, że jeżeli deklarujemy np 20 elemntową tablicę i wpiszemy jedną wartość w tablicy to automatycznie reszta wartości otrzymuje zera. W przeciwieństwie kiedy deklarujemy tylko tablice bez przypisywania jakichkolwiek wartości bo wtedy mamy przypadek dokładnie jak ze zmienną czyli mamy przypadkowe wartości.<br /><br />czyli starczy zapisać<br /><br />[syntax=c]volatile unsigned char OCR_&#91;20&#93; = {0}; //wartosci programowych PWM[/syntax]<br /><br />bo reszta tablicy zostaje wypełniona zerami <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />wykonanie super <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />Pozdrawiam<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=72">stachu</a> — 30 wrz 2013, o 22:45</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mopsiok]]></name></author>
<updated>2013-09-30T21:53:30+01:00</updated>
<published>2013-09-30T21:53:30+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51453#p51453</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51453#p51453"/>
<title type="html"><![CDATA[[ATmega88PA] Generator 20 kanałów PWM]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=4339&amp;p=51453#p51453"><![CDATA[
Cześć!<br />Chciałbym po raz pierwszy na tym forum pochwalić się swoim tworem <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />. Na wstępie zaznaczę, że ani toto nowatorskie, ani wybitne, ale kiedyś trzeba zacząć, a tak się złożyło że akurat skończyłem tworzyć coś nowego. Pragnę więc przedstawić Wam generator 20 kanałów PWM.<br /><a href="http://forum.atnel.pl/_obrazki/o/1371/82d5ffc1b06a2681b1858bc73b389b3e.JPG"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/1371/82d5ffc1b06a2681b1858bc73b389b3e.JPG" alt="Obrazek" /></a><br /><br />Projekt zrealizowany jest w oparciu o ATmegę88PA z kwarcem 20MHz. Postawiłem na prostą komunikację - 2 bajty po UART i mamy zmodyfikowany dowolny z 20 kanałów. Choć tak naprawdę w normalnej pracy można użyć tylko 19 - dwudziesty jest na pinie resetu, który trzeba wyłączyć by móc go używać jako kanału PWM. Raczej nigdy z niego nie skorzystam, nie mam narzędzi do późniejszego odblokowania procka.<br />W każdym razie, warto napisać coś o osiągach tego tworu. Przed kompilacją programu w pliku nagłówkowym należy określić które kanały mają być włączone - każdy taki jeden kanał to 8 cykli zegara więcej przy każdym przerwaniu timera. Dla wszystkich 20 kanałów cała funkcja generująca sygnały trwa 180 cykli, co przy 8-bitowej rozdzielczości sprawia że docelowa częstotliwość kanałów PWM nie może przekroczyć 434Hz. Oczywiście im więcej kanałów wyłączymy, tym większą częstotliwość możemy ustawić - przykładowo, dla 5 kanałów możemy ustawić częstotliwość do 1300Hz. <br />Wszystkie te opcje - wybór kanałów, częstotliwość, szybkość USART - można zmienić w pliku nagłówkowym.<br /><a href="http://forum.atnel.pl/_obrazki/o/1371/8b689146b429a3eeedcc9d34e4827aa8.png"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/1371/8b689146b429a3eeedcc9d34e4827aa8.png" alt="Obrazek" /></a><br /><br />Jeśli chodzi o sam kod generujący kanały, rozwiązanie jest bajecznie proste. Jest sobie tablica przechowująca wartości &quot;programowych OCR&quot; dla wszystkich 20 kanałów, jest również zmienna &quot;programowego TCNT&quot;. Ich działanie jest analogiczne ze sprzętowymi odpowiednikami - wartość TCNT jest zwiększana przy każdym wywołaniu funkcji, a potem sprawdzany jest warunek czy TCNT przekroczyło wartość OCR - jeśli tak, dany kanał jest zerowany. Przy powrocie TCNT do 0, następuje powtórne ustawienie wszystkich kanałów i jazda zaczyna się od nowa.<br /><br />Uwagi montażowe:<br />Po wytrawieniu i zlutowaniu płytki, należy jeszcze przystosować ją do docelowej pracy. Jeśli mamy zamiar wykorzystać pin resetu jako 20. kanał PWM, należy rozewrzeć zworkę resetEN. W moim przypadku mam tam na stałe wlutowany rezystor zworkopodobny (&quot;0R&quot;). Drugą sprawą jest wybór zasilania - zakładając zworkę regON włączamy do obwodu zasilającego stabilizator, na który możemy podać napięcie &gt;5V. W przeciwnym wypadku układ należy zasilić stabilizowanymi 5V.<br />Układ można zaprogramować bezpośrednio na płytce, podłączając linie programatora do odpowiednio oznaczonych wyprowadzeń. Podczas programowania stabilizator musi być odłączony.<br /><a href="http://forum.atnel.pl/_obrazki/o/1371/b515a4699f20cae8541f4fb897a13849.png"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/1371/b515a4699f20cae8541f4fb897a13849.png" alt="Obrazek" /></a><br /><br />Wnioski na dziś: <br />Spodziewałem się po tym dziwolągu nieco więcej niż mi dał <img src="https://forum.atnel.pl/images/smilies/icon_lol.gif" alt=":lol:" title="Śmieje się" />. Miałem nadzieję na jakiś sensowny multipleksing, ale według moich obserwacji wymagałby on innej komunikacji - najpierw wysyłanie modyfikacji PWMów, a dopiero potem &quot;zatrzaskiwanie&quot; wszystkich nowych wartości. Może komuś będzie się to chciało dopisać, ale ja nie mam już ochoty na zmianę sposobu komunikacji.<br /><br />Na koniec chciałbym jeszcze podkreślić, że zdaję sobie sprawę z istnienia dedykowanych scalaków do generowania PWM, które zapewne robią to lepiej niż ta oto zabaweczka. Nie zawsze chodzi jednak o możliwość wielu zastosowań - czasem warto coś zrobić dla samego faktu robienia <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" />. No a poza tym nie mogłem znaleźć tych scalaków w SMD. Dodatkowo sporym plusem jest fakt, że zabawka używa do komunikacji USART, co umożliwia sterowanie przy pomocy komputera. Poniżej zdjęcie i filmik z efektu sterowania PWMów komputerem przy pomocy Pythona. Genialny efekt to to może nie jest, ale dobrze ukazuje jak łatwo się tym steruje.<br /><a href="http://forum.atnel.pl/_obrazki/o/1371/86f31114fc5f2992e5275fd0bc3f83e8.JPG"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/1371/86f31114fc5f2992e5275fd0bc3f83e8.JPG" alt="Obrazek" /></a><br /><div style="width: 583px; height: 471px; margin: 0 auto; padding-left: 26px; padding-top: 48px; background: url('https://www.atnel.pl/download/atnel_tv.png') no-repeat;"> <strong>iframe</strong> </div><br /><br /><br />Tymczasem pozdrawiam i zapraszam do dyskusji <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br />mopsiok<br /><br /><br />Plik main.c:<br />[syntax=c]/*<br /> * PWM generator<br /> * ATmega88PA generujaca 20 sygnalow PWM o zadanej czestotliwosci wzorcowej i 8bitowej rozdzielczosci<br /> *<br /> * Aby zmienic wypelnienie jednego z kanalow, nalezy wyslac po USART 1-bajtowy numer kanalu &#91;0..19&#93;,<br /> * a nastepnie nowa wartosc wypelnienia.<br /> *<br /> * numeracja kanalow:<br /> *    PWM0..PWM3PD4..PD1<br /> *    PWM4..PWM9PC5..PC0<br /> *    PWM10..PWM15PB5..PB0<br /> *    PWM16..PWM18PD7..PD5<br /> *    PWM19PC6 (aktywny po wylaczeniu resetu)<br /> *<br /> * Fusebity - kwarc 20Mhz<br /> * low: 0xCF<br /> * high: 0xDF<br /> *<br /> * autor: mopsiok<br /> * data utworzenia: 23-09-2013<br /> */<br /><br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &quot;config.h&quot;<br /><br />//zmienne na potrzeby komunikacji<br />volatile unsigned char data_type = 0; //rodzaj odbieranych danych &#91;0: numer PWMa; 1: wartosc do ustawienia&#93;<br />volatile unsigned char i = 0; //indeks elementu do zmiany<br /><br />//zmienne na potrzeby generowania PWMow<br />volatile unsigned char timer_flag = 0; //flaga ustawiana przez timer<br />volatile unsigned char TCNT_ = 0; //licznik programowych PWM<br />volatile unsigned char OCR_&#91;20&#93; = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //wartosci programowych PWM<br /><br />//przerwania<br />ISR (TIMER0_COMPA_vect) { //przerwanie timera sprzetowego do generowania PWMow<br />timer_flag = 1;<br />}<br /><br />ISR (USART_RX_vect) { //przerwanie odebrania danych po USART<br />char byte = UDR0; //odbierz dane<br />if (data_type == 0) { //pierwszy bajt - numer kanalu<br />if (byte &lt; 20) i = byte; //jesli w zakresie tablicy, to zapisz indeks<br />else data_type = 1; //wroc do zapisu indeksu - pod koniec funkcji zamieni sie z powrotem na 0<br />} else OCR_&#91;i&#93; = byte; //lub drugi bajt - nowa wartosc<br />data_type = 1-data_type; //na zmiane 0 i 1<br />}<br /><br />ISR (BADISR_vect) {} //obsluga pozostalych przerwan<br /><br />//deklaracje funkcji<br />void compare(void); //funkcja porownujaca programowy TCNT z OCR<br /><br />int main(void) { //funkcja glowna programu<br />//konfiguracja portow - wszystko wyjscia<br />DDRB = 255, DDRC = 255, DDRD = 255;<br />PORTB = 0, PORTC = 0, PORTD = 0;<br /><br />//konfiguracja modulu USART<br />UBRR0H = (unsigned char)(_UBRR&gt;&gt;8);<br />UBRR0L = (unsigned char)_UBRR;<br />UCSR0B = (1&lt;&lt;RXEN0)|(1&lt;&lt;RXCIE0); //odbieranie danych i wlaczenie obslugi przerwania RXC<br />UCSR0C = (1&lt;&lt;UCSZ01)|(1&lt;&lt;UCSZ00); //8 bitow danych, 1 bit stopu<br /><br />//konfiguracja timera0 - tryb CTC<br />TCCR0A = (1&lt;&lt;WGM01);<br />TCCR0B = __PRESCALER;<br />OCR0A = _OCR;<br />TIMSK0 |= (1&lt;&lt;OCIE0A);<br /><br />sei(); //globalna obsluga przerwan<br /><br />for (;;) {<br />if (timer_flag) {<br />compare();<br />timer_flag = 0;<br />}<br />}<br /><br />return 0;<br />}<br /><br />void compare(void) { //funkcja porownujaca programowy TCNT z OCR<br />char b=PORTB, c=PORTC, d=PORTD; //bufory dla portow (zeby nie ustawialo kanalu jesli dany OCR=0)<br /><br />if (++TCNT_ == 0) { //jesli nastapilo przepelnienie<br />b=255, c=255, d=255; } //to trzeba z powrotem ustawic wszystkie kanaly<br /><br />#ifdef PWM0 //instrukcje preprocesora pomijaja wylaczone kanaly, co skraca czas wykonania funkcji<br />if (TCNT_ &gt;= OCR_&#91;0&#93;)  d &amp;= 0b11101111; //zeruj bit jesli licznik przekroczyl dane wypelnienie<br />#endif<br />#ifdef PWM1<br />if (TCNT_ &gt;= OCR_&#91;1&#93;)  d &amp;= 0b11110111;<br />#endif<br />#ifdef PWM2<br />if (TCNT_ &gt;= OCR_&#91;2&#93;)  d &amp;= 0b11111011;<br />#endif<br />#ifdef PWM3<br />if (TCNT_ &gt;= OCR_&#91;3&#93;)  d &amp;= 0b11111101;<br />#endif<br />#ifdef PWM4<br />if (TCNT_ &gt;= OCR_&#91;4&#93;)  c &amp;= 0b11011111;<br />#endif<br />#ifdef PWM5<br />if (TCNT_ &gt;= OCR_&#91;5&#93;)  c &amp;= 0b11101111;<br />#endif<br />#ifdef PWM6<br />if (TCNT_ &gt;= OCR_&#91;6&#93;)  c &amp;= 0b11110111;<br />#endif<br />#ifdef PWM7<br />if (TCNT_ &gt;= OCR_&#91;7&#93;)  c &amp;= 0b11111011;<br />#endif<br />#ifdef PWM8<br />if (TCNT_ &gt;= OCR_&#91;8&#93;)  c &amp;= 0b11111101;<br />#endif<br />#ifdef PWM9<br />if (TCNT_ &gt;= OCR_&#91;9&#93;)  c &amp;= 0b11111110;<br />#endif<br />#ifdef PWM10<br />if (TCNT_ &gt;= OCR_&#91;10&#93;) b &amp;= 0b11011111;<br />#endif<br />#ifdef PWM11<br />if (TCNT_ &gt;= OCR_&#91;11&#93;) b &amp;= 0b11101111;<br />#endif<br />#ifdef PWM12<br />if (TCNT_ &gt;= OCR_&#91;12&#93;) b &amp;= 0b11110111;<br />#endif<br />#ifdef PWM13<br />if (TCNT_ &gt;= OCR_&#91;13&#93;) b &amp;= 0b11111011;<br />#endif<br />#ifdef PWM14<br />if (TCNT_ &gt;= OCR_&#91;14&#93;) b &amp;= 0b11111101;<br />#endif<br />#ifdef PWM15<br />if (TCNT_ &gt;= OCR_&#91;15&#93;) b &amp;= 0b11111110;<br />#endif<br />#ifdef PWM16<br />if (TCNT_ &gt;= OCR_&#91;16&#93;) d &amp;= 0b01111111;<br />#endif<br />#ifdef PWM17<br />if (TCNT_ &gt;= OCR_&#91;17&#93;) d &amp;= 0b10111111;<br />#endif<br />#ifdef PWM18<br />if (TCNT_ &gt;= OCR_&#91;18&#93;) d &amp;= 0b11011111;<br />#endif<br /><br />//po wylaczeniu resetu<br />#if PWM19 == 1<br />if (TCNT_ &gt;= OCR_&#91;19&#93;) c &amp;= 0b10111111;<br />#endif<br /><br />PORTB=b, PORTC=c, PORTD=d; //aktualizacja portow<br />}[/syntax]<br /><br /><br />Plik config.h:<br />[syntax=c]/*<br /> * PWM generator - plik konfiguracyjny<br /> * autor: mopsiok<br /> * data utworzenia: 23-09-2013<br /> *<br /> * UWAGA!<br /> * Duza ilosc kanalow PWM ogranicza maksymalna czestotliwosc sygnalow - wlacz tylko te kanaly, ktorych uzyjesz.<br /> *<br /> * obliczanie czestotliwosci kanalow PWM:<br /> *    f_pwm = f_cpu / PRESKALER / (OCR+1) / 256<br /> *<br /> * w zaleznosci od wybranego preskalera, w makro _PRESCALER wpisac odpowiednia wartosc:<br /> *    1/8/64/256/1024<br /> */<br /><br />#ifndef CONFIG_H_<br />#define CONFIG_H_<br /><br />//konfiguracja timera Timer0<br />#define _PRESCALER 8<br />#define _OCR 15<br /><br /><br />//konfiguracja modulu USART (ubrr = f_osc/16/baud - 1): komunikacja obustronna, format ramki 8;1;N<br />#define _UBRR 24 //50000 baud<br /><br />//wlaczanie kanalow - aby wlaczyc dany kanal, nalezy zdefiniowac jego nazwe<br />#define PWM0<br />#define PWM1<br />#define PWM2<br />#define PWM3<br />#define PWM4<br />#define PWM5<br />#define PWM6<br />#define PWM7<br />/*#define PWM8<br />#define PWM9<br />#define PWM10<br />#define PWM11<br />#define PWM12<br />#define PWM13<br />#define PWM14<br />#define PWM15<br />#define PWM16<br />#define PWM17<br />#define PWM18*/<br /><br />/* UWAGA!<br /> * odkomentowanie ponizszego makra wlaczy obsluge 20. kanalu PWM, znajdujacego sie na pinie resetu<br /> * konieczne bedzie zablokowanie pinu resetu, co uniemozliwi ponowne zaprogramowanie mikrokontrolera przez ISP<br /> */<br />//#define PWM19 1<br /><br />//nie ruszac!<br />#if _PRESCALER == 1<br />#define __PRESCALER 1<br />#elif _PRESCALER == 8<br />#define __PRESCALER 2<br />#elif _PRESCALER == 64<br />#define __PRESCALER 3<br />#elif _PRESCALER == 256<br />#define __PRESCALER 4<br />#else<br />#define __PRESCALER 5<br />#endif<br /><br />#endif /* CONFIG_H_ */[/syntax]<br /><br /><br />Skrypt w Pythonie generujący powyższy efekt:<br />[syntax=python]import serial, time<br />from math import *<br /><br />p = serial.Serial(8, 50000)<br />p.open()<br /><br />def _sin(x, fi=0, m=255):<br />return int(m*(sin(radians(x+fi))+1)/2)<br /><br />for i in range(180*2+1):<br />for j in range(8):<br />_ = p.write(chr(j) + chr(_sin(i*2, -12*j, 50)))<br />time.sleep(0.015)[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1371">mopsiok</a> — 30 wrz 2013, o 21:53</p><hr />
]]></content>
</entry>
</feed>