Arduino am Charlieplexing-Display

                      Elektronik-Labor  Bastelecke  Projekte  Mikrocontoller                        



Video: https://www.youtube.com/watch?v=VvY9Pa5idqo


Eigentlich wollte ich nur einen gebrauchten Akku aus einer alten E-Zigarette ausbauen. aber dann fand ich darin ein besonderes Charlieplexing-Display mit nur sechs Anschlüssen. Es wurde für die Ladekontrolle einegsetzt. Aber für eine Zigarette ist es viel zu schade. Deshalb habe ich es ausgebaut und auf einen Arduono Nano gelötet.



Mit 6 Anschlüssen kann man im Charlieplexing bis zu 30 LEDs ansteuern. Dieses Display hat etwas weniger. Mit Batterie,Vorwiderstand und zwei Messspitzen konnte ich rausbekommen, wie die Segmente angeschlossen sind. Das Beispielprogramm enthält alle Segmente mit den Anoden im Array dd und den Kathoden im Array ee. Die jeweils ersten 16 Positionen betreffen die beiden Siebensegmentziffern. Der Rest steht für die weißen Symbole und die farbigen Balken. Im Arduino muss man für alle sechs Ports jeweils die Datenrichtung (DDRD) und den Portzustand (PORDD) einschalten. das geschieht in einem Timer-Interrupt mit 4 kHz.

//Charlieplexing-Display am Pin 2...7

int d,e,n,i,z,c,w,s;
int dd[]={64,32,16,16,8,8,8,0,128,64,128,32,128,16,8,0 ,0,16,32,64,128,48,112,240,0,8,16,32,64,128,248,0,0,32,64,96};
int ee[]={32,64,32,64,64,32,16,0,64,128,32,128,16,128,128,0,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,0,0,16,16,16};
int seg[]={0xfc,0x60,0xda, 0xf2,0x66,0xb6,0xbe,0xe4,0xfe,0xf6};

void setup() {
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS11);
  TCNT1  = 0;
  OCR1A = 499;// 4000 Hz
  TIMSK1 |= (1 << OCIE1A);
  sei();//allow interrupts
}

ISR(TIMER1_COMPA_vect) {//Interrupt 4kHz
  if(n>35){n=0;}
    DDRD=0; PORTD==0;
    if(n<8 && seg[z]&(128>>n)){
    DDRD=(dd[n]+ee[n]) & 254;
    PORTD=ee[n];
    }
    if(n>7 && n<16 && seg[e]&(128>>(n-8))){
    DDRD=(dd[n]+ee[n]) & 254;
    PORTD=ee[n];
    }
    if(n>15 && n<24){
    DDRD=(dd[c+16]+ee[c+16]) & 254;
    PORTD=ee[c+16];
    }
    if(n>23 && n<30){
    DDRD=(dd[w+24]+ee[w+24]) & 254;
    PORTD=ee[w+24];
    }   
    if(n>31 && n<35){
    DDRD=(dd[s+32]+ee[s+32]) & 254;
    PORTD=ee[s+32];
    }   
    n++;
  }

void loop(){
  for (z=0;z<10;z++){   //Zehner  
    for (e=0;e<10;e++){ //Einer
      c=e/2+1;                //Colour
      if (c>1) {c+=3;}
      for(w=7;w>0;w--){ //White
        delay(100);}
      s=e/2;                      //Symbole
    }
  }
}

Die Software steuert das Display in der Haupt-Loop. Zehner, Einer, Farbbalken, weiße Umrandung und weiße Symbole werden jeweils durch eigene Variablen gesteuert.



Im Internet konnte ich nichts zu diesem Display finden, kein Datenblatt, keinen Hersteller, nichts. Ich verdanke es meinem Bruder, der achtlos weggeworfene E-Zigaretten im Interesse des Umweltschutzes und der Bastelfreude aufsammelt.




Erweiterte Software von Lily

Hier meine Version der Fumot-LED-Ansteuerung, bei der maximal 5 LEDs gleichzeitig leuchten. Das Programm läuft auf Ihrer Hardware, die Anzeige sollte deutlich heller leuchten  (geht mit 3,3V auch noch, sie wird ja im Original auch nur an einer Li-Zelle betrieben). Kein vorbildlicher Code, ich weiß, aber funktioniert gut.

// auf der Platine _im Display_ steht 1709 JR, finde aber nichts dazu
// Auf dem 20-poligen Prozessor U2: 5840 BC0202 0700Z1
// 20:08 14.10.2024 sehe gerade: es gibt andere Fumot, die 100%
anzeigen können, also 2,5-stellig, d.h. bis 199: Fumot Tornado 4 in 1
// siehe auch www.mikrocontroller.net/topic/572607
// 7 6 5 4 3 2 1 0
// 80 40 20 10 08 04 02 01
// a b c d e f g -
//
// a
// f b
// g
// e c
// d
const byte PROGMEM
//0:0c:00001100
//1:8C:10001100
//2:84:10000100
//3:C4:11000100
//4:44:01000100
//5:64:01100100
//6:24:00100100
//7:34:00110100
//8:14:00010100
//9:1C:00011100
t[]={0x0C,0x8C,0x84,0x84,0xC4,0xC4,0x44,0x44,0x64,0x24,0x34,0x14,0x1C}, //zirkulierender Tropfen
// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 3637
// 0 1 2 3 4 5 6 7 8 9 A b C d E F G H i J K L M n o P Q R S T U v W X Y Z _ _
a[]={0xF6,0x44,0xEA,0xEC,0x5C,0xBC,0xBE,0xC4,0xFE,0xFC,0xDE,0x3E,0xB2,0x6E,0xBA,0x9A,0xB6,0x5E,0x04,0x64,0x1E,0x32,0xD6,0x0E,0x2E,0xDA,0xDC,0x0A,0xBC,0x92,0x76,0x26,0x7E,0x56,0x7C,0xEA,0,0},//Einer
b[]={0x5F,0x14,0x67,0x76,0x3C,0x7A,0x7B,0x54,0x7F,0x7E,0x7D,0x3B,0x4B,0x37,0x6B,0x69,0x5B,0x3D,0x10,0x16,0x39,0x0B,0x5D,0x31,0x33,0x6D,0x7C,0x21,0x7A,0x49,0x1F,0x13,0x3F,0x1D,0x3E,0x67,0,0};//Zehner
byte E,T,Z,c,d,i,j,k,n,u;volatile byte z,e=37;volatile uint16_t w; // evtl. H und K vertauschen
void dela(){for(i=0;i<30;i++){delay(10);w=0;}}
void setup(){
Serial.begin(115200);Serial.write(10);
for(i=0;i<37;i++){j=pgm_read_byte(&a[i]);Serial.print(",0x");if(j<16)Serial.write(48);Serial.print(j,16);}Serial.write(10);
for(i=0;i<37;i++){j=pgm_read_byte(&b[i]);Serial.print(",0x");if(j<16)Serial.write(48);Serial.print(j,16);}Serial.write(10);
for(i=0;i<37;i++){j=pgm_read_byte(&a[i]);Serial.print(",0x");k=0;
// if(c&128)k|= 0;
if(j& 8)k|= 32;//1g
if(j& 16)k|= 8;//1f
if(j& 2)k|= 1;//1e
if(j& 32)k|= 2;//1d
if(j& 4)k|= 16;//1c
if(j& 64)k|= 4;//1b
if(j&128)k|= 64;//1a
// if(c&0x80)d+=128; if(c&0x40)d+=128; if(c&0x20)d+=128; if(c&0x10)d+=128;
// if(c&0x08)d+=128; if(c&0x04)d+=128; if(c&0x02)d+=128; if(c&0x01)d+=128;
if(k<16)Serial.write(48);Serial.print(k,16);};Serial.write(10);
cli();TCCR1A=0;TCNT1=0;
TCCR1B = (1 << WGM12) //Waveform Generation Mode (CTC1)
| (2 << CS10); //Clock select clkI/O/8 (From prescaler)
OCR1A = 4999;//16000000/8/ 5000= 400 Hz /6=66,7 Hz kann auch deutlich höher sein, z.B. 499 für 4000 / 667 Hz.
TIMSK1 |= (1 << OCIE1A); //Timer/Counter1, Output Compare A Match Interrupt Enable
sei();//allow interrupts
z=e;e=17;dela();//H müssen volatile sein, sonst wird wegoptimiert
z=e;e=10;dela();//A
z=e;e=21;dela();//L
z=e;e=21;dela();//L
z=e;e= 0;dela();//O
z=e;e=37;dela();//_
z=e;e=37;dela();//_
z=e;e=31;dela();//v/u
z=e;e=23;dela();//n
z=e;e=13;dela();//d
z=e;e=37;dela();//_
z=e;e=13;dela();//d
z=e;e=10;dela();//A
z=e;e=23;dela();//n
z=e;e=17;dela();//H/k
z=e;e=14;dela();//E
z=e;e=37;dela();//_
z=e;e=17;dela();//H
z=e;e=14;dela();//E
z=e;e=27;dela();//r
z=e;e=27;dela();//r
z=e;e=37;dela();//_
z=e;e=37;dela();//_
z=e;e=20;dela();//K
z=e;e=10;dela();//A
z=e;e= 1;dela();//I
z=e;e=23;dela();//n
z=e;e=20;dela();//K
z=e;e=10;dela();//A
z=e;e=37;dela();//_
z=e;e=37;dela();//_
}
ISR(TIMER1_COMPA_vect){//Interrupt 400Hz
c=w/512;n=(byte)w%6;u=w/8;T=w/128%13;//E=a[e];Z=b[z];
E=pgm_read_byte(&a[e]);Z=pgm_read_byte(&b[z]);
if(n==0){PORTD=0;DDRD=128|E&0x78;PORTD=128;}else
if(n==1){PORTD=0;DDRD= 64|(E&128)+((Z&7)<<3);PORTD=64;}else
if(n==2){PORTD=0;DDRD= 32|Z&0x58;if(E&4)DDRD|=128;PORTD=32;}else //2c
if(n==3){PORTD=0;DDRD= 16;
if(E& 2)DDRD|=128; //2e
if(u&32)DDRD|= 64; //%
if(u&64)DDRD|= 32; //Flash
if(Z&32)DDRD|= 8; //1g
PORTD=16;}else
if(n==4){PORTD=0;DDRD=8|c<<4;PORTD=8;}else
if(n==5){PORTD=0;DDRD=pgm_read_byte(&t[T]);PORTD=4;}
w++;
}
void loop(){delay(400);if(e++>35){e=0;if(z++>35)z=0;}}

BK: Ich hab' s getestet, läuft super, sehr hell! Und es werden nicht nur die Ziffern, sondern auch Buchstaben angezeigt. Danke!


Elektronik-Labor  Bastelecke  Projekte  Mikrocontoller