<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>EE &#38; IT blog</title>
	<atom:link href="http://www.leniwiec.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.leniwiec.org</link>
	<description>www.leniwiec.org</description>
	<lastBuildDate>Fri, 20 Apr 2012 21:19:39 +0000</lastBuildDate>
	<language>pl</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Ubuntu i Apache – Certyfikat SSL w 5 min!</title>
		<link>http://www.leniwiec.org/2012/04/16/ubuntu-i-apache-certyfikat-ssl-w-5-min/</link>
		<comments>http://www.leniwiec.org/2012/04/16/ubuntu-i-apache-certyfikat-ssl-w-5-min/#comments</comments>
		<pubDate>Mon, 16 Apr 2012 09:59:49 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Codes Scratches]]></category>
		<category><![CDATA[administracja]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[ssl]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=336</guid>
		<description><![CDATA[Tym razem bardzo krótko i na temat - moja metoda (ściągawka) do instalacji certyfikatów ssl na apache'u. ]]></description>
			<content:encoded><![CDATA[<p>Tym razem bardzo krótko i na temat &#8211; moja metoda (ściągawka) do instalacji certyfikatów ssl na apache&#8217;u. </p>
<h2>Generujemy żądanie certyfikatu dla organu wydającego</h2>
<p>Pierwszym krokiem, który musimy zrobić, aby uzyskać (a później też zainstalować) certyfikat, to wygenerowanie klucza prywatnego, a następnie przy jego pomocy stworzyć plik żądania (CSR), który wyślemy do organu wydającego certyfikaty. Następnie parę w postaci naszego klucza prywatnego + otrzymany certyfikat zainstalujemy na serwerze www.</p>
<p>Najpierw generujemy klucz. Najlepiej robić to wszystko w katalogu <em>/etc/apache2/ssl</em>:<br />
Wersja z hasłem (hasło będzie konieczne podczas startu/restartu apache&#8217;a)</p>
<p><code>openssl genrsa -des3 -out PVK.pem 2048</code></p>
<p>lub bez hasła:</p>
<p><code>openssl genrsa -out PVK.pem 2048</code></p>
<p>Następny krok to stworzenie pliku żądania CSR:</p>
<p><code>openssl req -new -key PVK.pem -out CSR.pem</code></p>
<p>Po tym poleceniu program zapyta nas o kilka informacji, które należy podać w celu dostarczenia niezbędnych informacji organowi wydającemu certyfikaty.</p>
<p>Ok, mamy teraz dwa pliki: PVK.pem – klucz prywatny oraz CSR.pem – plik żądania, który zaraz wyślemy do organu wydającego certyfikaty (CA).</p>
<p>Zanim wyślemy pliki, możemy sobie jeszcze je zweryfikować przy pomocy następujących poleceń:<br />Weryfikacja klucza prywatnego:</p>
<p><code>openssl rsa -noout -text -in PVK.pem</code></p>
<p>Weryfikacja pliku csr:</p>
<p><code>openssl req -noout -text -in CSR.pem</code></p>
<h2>Wysyłamy pliki</h2>
<p>Teraz należy wysłać do wybranego przez siebie CA (certificate Authority) – instytucji/firmy wydającej certyfikaty plik CSR.pem, w odpowiedzi powinniśmy dostać plik certyfikatu *.crt.</p>
<h2>Instalujemy certyfikat w apache&#8217;u</h2>
<p>W pierwszej kolejności musimy uruchomić ssl na serwerze&#8230;</p>
<p><code>a2enmod ssl</code></p>
<p>Jeśli nie mamy zainstalowanego open-ssl, należy to uczynić, korzystając np. z tej komendy:</p>
<p><code>sudo apt-get install apache2 libapache-mod-ssl</code></p>
<p>Dalej powiedzmy, że mamy już skonfigurowaną jakąś wirtualkę, np. example.com, zatem przechodzimy do katalogu <em>/etc/apache2/sites-available</em></p>
<p><code>cd /etc/apache2/sites-available</code></p>
<p>I kopiujemy ją jako <em>example.com-ssl</em></p>
<p><code>cp example.com example.com-ssl</code></p>
<p>Otwieramy plik <em>example.com-ssl</em> w swoim ulubionym edytorze tekstu i modyfikujemy port, na którym nasłuchuje server na 443 oraz dodajemy 4 linijki aktywujące ssl na tej wirtualce.</p>
<p><code>SSLEngine On<br />
SSLCertificateFile /etc/apache2/ssl/example_com.crt #certyfikat, który dostaliśmy od CA<br />
SSLCertificateKeyFile /etc/ssl/certs/PVK.pem #klucz prywatny<br />
SSLCertificateChainFile /etc/apache2/ssl/AddTrustExternalCARoot.crt #chain autoryzacyjny 2 pozycje, tutaj zależy co dostaniemy w odpowiedzi od CA<br />
SSLCertificateChainFile /etc/apache2/ssl/COMODOHigh-AssuranceSecureServerCA.crt<br />
</code></p>
<p>Cały wpis virtual hosta może wyglądać m/w tak:</p>
<p><code>&lt;VirtualHost *:443&gt;<br />
	ServerAdmin webmaster@example.com<br />
	ServerName example.com<br />
	ServerAlias www.example.com<br />
	DocumentRoot /home/www/example.com/public_html</p>
<p>	SSLEngine On<br />
	SSLCertificateFile /etc/apache2/ssl/example_com.crt #certyfikat, który dostaliśmy od CA<br />
	SSLCertificateKeyFile /etc/ssl/certs/PVK.pem #klucz prywatny<br />
	SSLCertificateChainFile /etc/apache2/ssl/AddTrustExternalCARoot.crt #chain autoryzacyjny 2 pozycje, tutaj zależy co dostaniemy w odpowiedzi od CA<br />
	SSLCertificateChainFile /etc/apache2/ssl/COMODOHigh-AssuranceSecureServerCA.crt</p>
<p>	&lt;Directory /home/www/example.com/public_html&gt;<br />
		Options Indexes FollowSymLinks MultiViews<br />
		AllowOverride All<br />
		Order allow,deny<br />
		Allow from all<br />
	&lt;/Directory&gt;</p>
<p>	CustomLog /home/www/example.com/log/access-ssl.log combined<br />
	ErrorLog /home/www/example.com/log/error-ssl.log<br />
&lt;/VirtualHost&gt;<br />
</code></p>
<p>I to właściwie tyle. Jeśli chcemy, możemy jeszcze ustawić przekierowania tak, aby wymusić zawsze oglądanie strony poprzez https. W tym celu w virtualce (tym razem tej „normalnej” na porcie 80), dodajemy krótką regułką mod_rewrite:</p>
<p><code>RewriteEngine on<br />
RewriteCond %{SERVER_PORT} ^80$<br />
RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]</code></p>
<p>Cały VirtualHost może wyglądać m/w tak:</p>
<p><code>&lt;VirtualHost *:80&gt;<br />
	ServerAdmin webmaster@example.com<br />
	ServerName example.com<br />
	ServerAlias www.example.com<br />
	DocumentRoot /home/www/example.com/public_html</p>
<p>	RewriteEngine on<br />
	RewriteCond %{SERVER_PORT} ^80$<br />
	RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]<br />
&lt;/VirtualHost&gt;<br />
</code></p>
<p>Teraz pozostaje nam tylko włączyć virtualkę&#8230;</p>
<p><code>a2ensite example.com-ssl</code></p>
<p>Oraz zrestartować apache&#8217;a:</p>
<p><code>/etc/init.d/apache2 restart</code></p>
<p>Jeśli w pierwszym punkcie wybraliśmy klucz prywatny chroniony hasłem, wówczas zostaniemy o to hasło poproszeni, a jeśli nie, apache powinien uruchomić się od razu. </p>
<p>No i mamy działający ssl <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  Teraz po wpisaniu w przeglądarkę adresu http://example.com zostaniemy automatycznie przeniesieni na https://example.com, która będzie zabezpieczona nowo zainstalowanym certyfikatem.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2012/04/16/ubuntu-i-apache-certyfikat-ssl-w-5-min/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Budujemy „cyfrowy zasilacz” cz. 3 – przetwornik DAC oparty na R-2R</title>
		<link>http://www.leniwiec.org/2012/04/12/budujemy-cyfrowy-zasilacz-cz-3-przetwornik-dac-oparty-na-r-2r/</link>
		<comments>http://www.leniwiec.org/2012/04/12/budujemy-cyfrowy-zasilacz-cz-3-przetwornik-dac-oparty-na-r-2r/#comments</comments>
		<pubDate>Thu, 12 Apr 2012 09:06:30 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Elektronika]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[atmega]]></category>
		<category><![CDATA[dac]]></category>
		<category><![CDATA[elektronika]]></category>
		<category><![CDATA[przetwornik analogowo cyfrowy]]></category>
		<category><![CDATA[r-2r]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=329</guid>
		<description><![CDATA[Lepiej późno niż wcale... Jak obiecałem, tak piszę. Tym razem rzecz będzie o przetworniku cyfrowo-analogowym opartym na drabince rezystorowej (DAC na R-2R). No to do roboty, bez zbędnych wstępów...]]></description>
			<content:encoded><![CDATA[<p>Lepiej późno niż wcale&#8230; Jak obiecałem, tak piszę. Tym razem rzecz będzie o przetworniku cyfrowo-analogowym opartym na drabince rezystorowej (DAC na R-2R). No to do roboty, bez zbędnych wstępów&#8230;</p>
<h2>Na początek odrobina teorii&#8230;</h2>
<p>Zacznijmy od odrobiny teorii. Czym jest drabinka R-2R? Drabinka R-2R, jak sama nazwa wskazuje, to takie połączenie wielu rezystorów tej samej wartości, aby tworzyły one „drabinkę”, w której każdy kolejny szczebel ma wartość 2xR w stosunku do każdego kolejnego pionowego elementu. Poniżej widzimy, jak taka drabinka wygląda teoretycznie.</p>
<p><img src="http://www.leniwiec.org/wp-content/uploads/2012/04/drabinka.png" alt="" title="drabinka R-2R" width="607" height="225" class="aligncenter size-full wp-image-330" /></p>
<p>
Bity od A0 do An są sterowane z wyjść bramek logicznych (np. wyjścia mikrokontrolera lub rejestru przesuwnego). Czyli mogą na nich występować dwa stany &#8211; niski i wysoki, który będzie odpowiednio na potencjale GND lub na potencjale napięcia zasilania danego układu – Vcc. (Oczywiście stan wysoki może być na innym poziomie, jednak w większości przypadków, gdy drabinka będzie podłączona bezpośrednio do wyjść np. mikrokontrolera, to właśnie w stanie wysokim będzie się pojawiało na wyjściach napięcie zasilania).<br />Jak już pewnie zauważyłeś/łaś, w dużym uproszczeniu mamy tu do czynienia z rezystorowym dzielnikiem napięcia. Spróbujmy sobie zatem obliczyć, jakie napięcie wyjściowe będziemy mieli na wyjściu takiego DAC&#8217;a w przypadku, gdy nasza drabinka będzie miała 8 strzebli (8bitów), a poziom wysoki każdego z nich będzie równy 5V.</p>
<p>Najpierw ogólnie:</p>
<p class="aligncenter">Vout = Vref x VAL / 2^N</p>
<p>Gdzie:<br />
<strong>N</strong> – liczba bitów (w naszym przykładzie będzie to <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> </p>
<p><strong>VAL</strong> – wartość podana na wejścia A0&#8230;An (dla N = 8, będzie to wartość z przedziału 00000000 do 11111111)<br />
<strong>Vref</strong> – Napięcie referencyjne, czyli to, które reprezentuje stan wysoki układu. W naszym przykładzie będzie to 5V (dla typowej bramki CMOS będzie to 3.3V).
</p>
<p>Weźmy teraz sobie konkretną wartość, np. 128, czyli binarnie będzie to 10000000 (2^8). Podstawiając do powyższego wzoru:</p>
<p class="aligncenter">Vout = 5V x 128 / 2^8 <br />
Vout = 2.5V</p>
<p>To teraz policzmy sobie, jaka będzie rozdzielczość takiej drabinki&#8230;</p>
<p class="aligncenter">Vout = 5V x 1 / 2^8<br />
Vout ~= 0.02V </p>
<p>Czyli pojedynczy krok będzie zwiększał napięcie dokładnie o ok. 0.02V, co daje 255 kroków, aby osiągnąć napięcie 5V, czyli wszystko się zgadza! (Największa możliwa do zapisania wartość na 8bitach to właśnie 255, czyli mamy 255 bitowych kombinacji, czyli 255 kroków w naszym przetworniku). </p>
<h2>Przejdźmy do praktyki&#8230;</h2>
<p>Spróbuję teraz zademonstrować, jak w praktyce możemy wykorzystać taką drabinkę. W tym celu zbudujmy sobie prosty 16botowy DAC oparty na drabince R-2R.</p>
<p>Zbudujmy sobie układ jak z poniższego schematu&#8230;</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/04/uklad.png"><img src="http://www.leniwiec.org/wp-content/uploads/2012/04/uklad-300x194.png" alt="" title="74HC595 cascade" width="300" height="194" class="aligncenter size-medium wp-image-331" /></a></p>
<p>U mnie to wyglądało m/w tak:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/04/2011-12-05-16.06.18.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2012/04/2011-12-05-16.06.18-300x225.jpg" alt="" title="2011-12-05 16.06.18" width="300" height="225" class="aligncenter size-medium wp-image-332" /></a></p>
<p>O tym, jak działa rejestr 74HC595, pisałem już w <a href="http://www.leniwiec.org/2010/12/26/swieta-z-arduino-czyli-gramy-koledy/" title="Święta z arduino, czyli gramy kolędy ">tym</a> miejscu, więc nie będę przytaczał tego samego tekstu tutaj. Jedyna różnica między naszym układem a tym przedstawionym w linku powyżej to drabinka podłączona do wyjść Q0&#8230;Q7 układów U1 oraz U2, a także połączenie ich kaskadowo (z ang. daisy chaining), dzięki czemu możemy „wlać” w taką kaskadę wielokrotność liczby bitów każdej z nich. W tym przypadku dokładnie 16 bitów. Działa to w ten sposób, że gdy pierwszy z układów przepełni się, wówczas zaczyna „przelewać” kolejne bity do następnego układu. </p>
<p>Ok! Mamy już przetwornik, podłączmy go zatem do jakiegoś mikrokontrolera i spróbujmy wysłać na niego jakąś wartość. Żeby było prosto i przyjemnie, użyjmy do tego celu Arduino&#8230; które podłączymy jak na rysunku powyżej (wykorzystamy piny DIGITAL8, DIGITAL12, DIGITAL~11)</p>
<p>Jak już pewnie zauważyłeś/łaś, jest to takie same podłączenie jak w przypadku pozytywki z linku powyżej. Ba! Program sterujący będzie też bardzo podobny, z tą tylko różnicą, że będziemy wysyłać 16 bitów, a nie 8. Będzie to wyglądało m/w tak:</p>
<p><code></p>
<pre>
<span style="color: #7E7E7E;">//Pin&nbsp;connected&nbsp;to&nbsp;ST_CP&nbsp;of&nbsp;74HC595</span>
<span style="color: #CC6600;">int</span> latchPin = 8;
<span style="color: #7E7E7E;">//Pin&nbsp;connected&nbsp;to&nbsp;SH_CP&nbsp;of&nbsp;74HC595</span>
<span style="color: #CC6600;">int</span> clockPin = 12;
<span style="color: #7E7E7E;">//Pin&nbsp;connected&nbsp;to&nbsp;DS&nbsp;of&nbsp;74HC595</span>
<span style="color: #CC6600;">int</span> dataPin = 11;
<span style="color: #7E7E7E;">//Pin&nbsp;connected&nbsp;to&nbsp;UP&nbsp;button</span>
<span style="color: #CC6600;">int</span> btnA = 2;
<span style="color: #7E7E7E;">//Pin&nbsp;connected&nbsp;to&nbsp;DOWN&nbsp;button</span>
<span style="color: #CC6600;">int</span> btnB = 3;

<span style="color: #7E7E7E;">//int&nbsp;in&nbsp;arduino&nbsp;are&nbsp;16bit&nbsp;length</span>
<span style="color: #CC6600;">int</span> dataToSend = 0;

<span style="color: #CC6600;">void</span> setData(<span style="color: #CC6600;">int</span> data)
{
&nbsp;&nbsp;<span style="color: #CC6600;">byte</span> dataA = 0;
&nbsp;&nbsp;<span style="color: #CC6600;">byte</span> dataB = 0;
&nbsp;&nbsp;
&nbsp;&nbsp;<span style="color: #7E7E7E;">//split 16bit var into two 8bit</span>
&nbsp;&nbsp;dataA&nbsp;=&nbsp;data&nbsp;&amp;&nbsp;0xff;&nbsp;
&nbsp;&nbsp;dataB&nbsp;=&nbsp;data&nbsp;&gt;&gt;&nbsp;8;
&nbsp;&nbsp;
&nbsp;&nbsp;<span style="color: #7E7E7E;">//ground latchPin and hold low for as long as you are transmitting</span>
&nbsp;&nbsp;<span style="color: #CC6600;">digitalWrite</span>(latchPin, <span style="color: #006699;">LOW</span>);
&nbsp;&nbsp;<span style="color: #7E7E7E;">//move &#8216;em out</span>
&nbsp;&nbsp;<span style="color: #CC6600;">shiftOut</span>(dataPin, clockPin, <span style="color: #006699;">MSBFIRST</span>, dataA);
&nbsp;&nbsp;<span style="color: #CC6600;">shiftOut</span>(dataPin, clockPin, <span style="color: #006699;">MSBFIRST</span>, dataB);
&nbsp;&nbsp;<span style="color: #7E7E7E;">//return the latch pin high to signal chip that it</span>
&nbsp;&nbsp;<span style="color: #7E7E7E;">//no longer needs to listen for information</span>
&nbsp;&nbsp;<span style="color: #CC6600;">digitalWrite</span>(latchPin, <span style="color: #006699;">HIGH</span>);
}

<span style="color: #CC6600;">void</span> <span style="color: #CC6600;"><b>setup</b></span>() {
&nbsp;&nbsp;<span style="color: #CC6600;">pinMode</span>(latchPin, <span style="color: #006699;">OUTPUT</span>);
&nbsp;&nbsp;<span style="color: #CC6600;">pinMode</span>(clockPin, <span style="color: #006699;">OUTPUT</span>);
&nbsp;&nbsp;<span style="color: #CC6600;">pinMode</span>(dataPin, <span style="color: #006699;">OUTPUT</span>);
&nbsp;&nbsp;<span style="color: #CC6600;">pinMode</span>(btnA, <span style="color: #006699;">INPUT</span>);
&nbsp;&nbsp;<span style="color: #CC6600;">pinMode</span>(btnB, <span style="color: #006699;">INPUT</span>);
}

<span style="color: #CC6600;">void</span> <span style="color: #CC6600;"><b>loop</b></span>() {

&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(<span style="color: #CC6600;">digitalRead</span>(btnA)==<span style="color: #006699;">HIGH</span> &amp;&amp; dataToSend&lt;32768)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;dataToSend++;
&nbsp;&nbsp;&nbsp;&nbsp;setData(dataToSend);
&nbsp;&nbsp;}
&nbsp;&nbsp;<span style="color: #CC6600;">else</span> <span style="color: #CC6600;">if</span>(<span style="color: #CC6600;">digitalRead</span>(btnB)==<span style="color: #006699;">HIGH</span> &amp;&amp; dataToSend&gt;0)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;dataToSend--;
&nbsp;&nbsp;&nbsp;&nbsp;setData(dataToSend);
&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;
}
</pre>
<p></code></p>
<p>No i mamy działający 16bitowy DAC za parę groszy <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h2>Problemy, ograniczenia, wady&#8230;</h2>
<p>Tak, tak&#8230; To wszystko było zbyt piękne i gdyby nie było jakiegoś haczyka, to pewnie producenci specjalizowanych układów DAC by zbankrutowali&#8230; I rzeczywiście haczykiem jest precyzja, a dokładniej precyzja, jaką muszą się charakteryzować rezystory, z których składamy taką drabinkę, aby napięcia wyjściowe na niej wygenerowane choć trochę odpowiadały tym, które sobie wyliczyliśmy i których oczekujemy na wyjściu. Przykładowo dla 8bitowej drabinki rezystory muszą mieć dokładność większą niż 0.4%, co już stanowi spory problem, zarówno finansowy, jak i w realizacji praktycznej układu. Można oczywiście taką drabinkę próbować kompensować programowo, jednak jest to rozwiązanie mało eleganckie, które osobiście odradzam jako rozwiązanie w poważnym projekcie. Nie mniej jednak zachęcam do eksperymentowania z R-2R, które może się przydać wszędzie tam, gdzie potrzebna jest mała rozdzielczość lub zadowalający jest nastaw z grubsza.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2012/04/12/budujemy-cyfrowy-zasilacz-cz-3-przetwornik-dac-oparty-na-r-2r/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dodawanie obrazków w programie pcb pakietu gEDA</title>
		<link>http://www.leniwiec.org/2012/02/09/dodawanie-obrazkow-w-programie-pcb-pakietu-geda/</link>
		<comments>http://www.leniwiec.org/2012/02/09/dodawanie-obrazkow-w-programie-pcb-pakietu-geda/#comments</comments>
		<pubDate>Thu, 09 Feb 2012 19:38:08 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Elektronika]]></category>
		<category><![CDATA[Ogólne]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[geda]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[pcb]]></category>
		<category><![CDATA[projektowanie pcb]]></category>
		<category><![CDATA[płytka drukowana]]></category>
		<category><![CDATA[silkscreen]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=307</guid>
		<description><![CDATA[W tym krótkim wpisie chciałbym przedstawić Wam moją metodę na dodawanie obrazków do warstw w layoucie pcb wykonywanym przy pomocy oprogramowania z pakietu gEDA.]]></description>
			<content:encoded><![CDATA[<p>W tym krótkim wpisie chciałbym przedstawić Wam moją metodę na dodawanie obrazków do warstw w layoucie pcb wykonywanym przy pomocy oprogramowania z pakietu gEDA. </p>
<p>Domyślnie program pcb (gEDA) nie daje nam możliwości dodawania obrazków bezpośrednio, trzeba to zrobić trochę na okrętkę. </p>
<p>Aby tego dokonać potrzebne nam będzie kilka narzędzi: Inkscape oraz pstoedit. Obydwa programy są dostępne w repozytorium ubuntu i można jest zainstalować przy pomocy poniższego polecenia:</p>
<p><code>$ sudo apt-get install inkscape pstoedit</code></p>
<p>Teraz gdy mamy już wszystkie niezbędne narzędzia, otwieramy obrazek, który chcemy umieścić w naszym projekcie pcb przy pomocy inkscape&#8217;a. </p>
<p><code>Plik → Importuj </code></p>
<p>A następnie, gdy program nas zapyta o to, czy chcemy importowany obrazek połączyć czy osadzić, odpowiadamy „łącze”. </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu.png"><img src="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-300x158.png" alt="" title="zrzut_ekranu" width="300" height="158" class="aligncenter size-medium wp-image-308" /></a></p>
<p>Następnie zaznaczamy zaimportowany obrazek i z górnego menu wybieramy </p>
<p><code>Ścieżka → Wektoryzuj bitmapę </code></p>
<p>A następnie w oknie, które nam się pokazało dajemy po prostu OK (można dostroić również w nim parametry).</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-1.png"><img src="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-1-300x157.png" alt="" title="zrzut_ekranu-1" width="300" height="157" class="aligncenter size-medium wp-image-309" /></a></p>
<p>Następnie musimy dopasować rozmiar naszego obrazka tak, aby był odpowiedni dla naszego projektu PCB. W tym celu w inkscapie wybieramy z menu:</p>
<p><code>Plik → Właściwości dokumentu</code></p>
<p>I w oknie,które nam się pokazało, wybieramy jako jednostka mm i określamy wysokość i szerokość tak, jak widać to na poniższym rysunku:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-2.png"><img src="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-2-300x158.png" alt="" title="zrzut_ekranu-2" width="300" height="158" class="aligncenter size-medium wp-image-310" /></a></p>
<p>Następnie, używając narzędzia strzałki, ustawiamy oraz zmieniamy rozmiar obrazka tak, aby mieścił się na stronie. Podczas zmiany rozmiaru przytrzymujemy Ctrl, w ten sposób podczas zmiany rozmiaru nie zmienią się proporcje obrazka.</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-3.png"><img src="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-3-300x157.png" alt="" title="zrzut_ekranu-3" width="300" height="157" class="aligncenter size-medium wp-image-311" /></a></p>
<p>Teraz mamy już gotowy obrazek, który zapisujemy jako postscript:</p>
<p><code>Plik → Zapisz jako</code></p>
<p>W tym momencie kończy się nasza praca z Inkscapeam. Teraz należy otworzyć konsolę i przejść do katalogu, w którym zapisaliśmy nasz plik ps, a następnie wydać polecenie:</p>
<p><code>$ pstoedit -f pcb Rysunek.ps Rysunek.pcb</code></p>
<p>W ten sposób nasz obrazek został zmieniony w plik pcb. Otwieramy teraz go w programie pcb i oto efekt:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-4.png"><img src="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-4-300x157.png" alt="" title="zrzut_ekranu-4" width="300" height="157" class="aligncenter size-medium wp-image-312" /></a></p>
<p>Jak widzimy, nasz obrazek został umieszczony na warstwie oznaczonej jako „poly”, która jest tak naprawdę warstwą „components”, czyli widokiem ścieżek od strony elementów. Aby nasz obrazek przenieść na warstwę opisową „silkscreen”, należy otworzyć plik pcb w edytorze tekstu i przekopiować odpowiedni fragment na odpowiednią warstwę. Widać to na poniższym zrzucie ekranu:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-5.png"><img src="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-5-300x157.png" alt="" title="zrzut_ekranu-5" width="300" height="157" class="aligncenter size-medium wp-image-313" /></a></p>
<p>Fragment opisujący nasz obrazek (<em>Polygon(&#8222;clearpoly&#8221;) (&#8230;)</em>) możemy równie dobrze przekopiować do innego pliku. </p>
<p>Po zapisaniu obrazka i otwarciu naszego pliku PCB mamy nasz obrazek na warstwie silk&#8230;</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-6.png"><img src="http://www.leniwiec.org/wp-content/uploads/2012/02/zrzut_ekranu-6-300x157.png" alt="" title="zrzut_ekranu-6" width="300" height="157" class="aligncenter size-medium wp-image-314" /></a></p>
<p>I to wszystko, osadziliśmy nasz obrazek w projekcie PCB. Swoją drogą, dziwi mnie fakt, że nie ma bezpośrednio opcji zaimportowania obrazka do projektów prosto z gedy i trzeba korzystać z takich udziwnień&#8230; </p>
]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2012/02/09/dodawanie-obrazkow-w-programie-pcb-pakietu-geda/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moja kolekcja symboli gEDA (gschem i xpcb)</title>
		<link>http://www.leniwiec.org/2012/01/20/kolekcja-symboli-geda-gschem-i-xpcb/</link>
		<comments>http://www.leniwiec.org/2012/01/20/kolekcja-symboli-geda-gschem-i-xpcb/#comments</comments>
		<pubDate>Fri, 20 Jan 2012 12:28:34 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Elektronika]]></category>
		<category><![CDATA[electronic]]></category>
		<category><![CDATA[footprints]]></category>
		<category><![CDATA[geda]]></category>
		<category><![CDATA[gschem]]></category>
		<category><![CDATA[symbols]]></category>
		<category><![CDATA[xpcb]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=289</guid>
		<description><![CDATA[<p>Poniżej lista opracowanych przeze mnie symboli elementów dla gschem oraz xpcb, może komuś to zaoszczędzi trochę czasu.
<br />Na liście na razie tylko kilka elementów, ale z biegiem czasu będę tutaj dodawał kolejne. </p>]]></description>
			<content:encoded><![CDATA[<p>Poniżej lista opracowanych przeze mnie symboli elementów dla gschem oraz xpcb, może komuś to zaoszczędzi trochę czasu.<br />
<br />Na liście na razie tylko kilka elementów, ale z biegiem czasu będę tutaj dodawał kolejne. </p>
<ul>
<li><a href="http://www.leniwiec.org/wp-content/uploads/2012/01/max6126.sym_.zip">max6126.sym (Ultra-High-Precision, Ultra-Low-Noise, Series Voltage Reference)</a></li>
<li><a href="http://www.leniwiec.org/wp-content/uploads/2012/01/max531.sym_.zip">max531.sym (+5V, Low-Power, Voltage-Output, Serial 12-Bit DACs)</a></li>
<li><a href="http://www.leniwiec.org/wp-content/uploads/2012/01/max144.sym_.zip">max144.sym (+2.7V, Low-Power, 2-Channel, 108ksps, Serial 12-Bit ADCs in 8-Pin μMAX)</a></li>
<li><a href="http://www.leniwiec.org/wp-content/uploads/2012/01/INA168.sym_.zip">INA168.sym (High-Side Measurement CURRENT SHUNT MONITOR)</a></li>
<li><a href="http://www.leniwiec.org/wp-content/uploads/2012/01/DS18B20.sym_.zip">DS18B20.sym (DS18B20 Programmable Resolution 1-Wire Digital Thermometer)</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2012/01/20/kolekcja-symboli-geda-gschem-i-xpcb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Klawiatura numeryczna z wyjściem szeregowym lub spi</title>
		<link>http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/</link>
		<comments>http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 23:54:19 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Elektronika]]></category>
		<category><![CDATA[Ogólne]]></category>
		<category><![CDATA[atmega]]></category>
		<category><![CDATA[avr]]></category>
		<category><![CDATA[diy]]></category>
		<category><![CDATA[elektronika]]></category>
		<category><![CDATA[klawiatura numeryczna]]></category>
		<category><![CDATA[port szeregowy]]></category>
		<category><![CDATA[serial]]></category>
		<category><![CDATA[spi]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=266</guid>
		<description><![CDATA[<p>Tym razem mała odskocznia od teoretycznego cyklu opisującego budowę „cyfrowego zasilacza” i coś bardziej praktycznego. Choć kto wie? Może nie do końca niezwiązanego z tamtymi artykułami ;)<br />
Dzisiaj chcę Wam przedstawić mini projekt klawiaturki numerycznej wyposażonej w wyjście szeregowe, które można bezpośrednio podłączyć do UARTu mikrokontrolera (u mnie były to np. Atmega8 i Atmega32). </p>

<a href="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.55.19.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.55.19-300x225.jpg" alt="Klawiatura numeryczna z wyjściem szeregowym lub spi" title="Klawiatura numeryczna z wyjściem szeregowym lub spi" width="300" height="225" class="aligncenter size-medium wp-image-274" /></a>]]></description>
			<content:encoded><![CDATA[<p>Tym razem mała odskocznia od teoretycznego cyklu opisującego budowę „cyfrowego zasilacza” i coś bardziej praktycznego. Choć kto wie? Może nie do końca niezwiązanego z tamtymi artykułami <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> <br />
Dzisiaj chcę Wam przedstawić mini projekt klawiaturki numerycznej wyposażonej w wyjście szeregowe, które można bezpośrednio podłączyć do UARTu mikrokontrolera (u mnie były to np. Atmega8 i Atmega32). </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.55.19.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.55.19-300x225.jpg" alt="Klawiatura numeryczna z wyjściem szeregowym lub spi" title="Klawiatura numeryczna z wyjściem szeregowym lub spi" width="300" height="225" class="aligncenter size-medium wp-image-274" /></a></p>
<h2>Jak to działa?</h2>
<p>Jest to typowa klawiaturka numeryczna 0-9 dodatkowo wyposażona w 4 przyciski funkcyjne (a,b,c,d), zasilana z 5V DC, z wyjściem szeregowym (9600 boud rate) lub spi. Przyciski w celu zaoszczędzenia pinów kontrolera są ułożone w macierz, tzn. wszystkie przyciski w danej kolumnie  są połączone i wszystkie w danym wierszu również. Poniżej schemat takiego połączenia:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/01/schemat.png"><img src="http://www.leniwiec.org/wp-content/uploads/2012/01/schemat-300x194.png" alt="Schemat ideowy" title="Schemat ideowy" width="300" height="194" class="aligncenter size-medium wp-image-277" /></a></p>
<p>Następnie program zapisany w mikrokontrolerze (ja użyłem AT90S2313, jednak może to być cokolwiek innego rodziny avr np. jakaś atmega) „skanuje” taką macierz w poszukiwaniu zwartych styków. Odbywa się to w następujący sposób:</p>
<p>Wiersze od góry są podpięte do portów PD6, PB0, PB1 oraz PB7 mikrokontrolera, a kolumny do portów PB6, PB5, PB4, PB3, PB2, co widać na rysunku powyżej. W pierwszej kolejności porty podłączone do wierszy są ustawiane jako wyjścia:</p>
<p><code>
<pre>
	DDRB&nbsp;|=&nbsp;(1&lt;&lt;PB0);&nbsp;<span style="color: #7E7E7E;">//port as output</span>
	DDRB&nbsp;|=&nbsp;(1&lt;&lt;PB1);&nbsp;<span style="color: #7E7E7E;">//port as output</span>
	DDRB&nbsp;|=&nbsp;(1&lt;&lt;PB7);&nbsp;<span style="color: #7E7E7E;">//port as output</span>
	DDRD&nbsp;|=&nbsp;(1&lt;&lt;PD6);&nbsp;<span style="color: #7E7E7E;">//port as output</span>
</pre>
<p></code></p>
<p>a te podłączone do kolumn jako wejścia:</p>
<p><code>
<pre>
	DDRB&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;PB2);&nbsp;<span style="color: #7E7E7E;">//port as input</span>
	DDRB&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;PB3);&nbsp;<span style="color: #7E7E7E;">//port as input</span>
	DDRB&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;PB4);&nbsp;<span style="color: #7E7E7E;">//port as input</span>
	DDRB&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;PB5);&nbsp;<span style="color: #7E7E7E;">//port as input</span>
	DDRB&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;PB6);&nbsp;<span style="color: #7E7E7E;">//port as input</span>
</pre>
<p></code></p>
<p>z włączonymi wewnętrznymi rezystorami podciągającymi je do plusa:</p>
<p><code>
<pre>
	PORTB&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;PB2);&nbsp;<span style="color: #7E7E7E;">//pull-up enable</span>
	PORTB&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;PB3);&nbsp;<span style="color: #7E7E7E;">//pull-up enable</span>
	PORTB&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;PB4);&nbsp;<span style="color: #7E7E7E;">//pull-up enable</span>
	PORTB&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;PB5);&nbsp;<span style="color: #7E7E7E;">//pull-up enable</span>
	PORTB&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;PB6);&nbsp;<span style="color: #7E7E7E;">//pull-up enable</span>
</pre>
<p></code></p>
<p>a wszystkie porty ustawione jako wyjścia są ustawiane w stan wysoki. </p>
<p>Następnie po kolei od góry do dołu podawany jest stan niski na kolejne wiersze aż do ostatniego.<br />
Po podaniu stanu niskiego na pierwszy wiersz program sprawdza po kolei od lewej do prawej strony, czy któryś z przycisków nie został zwarty, a tym samym nie powoduje stanu niskiego na jednym z wejść podłączonych do kolumn. Jeśli któreś z wejść jest ustawione na stan niski, wówczas odczytywana jest aktualna pozycja, tj. numer kolumny i wiersza, i na tej podstawie określany jest przycisk, który został wciśnięty. Jeśli w danej kolumnie żaden przycisk nie został wciśnięty, wówczas program kontynuuje przeszukiwanie aż do ostatniej kolumny i ostatniego wiersza, a następnie zaczyna od początku. Poniższa animacja obrazuje działanie algorytmu.</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/01/animacja.gif"><img src="http://www.leniwiec.org/wp-content/uploads/2012/01/animacja.gif" alt="Zasada działania skanowania klawiszy przy pomocy mikrokontrolera" title="Zasada działania skanowania klawiszy przy pomocy mikrokontrolera" width="309" height="240" class="aligncenter size-full wp-image-275" /></a></p>
<p>Po wykryciu, że któryś z przycisków został wciśnięty, zostaje uruchomiony prosty kod mający na celu debounce sygnału wejściowego z przycisku, a następnie zostaje wysłany przez port szeregowy znak odpowiadający danemu klawiszowi. </p>
<p>Obsługa portu szeregowego jest typowa i jest on skonfigurowany w trybie tylko do wysyłania znaków. Czyli po kolei mamy:</p>
<p><code>
<pre>
#define&nbsp;F_CPU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8000000L
</pre>
<p></code></p>
<p>Definiujemy sobie prędkość oscylatora mikrokontrolera, a następnie definiujemy żądaną prędkość transmisji:</p>
<p><code>
<pre>
#define&nbsp;UART_BAUD&nbsp;&nbsp;&nbsp;9600
</pre>
<p></code></p>
<p>a także tworzymy sobie proste makro, które służy do obliczenia stałej dla portu wyjściowego:</p>
<p><code>
<pre>
#define&nbsp;UART_CONST&nbsp;&nbsp;(F_CPU/(16ul*UART_BAUD)-1)
</pre>
<p></code></p>
<p>której wartość następnie przypisujemy do rejestru UBRR, czym jednocześnie definiujemy prędkość transmisji </p>
<p><code>
<pre>
UBRR&nbsp;=&nbsp;(<span style="color: #CC6600;">unsigned</span> <span style="color: #CC6600;">char</span>)UART_CONST;
</pre>
<p></code></p>
<p>a następnie korzystamy z rejestru UCR, w którym ustawiamy bit TXEN (TX Enable), który oznacza zgodę na wysyłanie znaków (analogicznie istnieje w tym rejestrze bit dla odbioru danych RXEN).</p>
<p>Po tych operacjach mamy już działający port szeregowy z prędkością 9600. </p>
<p>Teraz czas, aby coś na niego wysłać. W tym celu mamy stworzoną procedurkę <em>UART_putchar()</em>, która wygląda tak:</p>
<p><code>
<pre>
<span style="color: #CC6600;">void</span> UART_putchar(<span style="color: #CC6600;">char</span> c)
{&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;UDR=c;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;loop_until_bit_is_set(USR,TXC);&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;USR&nbsp;|=&nbsp;(1&lt;&lt;TXC);&nbsp;
}<span style="color: #7E7E7E;">//end of UART_putchar()</span>
</pre>
<p></code></p>
<p>UDR to rejestr wyjściowy portu szeregowego – jego zawartość zostanie wysłana przez port, a kiedy się już to stanie (transmisja zostanie zakończona), zostanie ustawiony bit TXC w rejestrze USR, który po wysłaniu możemy już skasować (ostatnia linijka powyższej procedury), tym samym umożliwiając wysłanie kolejnego znaku. </p>
<p>Korzystając z portu szeregowego w swoich aplikacjach mikrokontrolerowych, należy zwrócić uwagę na dobór odpowiedniego kwarcu, którym napędzamy nasz układ. Jest to o tyle istotne, że dla różnych wartości prędkości oscylatora występują różne procentowe wartości błędów transmisji, które mogą wynosić od zera do kilku procent. W poniższej tabelce, która pochodzi z noty katalogowej, jest pokazana ta zależność. </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2012/01/kwarce.png"><img src="http://www.leniwiec.org/wp-content/uploads/2012/01/kwarce.png" alt="" title="kwarce" width="648" height="635" class="aligncenter size-full wp-image-287" /></a></p>
<h2>Konstrukcja</h2>
<p>Ja swój prototyp wykonałem na dwustronnym laminacie FR4 (szklano-epoksydowy), ścieżki przenosiłem termotransferem (pozdrowienia dla mojej laminarki <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> , a całość jest zabezpieczona termoutwardzalną solder-maską. </p>
<p>Gumki stykowe oraz klawisze są wymontowane z kalkulatora ActiveJet ASC-8003 (koszt ok. 3 do 9zł), w kalkulatorku jest też fajny wyświetlacz LCD o dużych czytelnych cyfrach, który myślę, że w najbliższym czasie zhakuję i opiszę jak go podłączyć do kontrolera. </p>
<h2>Obrazki, filmiki, pliki, szał!</h2>
<p>Poniżej na filmiku prezentuję mój układ prototypowy klawiaturki. Jest ona na nim podłączona przejściówką USB->RS232 z wyjściami TTL bezpośrednio do komputera, na którym jest uruchomiony gtkterm.</p>
<p><object style="height: 390px; width: 640px"><param name="movie" value="http://www.youtube.com/v/LU-gVd4DANI?version=3&#038;feature=player_detailpage"><param name="allowFullScreen" value="true"><param name="allowScriptAccess" value="always"><embed src="http://www.youtube.com/v/LU-gVd4DANI?version=3&#038;feature=player_detailpage" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="360"></object></p>
<p>Poniżej pliki do ściągnięcia oraz galeria zdjęć prototypu, have fun!</p>
<ul>
<li><a href='http://www.leniwiec.org/wp-content/uploads/2012/01/pcb.pdf'>PCB</a></li>
<li><a href='http://www.leniwiec.org/wp-content/uploads/2012/01/pcb_mirror.pdf'>PCB &#8211; odbicie lustrzane</a></li>
<li><a href='http://www.leniwiec.org/wp-content/uploads/2012/01/klawiatura_numeryczna_serial-0.1.zip.zip'>Paczka z kodem oraz wszystkimi plikami</a></li>
</ul>

<a href='http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/2012-01-04_16-48-12/' title='2012-01-04_16.48.12'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.48.12-150x150.jpg" class="attachment-thumbnail" alt="2012-01-04_16.48.12" title="2012-01-04_16.48.12" /></a>
<a href='http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/2012-01-04_16-48-55/' title='2012-01-04_16.48.55'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.48.55-150x150.jpg" class="attachment-thumbnail" alt="2012-01-04_16.48.55" title="2012-01-04_16.48.55" /></a>
<a href='http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/2012-01-04_16-49-18/' title='2012-01-04_16.49.18'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.49.18-150x150.jpg" class="attachment-thumbnail" alt="2012-01-04_16.49.18" title="2012-01-04_16.49.18" /></a>
<a href='http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/2012-01-04_16-54-41/' title='2012-01-04_16.54.41'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.54.41-150x150.jpg" class="attachment-thumbnail" alt="2012-01-04_16.54.41" title="2012-01-04_16.54.41" /></a>
<a href='http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/2012-01-04_16-54-54/' title='2012-01-04_16.54.54'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.54.54-150x150.jpg" class="attachment-thumbnail" alt="2012-01-04_16.54.54" title="2012-01-04_16.54.54" /></a>
<a href='http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/2012-01-04_16-55-06/' title='2012-01-04_16.55.06'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.55.06-150x150.jpg" class="attachment-thumbnail" alt="2012-01-04_16.55.06" title="2012-01-04_16.55.06" /></a>
<a href='http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/2012-01-04_16-55-19/' title='Klawiatura numeryczna z wyjściem szeregowym lub spi'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2012/01/2012-01-04_16.55.19-150x150.jpg" class="attachment-thumbnail" alt="Klawiatura numeryczna z wyjściem szeregowym lub spi" title="Klawiatura numeryczna z wyjściem szeregowym lub spi" /></a>
<a href='http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/animacja/' title='Zasada działania skanowania klawiszy przy pomocy mikrokontrolera'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2012/01/animacja-150x150.gif" class="attachment-thumbnail" alt="Zasada działania skanowania klawiszy przy pomocy mikrokontrolera" title="Zasada działania skanowania klawiszy przy pomocy mikrokontrolera" /></a>
<a href='http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/schemat-3/' title='Schemat ideowy'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2012/01/schemat-150x150.png" class="attachment-thumbnail" alt="Schemat ideowy" title="Schemat ideowy" /></a>
<a href='http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/kwarce/' title='kwarce'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2012/01/kwarce-150x150.png" class="attachment-thumbnail" alt="kwarce" title="kwarce" /></a>

]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2012/01/05/klawiatura-numeryczna-z-wyjsciem-szeregowym-lub-spi/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Budujemy „cyfrowy zasilacz” cz. 2 – przetwornik DAC (Atmega, PWM, DAC, R2R)</title>
		<link>http://www.leniwiec.org/2011/12/27/budujemy-cyfrowy-zasilacz-cz-2-przetwornik-dac-atmega-pwm-dac-r2r/</link>
		<comments>http://www.leniwiec.org/2011/12/27/budujemy-cyfrowy-zasilacz-cz-2-przetwornik-dac-atmega-pwm-dac-r2r/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 17:09:46 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Elektronika]]></category>
		<category><![CDATA[Ogólne]]></category>
		<category><![CDATA[atmega]]></category>
		<category><![CDATA[atmega8]]></category>
		<category><![CDATA[avr]]></category>
		<category><![CDATA[dac]]></category>
		<category><![CDATA[elektronika]]></category>
		<category><![CDATA[pwm]]></category>
		<category><![CDATA[rc]]></category>
		<category><![CDATA[zasilacz]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=254</guid>
		<description><![CDATA[W drugiej części tego minicyklu chciałbym Wam przedstawić różne metody wyprowadzania danych cyfrowych z mikrokontrolera w postaci napięcia proporcjonalnego do zdigitalizowanej wartości liczbowej. 
Mamy tutaj kilka możliwych rozwiązań realizacji naszego DAC (Digital Analog Converter – Konwerter Cyfrowo Analogowy). Weźmy zatem na pierwszy rzut modulację PWM.]]></description>
			<content:encoded><![CDATA[<p>W drugiej części tego minicyklu chciałbym Wam przedstawić różne metody wyprowadzania danych cyfrowych z mikrokontrolera w postaci napięcia proporcjonalnego do zdigitalizowanej wartości liczbowej. <br />
Mamy tutaj kilka możliwych rozwiązań realizacji naszego DAC (Digital Analog Converter – Konwerter Cyfrowo Analogowy). Weźmy zatem na pierwszy rzut modulację PWM.</p>
<h2>PWM (Puls Width Modulation)</h2>
<p>PWM (Puls Withd Modulation), czyli modulacja szerokości impulsu, to nic innego jak stały przebieg prostokątny o zmiennym wypełnieniu od 0% do 100%. Jeśli ktoś nie wie jak wygląda taki przebieg, to poniżej może zobaczyć kilka oscylografów (jeśli tak można nazwać te kiepskie fotki), które powinny rozwiać wątpliwości. Aby jednak wykorzystać taki przebieg w naszej aplikacji, musimy go najpierw scałkować&#8230; Bez obawy! Nie będziemy tutaj przeprowadzać karkołomnych obliczeń matematycznych, my naszą całkę zrobimy przy pomocy filtru RC. </p>
<div id="attachment_257" class="wp-caption aligncenter" style="width: 670px"><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/PWM.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/PWM.png" alt="Oscylografy przebiegów PWM" title="Oscylografy przebiegów PWM" width="660" height="165" class="size-full wp-image-257" /></a><p class="wp-caption-text">Oscylografy przebiegów PWM</p></div>
<p>Zacznijmy od wygenerowania takiego przebiegu przy pomocy mikrokontrolera. Ja użyję tutaj atmega8, jednak nie ma to większego znaczenia (może to być z powodzeniem inna atmega).</p>
<p>Atmega8 jest wyposażona w 3 kanały pwm (2 podpięte pod 16bitowy Timer1 oraz 1 na 8bitowym Timer2). Nas interesują te dwa kanały na 16 bitowym liczniku / tajmerze, ponieważ tylko one pozwalają (w przypadku atmegi8) na generowanie sygnału o rozdzielczości 10bitów. </p>
<p>Dostęp do timera 1 zapewnia nam kilka rejestrów, do których mamy dostęp, nas jednak interesować będą tylko:  TCCR1A , TCCR1B oraz OCR1A/B. Rejestry TCCR1A/B są to rejestry kontrolne, w których ustawiamy parametry timera, które nas interesują, natomiast OCR1A/B jest rejestrem porównawczym, który jest ciągle porównywany (w każdym cyklu timera) z aktualną wartością timera. Mówiąc prostymi słowy, jeśli nasz licznik naliczy tyle, ile mamy zapisane w OCR1A/B, wówczas __coś__ się stanie&#8230; w naszym przypadku, wartość ta będzie ustalała wartość wypełnienia przebiegu wyjściowego.</p>
<h2>TCCR1A</h2>
<p>Przyjrzyjmy się teraz bliżej rejestrom kontrolnym. Zgodnie z dokumentacją jest on zbudowany jak na poniższym rysunku:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/tccr1a.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/tccr1a.png" alt="" title="TCCR1A" width="650" height="85" class="aligncenter size-full wp-image-261" /></a></p>
<p>Bity COM1A1, COM1A0, COM1B1, COM1B0 służą do ustawiania trybu porównywania wyjścia licznika, a ich dokładny opis można znaleźć w tabelce poniżej:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/COM1A1.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/COM1A1.png" alt="" title="COM1A1" width="632" height="229" class="aligncenter size-full wp-image-255" /></a></p>
<p>FOC1A/B są wykorzystywane tylko w trybach niezwiązanych z PWM tak że pomińmy je sobie teraz. <br />
Dalej mamy WGM11 oraz WGM10 (w starszych układach było to odpowiednio PWM11 oraz PWM10), a także WGM12 i WGM13, które znajdują się już w rejestrze TCCR1B, służą one do ustawiania trybu pracy wyjścia. Poniższa tabelka przedstawia dostępne opcje. </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/WGM.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/WGM.png" alt="" title="WGM" width="606" height="336" class="aligncenter size-full wp-image-263" /></a></p>
<p>Nas będzie interesował tryb numer 3, czyli PWM, Phase Correct, 10-bit (ustawione bity WGM10 i WGM11). W tym trybie będziemy mieli do dyspozycji 10 bitowy PWM z korekcją fazy. Co to oznacza? Oznacza to tyle, że nasz przebieg będzie mógł mieć 1024 (10bit) różne wartości wypełnienia oraz będzie pracował w trybie korekcji fazy, który polega na tym, że timer zlicza od zera do góry, a następnie z powrotem z góry do zera, przy czym zeruje się, gdy jego wartość jest równa wartości zapisanej w rejestrze OCR1A/B. Dzieje się tak w obydwu kierunkach – podczas zliczania w górę, jak i w dół. W rezultacie na wyjściu otrzymujemy bardziej symetryczny przebieg. Częstotliwość tak generowanego sygnału jest niestety około dwukrotnie mniejsza niż w przypadku trybu fast-pwm, co wynika z konieczności zliczania w obu kierunkach.</p>
<h2>TCCR1B</h2>
<p>Rejestr TCCR1B jest zbudowany tak, jak pokazuje poniższy rysunek.</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/tccrb_1.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/tccrb_1.png" alt="" title="TCCR1B" width="660" height="88" class="aligncenter size-full wp-image-262" /></a></p>
<p>Bity ICNC1 oraz ICES1 służą odpowiednio do włączania redukcji szumów wejściowych na nóżce oznaczonej jako ICP1 oraz do określenia zbocza, które aktywuje ICP1. Nie będą one jednak przez nas wykorzystywane.</p>
<p>Bit 5 nie służy do niczego <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  Jest on po prostu zarezerwowany dla przyszłych ficzersów.</p>
<p>Bity WGM12 oraz WGM13 służą do ustalania trybu pracy timera i są opisane w powyższej tabelce.</p>
<p>Bity CS10, CS11 oraz CS12 służą do ustawiania preskalera. Czyli dzięki nim jesteśmy w stanie ustawić częstotliwość, z jaką będzie pędził nasz generator PWM! Na poniższym rysunku przedstawiony jest sposób ich ustawienia oraz odpowiadające im wartości podziału częstotliwości zegara (clk i/o).</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/cs_.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/cs_.png" alt="" title="cs_" width="637" height="259" class="aligncenter size-full wp-image-256" /></a></p>
<p>I to by było tyle, jeśli chodzi o te dwa rejestry kontrolne. W praktyce wszystko sprowadza się do wybrania trybu pracy (bity WGM*), trybu porównywania (bity COM*) oraz ustawienia preskalera (bity CS*).</p>
</p>
<h2>Program testowy</h2>
<p>Wyposażeni już w wiedzę na temat rejestrów odpowiedzialnych za kontrolowanie pracy timera zbudujmy sobie prosty układ testowy i napiszmy program testowy&#8230;</p>
<p>Poniżej schemat układu testowego (jest to właściwie ten sam układ co w części 1 artykułu)</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/schemat.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/schemat-238x300.png" alt="" title="schemat" width="238" height="300" class="aligncenter size-medium wp-image-260" /></a></p>
<p>Oraz nasz program testowy:</p>
<p><code></p>
<pre>

<span style="color: #CC6600;">int</span> PWMval = 0;

<span style="color: #CC6600;">void</span> init_dac()
{
	OCR1A&nbsp;=&nbsp;0;
	TCCR1A&nbsp;=&nbsp;_BV(COM1A1)|_BV(COM1A0)|_BV(WGM10)|_BV(WGM11);
	TCCR1B&nbsp;=&nbsp;1&lt;&lt;CS10;
}

<span style="color: #CC6600;">int</span> main()
{
&nbsp;<span style="color: #CC6600;">char</span> buffer[7];

&nbsp;init_encoder();
&nbsp;init_lcd();
&nbsp;init_dac();

&nbsp;&nbsp;<span style="color: #CC6600;">while</span>(1)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;read_encoder();
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(tackt != NEUTRAL)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
		<span style="color: #CC6600;">if</span>(tackt == LEFT &amp;&amp; PWMval &gt; 0)
		{
			PWMval--;
		}&nbsp;
		<span style="color: #CC6600;">else</span> <span style="color: #CC6600;">if</span>(tackt == RIGHT &amp;&amp; PWMval &lt; 1023)
		{
			PWMval++;
		}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
		lcd_clrscr();
		itoa(PWMval,&nbsp;buffer,&nbsp;10);
		lcd_puts(buffer);

		OCR1A&nbsp;=&nbsp;PWMval;

		tackt&nbsp;=&nbsp;NEUTRAL;
	}&nbsp;
&nbsp;&nbsp;}
}
</pre>
<p></code></p>
<p>Jak widać na powyższym kodzie, mamy procedurkę init_dac()I, która ustawia timer 1 w trybie 10bitowego PWM z korekcją fazy, dalej ustawiamy bity COM1A0 oraz COM1A1 tak, aby rejestr OC1A był ustawiany, kiedy wartość licznika, podczas zliczania w górę, osiągnie wartość zadaną z rejestru OCR1A, oraz kasowany, kiedy wartości te będą takie same podczas zliczania w dół.</p>
<p>Dalej ustawiamy bit CS10 w rejestrze kontrolnym TCCR1B, co odpowiada ustawieniu preskalera na 1 oraz rozpoczęcie pracy generatora. </p>
<p>W głównej pętli programu, podczas manipulowania enkoderem w lewo i prawo, wartość zmiennej PWMval jest odpowiednio inkrementowana oraz dekrementowana, a następnie przypisywana do rejestru OCR1A i tym samym ustawiana jest nowa wartość wypełnienia przebiegu wyjściowego. </p>
<p>I to tak naprawdę wszystko. Prawda, że proste? Raptem tylko 3 linijki dzielą nas od działającego 10bitowego PWM&#8217;a <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h2>Co dalej z prostokątem ?</h2>
<p>Ok, potrafimy już wygenerować przebieg prostokątny o wypełnieniu od 0% do 100%, teraz potrzebujemy, aby ten sygnał zmienił się w napięcie proporcjonalne do jego wypełnienia. Aby tego dokonać, należy sygnał ów uśrednić. Do tego celu zastosujemy odpowiedni filtr dolnoprzepustowy RC. </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/rc_pasive.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/rc_pasive-300x142.png" alt="" title="Pasywny filtr dolnoprzepustowy" width="300" height="142" class="aligncenter size-medium wp-image-259" /></a></p>
<p>Problem z tego typu filtrami polega na tym, że stosując zbyt małą pojemność (wysoka częstotliwość odcięcia), przebieg na wyjściu nie nadaje się jako źródło napięcia odniesienia czy też napięcia sterującego cokolwiek, a z drugiej strony, zwiększając wartość C (niska częstotliwość odcięcia), zwiększa się czas propagacji, czyli czas, który upłynie pomiędzy przekręceniem gałką a pojawieniem się żądanego napięcia na wyjściu. Aby zniwelować w pewnym stopniu tę niedogodność, możemy zastosować filtry aktywne. Filtr taki jest zbudowany na wzmacniaczu operacyjnym, który ma bardzo dużą rezystancję wejściową, co dodatkowo jest nam na rękę, ponieważ podłączając wyjście naszego filtra RC (pasywnego) do odbiornika, którego rezystancja wejściowa jest niewielka, odbiornik ten rozładowuje w pewnym stopniu kondensator C, co negatywnie wpływa na stabilność całego budowanego przetwornika DAC. </p>
<p>Częstotliwość odcięcia dla filtru pokazanego na powyższym rysunku jest określana następującym wzorem:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/rc_f.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/rc_f.png" alt="" title="rc_f" width="96" height="41" class="aligncenter size-full wp-image-258" /></a></p>
<p>Łącząc takie filtry w szereg, zwiększamy nachylenie filtru, tworząc filtr n-rzędu, jednak wówczas sygnał jest odpowiednio tłumiony (np. dla filtru 2go rzędu sygnał jest tłumiony dwa razy o 6db). <br />
Nie chciałbym tutaj się rozwodzić na temat filtrów, ponieważ jest to temat bardzo obszerny i ten artykuł mógłby urosnąć do gigantycznych rozmiarów&#8230; Niemniej jednak, aby nie pozostawiać Wam niedosytu w tym temacie, polecam pobrać darmowy program Filter Pro wydany przez texas instruments i poeksperymentować w nim z różnego rodzaju filtrami. <br />
Program ten jest dostępny pod tym linkiem: <a href="http://www.ti.com/tool/filterpro?DCMP=hpa_amp_general&#038;HQS=NotApplicable%252bOT%252bfilterpro">http://www.ti.com/tool/filterpro?DCMP=hpa_amp_general&#038;HQS=NotApplicable%252bOT%252bfilterpro</a>
</p>
<h2>Parametry</h2>
<p>Wiemy już, jak zrealizować prosty przetwornik cyfrowo-analogowy przy wykorzystaniu pwm. Spróbujmy sobie teraz przeanalizować jego parametry, możliwości ich poprawy oraz przydatność tego rozwiązania w naszej aplikacji. </p>
<p>Wbrew pozorom parametry tak wykonanego DACa mogą być całkiem przyzwoite, a wyjścia portów I/O, zresztą tak jak cały kontroler, są wykonane w technologi CMOS, dzięki czemu w stanie wysokim na wyjściu pojawia się praktycznie napięcie zasilania, natomiast w stanie niskim zero.<br />
Wykorzystując tę właściwość można zastosować popularną technikę zwiększającą precyzję tak generowanego sygnału, która polega na zasilaniu całego mikrokontrolera ze źródła napięcia odniesienia. Dzięki czemu otrzymywany na wyjściu sygnał jest całkiem niezłej jakości. <br />
Nie chcę tutaj jednak wchodzić w szczegóły i rzucać konkretnymi danymi liczbowymi, ponieważ tak zbudowany przetwornik ma jedną zasadniczą wadę, która dyskryminuje go całkowicie w naszym zastosowaniu. Jest nią nieakceptowalnie długi czas ustalania średniego napięcia na wyjściu filtra dolnoprzepustowego podłączonego do wyjścia generatora PWM. <br />
W przypadku gdyby nasz zasilacz korzystał z histerezy wykonanej przy pomocy wzmacniaczy operacyjnych, a kontroler służyłby tylko do zadawania odpowiednich napięć referencyjnych dla ustalenia napięcia i prądu wyjściowego, takie rozwiązanie byłoby akceptowalne. Niestety czas ustalania, nawet wykorzystując aktywne filtry dolnoprzepustowe, jest znacznie za długi i w przypadku zadziałania ogranicznika prądu lub przy skokach napięcia, zanim zdążyłoby się ustabilizować napięcie wyjściowe, podłączony do naszego zasilacza układ mógłby się upiec.
</p>
<h2>Podsumowanie</h2>
<p>Niemniej jednak, polecam wszystkim eksperymenty z PWM, gdyż jest to technika bardzo szeroko wykorzystywana w różnych aplikacjach i na pewno przyda się Wam jeszcze nieraz! <br />W następnym odcinku postaram się zaprezentować rozwiązanie DAC&#8217;a oparte o drabinkę rezystorową R2R, pokażę Wam, jak zrealizować 16bitowy przetwornik oparty na r2r, wykorzystując tylko 3 piny procesora, a do tego nie będzie to kosztowało więcej niż 2 zł <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Jako że zbliża się Nowy Rok, a niestety przed Świętami czasu na pisanie nie było, życzę Wam wszystkim (tak, tak, Wam, spam-boty nękające mnie codziennie – też!!), wszystkiego najlepszego w nadchodzącym nowym roku numer 0x7DC! (miejmy nadzieję, że nie będzie on ostatnim..)</p>
<p>Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2011/12/27/budujemy-cyfrowy-zasilacz-cz-2-przetwornik-dac-atmega-pwm-dac-r2r/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Budujemy „cyfrowy zasilacz” &#8211; enkoder obrotowy w praktyce – cz. 1</title>
		<link>http://www.leniwiec.org/2011/12/09/budujemy-cyfrowy-zasilacz-enkoder-obrotowy-w-praktyce-cz-1/</link>
		<comments>http://www.leniwiec.org/2011/12/09/budujemy-cyfrowy-zasilacz-enkoder-obrotowy-w-praktyce-cz-1/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 19:45:40 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Elektronika]]></category>
		<category><![CDATA[atmega8]]></category>
		<category><![CDATA[atmel]]></category>
		<category><![CDATA[elektronika]]></category>
		<category><![CDATA[enkoder]]></category>
		<category><![CDATA[lcd]]></category>
		<category><![CDATA[projekt]]></category>
		<category><![CDATA[zasilacz]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=232</guid>
		<description><![CDATA[Tym wpisem chcę zacząć krótką serię artykułów opisujących kolejne perypetie procesu projektowania, podejmowania decyzji oraz budowania zasilacza „cyfrowego”. Słowo cyfrowego zostało celowo napisane w cudzysłowie, gdyż nie będzie to zasilacz impulsowy (przez niektórych nazywany cyfrowym), nie będzie to też do końca zasilacz liniowy ze sterowaniem cyfrowym (np. pwm lub DAC). Będzie to natomiast zasilacz liniowy z tym, że pętla histerezy (dla niewtajemniczonych pętla stabilizująca napięcie, prąd, ustalająca limitery dla prądu i napięcia itd.) zostanie przeniesiona do programu. Koncepcja taka jest przez wielu elektroników bardzo mocno krytykowana, jako że taki zasilacz nie nadaje się do uruchamiania układów, gdyż jest zbyt wolny w stosunku do rozwiązań opartych na wzmacniaczach operacyjnych. Jak to będzie w naszym przypadku, to się okaże, w ostatnim odcinku obiecuję dokonać stosownych pomiarów gotowego układu. Ja natomiast zdecydowałem się, aby oprzeć ten projekt właśnie na takiej koncepcji z kilku względów. Po pierwsze, jestem bardziej software-guy, a więc przeniesienie ile się da do programu jest mi na rękę, poza tym daje to spore możliwości modyfikacji i zmiany funkcjonalności całego układu poprzez wymianę oprogramowania. Po drugie, takie rozwiązanie minimalizuje liczbę elementów elektronicznych oraz ich połączenia, co sprawia, że układ od strony elektronicznej staje się prostszy i łatwiejszy do wykonania przez młodych adeptów elektroniki.]]></description>
			<content:encoded><![CDATA[<p>Tym wpisem chcę zacząć krótką serię artykułów opisujących kolejne perypetie procesu projektowania, podejmowania decyzji oraz budowania zasilacza „cyfrowego”. Słowo cyfrowego zostało celowo napisane w cudzysłowie, gdyż nie będzie to zasilacz impulsowy (przez niektórych nazywany cyfrowym), nie będzie to też do końca zasilacz liniowy ze sterowaniem cyfrowym (np. pwm lub DAC). Będzie to natomiast zasilacz liniowy z tym, że pętla histerezy (dla niewtajemniczonych pętla stabilizująca napięcie, prąd, ustalająca limitery dla prądu i napięcia itd.) zostanie przeniesiona do programu. Koncepcja taka jest przez wielu elektroników bardzo mocno krytykowana, jako że taki zasilacz nie nadaje się do uruchamiania układów, gdyż jest zbyt wolny w stosunku do rozwiązań opartych na wzmacniaczach operacyjnych. Jak to będzie w naszym przypadku, to się okaże, w ostatnim odcinku obiecuję dokonać stosownych pomiarów gotowego układu. Ja natomiast zdecydowałem się, aby oprzeć ten projekt właśnie na takiej koncepcji z kilku względów. Po pierwsze, jestem bardziej software-guy, a więc przeniesienie ile się da do programu jest mi na rękę, poza tym daje to spore możliwości modyfikacji i zmiany funkcjonalności całego układu poprzez wymianę oprogramowania. Po drugie, takie rozwiązanie minimalizuje liczbę elementów elektronicznych oraz ich połączenia, co sprawia, że układ od strony elektronicznej staje się prostszy i łatwiejszy do wykonania przez młodych adeptów elektroniki. </p>
<h2>Zaczynamy</h2>
<p>Zanim zaczniemy cokolwiek projektować, musimy przygotować sobie odpowiednie narzędzia – w naszym przypadku będą to odpowiednie biblioteki programistyczne / komponenty, których później będziemy używać. Zacznijmy na początku od sterowania. Pierwsze, co przychodzi do głowy jako wejście danych do naszego programu/układu, to klawiatura i wszelkie jej odmiany: klawiatura up/down/ok, klawiatura numeryczna 0&#8230;9, joystick itp. itd. Kolejna opcja to sterowanie poprzez port szeregowy bezpośrednio z komputera. Pomysł ok, ale bardziej jako ficzers niż jako główne sterowanie (który nota bene zostanie przez nas dodany w następnych odcinkach) – nie wyobrażam sobie sytuacji, kiedy uruchamiam jakiś nowy układ i za każdym razem, kiedy chcę zmienić wartość napięcia albo ustawić ogranicznik prądu sięgam po laptopa. <br />To, co wydaje się, że byłoby najlepsze to mieć dużą wygodną gałkę, najlepiej potencjometr wieloobrotowy&#8230; zostaje tylko pytanie jak go podłączyć do procesora ? Otóż nie podłączać go wcale! W naszym projekcie użyjemy enkodera obrotowego&#8230;</p>
<h2>Enkoder obrotowy? Co to takiego?!</h2>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/enkoder_foto.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/enkoder_foto-300x225.jpg" alt="Zdjęcie enkodera" title="Zdjęcie enkodera" width="300" height="225" class="aligncenter size-medium wp-image-234" /></a></p>
<p>Enkoder obrotowy to takie małe pokrętełko (foto powyżej), a właściwie sprytny przełącznik, który zmienia swoje stany w zależności od tego, czy kręcimy go w prawo, czy w lewo.  Schemat enkodera typu ENC-11 znajduje się poniżej.</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/schemat_enkodera.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/schemat_enkodera-300x209.jpg" alt="Schemat enkodera ENC-11" title="Schemat enkodera ENC-11" width="300" height="209" class="aligncenter size-medium wp-image-235" /></a></p>
<p>Dlaczego akurat ten typ? Bo akurat jest dostępny na pewnym znanym portalu aukcyjnym i jest naprawdę tani. Koszt takiego enkodera to tylko kilka eurocentów, co dodatkowo czyni go jak najbardziej odpowiednim dla nas. Model, który udało mi się zakupić miał dodatkowo wbudowany przełącznik, który zamykał styki po naciśnięciu gałki – fajnie! Będziemy mogli zrobić takie fajne sterowanie menu jak np. w komputerku pokładowym w BMW E39 <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  </p>
<p>Zanim zaczniemy podłączać go do kontrolera i programować, przyjrzyjmy się, co jest napisane w dokumentacji. </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/datasheet_picture.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/datasheet_picture.png" alt="" title="datasheet_picture" width="666" height="375" class="aligncenter size-full wp-image-233" /></a></p>
<p>Na powyższym rysunku zaczerpniętym z noty katalogowej widzimy, jak wygląda sygnał wyjściowy z naszego enkoderka w momencie, gdy go kręcimy w lewo i w prawo. Jak już pewnie zauważyłeś, w zależności od tego, w którą stronę go kręcimy, sygnał na końcówce B jest przesunięty w fazie, tak że mamy albo zbocze opadające albo narastające w stosunku do sygnału wyzwalającego A. Tę właśnie właściwość wykorzystamy w programie. Sygnał z końcówki A będzie nam generował „przerwanie”, natomiast sygnał z końcówki B w zależności od zbocza będzie nas informował o kierunku, w jakim się on obraca. </p>
<h2>Podłączamy!</h2>
<p>W celu zaprogramowania oraz testowania układu, zbudujmy sobie (najlepiej na płytce stykowej) następujący układ: </p>
<div id="attachment_236" class="wp-caption aligncenter" style="width: 234px"><a href="http://www.leniwiec.org/wp-content/uploads/2011/12/schemat_ukladu_testowego.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/12/schemat_ukladu_testowego-224x300.png" alt="Schemat układu testowego" title="Schemat układu testowego" width="224" height="300" class="size-medium wp-image-236" /></a><p class="wp-caption-text">Schemat układu testowego</p></div>
<p>Jak widać na schemacie, będzie nam potrzebny kontroler (ja użyłem Atmega8, może to być jednak dowolny inny rodziny Atmega8..32), wyświetlacz oparty na układzie HD447780, no i nasz enkoder.</p>
<p>
Do obsługi samego enkodera wykorzystamy dwa porty procesora ustawione jako wejścia + dodatkowe jedno wejście dla wbudowanego przełącznika. </p>
<h2>Pora na kod&#8230;</h2>
<p>Zanim zacząłem pisać ten artykuł, zrobiłem małe rozeznanie w sieci, jak robią to inni ludzie, jednak ich metody mi się nie podobały. A to dlatego, że wszystkie rozwiązania, które widziałem były oparte o przerwania, co w naszym zastosowaniu nie jest najszczęśliwsze, gdyż kontroler będzie się zajmował również stabilizacją napięcia wyjściowego zasilacza. Zatem ewentualne opóźnienie, które mogłoby wprowadzić takie rozwiązanie obsługi enkodera, mogłoby skutkować niestabilną pracą zasilacza, a co za tym idzie &#8211; skokami napięcia wyjściowego. </p>
<p>Nasz program (biblioteka?) będzie się składał z dwóch procedur. Pierwsza z nich będzie uruchamiana na początku programu i będzie się w niej znajdował kod odpowiedzialny za inicjalizację i konfigurację portów – nazwijmy ją <strong><em>init_encoder()</em></strong>. Druga z kolei będzie uruchamiana w głównej pętli programu, a jej zadaniem będzie uaktualnianie zmiennej globalnej <em>tackt</em>, która będzie nas informowała o aktualnym stanie enkodera: LEFT, RIGHT, CLICK – nazwijmy ją <strong><em>read_encoder()</em></strong>.</p>
<h2>Konfiguracja</h2>
<p>Poniższy kod przedstawia ciało procedury <em>init_encoder()</em></p>
<p><code>
<pre>
#define&nbsp;ENC_PIN_1_PIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PINC
#define&nbsp;ENC_PIN_1_REG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DDRC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//first encoder pin register</span>
#define&nbsp;ENC_PIN_1_PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//first encoder pin port</span>
#define&nbsp;ENC_PIN_1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PC4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//first encoder pin</span>

#define&nbsp;ENC_PIN_2_PIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PINC
#define&nbsp;ENC_PIN_2_REG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DDRC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//second encoder pin register</span>
#define&nbsp;ENC_PIN_2_PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//second encoder pin port</span>
#define&nbsp;ENC_PIN_2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PC5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//second encoder pin</span>

#define&nbsp;ENC_BTN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PD7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//encoder button pin</span>
#define&nbsp;ENC_BTN_PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//encoder button port</span>
#define&nbsp;ENC_BTN_REG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DDRD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//encoder button register</span>
#define&nbsp;ENC_BTN_PIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PIND

#define&nbsp;LEFT&nbsp;&nbsp;&nbsp;&nbsp;1
#define&nbsp;RIGHT&nbsp;&nbsp;&nbsp;2
#define&nbsp;CLICK&nbsp;&nbsp;&nbsp;3
#define&nbsp;NEUTRAL&nbsp;0

uint8_t&nbsp;tackt;

<span style="color: #CC6600;">void</span> init_encoder(<span style="color: #CC6600;">void</span> )
{
&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_1_REG&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 1 input              */</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_1_PORT&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 1 pull-up enabled    */</span>

&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_2_REG&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 2 input              */</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_2_PORT&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 2 pull-up enabled    */</span>

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//click button</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_BTN_REG&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_BTN);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin button input              */</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_BTN_PORT&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_BTN);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin button pull-up enabled    */</span>
}<span style="color: #7E7E7E;">//end of init_encoder()</span>
</pre>
<p></code></p>
<p>Jak widać, nie ma tutaj wielkiej filozofii, po prostu ustawiamy 3 wybrane przez nas porty kontrolera jako wejścia oraz aktywujemy dla nich pull-up`y (podciągnięcia wewnętrznym rezystorem do plusa zasilania). Oprócz tego w globalnej przestrzeni programu definiujemy dwie zmienne globalne: 8mio bitową zmienną <em>tackt</em>, która będzie nas informowała o aktualnym stanie enkodera, oraz zmienną pomocniczą <em>last</em>. <br />Zdefiniowałem oprócz tego jeszcze kilka stałych LEFT, RIGHT, CLICK, NEUTRAL – te 4 stale są listą enumeratywnych wartości stanów enkodera, ENC_PIN_*, w których definiujemy, do których portów kontrolera jest podłączony enkoder.</p>
<h2>Czytanie stanu enkodera</h2>
<p>Poniższy fragment kodu przedstawia ciało procedury, która służy do odczytu aktualnego stanu enkodera.</p>
<p><code>
<pre>
<span style="color: #CC6600;">void</span> read_encoder(<span style="color: #CC6600;">void</span> )
{
&nbsp;&nbsp;&nbsp;&nbsp;uint8_t&nbsp;current&nbsp;=&nbsp;0;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">unsigned</span> <span style="color: #CC6600;">int</span> i = 0;

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_BTN_PIN, ENC_BTN))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">for</span>(i=0;i&lt;65535;i++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(!bit_is_clear(ENC_BTN_PIN, ENC_BTN))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">return</span> ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;CLICK;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">return</span> ;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN, ENC_PIN_1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;1;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;0;

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(last != current)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN,ENC_PIN_1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_2_PIN,ENC_PIN_2))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;LEFT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;RIGHT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN,ENC_PIN_2))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;RIGHT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;LEFT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last&nbsp;=&nbsp;current;
&nbsp;&nbsp;&nbsp;&nbsp;}
}<span style="color: #7E7E7E;">//end of read_encoder()</span>
</pre>
<p></code></p>
<p>W pierwszej kolejności sprawdzamy, czy został przyciśnięty przycisk wbudowany w pokrętło enkodera. </p>
<p><code>
<pre>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_BTN_PIN, ENC_BTN))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">for</span>(i=0;i&lt;65535;i++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(!bit_is_clear(ENC_BTN_PIN, ENC_BTN))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">return</span> ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;CLICK;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">return</span> ;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<p></code></p>
<p>Jeśli na pinie ustawionym jako wejście przycisku enkodera pojawi się stan niski, wówczas do zmiennej globalnej <em>tackt</em> przypisujemy wartość CLICK i kończymy wykonywanie procedury.<br />
Dodatkowo znajduje się tam pętla, która sprawdza, czy przez 65535 cyklów, cały czas przycisk jest non-stop wciśnięty – jest to bardzo prymitywny kod debouncujący. Co to znaczy? Podczas przełączania każdego elektromechanicznego przełącznika, zanim znajdzie się on w stabilnym stanie (włączonym bądź wyłączonym), to w czasie przełączania występuje zjawisko iskrzenia i „podskakiwania styków”, wejście kontrolera jest natomiast na tyle czułe, że wyłapuje te „migotania”  i interpretuje je jako zmiany stanu portu. Natomiast dzięki takiej pętli debouncującej upewniamy się, że przycisk jest już wciśnięty „na stałe”.</p>
<p>Dalej zaczyna się właściwy kod odpowiedzialny za wykrywanie aktualnego stanu enkodera</p>
<p><code></p>
<pre>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN, ENC_PIN_1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;1;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;0;
</pre>
<p></code></p>
<p>Na początku sprawdzamy, czy na pinie podłączonym do wyjścia A enkodera (nasze wyjście wyzwalające), został ustawiony stan niski, jeśli tak, to zapisujemy w zmiennej <em>current</em> jedynkę, jeśli natomiast nie, zapisujemy w niej wartość zero. W ten sposób w zmiennej <em>current</em> mamy aktualny stan wejścia wyzwalającego. </p>
<p>Dalej mamy warunek, w którym sprawdzamy, czy aktualnie odczytana wartość wejścia wyzwalającego jest różna od ostatnio odczytanej wartości, jeśli tak, oznacza to, że pokrętło zostało poruszone, nadal jednak nie wiemy, czy w lewo, czy w prawo. Aby to określić, mamy dalej odpowiednie warunki, w których sprawdzamy, czy ruch nastąpił w lewo, czy w prawo. Poniekąd można powiedzieć, że do tej pory kod, który został wykonany, jest swoistym substytutem przerwania, które mogłoby być wygenerowane podczas zmiany stanu enkodera.<br />
Mamy zatem następujący kod:</p>
<p><code>
<pre>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(last != current)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN,ENC_PIN_1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_2_PIN,ENC_PIN_2))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;LEFT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;RIGHT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN,ENC_PIN_2))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;RIGHT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;LEFT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last&nbsp;=&nbsp;current;
&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<p></code><br />
Najpierw sprawdzamy, czy na nóżce A enkodera jest aktualnie stan niski, jeśli tak, to sprawdzamy, czy na nóżce B enkodera jest również stan niski, jeśli tak, oznacza to sytuację z górnej części rysunku z datasheetu, czyli wiemy, że gałka enkodera została przesunięta w kierunku ruchu wskazówek zegara (clockwise). Jeżeli natomiast na nóżce B enkodera stan jest wysoki, oznacza to sytuację z dolnej części tego rysunku, czyli gałka została przekręcona w kierunku odwrotnym do ruchu wskazówek zegara (counter-clockwise). Po tych warunkach przypisujemy odpowiednią wartość do zmiennej globalnej tackt. Jeśli natomiast pierwszy warunek nie zostanie spełniony (na nóżce A enkodera jest stan wysoki), dokonujemy analogicznego testu. Jedynie tylko należy uwzględnić, że wartości z rysunku (datasheet) są przesunięte o pół okresu. </p>
<p>Na końcu przypisujemy aktualną wartość wejścia wyzwalającego (nóżka A enkodera) do zmiennej <em>last</em>. I na tym kończy się procedura. </p>
<h2>Złóżmy to do kupy&#8230;</h2>
<p>Poniżej cały złożony razem kod.</p>
<p><code>
<pre>
define&nbsp;ENC_PIN_1_PIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PINC
#define&nbsp;ENC_PIN_1_REG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DDRC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//first encoder pin register</span>
#define&nbsp;ENC_PIN_1_PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//first encoder pin port</span>
#define&nbsp;ENC_PIN_1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PC4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//first encoder pin</span>

#define&nbsp;ENC_PIN_2_PIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PINC
#define&nbsp;ENC_PIN_2_REG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DDRC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//second encoder pin register</span>
#define&nbsp;ENC_PIN_2_PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//second encoder pin port</span>
#define&nbsp;ENC_PIN_2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PC5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//second encoder pin</span>

#define&nbsp;ENC_BTN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PD7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//encoder button pin</span>
#define&nbsp;ENC_BTN_PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//encoder button port</span>
#define&nbsp;ENC_BTN_REG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DDRD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//encoder button register</span>
#define&nbsp;ENC_BTN_PIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PIND

#define&nbsp;LEFT&nbsp;&nbsp;&nbsp;&nbsp;1
#define&nbsp;RIGHT&nbsp;&nbsp;&nbsp;2
#define&nbsp;CLICK&nbsp;&nbsp;&nbsp;3
#define&nbsp;NEUTRAL&nbsp;0

uint8_t&nbsp;tackt&nbsp;=&nbsp;NEUTRAL;
uint8_t&nbsp;last&nbsp;=&nbsp;0;

<span style="color: #CC6600;">void</span> init_encoder(<span style="color: #CC6600;">void</span> )
{
&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_1_REG&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 1 input              */</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_1_PORT&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 1 pull-up enabled    */</span>

&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_2_REG&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 2 input              */</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_2_PORT&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 2 pull-up enabled    */</span>

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//click button</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_BTN_REG&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_BTN);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin button input              */</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_BTN_PORT&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_BTN);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin button pull-up enabled    */</span>
}<span style="color: #7E7E7E;">//end of init_encoder()</span>

<span style="color: #CC6600;">void</span> read_encoder(<span style="color: #CC6600;">void</span> )
{
&nbsp;&nbsp;&nbsp;&nbsp;uint8_t&nbsp;current&nbsp;=&nbsp;0;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">unsigned</span> <span style="color: #CC6600;">int</span> i = 0;

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_BTN_PIN, ENC_BTN))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">for</span>(i=0;i&lt;65535;i++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(!bit_is_clear(ENC_BTN_PIN, ENC_BTN))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">return</span> ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;CLICK;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">return</span> ;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN, ENC_PIN_1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;1;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;0;

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(last != current)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN,ENC_PIN_1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_2_PIN,ENC_PIN_2))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;LEFT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;RIGHT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN,ENC_PIN_2))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;RIGHT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;LEFT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last&nbsp;=&nbsp;current;
&nbsp;&nbsp;&nbsp;&nbsp;}
}<span style="color: #7E7E7E;">//end of read_encoder()</span>

<span style="color: #CC6600;">int</span> main()
{
&nbsp;&nbsp;init_encoder();
&nbsp;&nbsp;init_lcd();
&nbsp;&nbsp;
&nbsp;&nbsp;<span style="color: #CC6600;">while</span>(1)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;read_encoder();
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(tackt != NEUTRAL)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lcd_clrscr();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(tackt == LEFT)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lcd_puts(PSTR(<span style="color: #006699;">"Left"</span>));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span> <span style="color: #CC6600;">if</span>(tackt == RIGHT)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lcd_puts(PSTR(<span style="color: #006699;">"Right"</span>));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span> <span style="color: #CC6600;">if</span>(tackt == CLICK)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lcd_puts(<span style="color: #006699;">"Click"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;NEUTRAL;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;
&nbsp;&nbsp;}
}<span style="color: #7E7E7E;">//end of main()</span>
</pre>
<p></code></p>
<p>Zobaczmy po kolei, co się dzieje. Program wchodzi w funkcję main, najpierw inicjalizuje porty kontrolera odpowiedzialne za obsługę kontrolera oraz bibliotekę obsługi wyświetlacza.<br />
Dalej program przechodzi do głównej pętli, w której za każdym „przelotem” wywoływana jest procedura <em>read_encoder()</em>, która odczytuje aktualny stan enkodera. Następnie sprawdzamy, czy stan jest różny od NEUTRAL, czyli czy cokolwiek się dzieje z enkoderem, jeśli tak sprawdzamy jego stan i wyświetlamy odpowiedni komunikat na lcd. I na samym końcu czyścimy zmienną globalną <em>tackt</em> poprzez przypisanie jej wartości NEUTRAL. Jest to niezbędne, aby przy następnym wywołaniu procedury <em>read_encoder()</em> wykonała się ona poprawnie. </p>
<h2>Co dalej ?</h2>
<p>Wypadałoby przenieść nasz kod do osobnych plików, ustawić zmienną tackt jako extender oraz wszystko ładnie sformatować. Poniżej gotowy sformatowany kod:</p>
<p>encoder.h:<br />
<code>
<pre>
#ifndef&nbsp;ENCODER_H
#define&nbsp;ENCODER_H

#define&nbsp;ENC_PIN_1_PIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PINC
#define&nbsp;ENC_PIN_1_REG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DDRC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//first encoder pin register</span>
#define&nbsp;ENC_PIN_1_PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//first encoder pin port</span>
#define&nbsp;ENC_PIN_1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PC4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//first encoder pin</span>

#define&nbsp;ENC_PIN_2_PIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PINC
#define&nbsp;ENC_PIN_2_REG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DDRC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//second encoder pin register</span>
#define&nbsp;ENC_PIN_2_PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//second encoder pin port</span>
#define&nbsp;ENC_PIN_2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PC5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//second encoder pin</span>

#define&nbsp;ENC_BTN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PD7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//encoder button pin</span>
#define&nbsp;ENC_BTN_PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORTD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//encoder button port</span>
#define&nbsp;ENC_BTN_REG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DDRD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//encoder button register</span>
#define&nbsp;ENC_BTN_PIN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PIND

#define&nbsp;LEFT&nbsp;&nbsp;&nbsp;&nbsp;1
#define&nbsp;RIGHT&nbsp;&nbsp;&nbsp;2
#define&nbsp;CLICK&nbsp;&nbsp;&nbsp;3
#define&nbsp;NEUTRAL&nbsp;0

extern&nbsp;uint8_t&nbsp;tackt;

<span style="color: #CC6600;">void</span> init_encoder(<span style="color: #CC6600;">void</span> );
<span style="color: #CC6600;">void</span> read_encoder(<span style="color: #CC6600;">void</span> );

#endif
</pre>
<p></code></p>
<p>encoder.c:<br />
<code>
<pre>
#include&nbsp;&lt;stdlib.h&gt;
#include&nbsp;&lt;avr/io.h&gt;
#include&nbsp;&lt;util/<span style="color: #CC6600;">delay</span>.h&gt;

#include&nbsp;<span style="color: #006699;">"encoder.h"</span>

uint8_t&nbsp;tackt&nbsp;=&nbsp;NEUTRAL;
uint8_t&nbsp;last&nbsp;=&nbsp;0;

<span style="color: #CC6600;">void</span> init_encoder(<span style="color: #CC6600;">void</span> )
{
&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_1_REG&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 1 input              */</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_1_PORT&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 1 pull-up enabled    */</span>

&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_2_REG&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 2 input              */</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_PIN_2_PORT&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_PIN_2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin 2 pull-up enabled    */</span>

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">//click button</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_BTN_REG&nbsp;&amp;=~&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_BTN);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin button input              */</span>
&nbsp;&nbsp;&nbsp;&nbsp;ENC_BTN_PORT&nbsp;|=&nbsp;(1&nbsp;&lt;&lt;&nbsp;ENC_BTN);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7E7E7E;">/* Pin button pull-up enabled    */</span>
}<span style="color: #7E7E7E;">//end of init_encoder()</span>

<span style="color: #CC6600;">void</span> read_encoder(<span style="color: #CC6600;">void</span> )
{
&nbsp;&nbsp;&nbsp;&nbsp;uint8_t&nbsp;current&nbsp;=&nbsp;0;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">unsigned</span> <span style="color: #CC6600;">int</span> i = 0;

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_BTN_PIN, ENC_BTN))
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">for</span>(i=0;i&lt;65535;i++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(!bit_is_clear(ENC_BTN_PIN, ENC_BTN))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">return</span> ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;CLICK;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">return</span> ;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN, ENC_PIN_1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;1;
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;=&nbsp;0;

&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(last != current)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN,ENC_PIN_1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_2_PIN,ENC_PIN_2))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;LEFT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;RIGHT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(bit_is_clear(ENC_PIN_1_PIN,ENC_PIN_2))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;RIGHT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">else</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tackt&nbsp;=&nbsp;LEFT;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last&nbsp;=&nbsp;current;
&nbsp;&nbsp;&nbsp;&nbsp;}
}<span style="color: #7E7E7E;">//end of read_encoder()</span>
</pre>
<p></code></p>
<h2>Podsumowanie</h2>
<p>Polecam samemu poeksperymentować z enkoderem. Imo jest on bardzo wygodnym sposobem obsługi menu i generalnie dobrym interfejsem użytkownik->sprzęt. W następnym odcinku zajmiemy się kolejnym ważnym elementem, jakim jest przetwornik DAC. Będziemy również podejmować pierwsze poważne decyzje projektowe, które będą rzutować na dalszy przebieg prac i ostateczny produkt! Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2011/12/09/budujemy-cyfrowy-zasilacz-enkoder-obrotowy-w-praktyce-cz-1/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Modyfikacja (cheat) w grze sauerbraten</title>
		<link>http://www.leniwiec.org/2011/11/06/modyfikacja-cheat-w-grze-sauerbraten/</link>
		<comments>http://www.leniwiec.org/2011/11/06/modyfikacja-cheat-w-grze-sauerbraten/#comments</comments>
		<pubDate>Sun, 06 Nov 2011 12:15:52 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Codes Scratches]]></category>
		<category><![CDATA[Ogólne]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[cheat]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[mod]]></category>
		<category><![CDATA[sauerbraten]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=219</guid>
		<description><![CDATA[Ponieważ ostatnio nagromadziło się wiele pracy, a (jak powszechnie wiadomo) praca wywołuje stres... Należało ten stres rozładować ;-) Z pomocą nadeszła gra sauerbraten. Jest to chyba najlepsza darmowa propozycja dla użytkowników linuxa, a co więcej jest to aplikacja openSourcowa, a więc mamy dostęp do kodu źródłowego, czyli możemy sami modyfikować to i owo.]]></description>
			<content:encoded><![CDATA[<p>Ponieważ ostatnio nagromadziło się wiele pracy, a (jak powszechnie wiadomo) praca wywołuje stres&#8230; Należało ten stres rozładować <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  Z pomocą nadeszła gra sauerbraten. Jest to chyba najlepsza darmowa propozycja dla użytkowników linuxa, a co więcej jest to aplikacja openSourcowa, a więc mamy dostęp do kodu źródłowego, czyli możemy sami modyfikować to i owo.</p>
<p>Sauerbraten, aby zoptymalizować liczbę przesyłanych danych do/z serwera, większość pracy wykonuje po stronie klienta. Daje to możliwość wykonania pewnych modyfikacji kodu, które chciałbym tutaj przedstawić. Nie są to typowe cheaty, które nie dają przeciwnikowi żadnych szans, a jedynie drobne modyfikacje, które sprawiają, że gra się lepiej. </p>
<h2>Zaczynamy</h2>
<p>Po ściągnięciu źródeł gry (są one dołączone do jej dystrybucji), możemy przystąpić do modyfikacji. To, co będzie nas interesowało, to structura zawarta w pliku <em>src/fpsgame/game.h</em>. Odpowiada ona za zachowanie się konkretnych typów broni używanych w grze. Wygląda ona następująco:</p>
<p><code>
<pre>
<span style="color: #CC6600;">static</span> const struct guninfo { <span style="color: #CC6600;">short</span> sound, attackdelay, damage, projspeed, part,
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kickamount,&nbsp;range;&nbsp;const&nbsp;<span style="color: #CC6600;">char</span> *name, *file;
			&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;guns[NUMGUNS]&nbsp;=
&nbsp;{
&nbsp;{&nbsp;S_PUNCH1,&nbsp;250,&nbsp;50,&nbsp;0,&nbsp;0,&nbsp;0,&nbsp;14,&nbsp;<span style="color: #006699;">"fist"</span>, <span style="color: #006699;">"fist"</span> },
&nbsp;{&nbsp;S_SG,&nbsp;1400,&nbsp;10,&nbsp;0,&nbsp;0,&nbsp;20,&nbsp;1024,&nbsp;<span style="color: #006699;">"shotgun"</span>, <span style="color: #006699;">"shotg"</span> }, <span style="color: #7E7E7E;">// *SGRAYS</span>
&nbsp;{&nbsp;S_CG,&nbsp;100,&nbsp;30,&nbsp;0,&nbsp;0,&nbsp;7,&nbsp;1024,&nbsp;<span style="color: #006699;">"chaingun"</span>, <span style="color: #006699;">"chaing"</span>},
&nbsp;{&nbsp;S_RLFIRE,&nbsp;800,&nbsp;120,&nbsp;80,&nbsp;0,&nbsp;10,&nbsp;1024,&nbsp;<span style="color: #006699;">"rocketlauncher"</span>, <span style="color: #006699;">"rocket"</span>},
&nbsp;{&nbsp;S_RIFLE,&nbsp;1500,&nbsp;100,&nbsp;0,&nbsp;0,&nbsp;30,&nbsp;2048,&nbsp;<span style="color: #006699;">"rifle"</span>, <span style="color: #006699;">"rifle"</span> },
&nbsp;{&nbsp;S_FLAUNCH,&nbsp;500,&nbsp;75,&nbsp;80,&nbsp;0,&nbsp;10,&nbsp;1024,&nbsp;<span style="color: #006699;">"grenadelauncher"</span>, <span style="color: #006699;">"gl"</span> },
&nbsp;{&nbsp;S_PISTOL,&nbsp;500,&nbsp;25,&nbsp;0,&nbsp;0,&nbsp;7,&nbsp;1024,&nbsp;<span style="color: #006699;">"pistol"</span>, <span style="color: #006699;">"pistol"</span> },
&nbsp;{&nbsp;S_FLAUNCH,&nbsp;200,&nbsp;20,&nbsp;50,&nbsp;PART_FIREBALL1,&nbsp;1,&nbsp;1024,&nbsp;<span style="color: #006699;">"fireball"</span>, NULL },
&nbsp;{&nbsp;S_ICEBALL,&nbsp;200,&nbsp;40,&nbsp;30,&nbsp;PART_FIREBALL2,&nbsp;1,&nbsp;1024,&nbsp;<span style="color: #006699;">"iceball"</span>, NULL },
&nbsp;{&nbsp;S_SLIMEBALL,&nbsp;200,&nbsp;30,&nbsp;160,&nbsp;PART_FIREBALL3,&nbsp;1,&nbsp;1024,&nbsp;<span style="color: #006699;">"slimeball"</span>, NULL },
&nbsp;{&nbsp;S_PIGR1,&nbsp;250,&nbsp;50,&nbsp;0,&nbsp;0,&nbsp;1,&nbsp;12,&nbsp;<span style="color: #006699;">"bite"</span>, NULL },
&nbsp;{&nbsp;-1,&nbsp;0,&nbsp;120,&nbsp;0,&nbsp;0,&nbsp;0,&nbsp;0,&nbsp;<span style="color: #006699;">"barrel"</span>, NULL }
};
</pre>
<p></code></p>
<p>Pola, które będą nas interesowały, to:</p>
<table border="1" cellspacing="0" cellpadding="5">
<tr>
<td>Numer kolejny pola</td>
<td>Nazwa</td>
<td>Opis</td>
</tr>
<tr>
<td>2</td>
<td>attackdelay</td>
<td>Zwłoka potrzebna na przeładowanie broni. Szczególnie uciążliwa dla rifle.</td>
</tr>
<tr>
<td>6</td>
<td>kickamount</td>
<td>Siła odrzutu po wykonaniu strzału. 0 – brak odrzutu, 1024 – zaczynamy latać po każdym strzale <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </td>
</tr>
<tr>
<td>4</td>
<td>projspeed</td>
<td>Szybkość „projekcji”, czyli czas potrzebny na przebycie drogi przez pocisk&#8230; Przydatne przy graniu z wyrzutnią rakiet, wówczas pocisk nie leci w powietrzu, zanim trafi w cel. 0 – trafia od razu, 1024 – wlecze się okrutnie</td>
</tr>
</table>
<p>Polecam poeksperymentować z tymi parametrami i ustawić je pod siebie tak, aby grało się nam komfortowo, dla przykładu poniżej moja własna structurka.</p>
<p><code>
<pre>
<span style="color: #CC6600;">static</span> const struct guninfo { <span style="color: #CC6600;">short</span> sound, attackdelay, damage, projspeed, part,
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kickamount,&nbsp;range;&nbsp;const&nbsp;<span style="color: #CC6600;">char</span> *name, *file;
			&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;guns[NUMGUNS]&nbsp;=
{
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_PUNCH1,&nbsp;&nbsp;&nbsp;&nbsp;250,&nbsp;&nbsp;50,&nbsp;0,&nbsp;&nbsp;&nbsp;0,&nbsp;0,&nbsp;&nbsp;&nbsp;4,&nbsp;&nbsp;<span style="color: #006699;">"fist"</span>,            <span style="color: #006699;">"fist"</span>  },
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_SG,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1400,&nbsp;&nbsp;10,&nbsp;0,&nbsp;&nbsp;&nbsp;0,&nbsp;0,&nbsp;1024,&nbsp;<span style="color: #006699;">"shotgun"</span>,         <span style="color: #006699;">"shotg"</span> },  <span style="color: #7E7E7E;">// *SGRAYS</span>
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_CG,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;100,&nbsp;&nbsp;30,&nbsp;0,&nbsp;&nbsp;&nbsp;0,&nbsp;0,&nbsp;1024,&nbsp;&nbsp;<span style="color: #006699;">"chaingun"</span>,        <span style="color: #006699;">"chaing"</span>},
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_RLFIRE,&nbsp;&nbsp;&nbsp;&nbsp;800,&nbsp;0,&nbsp;0,&nbsp;&nbsp;0,&nbsp;0,&nbsp;1024,&nbsp;<span style="color: #006699;">"rocketlauncher"</span>,  <span style="color: #006699;">"rocket"</span>},
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_RIFLE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;200,&nbsp;100,&nbsp;0,&nbsp;&nbsp;&nbsp;0,&nbsp;0,&nbsp;2048,&nbsp;<span style="color: #006699;">"rifle"</span>,           <span style="color: #006699;">"rifle"</span> },
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_FLAUNCH,&nbsp;&nbsp;&nbsp;500,&nbsp;&nbsp;75,&nbsp;80,&nbsp;&nbsp;0,&nbsp;0,&nbsp;1024,&nbsp;<span style="color: #006699;">"grenadelauncher"</span>, <span style="color: #006699;">"gl"</span> },
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_PISTOL,&nbsp;&nbsp;&nbsp;&nbsp;500,&nbsp;&nbsp;25,&nbsp;0,&nbsp;&nbsp;&nbsp;0,&nbsp;&nbsp;0,&nbsp;1024,&nbsp;<span style="color: #006699;">"pistol"</span>,          <span style="color: #006699;">"pistol"</span> },
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_FLAUNCH,&nbsp;&nbsp;&nbsp;200,&nbsp;&nbsp;20,&nbsp;50,&nbsp;&nbsp;PART_FIREBALL1,&nbsp;&nbsp;0,&nbsp;1024,&nbsp;<span style="color: #006699;">"fireball"</span>,  NULL },
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_ICEBALL,&nbsp;&nbsp;&nbsp;200,&nbsp;&nbsp;40,&nbsp;30,&nbsp;&nbsp;PART_FIREBALL2,&nbsp;&nbsp;0,&nbsp;1024,&nbsp;<span style="color: #006699;">"iceball"</span>,   NULL },
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_SLIMEBALL,&nbsp;200,&nbsp;&nbsp;30,&nbsp;160,&nbsp;PART_FIREBALL3,&nbsp;&nbsp;0,&nbsp;1024,&nbsp;<span style="color: #006699;">"slimeball"</span>, NULL },
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;S_PIGR1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;250,&nbsp;&nbsp;50,&nbsp;0,&nbsp;&nbsp;&nbsp;0,&nbsp;&nbsp;0,&nbsp;&nbsp;&nbsp;12,&nbsp;<span style="color: #006699;">"bite"</span>,            NULL },
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;-1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0,&nbsp;120,&nbsp;0,&nbsp;&nbsp;&nbsp;0,&nbsp;&nbsp;0,&nbsp;&nbsp;&nbsp;&nbsp;0,&nbsp;<span style="color: #006699;">"barrel"</span>,          NULL }
};
</pre>
<p></code></p>
<h2>Celność</h2>
<p>Oprócz powyżej opisanych własności broni możemy jeszcze poprawić celność shotguna. W tym celu należy zmodyfikować plik <em>src/fpsgame/weapon.cpp</em> około linii 130 wygląda on tak:</p>
<p><code>
<pre>
<span style="color: #CC6600;">void</span> offsetray(const vec &amp;from, const vec &amp;to, <span style="color: #CC6600;">int</span> spread, <span style="color: #CC6600;">float</span> range, vec &amp;dest)
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">float</span> f = to.dist(from)*spread/1000;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">for</span>(;;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;RNDD&nbsp;rnd(101)-50
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vec&nbsp;v(RNDD,&nbsp;RNDD,&nbsp;RNDD);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">if</span>(v.magnitude()&gt;50) <span style="color: #CC6600;">continue</span>;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.mul(f);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.z&nbsp;/=&nbsp;2;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dest&nbsp;=&nbsp;to;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dest.add(v);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vec&nbsp;dir&nbsp;=&nbsp;dest;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir.sub(from);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir.normalize();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raycubepos(from,&nbsp;dir,&nbsp;dest,&nbsp;range,&nbsp;RAY_CLIPMAT|RAY_ALPHAPOLY);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #CC6600;">return</span>;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;}
</pre>
<p></code></p>
<p>Zmieniamy linijkę</p>
<p><code>#define RNDD rnd(101)-50 </code></p>
<p>na</p>
<p><code>#define RNDD rnd(2)-1</code></p>
<p>Co minimalizuje rozrzut shotguna i daje mu celność rifle&#8217;a. </p>
<p>Po tych modyfikacjach możemy cieszyć się na nowo grą, którą sobie sami skompilujemy. Kompilacja jest banalnie prosta i polega na wydaniu jednego polecenia make, piszemy po prostu make i to wszystko. Jedyne, o czym należy pamiętać, to zależności, których wymaga sauerbraten do kompilacji i są to wersje developerskie następujących pakietów:</p>
<ul>
<li>OpenGL</li>
<li>SDL</li>
<li>SDL_mixer</li>
<li>SDL_image </li>
<li>zlib</li>
</ul>
<p>W razie problemów dokładniejszy opis kompilacji znajduje się w pliku src/readme_source.txt</p>
<h2>Inne możliwości modyfikacji ?</h2>
<p>Bardzo często spotykaną u graczy modyfikacją jest manipulacja w pliku <em>client.cpp</em>, polegająca na tym, że klient wysyła do serwera strukturę, w której znajdują się koordynaty, w których się aktualnie znajduje, tyle tylko, że te koordynaty nie są prawdziwe. Efekt jest taki, że wszyscy gracze widzą Cię w innym miejscu, niż naprawdę się znajdujesz. Nie przedstawiłem jednak w tym wpisie dokładnie, jak to zrobić, ponieważ moim zdaniem modyfikacja ta odbiera przyjemność z gry zarówno nam, jak i innym współgraczom. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2011/11/06/modyfikacja-cheat-w-grze-sauerbraten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Atmega8A-PU, MAX232, DS18B20 w promocji u Leniwca! ;-)</title>
		<link>http://www.leniwiec.org/2011/07/27/atmega8a-pu-max232-ds18b20-w-promocji-u-leniwca-najtaniej-w-sieci/</link>
		<comments>http://www.leniwiec.org/2011/07/27/atmega8a-pu-max232-ds18b20-w-promocji-u-leniwca-najtaniej-w-sieci/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 19:21:53 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Elektronika]]></category>
		<category><![CDATA[atmega]]></category>
		<category><![CDATA[atmega8]]></category>
		<category><![CDATA[atmega8a-pu]]></category>
		<category><![CDATA[avr]]></category>
		<category><![CDATA[czujnik temperatury]]></category>
		<category><![CDATA[DS18B20]]></category>
		<category><![CDATA[konwerter rs232]]></category>
		<category><![CDATA[max232]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=210</guid>
		<description><![CDATA[Dzisiaj będzie troszkę komercyjnie, otóż Leniwiec pucuje swoje magazyny i ma co nieco Wam do sprzedania. I tak więc po różnych projektach i produkcjach małoseryjnych pozostało około 100 sztuk Atmega8A-PU, 100 sztuk czujników temperatury DS18B20 oraz 100 sztuk konwerterów MAX232. Sprzedam w całości lub w kawałkach, na każdy element paragon lub faktura VAT, jak kto chce. Poniżej lista z cenami. W razie pytań lub wątpliwości nie bójcie się kontaktować ze mną.

<a href="http://www.leniwiec.org/wp-content/uploads/2011/07/atmega8_max232_ds18b20.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2011/07/atmega8_max232_ds18b20-300x225.jpg" alt="ATMega8A-PU, DS18B20, MAX232" title="ATMega8A-PU, DS18B20, MAX232" width="300" height="225" class="size-medium wp-image-211 aligncenter" /></a>]]></description>
			<content:encoded><![CDATA[<p><b>Dzisiaj będzie troszkę komercyjnie, otóż Leniwiec pucuje swoje magazyny i ma co nieco Wam do sprzedania. I tak więc po różnych projektach i produkcjach małoseryjnych pozostało około 100 sztuk Atmega8A-PU, 100 sztuk czujników temperatury DS18B20 oraz 100 sztuk konwerterów MAX232. Sprzedam w całości lub w kawałkach, na każdy element paragon lub faktura VAT, jak kto chce. Poniżej lista z cenami. W razie pytań lub wątpliwości nie bójcie się kontaktować ze mną.</b></p>
<div id="attachment_211" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.leniwiec.org/wp-content/uploads/2011/07/atmega8_max232_ds18b20.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2011/07/atmega8_max232_ds18b20-300x225.jpg" alt="ATMega8A-PU, DS18B20, MAX232" title="ATMega8A-PU, DS18B20, MAX232" width="300" height="225" class="size-medium wp-image-211" /></a><p class="wp-caption-text">Części na sprzedaż - real foto</p></div>
<ul>
<li>Atmega8A-PU &#8211; 7,50 zł (brutto)</li>
<li>DS18B20 &#8211; 3,50 zł (brutto)</li>
<li>MAX232 &#8211; 2,00 zł (brutto)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2011/07/27/atmega8a-pu-max232-ds18b20-w-promocji-u-leniwca-najtaniej-w-sieci/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Huawei e173 + BlueConnect + UBUNTU w 5 minut</title>
		<link>http://www.leniwiec.org/2011/07/17/huawei-e173-blueconnect-ubuntu-w-5-minut/</link>
		<comments>http://www.leniwiec.org/2011/07/17/huawei-e173-blueconnect-ubuntu-w-5-minut/#comments</comments>
		<pubDate>Sun, 17 Jul 2011 21:34:27 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Ogólne]]></category>
		<category><![CDATA[blueconnect]]></category>
		<category><![CDATA[era internet]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[huawei e173]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=199</guid>
		<description><![CDATA[Ostatnio w moim życiu zaistniała potrzeba zaopatrzenia się w internet mobilny, a jako że zdobyłem z odzysku BlueConnecta z modemem Huawei E173, postanowiłem podzielić się z wami moimi spostrzeżeniami na temat instalacji tego cuda w ubuntu (lub jakimkolwiek innym linuxie).]]></description>
			<content:encoded><![CDATA[<p><b>Ostatnio w moim życiu zaistniała potrzeba zaopatrzenia się w internet mobilny, a jako że zdobyłem z odzysku BlueConnecta z modemem Huawei E173, postanowiłem podzielić się z wami moimi spostrzeżeniami na temat instalacji tego cuda w ubuntu (lub jakimkolwiek innym linuxie).</b></p>
<p>Po przerobieniu niemalże wszystkich dostępnych w sieci „instrukcji”, oczywiście żadna z nich nie doprowadziła do sukcesu. <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  Znalazłem&#8230; sterowniki dla linuxa dla tego modelu, wydane przez firmę Movistar (hiszpański telecom), które działają w sposób automagiczny&#8230;<br />
Jedyne co jest potrzebne, aby uruchomić ten modem, to paczka zip, która jest dostępna na dole artykułu. <br />
Po jej ściągnięciu i rozpakowaniu, należy nadać znajdującemu się w nim plikowi `install` prawa do wykonywania, można to zrobić z konsoli (chmod +x install) lub z poziomu managera okien, we właściwościach pliku. Po tym wystarczy go uruchomić.<br />
Automatycznie skompiluje się i zainstaluje sterownik dla jądra oraz program Movistar.<br />
Po tej operacji dobrze jest zrestartować komputer. Następnie, gdy włożymy modem w gniazdo USB, automatycznie zostanie uruchomiony program Movistar, który wygląda jak poniżej.</p>
<div id="attachment_200" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.leniwiec.org/wp-content/uploads/2011/07/zrzut_ekranu.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/07/zrzut_ekranu-300x220.png" alt="Movistar Main screen" title="Movistar Main screen" width="300" height="220" class="size-medium wp-image-200" /></a><p class="wp-caption-text">Movistar Main screen</p></div>
<p>Domyślnie interfejs jest po hiszpańsku, można go zmienić na angielski, wybierając z menu kolejno <i>„Herramientas -> Idioma -> English”</i>. Później już wystarczy tylko dodać nowy profil w <i>Tools->options->Profile Management</i>, dla sieci Era (blueconnect), będzie to wyglądać jak poniżej.</p>
<div id="attachment_201" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.leniwiec.org/wp-content/uploads/2011/07/zrzut_ekranu-1.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/07/zrzut_ekranu-1-300x220.png" alt="Profile Management" title="Profile Management" width="300" height="220" class="size-medium wp-image-201" /></a><p class="wp-caption-text">Profile Management</p></div>
<p>Po czym zatwierdzamy wszystko przyciskiem OK i wybieramy na głównym ekranie &#8216;Connect&#8217;. To wszystko! 5 min i mamy działającego blue connecta w linuxie <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<ul>
<li><a href="http://frontlinesms.ning.com/forum/attachment/download?id=2052630%3AUploadedFile%3A51370" target="_blank">Sterowniki &#8211; Linux.zip</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2011/07/17/huawei-e173-blueconnect-ubuntu-w-5-minut/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

