Arduino am Charlieplexing-Display
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!