<?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>Thu, 09 Feb 2012 20:07:29 +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>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>6</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>9</slash:comments>
		</item>
		<item>
		<title>Dodatkowe wejścia audio w zestawie 2.1 Creative Inspire T3000</title>
		<link>http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/</link>
		<comments>http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/#comments</comments>
		<pubDate>Thu, 14 Jul 2011 11:56:11 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Elektronika]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[creative]]></category>
		<category><![CDATA[electronic]]></category>
		<category><![CDATA[elektronika]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[mod]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=175</guid>
		<description><![CDATA[Tym razem chciałbym wam przedstawić prostą modyfikację, której dokonałem na swoim wysłużonym zestawie 2.1 Creativa. Problem, przed którym stanąłem, to podłączenie więcej niż jednego źródła sygnału (w moim przypadku laptop+domowy serwerek+blaszak) do moich głośniczków komputerowych. ]]></description>
			<content:encoded><![CDATA[<p><b>Tym razem chciałbym wam przedstawić prostą modyfikację, której dokonałem na swoim wysłużonym zestawie 2.1 Creativa. Problem, przed którym stanąłem, to podłączenie więcej niż jednego źródła sygnału (w moim przypadku laptop+domowy serwerek+blaszak) do moich głośniczków komputerowych.</b></p>
<p>Na samym początku myślałem o zrobieniu miksera i wbudowaniu go w obudowę zestawu, pomysł ten jednak upadł z dwóch powodów&#8230; Po pierwsze nie chciało mi się <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  A po drugie o 2 w nocy ciężko znaleźć otwarty sklep z elektroniką. Zatem stanęło na rozwiązaniu bazującym na tym, co miałem pod ręką, a to, co wyszło, to mikser tyle, że zupełnie pasywny. Rozwiązanie to w moim konkretnym przypadku jest OK, ponieważ wyjścia kart dźwiękowych dają sygnał o amplitudzie około 1 volta, natomiast sygnał potrzebny do wysterowania wzmacniacza wbudowanego w ten zestaw to ok. 0,775 volta. Tak, że mogłem sobie pozwolić na drobne straty w układzie.</p>
<h2>Overview</h2>
<p>A tak oto wyglądał mój pacjent przed całą operacją:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4119.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4119-224x300.jpg" alt="Creative Inspire T3000" title="Creative Inspire T3000" width="224" height="300" class="aligncenter size-medium wp-image-176" /></a></p>
<p>Z tyłu widać panel, który jest przykręcony sześcioma wkrętami, po ich odkręceniu&#8230; spodziewałem się, że elegancko zdemontuję go wraz z przyczepioną do niego elektroniką. Tak jednak się nie stało za sprawą jakiejś paskudnej pianki udającej klej, którą firma creative szczodrze obdarzyła cały ten układ gwarantując mu ochronę przed wibracjami (większości kobiet pewnie by się to nie spodobało). </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4129.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4129-300x225.jpg" alt="Glut na płytce" title="Glut na płytce" width="300" height="225" class="aligncenter size-medium wp-image-177" /></a></p>
<p>Myślę, że kwestię wibracji można było rozwiązać bardziej elegancko, nawet w produkcie takim jak ten – z dolnej półki. Tak, że minus dla creativa za tego gluta! Po nieudanej próbie dostania się od strony głośniczka do wnętrza i zbadania tej sprawy nie pozostało mi nic innego jak tylko wyszarpać przylepione, a właściwie obglucone pcb. </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4131.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4131-300x225.jpg" alt="" title="PCB" width="300" height="225" class="aligncenter size-medium wp-image-178" /></a></p>
<p>Na płytce znalazła się typowa aplikacja układu TDA7378. Jedna rzecz, która wydaje mi się dość dziwna, to sposób zasilania całego układu. Otóż spodziewałem się, że po wyłączeniu całego układu za pomocą kółeczka w tym dziwnym „pilocie” na kablu, zostaje odcięte główne zasilanie w jakiś sposób. Tymczasem, układ jest tak zaprojektowany, że cały czas zasilanie jest podłączone, a przy wyłączeniu go, końcówka mocy ustawiana jest w trybie standby&#8230;</p>
<h2>Układy wejściowe</h2>
<p>Układ wejściowy creativa wygląda jak na schemacie poniżej:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/07/przed.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/07/przed.png" alt="" title="przed" width="419" height="325" class="aligncenter size-full wp-image-179" /></a></p>
<p>Dla mniej wtajemniczonych pozwolę sobie wyjaśnić, co do czego i po co. JP435 i JP436 to zworki, które będą przez nas wykorzystane później. C59 i C60 to kondensatory „separujące”, które zapobiegają pojawieniu się składowej stałej na wejściu układu. Mówiąc inaczej, przewodzą tylko sygnały zmienne, a ewentualnie pojawiający się prąd stały jest „ignorowany”. Rezystory R59 i R60 służą do rozładowania kondensatorów separujących, gdy nie jest podawany żaden sygnał na wejście. Ma to na celu zapobieganie pojawiania się szpilek i innych śmieci, podczas włączania, wyłączania itp. Rezystory oznaczone Rs na schemacie należą już do dalszej części układu, które już mnie nie interesują z punktu widzenia tej modyfikacji. Zaznaczyłem je jednak na schemacie, ponieważ zostaną one wykorzystane jako rezystory „sumacyjne”, na których będą się „łączyć” sygnały z dwóch wejść – oryginalnego i nowo dodanego. </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4139.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4139-224x300.jpg" alt="" title="100_4139" width="224" height="300" class="aligncenter size-medium wp-image-180" /></a></p>
<h2>Modyfikacja</h2>
<p>Schemat układów wejściowych po mojej modyfikacji można zobaczyć poniżej:</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/07/po.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/07/po-300x232.png" alt="" title="po" width="300" height="232" class="aligncenter size-medium wp-image-181" /></a></p>
<p>Jak widać na schemacie, jedyna modyfikacja w oryginalnej płytce polegała na zastąpieniu zworek JP435 i JP346 rezystorami 10k. A następnie dolutowaniu kolejnego identycznego układu wejściowego w pająku i spięcie ich wyjść na rezystorach Rs. </p>
<p>Poniżej kilka fotek całości. </p>

<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/100_4119/' title='Creative Inspire T3000'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4119-150x150.jpg" class="attachment-thumbnail" alt="Creative Inspire T3000" title="Creative Inspire T3000" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/100_4129/' title='Glut na płytce'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4129-150x150.jpg" class="attachment-thumbnail" alt="Glut na płytce" title="Glut na płytce" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/100_4131/' title='PCB'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4131-150x150.jpg" class="attachment-thumbnail" alt="PCB" title="PCB" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/przed/' title='przed'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/przed-150x150.png" class="attachment-thumbnail" alt="przed" title="przed" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/100_4139/' title='100_4139'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4139-150x150.jpg" class="attachment-thumbnail" alt="100_4139" title="100_4139" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/po/' title='po'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/po-150x150.png" class="attachment-thumbnail" alt="po" title="po" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/100_4122/' title='100_4122'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4122-150x150.jpg" class="attachment-thumbnail" alt="100_4122" title="100_4122" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/100_4125/' title='100_4125'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4125-150x150.jpg" class="attachment-thumbnail" alt="100_4125" title="100_4125" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/100_4128/' title='100_4128'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4128-150x150.jpg" class="attachment-thumbnail" alt="100_4128" title="100_4128" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/100_4130/' title='100_4130'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4130-150x150.jpg" class="attachment-thumbnail" alt="100_4130" title="100_4130" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/100_4139-2/' title='100_4139'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_41391-150x150.jpg" class="attachment-thumbnail" alt="100_4139" title="100_4139" /></a>
<a href='http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/100_4146/' title='100_4146'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/07/100_4146-150x150.jpg" class="attachment-thumbnail" alt="100_4146" title="100_4146" /></a>

<h2>Lista materiałów:</h2>
<ul>
<li>Rezystory: 4 x 10k, 2x100k</li>
<li>Kondensatory: 2x 1uF@50v</li>
<li>Gniazdo jack 3.5mm stereo</li>
<li>Narzędzia: lutownica, wiertarka, cążki</li>
<li>Materiały: cyna, kawałek przewodu w izolacji, klej typu SuperGlue</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2011/07/14/dodatkowe-wejscia-audio-w-zestawie-2-1-creative-inspire-t3000/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>8-kanałowa karta przekaźników na RS232</title>
		<link>http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/</link>
		<comments>http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 17:16:07 +0000</pubDate>
		<dc:creator>leniwiec</dc:creator>
				<category><![CDATA[Elektronika]]></category>
		<category><![CDATA[AT90S2313]]></category>
		<category><![CDATA[automatyka]]></category>
		<category><![CDATA[elektronika]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[rs232]]></category>
		<category><![CDATA[serial]]></category>
		<category><![CDATA[sterowanie]]></category>

		<guid isPermaLink="false">http://www.leniwiec.org/?p=123</guid>
		<description><![CDATA[Poniższy projekt powstał jako część domowej automatyki. Jest to karta przekaźników sterowana poprzez port RS232 komputera która może zostać dodatkowo rozbudowana o 5 wejść. Opisywany projekt to kompletne rozwiązanie zawierające część sprzętową wraz z firmwarem jak i część programową (PC) na która składa się konsolowy program (linux) do sterowania, biblioteka dla języka php oraz okienkowa aplikacja napisana w javie/swing.

<a href=http://www.leniwiec.org/wp-content/uploads/2011/04/100_3932.jpg><img src=http://www.leniwiec.org/wp-content/uploads/2011/04/100_3932-300x225.jpg alt=\ title=Gotowy układ width=300 height=225 class=aligncenter size-medium wp-image-126 /></a>]]></description>
			<content:encoded><![CDATA[<p>Poniższy projekt powstał jako część domowej automatyki. Jest to karta przekaźników sterowana poprzez port RS232 komputera która może zostać dodatkowo rozbudowana o 5 wejść. Opisywany projekt to kompletne rozwiązanie zawierające część sprzętową wraz z firmwarem jak i część programową (PC) na która składa się konsolowy program (linux) do sterowania, biblioteka dla języka php oraz okienkowa aplikacja napisana w javie/swing.</p>
<h2>Hardware</h2>
<p>Można by powiedzieć że jest on typowy – mikrokontroler, driver max232, karta przekaźników. Mimo wszystko postaram się pokrótce opisać zasadę działania sterownika i części wykonawczej.<br />
Na rysunku poniżej widać schemat części sterownika karty.</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/04/schema.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/04/schema-300x194.png" alt="" title="Schemat sterownika" width="300" height="194" class="aligncenter size-medium wp-image-124" /></a></p>
<p>Głównym jego elementem jest mikrokontroler AT90S2313 (U1) taktowany kwarcem 10,7 Mhz (Q1, C1, C2). Następnie mamy driver rs232 typu MAX232 wraz z elementami towarzyszącymi C3,C4,C5,C6 którego wyjście jest wyprowadzone na gniazdo DB9 typu męskiego (aby połączyć układ z komputerem należy korzystać z kabla z przeplotem, tzw. Null-modem). Dalej reset mikrokontrolera podciągnięty do plusa zasilania, a port B (piny PB) poprzez rezystory ograniczające prąd (R2-R9) podane na tranzystory sterujące przekaźnikami i diodami LED – T1..T8. Tranzystory te pracują w układzie wspólnego emitera (wzmocnienie prądowe jest większe od jedności). Z kolektorów tych tanzystorów sygnał jest podawany na 8 identycznych bloków przekaźników które wyglądają jak na rysunku poniżej.</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/04/relay.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/04/relay.png" alt="" title="Schamat części wykonawczej" width="266" height="398" class="aligncenter size-full wp-image-125" /></a></p>
<p>Każdy blok składa się z przekaźnika wraz z diodą prostowniczą (na rysunku powyżej D9). Dioda ta służy do wytracenia energii impulsu wyindukowanego w cewce przekaźnika, wytworzonego podczas nagłego przerwania jej zasilania. Oprócz tego, w każdym bloku znajduje się dioda LED (D1) wraz z rezystorem ograniczającym prąd (R10). Styki samego przekaźnika zostały połączone równolegle tak aby zwiększyć dopuszczalny prąd przez nie płynący. </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3932.jpg"><img src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3932-300x225.jpg" alt="" title="Gotowy układ" width="300" height="225" class="aligncenter size-medium wp-image-126" /></a></p>
<h2>Firmware</h2>
<p>Program dla mikrokontrolera został napisany w języku C a skompilowany przy pomocy avr-gcc a następnie wgrany do pamięci układu przy pomocy programatora USBasp. <br />Procedury odpowiedzialne za komunikację, podobnie jak część sprzętowa, są typowe, można by powiedzieć że książkowe i wyglądają jak poniżej.</p>
<p><code>#define UART_BAUD 9600				/* serial transmission speed */</p>
<p>void UART_putchar(char c)<br />
{<br />
	UDR = c;<br />
	loop_until_bit_is_set(USR, TXC);<br />
	sbi(USR, TXC);<br />
} // end of UART_putchar()</p>
<p>char UART_getchar(void)<br />
{<br />
	loop_until_bit_is_set(USR,RXC);<br />
	cbi(USR,RXC);<br />
	return UDR;<br />
} // end of UART_getchar()</p>
<p>void UART_init()<br />
{<br />
	UBRR = (unsigned char)UART_CONST;		//spped<br />
	UCR = _BV(RXEN)|_BV(TXEN);	//RXEN - permit recive, TXEN - permit send, RXCIE - interrupt on recive<br />
} // end of UART_init()<br />
</code></p>
<p>Jak widać w fragmencie powyższego kodu, mamy 3 procedurki: UART_init(), UART_putchar() oraz UART_getchar(), które służą kolejno do skonfigurowania, wysłania znaku oraz odebrania znaku. Oprócz tego jest jeszcze jedna ważna stała UART_BAUD która określa prądkość komunikacji i jest ustawiona na 9600. <br/><br />
Procedura UART_init() składa się jedynie z dwóch linijek, w pierwszej przypisywana jest do rejestru UBRR żądana prędkość transmisji, natomiast w drugiej ustawiamy bity RXEN i TXEN rejestru UCR, które odpowiednio uaktywniają nadawanie i odbieranie (jak można wywnioskować z ich nazw RX/TX recive/transmit, EN – enable).<br />
Procedura UART_putchar() przyjmuje jeden parametr, którym jest znak który ma zostać wysłany. Znak ten jest przypisywany do rejestru UDR a następnie wykonywana jest pętla tak długo aż zostanie ustawiony bit TXC w rejestrze USR co oznacza wysłanie znaku. <br />
Procedura UART_getchar() działa podobnie, z tym że tutaj najpierw wykonywana jest pętla tak długo aż zostanie ustawiony bit RXC w rejestrze USR co oznacza nadejście znaku, a następnie ten znak zostaje zwrócony. <br />
Oprócz samej komunikacji został jeszcze w mikrokontrolerze zaprogramowany prosty protokuł, który składa się z dwóch komend. Pierwsza z nich służy do ustawiania stanów na porcie PB (włączania i wyłączania przekaźników) druga do odczytu aktualnego stanu urządzenia. <br />
Poniżej fragment przykładowej sessji w której zostają włączone przekaźniki PK1 oraz PK6, a następnie urządzenie zostaje poproszone o zwrócenie aktualnego stanu.</p>
<p><code><br />
s10000100sOK<br />
g10000100<br />
</code></p>
<p>Jak widać powyżej, wysyłamy do urządzenia ciąg znaków 0 i 1 (są to znaki nie liczby!) reprezentujące kolejne wyjścia urządzenia i tak kolejno 0 oznacza przekaźnik wyłączony natomiast 1 oznacza przekaźnik włączony. Ponadto ciąg zer i jedynek jest rozpoczęty i zakończony znakiem &#8216;s&#8217;. W odpowiedzi odtrzymujemy 4 znaki kolejno: &#8216;OK\n\r&#8217; jeśli operacja została wykonana poprawnie, natomiast jeśli coś poszło by nie tak w samym urządzeniu, zwróciło by ono ciąg znaków: &#8216;Error 2\n\r&#8217; lub &#8216;Error 3\n\r&#8217;. <br />
W następnej linijce powyższego przykładu mamy odczyt aktualnego stanu urządzenia. Wysyłany jest znak &#8216;g&#8217; natomiast w odpowiedzi otrzymujemy 8 znaków, zer i jedynek, które reprezentują stany kolejnych portów urządzenia.<br />
Reasumując można by powiedzieć że mamy dwie komendy &#8216;s&#8217; (set) oraz &#8216;g&#8217; (get). W przypadku gdy do układu zostanie wysłany jakiś inny – niezrozumiały, ciąg znaków zostanie zwrócony ciąg znaków: &#8216;Error 0\n\r&#8217;. Tak mniej więcej wygląda cały protokół komunikacyjny. </p>
<h2>Software</h2>
<p>Od strony komputer / serwera, zostały przygotowane 3 różne aplikacje, konsolowy program dla środowiska linux, aplikacja okienkowan napisana w Javie/Swing, oraz klasa w php umożliwiająca sterowanie za pośrednictwem interfejsu www – to rozwiązanie jednak wykorzystuje  oprogramowanie ser2net jako proxy.</p>
<h3>Aplikacja konsolowa dla linux-a</h3>
<p>Aplikacja ta umożliwia sterowanie urządzeniem oraz odczytywanie jego stanów z poziomu konsoli. Osobiście wykorzystuję tą aplikację w swoich skryptach cron&#8217;a – mam w ten sposób zorganizowany budzik – o odpowiedniej godzinie włącza się wzmacniacz podłączony do karty dźwiękowej domowego serwerka a następnie zostaje odtworzona playlista przy pomocy MPD.<br />
Opcje dostępne w tym programie wyglądają następująco:
</p>
<p><code><br />
$ ./io_card<br />
Usage: ./io_card -p port [-s (8bit data)] [-g] [-1..8 (on|off)]<br />
</code></p>
<p>
<pre>
-p 	ścieżka do portu np. /dev/ttyS0 lub /dev/ttyUSB0 itp.
-s	ustawienie wyjść, jako parametr podajemy odpowiedni ciąg 8 zer i jedynek
-g	pobiera aktualny stan urządzenia, w tym przypadku zwracany jest ciąg 8 zer i jedynek
-1..8	ustawienie lub skasowanie wyjścia od 1 do 8. Jako parametr możemy podać on lub off.
</pre>
</p>
<p>Przykładowo, aby załączyć przekaźniki  4 i 6 możemy wykonać takie polecenie:</p>
<p><code>$ ./io_card -p /dev/ttyUSB0 -s00010100<br />
OK</code></p>
<p>lub możemy to zrobić tak:</p>
<p><code><br />
$ ./io_card -p /dev/ttyUSB0 -4 on -6 on<br />
OK<br />
</code></p>
<p>teraz aby odczytać aktualny stan:</p>
<p><code><br />
$ ./io_card -p /dev/ttyUSB0 -g<br />
00010100<br />
</code></p>
<p>następnie aby wyłączyć przekaźnik numer 4 i włączyć przekaźniki 1 i 2 możemy wykonać polecenie:</p>
<p><code><br />
$ ./io_card -p /dev/ttyUSB0 -4 off -1 on -2 on<br />
OK<br />
</code></p>
<p>W załączniku na dole tego artykułu znajduje się spakowany plik zawierający między innymi tą aplikację wraz kodem źródłowym. </p>
<h3>ser2net i PHP</h3>
<p>Aby skorzystać z klasy napisanej w php należy najpierw zainstalować i skonfigurować program ser2net. Wybrałem taką właśnie metodą komunikacji ponieważ jest ona bardziej uniwersalny, odpowiednio konfigurując ser2net możemy wystawić urządzenie na jakimś adresie zewnętrznym i kontrolować je zdalnie przy pomocy innej aplikacji klienckiej. <br />
I tak, aby zainstalować w ubuntu w/w program, musimy wykonać polecenie:</p>
<p><code><br />
sudo apt-get install ser2net<br />
</code></p>
<p>Po wykonaniu tego polecenia zostaje ściągnięty a następnie zainstalowany pakiet ser2net, po czym możemy przystąpić do jego konfiguracji.<br />
W pliku /etc/ser2net.conf należy dodać linijkę jak poniżej:</p>
<p><code><br />
localhost,3000:telnet:600:/dev/ttyUSB0:9600 8DATABITS NONE 1STOPBIT<br />
</code></p>
<p>Możemy ją odczytać jako: wystaw port /dev/ttyUSB0 na porcie 3000 localhost`a, prądkość transmisji to 9600, 8 bitów danych, 1 bit stopu, brak sprzętowej kontroli. <br />
Zmieniając odpowiednio ścieżkę do porty, oraz host i port można dostosować działanie ser2net do własnych potrzeb.<br />
Po zapisaniu pliku musimy zrestartować deamon ser2net, możemy to zrobić przy pomocy poniższego polecenia:</p>
<p><code><br />
sudo /etc/init.d/ser2net restart<br />
</code></p>
<p>Po tym zabiegu mamy na localhost:3000 zmapowany port /dev/ttyUSB0, możemy zatem przejść do zabawy z php.<br />
W załącznikach na dole artykułu została dodana klasa php IoCart, która udostępnia następujący interfejs: </p>
<ul>
<li>IoCart::__construct($strHost, $strPort) – konstruktor, jako parametry podajemy host i port na jakim nasłuchuje ser2net</li>
<li>IoCart::close() &#8211; zamknięcie połączenia</li>
<li>IoCart::getStatus() &#8211; pobieranie aktualnego stanu urządzenia, wartość zwracana to string składający się z 8 znaków – zer i jedynek</li>
<li>IoCart::checkStatus($intPortNumber) – sprawdzanie aktualnego stanu jednego wybranego porty &#8211; $intPorNumber, wartość zwracana to odpowiednio boolowskie true lub false</li>
<li>IoCart::setPort($intPort, $bolState) – ustawienie jednego wybranego portu, $intPort &#8211; numer portu od 1 do 8, $bolState – wartość boolowska oznaczająca włączony lub wyłączony dany port</li>
<li>IoCart::set($strByte) – ustawienie wszystkich portów naraz, jako parametr przyjmuje odpowiedni ciąg zer i jedynek, reprezentujący zadane stany kolejnych przekaźników.</li>
</ul>
<p>Poniżej zrzut ekranu oraz kod przykładowego działającego skryptu (również dołączony do pczaki zip).</p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/04/www.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/04/www-300x168.png" alt="" title="Interfejs www" width="300" height="168" class="aligncenter size-medium wp-image-127" /></a></p>
<p>
<code><br />
<span style="color: #000000"><br />
<span style="color: #0000BB">&lt;?php&nbsp;<br />&nbsp;</span><span style="color: #007700">include&nbsp;</span><span style="color: #DD0000">"IoCart.php"</span><span style="color: #007700">;<br />&nbsp;</span><span style="color: #0000BB">$objCard&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">IoCart</span><span style="color: #007700">(</span><span style="color: #DD0000">'localhost'</span><span style="color: #007700">,</span><span style="color: #0000BB">3000</span><span style="color: #007700">);</p>
<p>&nbsp;if(isset(</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'change'</span><span style="color: #007700">])&nbsp;&amp;&amp;&nbsp;</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'change'</span><span style="color: #007700">]==</span><span style="color: #DD0000">'1'&nbsp;</span><span style="color: #007700">&amp;&amp;&nbsp;isset(</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'value'</span><span style="color: #007700">])&nbsp;&amp;&amp;&nbsp;isset(</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'port'</span><span style="color: #007700">]))<br />&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$objCard</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">setPort</span><span style="color: #007700">(</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'port'</span><span style="color: #007700">],&nbsp;</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'value'</span><span style="color: #007700">]==</span><span style="color: #DD0000">'1'&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">true&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">);<br />&nbsp;}</p>
<p></span><span style="color: #0000BB">?&gt;</span>&lt;!DOCTYPE&nbsp;html&nbsp;PUBLIC&nbsp;"-//W3C//DTD&nbsp;XHTML&nbsp;1.0&nbsp;Strict//EN"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;<br />&lt;html&nbsp;xmlns="http://www.w3.org/1999/xhtml"&nbsp;xml:lang="pl"&nbsp;lang="pl"&gt;<br />&nbsp;&lt;head&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;8&nbsp;bit&nbsp;IO&nbsp;Card&nbsp;Example&lt;/title&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;meta&nbsp;http-equiv="Content-Type"&nbsp;content="text/html;&nbsp;charset=utf-8"/&gt;<br />&nbsp;&lt;/head&gt;<br />&lt;body&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;table&nbsp;border="1"&nbsp;align="center"&nbsp;cellpadding="15"&gt;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt;<br /><span style="color: #0000BB">&lt;?php&nbsp;<br />&nbsp;$strStatus&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$objCard</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getStatus</span><span style="color: #007700">();&nbsp;<br />&nbsp;for(</span><span style="color: #0000BB">$intI</span><span style="color: #007700">=</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$intI&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">8</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$intI</span><span style="color: #007700">++):<br /></span><span style="color: #0000BB">?&gt;<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt;Port&nbsp;<span style="color: #0000BB">&lt;?=&nbsp;</span><span style="color: #007700">(</span><span style="color: #0000BB">$intI</span><span style="color: #007700">+</span><span style="color: #0000BB">1</span><span style="color: #007700">).</span><span style="color: #DD0000">':&nbsp;'</span><span style="color: #007700">.(</span><span style="color: #0000BB">$strStatus</span><span style="color: #007700">[</span><span style="color: #0000BB">$intI</span><span style="color: #007700">]==</span><span style="color: #DD0000">'1'&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">'On'&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #DD0000">'Off'</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">?&gt;</span>&lt;/td&gt;<br /><span style="color: #0000BB">&lt;?php&nbsp;</span><span style="color: #007700">endfor;&nbsp;</span><span style="color: #0000BB">?&gt;<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt;<br /><span style="color: #0000BB">&lt;?php&nbsp;<br />&nbsp;</span><span style="color: #007700">for(</span><span style="color: #0000BB">$intI</span><span style="color: #007700">=</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$intI&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">8</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$intI</span><span style="color: #007700">++):<br /></span><span style="color: #0000BB">?&gt;<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;align="center"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;form&nbsp;action=""&nbsp;method="post"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type="hidden"&nbsp;name="port"&nbsp;value="<span style="color: #0000BB">&lt;?=&nbsp;$intI</span><span style="color: #007700">+</span><span style="color: #0000BB">1?&gt;</span>"&nbsp;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type="hidden"&nbsp;name="value"&nbsp;value="<span style="color: #0000BB">&lt;?=&nbsp;</span><span style="color: #007700">(</span><span style="color: #0000BB">$strStatus</span><span style="color: #007700">[</span><span style="color: #0000BB">$intI</span><span style="color: #007700">]==</span><span style="color: #DD0000">'1'&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">'0'&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #DD0000">'1'</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">?&gt;</span>"&nbsp;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type="hidden"&nbsp;name="change"&nbsp;value="1"&nbsp;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type="submit"&nbsp;value="<span style="color: #0000BB">&lt;?=&nbsp;</span><span style="color: #007700">(</span><span style="color: #0000BB">$strStatus</span><span style="color: #007700">[</span><span style="color: #0000BB">$intI</span><span style="color: #007700">]==</span><span style="color: #DD0000">'1'&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">'Off'&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #DD0000">'On'</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">?&gt;</span>"&nbsp;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/form&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;<br /><span style="color: #0000BB">&lt;?php&nbsp;</span><span style="color: #007700">endfor;&nbsp;</span><span style="color: #0000BB">?&gt;<br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/table&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;<br /></span></p>
<p></code>
</p>
<h3>Aplikacja okienkowa</h3>
<p>No i na koniec mały smaczek, aplikacja okienkowa w javie. Skompilowana również dostępna w załączniku. </p>
<p><a href="http://www.leniwiec.org/wp-content/uploads/2011/04/java.png"><img src="http://www.leniwiec.org/wp-content/uploads/2011/04/java.png" alt="" title="Aplikacja okienkowa" width="276" height="261" class="aligncenter size-full wp-image-128" /></a></p>
<p>Jak już prędzej wspominałem jest ona oparta na javie/swingu, oraz wykorzystuje do komunikacji bibliotekę RXTXcomm. Biblioteka ta jest również dołączona w pliku zip w katalogu lib. Jest to wersja .so jak i dll, niestety nie testowałem działania tego programu pod windowsem, jednak powinien on działać poprawnie <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  </p>
<p>Nie dołączam pełnych źródeł tej aplikacji ponieważ oprócz klasy SerialHandler cała reszta to w zasadzie interfejs graficzny, który każdy kto zna choć trochę jave może sobie napisać (wyklikać) według własnego uznania i dostosowany do własnych potrzeb. </p>
<h2>Uwagi końcowe</h2>
<p>Oczywiście w tym całym mini-projekcie jest kilka mniejszych lub większych mankamentów lub wręcz błędów projektowych, których jestem świadomy (jak np. Nie najlepiej zaprojektowane pcb, brak kondensatorów filtrujących, brak układu resetu), samo oprogramowanie na PC również jest napisane na szybko i byle jak. Całość jednak działa i spełnia swoją rolę. </p>
<p>Jeśli ktoś był by zainteresowany zakupem całego układu w postaci kit`u (lub zmontowanego układu) lub chciał uzyskać dodatkowe informację lub pomoc podczas uruchomienia, zapraszam do kontaktu <img src='http://www.leniwiec.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h2>Załączniki</h2>
<ul>
<li><a href='http://www.leniwiec.org/wp-content/uploads/2011/04/main.hex'>main.hex</a> &#8211; wsad do konktrolera</li>
<li><a href='http://www.leniwiec.org/wp-content/uploads/2011/04/board_v2.ps'>board_v2.ps</a> &#8211; Płytka drukowana (PostScript)</li>
<li><a href='http://www.leniwiec.org/wp-content/uploads/2011/04/board_v2_mirror.ps'>board_v2_mirror.ps</a> &#8211; Płytka drukowana &#8211; odbicie lustrzane (PostScript)</li>
<li><a href='http://www.leniwiec.org/wp-content/uploads/2011/04/IO_Karta.zip'>IO_Karta.zip</a> &#8211; załącznik z wszystkimi plikami, wzorem pcb, schematem oraz aplikacjami klienckimi i wsadu.</li>
</ul>
<h2>Galeria</h2>

<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/schema/' title='Schemat sterownika'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/schema-150x150.png" class="attachment-thumbnail" alt="Schemat sterownika" title="Schemat sterownika" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/relay/' title='Schamat części wykonawczej'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/relay-150x150.png" class="attachment-thumbnail" alt="Schamat części wykonawczej" title="Schamat części wykonawczej" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3932/' title='Gotowy układ'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3932-150x150.jpg" class="attachment-thumbnail" alt="Gotowy układ" title="Gotowy układ" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/www/' title='Interfejs www'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/www-150x150.png" class="attachment-thumbnail" alt="Interfejs www" title="Interfejs www" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/java/' title='Aplikacja okienkowa'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/java-150x150.png" class="attachment-thumbnail" alt="Aplikacja okienkowa" title="Aplikacja okienkowa" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3931/' title='100_3931'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3931-150x150.jpg" class="attachment-thumbnail" alt="100_3931" title="100_3931" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3933/' title='100_3933'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3933-150x150.jpg" class="attachment-thumbnail" alt="100_3933" title="100_3933" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3934/' title='100_3934'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3934-150x150.jpg" class="attachment-thumbnail" alt="100_3934" title="100_3934" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3935/' title='100_3935'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3935-150x150.jpg" class="attachment-thumbnail" alt="100_3935" title="100_3935" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3936/' title='100_3936'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3936-150x150.jpg" class="attachment-thumbnail" alt="100_3936" title="100_3936" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3937/' title='100_3937'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3937-150x150.jpg" class="attachment-thumbnail" alt="100_3937" title="100_3937" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3938/' title='100_3938'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3938-150x150.jpg" class="attachment-thumbnail" alt="100_3938" title="100_3938" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3939/' title='100_3939'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3939-150x150.jpg" class="attachment-thumbnail" alt="100_3939" title="100_3939" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3940/' title='100_3940'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3940-150x150.jpg" class="attachment-thumbnail" alt="100_3940" title="100_3940" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3943/' title='100_3943'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3943-150x150.jpg" class="attachment-thumbnail" alt="100_3943" title="100_3943" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3944/' title='100_3944'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3944-150x150.jpg" class="attachment-thumbnail" alt="100_3944" title="100_3944" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3945/' title='100_3945'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3945-150x150.jpg" class="attachment-thumbnail" alt="100_3945" title="100_3945" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3946/' title='100_3946'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3946-150x150.jpg" class="attachment-thumbnail" alt="100_3946" title="100_3946" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3947/' title='100_3947'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3947-150x150.jpg" class="attachment-thumbnail" alt="100_3947" title="100_3947" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3948/' title='100_3948'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3948-150x150.jpg" class="attachment-thumbnail" alt="100_3948" title="100_3948" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3949/' title='100_3949'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3949-150x150.jpg" class="attachment-thumbnail" alt="100_3949" title="100_3949" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3950/' title='100_3950'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3950-150x150.jpg" class="attachment-thumbnail" alt="100_3950" title="100_3950" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3951/' title='100_3951'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3951-150x150.jpg" class="attachment-thumbnail" alt="100_3951" title="100_3951" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3952/' title='100_3952'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3952-150x150.jpg" class="attachment-thumbnail" alt="100_3952" title="100_3952" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3953/' title='100_3953'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3953-150x150.jpg" class="attachment-thumbnail" alt="100_3953" title="100_3953" /></a>
<a href='http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/100_3954/' title='100_3954'><img width="150" height="150" src="http://www.leniwiec.org/wp-content/uploads/2011/04/100_3954-150x150.jpg" class="attachment-thumbnail" alt="100_3954" title="100_3954" /></a>

]]></content:encoded>
			<wfw:commentRss>http://www.leniwiec.org/2011/04/10/8-kanalowa-karta-przekaznikow-na-rs232-usb/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>

