Led aanduider
Led aanduider met cijfers aangestuurd met arduino
TechTalk
Root server » TechTalk » Electronica » LED aanduider
Een arduino kan bijvoorbeeld een LCD scherm aansturen. Dit kan gemakkelijk serieel (TTL serieel en niet RS-232 zodat er zelfs geen niveauconversie nodig is). Maar als je gemakkelijk een LCD panel kan aansturen, dan zou je toch even gemakkelijk een eenvoudig led cijferdisplay kunnen aansturen?
-

-

Een led panel aansturen zou toch niet zo moeilijk moeten zijn, als de communicatie tussen een arduino en een LCD scherm eenvoudigweg via seriele communicatie mogelijk is?

Dit is echter niet zo eenvoudig: er zit geen electronica in de led modules, er zijn gewoon zoveel ingangen als er segmenten zijn en de module heeft een gemeenschappelijke anode (of minder voorkomend: een gemeenschappelijke cathode). Per cijfer heeft men dus 7 segmenten en eventueel een decimaal punt.

Multiplex aansturen

Vroeger werden deze cijfermodules gemultiplext aangestuurd. Om 4 cijfers aan te sturen waren er 4 PNP transistoren nodig om de anodestroom te leveren. Bij een bepaalde cijfer werden de bijhorende segmenten aangestuurd via NPN transistoren, want de processoren konden toen slechts een paar milliamps leveren. Nadat de eerste cijfer aangestuurd werd, werd de volgende cijfer aangestuurd, met hier ook de bijhorende segmenten.

Voor een 4-cijferige display waren er dus 4 + 7 = 11 uitgangen nodig op de processor. Voor een processor die in een klok gebruikt werd was dit geen bezwaar, de processor had weinig extra ingangen of uitgangen nodig. Maar in onze situatie (aansturing door een arduino) betekent dit dat we bijna geen digitale in- of uitgangen meer over hebben.

Deze methode wordt tegenwoordig ook minder toegepast vanwege de sterke electrosmog die zo'n schakeling produceert. Omdat iedere cijfer slechts 1/4 van de tijd stroom krijgt, moet de stroom ook wat hoger zijn, doorgaans 50mA in plaats van 10 à 20mA. Het multiplexen kunnen we voorgoed vergeten, dit is nu geschiedenis.

Op de skoopbeeld hebben we de drie uitgangen van de arduino:

  • de kloklijn in het geel, met iedere keer 8 klokpulsen
  • de datalijn die eerst de data doorstuurt (4 bits BCD, LSB first) en dan de adres (4 bits, waarvan één hoog is). Eerste en tweede cijfer zijn "5", we schrijven naar adrespositie 2 en dan 3 met tussen beide iedere keer een byte met data maar geen adres
  • de strobe lijn zorgt voor de overdracht van de seriele data naar de parallele uitgang.

CMOS cijferdecoder 4543

Er bestaan CMOS cijferdecoders die een BCD ingang (binary coded decimal) omzetten in de aansturing van een cijfer met 7 segmenten. Deze decoders kunnen zowel werken met cijfers met gemeenschappelijke anode als cathode, en kunnen zelfs LCD displays aansturen door een wisselspanning op één van de pennen te zetten. Zoals met alle CMOS IC's is eenzelfde funktie beschikbaar onder verschillende kodes: 4054, 4543, 4558,...

Deze IC's hebben één groot voordeel, dat is de geheugenfunktie: als de latch pin hoog is, dan wordt de BCD kode continu omgezet naar de bijhorende segmentcode, als de ingang laag is, dan wordt er niet meer gekeken naar de ingang en blijft de oude kode bewaard. Men kan dus heel gemakkelijk een cijfer selectionneren door de latch van de decoder hoog te maken, terwijl de 4 BCD lijnen gemeenschappelijk zijn voor alle cijfers.

Naast de BCD ingang en segment uitgang heeft het IC nog andere ingangen: blanking ingang (1 = blanking), phase (1 = common anode), latch (1 = connect in to out)

Dit is al een hele verbetering, met 4 "adres"lijnen (selectie van de cijferpositie) en 4 "data"lijnen kan men het display aansturen. Maar hier gebruikt men nog altijd 8 processoruitgangen, terwijl het met minder lijnen ook kan.

CMOS serial to parallel 4094

De CMOS familie heeft een hoop interessante modules, één ervan is de serial tot parallel interface. De 8 bits worden serieel ingelezen op de stijgende flank van de klokpuls en na de 8 bits komt er een strobe puls om de data over te brengen naar de uitgang (8 lijnen: 4 adres en 4 datalijnen).

Met zo'n relatief eenvoudige IC is er een kloksignaal nodig (het werkt niet met een gewonen seriele uitgang) en er is ook geen automatische strobe. In plaats van 1 lijn heeft men dus 3 processorlijnen nodig, maar dat is toch beter dan de 8 of 11 lijnen die nodig zijn bij de vorige schakelingen.

Decimaal punt aansturen
Men kan eventueel ook het decimaal punt aansturen, hier gebruikt men ook een programmatorische ingreep. Normaal worden de cijfers één voor één geselecteerd, maar het is niet noodzakelijk dat dit continu gebeurt. Het is enkel nodig om een nieuw getal door te sturen, als die effektief gewijzigd is geweest, dit is dan om de minuut bij een klok. Nadat de 4 cijfers doorgestuurd zijn geweest, wordt opnieuw de cijferdecoder geselecteerd (gedurende de tijd dat de cijfers niet gewijzigd moeten worden). Daardoor gaat ook de betreffende punt oplichten door middel van de extra transistor. Er moet één transistor en bijhorende weerstanden voorzien worden per decimaal punt dat moet oplichten, ik heb hier het deel voor één decimaal punt getekend. Zo kan men auto-range implementeren. Heeft men een vaste punt nodig, dan kan de dp pen aan de massa aangesloten worden via een weerstand.

BCD kode tweemaal doorsturen
De kode voor een cijfer moet noodzakelijkerwijze tweemaal doorgestuurd worden: éénmaal de adresselectie + BCD data en éénmaal de BCD data zonder adresselectie. Bij de tweede stap wordt er geen cijferpositie geselecteerd, maar blijft de data nog geldig zodat de cijfer vastgezet kan worden. Met één enkele schijfopdracht kunnen er verkeerde getallen verschijnen: als de adreslijn naar nul gaat, veranderen ook de datalijnen naar de waarde van de volgende cijfer. Het IC kan de oude waarden blijven tonen of reeds de nieuwe waarden tonen.

Het IC heeft nog een extra ingang, een output enable (bij 1) en twee uitgangen om gemakkelijker verschillende modules aan elkaar te koppelen.

CMOS BCD to decimal decoder 4028


Maar het is eenvoudig om tot 10 cijfers aan te sturen zonder extra processorlijnen te moeten gebruiken: we hebben hier immers een adresbus waarvan er slechts één lijn hoog is op een gegeven ogenblik. Met een BCD naar decimaal decoder kan men met dezelfde 4 adreslijnen (BCD gedodeerd) nu 10 cijfers (en eventueel de bijhorende decimale punten) aansturen. Om data zonder adres te versturen wordt er een ongeldige BCD code doorgestuurd, om de laatst doorgestuurde cijfer vast te zetten op de neergaande flank van de adreslijn.

Het IC wordt geplaatst tussen de adres uitgang van de 4094 (serial to parallel decoder) en de select ingang van de 4543 (7-segmentdecoder). Deze mogelijkheid is niet aangegeven op de schakeling.

De 4028 wordt ook gebruikt bij de nixie klok met arduino sturing. Opgelet, bepaalde IC's zetten de uitgangslijnen niet op nul bij het versturen van een ongeldige bcd kode, zoals de CD4028CN.

Het display kan gedoofd worden door de blanking ingang van het IC 4543, door een ongeldige kode te sturen (11 à 15) of door de eigen 5V voeding te onderbreken. Zo kan men bijvoorbeeld niet beduidende cijfers onderdrukken zoals in onderstaande voorbeeld. Het is ook mogelijk de helderheid van de cijfers wat te veranderen door de 5V spanning te veranderen, maar de 4543 is eigenlijk maar voorzien om 5mA te sinken.


#define CLOCK 2
#define DATA 3
#define STROBE 4

void setup() {
  pinMode(CLOCK, OUTPUT);  pinMode(DATA, OUTPUT);  pinMode(STROBE, OUTPUT);
}

void seriel(byte x)  {            // seriel transmet un byte
static byte i, k;                 // contenant une adresse
  k = x;                          // et une donnée BCD
  for (i = 0; i < 8; i++) {       // send each bit
    // begin with first bit = most significant
    if (i == 4) {                 // séparer data de addr. sur l'oscilloscope
      digitalWrite(DATA, 0);          delay(1);
    }
    digitalWrite(DATA, k > 127);      delay(1);
    k = k << 1;                   // shift 1 bit left = *2
    digitalWrite(CLOCK, 1);           delay(1);
    // accept data sur flanc positif
    digitalWrite(CLOCK, 0);           delay(1);
  }
  digitalWrite(DATA, 0);              delay(1);
  // pas vraiment nécessaire mais c'est plus beau sur l'oscilloscope
  digitalWrite(STROBE, 1);            delay(1);
  // transfer serial data to parallel out byte complet
  digitalWrite(STROBE, 0);            delay(1);
}

  
void loop() {
static byte i, y, t[4], ot[4];
static int cnt, z;
static long ms, oms;
bool s = false;                 // pas static! doit être remis à 0
  z = analogRead(AIN);          // à chaque boucle
  y = 128;

  for (i = 0; i < 4; i++) {     // mettre chiffre à chaque position
    t[i] = z % 10;              // dans un tableau
    z = z / 10;
  }

  for (i = 3; i != 255; i--)  {   // envoi du tableau en sériel
    if (t[i] != 0)      s = true; // si le chiffre n'est pas 0,
                                  // il est significatif
    if (!s && i != 0)   t[i] = 11; // si non-signif. et non dernière pos
                                  // on efface le chiffre
    if (ot[i] != t[i]) {          // si le chiffre a changé,
      seriel (t[i] + y);          // on transmet: data + address
      seriel (t[i]);              // puis data sans address pour figer
      ot[i] = t[i];               // nouveau chiffre --> ancien chiffre
    }
    y = y >> 1;                   // bit suivant de l'adresse (shift right)
  }
}
Arduino beschikt ook over een ingebouwde funktie om de data serieel door te sturen, dat is de shiftOut() instructie. De instructie is eenvoudig maar er is geen scheiding tussen de twee nibbles.

void seriel(byte x)	{
	shiftOut(DATA, CLOCK, MSBFIRST, x);    // Most Significant bit first
	digitalWrite(STROBE, 1);	              // Omgekeerde parameter is LSBFIRST
	delayMicroseconds(10);
	digitalWrite(STROBE, 0);            
}

De bewegende punten geven de positie die geschreven wordt. Het is geen uuraanduiding maar een niveaumeting.

Publicités - Reklame

-