Několik drobných poznámek k Charlieplexingu

Few small notes adout Charlieplexing

V rámci své zvědavosti jsem se trochu zajímal o charlieplexing. Jedná se o jednoduchou úvahu nad tím, jak efektivně využít vývodu mikroprocesoru (jednočipového řadiče) pro rozsvěcení maximálního počtu signalizačních LED. (v multiplexním režimu)

Podstata je celkem jednoduchá, Charlie Allen si všiml, že na dva výstupy (P1 a P2) lze připojit jednu LED diodu, ale také dvě antiparalelně. Pokud jsou pak vývody ve stavu 1-0 svítí jedna dioda a pokud 0-1, svítí druhá. Pokud je alespoň jeden výstup ve třetím stavu, nesvítí žádná
Zároveň, pokud použijeme další výstup (P3), můžeme připojit další LED diody a to rovnou 4 - dvě proti výstupu P1 a dvě proti výstupu P2. Takto jsme schopni ze 3 výstupů rozsvěcet 6 LED diod - každou samostatně, nikoli společně. Další detaily na wikipedii.
I was little interested by charlieplexing. It is a method, how to drive maximum number of indication LEDs with minimum used pins of microcontroller. (in multiplexed mode)

The principle is easy, Charlie Allen found, that you can connect one LED to two outputs (P1 and P2), but you can connect also 2 LEDS in antiparallel. When outputs are in state 1-0, lights first, and in state 0-1 second. If at minimum one of pin is in third state, no one LED lighting.
We can also add next output (P3), we can add next 4 LEDs - two to P1 and two to P2. Then we can drive 6 LEDs using 3 outputs - one by one. More details on wikipedia.
Chtěl jsem vědět jaké jsou reálně použitelné možnosti této metody. Rozhodl jsem se postavit si malé zařízení, které využije jeden port osmi bitového procesoru. Tedy 56 LED diod.
V takovém množství diod je celkem důležité se neztratit. Já jsem se trochu inspiroval na stránce Andrew Magill, který popisuje jak definovat matici pro jednotlivé diody.
Podstata je jednoduchá - vytvoříme si tabulku, která má tolik řádků a sloupců, kolik máme výstupů. Řádky i sloupce podle výstupů pojmenujeme. Zároveň si definujeme, že například sloupec definuje logickou 1 a řádek logickou 0. Diagonálu proškrtáme, protože jeden vývod nemůže být ve stavu 0 a 1 zároveň.
Nyní je potřeba si definovat posun, abychom dostali plnou matici a nikoli díru na diagonále. V mém případě jsem si definoval posun nahoru. Nakonec do jednotlivých polí vepíšeme pořadová čísla LED diod. Pochopitelně tady je důležité se neztratit v posunu.
I was interested what real possibilities of this method are. I decided to build small device, which will use one port on eight bit processor. Then 56 LED diodes
In that amount of diodes is good to not get lost. I was little inspired on page of Andrew Magill, it describes method, how to define matrix for diodes.
Principle is easy - we will create a table, with same amount of rows and columns as we have outputs. Rows and columns have names corresponding with output names. Next we should define, that for example columns mean logical 1 and row logical 0. Cells on diagonal can be discarded, because one output cannot be in state 0 and 1 in same time.
Next is necessary to define shift to get full rectangle instead of empty diagonal. In my case I decided to shift up. At the end we can write ordinary numbers of LED diodes into fields. It is good to not forget about shift.
Z takto definované tabulky je poměrně jednoduché vytvořit schéma a ze schématu následně i plošný spoj. Plošný spoj vychází pochopitelně maticový, pouze se na něm odráží posun.
Já jsem plošný spoj vytvořil jako oboustranný, ale připravený pro domácí výrobu, bez prokovených otvorů, pokud se smíříme s pájením z dolní a horní strany.
This table can be easy used to create schematics and PCB from schematics. PCB is of course matrix style, only is visible that shift.
My one PCB is created as double sided, but ready for home made. It mean without metallic through holes, only we must solder parts on both sides.
silk
Z takto definované matice potřebujeme vytvořit tabulku výstupů. Jednoduše si přepíšeme jednotlivé diody pod sebe a ke každé si definujeme který vývod je pro ní ve stavu 1 a který ve stavu 0.
Logický součet pak vytváří tabulku pro třístavový registr.
Je možné si všimnout, že z té strany kterou jsme nezdeformovali posunem vychází data celkem slušně pouze jako posun "jedničky" (nebo naopak "nuly"). Toho lze využít a definovat si tuto informaci jako bázovou. Potom je tabulka pro výstup jednoduchá a obsahuje pouze tolik hodnot, kolik použijeme výstupů. (nebo lze použít rotace jedničky v registru). Situace pro třístavový registr je komplikovanější, protože zahrnuje kombinaci obou částí, takže je většinou výhodnější použít tabulku.
From matrix defined like this we need to create table of outputs. Easily we re-write every diodes to single rows and will write which output is in logical one and which in logical zero for this diode.
Logical OR will then create table for tri state register.
It is possible to recognize, that from side which is not affected by shift the data is simple as a rotation of "logical one" (or "logical zero"). It can be used for define this information as a base. Then table for outputs will be simple and will contain only that amount of rows, how many outputs we have. (or we can use rotation of one in register). Situation for tri-state register is little complicated, because contain combination of both sides. Then it is usually better to create table for it.

Software

Software

Využil jsem jednoduchého procesoru PIC16F628A, který umožňuje definovat jeden časovač jako opakující se časovou základnu. Já jsem využil vnitřního oscilátoru, který pracuje na kmitočtu 4MHz. Jeho kmitočet je pak dělen 4 na strojové cykly.
Čítač tedy počítá 250 strojových cyklů, takže 4000Hz frekvence obnovování bodu, při 56 diodách bude obnovovací frekvence zhruba 71Hz.
Čítač vyvolává přerušení. Přerušovací rutina nejprve rozsvítí další diodu z připravených a následně vypočítá další diodu v pořadí. Je to proto, aby bylo rozsvěcení diod pravidelné, vždy ve stejný okamžik.
Přerušovací rutina také posouvá čítač 1milisekundových událostí, který je použit v hlavním programu pro generování "snímků".

Z pohledu hlavního programu se pak matice chová jako klasická obrazovka s maticovou adresací.

V příloze jsou dva zdrojové kódy. Jedna verze pracuje, jak je zde popsáno, druhá se pokoušela vytvářet 4 odstíny šedé, v praxi však byla víceméně nepoužitelná.
I was used simple processor PIC16F628A. This processor allows me to define one counter as a periodically repeating time base. I was used internal oscillator, running on 4MHz. His frequency is divided by 4 to instruction cycles.
Counter then counts 250 instruction cycles. Then pixel frequency ir 4000Hz. Because we have 56 leds, then refresh rate of all screen is around 71Hz. Counter call interrupt. Interrupt routine at the begin light next diode from prepared data; then will calculate data for next diode. It is because I want to have lighting in good defined period.
Interrupt routine also decrease counter of 1 millisecond events. This counter is used in main program for creation "frames".
From main program point of view matrix look like usual screen with usual matrix addressing.

In the attachment you can find two source codes. One version working as described, second one is trying to create 4 levels of gray. In a reality second one is useless.





Helo World


Arkanoid

Možné úpravy

Possible changes

Kamarád mne upozornil na možnost úpravy programu. Pokud si číslovací plán navrhneme obráceně, můžeme dostat zajímavé zjednodušení. V tomto případě lze nahradit dlouhou tabulku použitím několika proměných.
Pokud si definujeme proměnou pro řádek a pro sloupec, pak bude jejich zpracování celkem jednoduché.
Na začátku si nastavíme do proměnné "řádek" hodnotu 01 (první řádek) a do proměnné "sloupec" 0x80 (poslední sloupec). Tím je rpvnou definovaná hodnota výstupu (přímo hodnota "sloupec") a hodnota třístavového registru (logický součet (or) řádku a sloupce). V dalším kroku pak provedeme rotaci "sloupce" vlevo (na polovinu - podle typu procesoru). V případě, že je hodnota "řádek" a "sloupec" shodná, pak provedeme ještě rotaci "řádku" vpravo (na dvojnásobek - podle typu procesoru). Přičemž hodnoty rotujeme v rámci 8 bitů registru, tím pádem po rotaci z maximální hodnoty dostáváme znovu minimální.
Friend of mine was informed me about possibility to change program. If we will revert numbering plan, we will get interesting simplification of code. In this case we can replace long table by using of few variables.
We can define one variable for row and second for column, and then calculation of variables will be simple.
At begin we should define "row" value "01" (first row) and variable "column" value 0x80 (last column). Then value of output is defined as a value of "column" and value of tri-state as a value of logical OR of "row" and "column". In next step we should rotate of "column" left (divide by 2 - depend of processor). In a case that "column" is same as "row", we must rotate also "row" right (double it - depend on processor type). The values should be rotated inside 8 bit register, and then we will after maximum values get again minimum.
Source.zip