Pinnen sparen met Multi- en Charlieplexen
Het eeuwenoude probleem. Je hebt één oscilloscoop, maar vijf technici willen hem gebruiken; één telefoonlijn, maar drie mensen willen bellen; 20 LEDs, maar er blijven maar acht GPIO's over op je microcontroller. Wat doe je dan? Je deelt! Of, in technische termen, je multiplext. Laten we het hier eens over multiplexen hebben. Een van de grootste uitdagingen bij het kiezen van een microcontroller (MCU) is het vinden van een device met voldoende pinnen voor de taak en dat binnen het budget valt. Een device met 64 pinnen is meestal duurder dan een met 32. Ongeveer 10% tot 15% van die pinnen zijn voedingspinnen. Wat overblijft is een mengeling van digitale, analoge en speciale pinnen. Er is bijvoorbeeld een reset-pin, pinnen voor de kristaloscillator en misschien een speciale pin om een bootloader te ondersteunen. En soms zijn pinnen speciaal voor gebruik van specifieke periferie, zoals USB of I2C, omdat de schakelingen daaromheen een beetje anders zijn. Laten we dus aannemen dat we hebben vastgesteld dat onze toepassing 20 puur digitale pinnen nodig heeft, misschien voor schakelaars en het aansturen van LEDs voor een mens-machine interface. Op een 32-pins MCU trekken we de voedingspinnen (bijvoorbeeld 6), de analoge pinnen (bijvoorbeeld 8), USB en I2C (bijvoorbeeld 4) hiervan af, en houden slechts 14 pinnen
over. Dus, als je je commerciële pet opzet, kun je het dan rechtvaardigen om een duurdere MCU met een hoger aantal pinnen te kiezen waarbij niet alle pinnen worden gebruikt? Of kun je met wat technisch vernuft 14 pinnen 20 signalen laten produceren?
Multiplexen begon met de telegraaf
Het idee om meer uit een enkele elektrische verbinding te halen, begon met de telegraaf. Toen Morse en zijn vrienden eenmaal hadden uitgevonden hoe ze gegevens over lange afstanden konden versturen, was het duidelijk dat het duur zou zijn om voortdurend draden toe te voegen om capaciteit op te bouwen. En dat niet alleen, het betekende ook meer werk voor het team dat het netwerk onderhield.Natuurlijk begonnen een paar knappe koppen uit die tijd na te denken over de vraag of deze enkele draden gedeeld konden worden door meerdere telegrafisten, zodat twee of meer berichten verzonden konden worden over elk van de bestaande draden. Eén van hen was Émile Baudot.
Het systeem moest aan beide uiteinden gesynchroniseerd worden. Aan de ontvangende kant draaide een schrijfwiel, dat veel leek op de kop van een margrietprinter, volledig rond. Aan de verzendende kant werden alle lettertoetsen in dezelfde volgorde opgenomen. Als er op een toets werd gedrukt, werd de corresponderende letter van het letterwiel geactiveerd terwijl deze over een papieren band ging. Dit beperkte de overdracht van berichten tot ongeveer 40 woorden per minuut (een woord was gemiddeld vijf letters plus een spatie).
Deze uitdaging werd opgelost door een nieuw coderingsschema dat bestond uit hetzelfde aantal symbolen van gelijke lengte voor elke letter. Zijn systeem bestond uit vijf bits en gebruikte positieve en negatieve pulsen om een letter te verzenden. Door beide uiteinden te synchroniseren, konden tot zes gebruikers tegelijkertijd berichten verzenden over één draad. Zo zag het er dus uit. In werkelijkheid was het een time-division multiplexing systeem dat elke telegrafist een zesde van een slot gaf om de volgende letter te verzenden.
LEDs Multiplexen
Zeven-segment-LEDs en matrix toetsenborden zijn al tientallen jaren een steunpilaar van elektronische systemen. Zelfs voordat microcontrollers gemeengoed waren, zochten elektronica-ingenieurs naar manieren om te besparen op het aantal signalen dat nodig was om deze componenten te implementeren.Laten we zeven-segment LED-displays onder de loep nemen als ons eerste voorbeeld. Als je ook het decimaalteken meerekent, bevatten deze komponenten acht LEDs. Als je een voeding bouwt, kijk je waarschijnlijk naar vier cijfers in totaal (XX.YY) om de spanning of stroom weer te geven. Dan hebben we 8 x 4 = 32 pinnen nodig - dat is veel.
Als we dus dezelfde LED van elk nummer op dezelfde MCU-pin aansluiten, kunnen we 24 pinnen besparen. Om te bepalen welk van onze vier zeven-segment displays wordt aangestuurd, hebben we vier pinnen nodig om één van de gemeenschappelijke kathodes met massa te verbinden. Om 32 LEDs aan te sturen, hebben we dus 8 + 4 = 12 pinnen nodig - 20 minder dan wanneer we een pin per LED zouden gebruiken.
.
Matrix-toetsenborden Multiplexen
Dezelfde benadering kan worden gebruikt voor een matrix van drukknopschakelaars als input voor een embedded systeem. Als je slechts twee of drie schakelaars hebt, kun je ze waarschijnlijk combineren met een pull-up/down weerstand en hun status detecteren met hetzelfde aantal GPIO's geconfigureerd als ingangen.Als je echter meer dan zes schakelaars hebt, kan het zinvol zijn om een matrix te implementeren om ze uit te lezen. In plaats van de schakelaars via pull-up weerstanden aan te sluiten op de voeding, worden de schakelaars aangesloten op een GPIO-uitgang. Wanneer de uitgang hoog is en de schakelaar wordt ingedrukt, zal de ingang dit detecteren als een 1. De weerstanden zijn er om te voorkomen dat de Vcc wordt kortgesloten naar massa via de GPIO's.
Om een matrix te maken, moeten reeksen schakelaars om de beurt worden ingeschakeld door enkele GPIO-pinnen die als uitgangen zijn geconfigureerd.
We beginnen met zes schakelaars en groeperen ze in twee groepen van drie. Elke groep van drie heeft één zijde verbonden met een GPIO-uitgang. Vervolgens groeperen we ze in tweetallen, waarbij de andere kant van elke schakelaar is verbonden met een GPIO-ingang
// INITIALIZE PINS
SET D0 as OUTPUT
SET D1 as OUTPUT
SET D0 LOW
SET D1 LOW
// SCAN BUTTONS
SET D0 HIGH
READ D2, D3, D4 and STORE STATE as BUTTON 1, BUTTON 2, BUTTON 3
SET D0 LOW
SET D1 HIGH
READ D2, D3, D4 and STORE STATE as BUTTON 4, BUTTON 5, BUTTON 6
SET D1 LOW
Het is belangrijk om de kolommen snel genoeg te scannen om ervoor te zorgen dat de invoermethode reactief blijft. Mensen beschouwen een reactietijd van minder dan 200 ms als 'onmiddellijk', dus je moet de volledige matrix van drukknoppen minstens vijf keer per seconde scannen. Deze methode is ook geschikt voor het detecteren van drukknop-combinaties, die kunnen helpen om meer gebruikersinterfacefuncties te bieden dan drukknoppen.
LEDs Charlieplexen
Terwijl multiplexing het aantal GPIO's vermindert dat nodig is om LEDs aan te sturen, kun je met Charlieplexen dit zelfs met nog minder pinnen realiseren! Dit maakt gebruik van het feit dat MCU GPIO-pinnen drie toestanden hebben; hoog en laag als uitgang en hoge impedantie als ingang.Om eenvoudig te beginnen kunnen we twee LEDs in tegengestelde polariteit aansluiten tussen twee MCU-pinnen. Als ze als uitgangen zijn geconfigureerd, gaat een van de LEDs aan als de ene pin hoog is en de andere laag. Draai dit om en de andere gaat aan. Om ze uit te schakelen, stel je beide GPIO's in als ingangen.
// INITIALIZE PINS
SET D0 LOW
SET D1 LOW
SET D0 as INPUT
SET D1 as INPUT
// TURN ON LED 2
SET D0 as OUTPUT
SET D1 as OUTPUT
SET D1 HIGH
SET D0 LOW
// TURN ON LED 1
SET D1 LOW
SET D0 HIGH
// TURN LEDS OFF
SET D0 as INPUT
SET D1 as INPUT
SET D0 LOW
SET D1 LOW
Tot nu toe niet indrukwekkend. We hebben twee GPIO's gebruikt om twee LEDs aan te sturen. De pret begint wanneer we een extra GPIO toevoegen... en nog vier LEDs meer. We voegen nog twee LEDs met tegengestelde polariteit toe tussen GPIO één en drie en twee tussen GPIO twee en drie. Om een enkele LED aan te sturen, moet één GPIO hoog worden, de tweede laag en de derde moet als ingang worden geconfigureerd.
// INITIALIZE GPIOs
SET D0 LOW
SET D1 LOW
SET D2 LOW
SET D0 as INPUT
SET D1 as INPUT
SET D2 as INPUT
// TURN ON LED1
SET D0 HIGH
SET D1 LOW
SET D0 as OUTPUT
SET D1 as OUTPUT
// TURN ON LED4
SET D0 LOW
SET D1 LOW
SET D0 as INPUT
SET D2 HIGH
SET D1 LOW
SET D2 as OUTPUT
Uitgangen | LED1 | LED2 | LED3 | LED4 | LED5 | LED6 |
D0 | Uit hoog | Uit laag | In | In | Uit hoog | Uit laag |
D1 | Uit laag | Uit hoog | Uit hoog | Uit laag | In | In |
D2 | In | In | Uit laag | Uit hoog | Uit laag | Uit hoog |
Met twee LEDs in serie tussen pinnen 1 en 3 (Arduino D0 en D2 in het schema hieronder) zou je je terecht kunnen afvragen waarom deze LEDs niet oplichten wanneer je probeert een LED tussen deze pennen aan te zetten. Dit is een risico, maar is afhankelijk van de lage voedingsspanning van de MCU en de doorlaatspanning van de LEDs. Met een voeding van 3,3 V is de spanning over de twee LEDs, 3,3 ÷ 2 = 1,65 V, niet genoeg om één LED te laten branden. Werken met 5,0 V kan eventueel andere problemen veroorzaken.
Net als bij multiplexen kan Charlieplexen ook de tijdduur dat de uitgangspin hoog is, variëren om de LED-helderheid te veranderen. Dit vereist een timer met interrupt service routine, samen met enkele schakelinstructies.
Omdat Charlieplexing zulke grote mogelijkheden biedt, zal een kleine vergelijking helpen om te verduidelijken hoeveel LEDs kunnen worden aangestuurd met hoeveel pinnen.
LEDs = GPIOs × (GPIOs - 1)
Dus voor onze vier zeven-segment displays (32 LEDs) van eerder, hebben we zeven GPIO's nodig en kunnen we nog 10 LEDs aansluiten voor andere toepassingen.
Waarom Charlieplexen?
De term Charlieplexen komt van een ingenieur bij Analog Devices, Charlie Allen, die het gebruik van deze techniek binnen de organisatie propageerde. Hierdoor werd zijn naam een soort steno bij het benoemen van deze besturingsaanpak. Analog Devices produceert een aantal specifieke zeven-segment LED-drivers, zoals de MAX6950.Deze chip met 16 pinnen kan tot vijf zeven-segment displays of 40 discrete LEDs aansturen. Slechts acht van de pinnen worden gebruikt om de LEDs aan te sturen. De gebruikte besturingsmethode is iets anders dan hierboven beschreven, met een stroombron die de LEDs voedt en MOSFETs die het pad naar massa verzorgen voor de gemeenschappelijke kathode. De stroombron is instelbaar van 2,5 mA tot 37,5 mA, waardoor de helderheid van de LEDs kan worden geregeld. Een MCU bestuurt de chip via SPI. Indien nodig kunnen meerdere ICs in serie worden aangesloten om nog meer displays aan te sturen