Retrouhr mit Bubble-LEDs

Mit dem alten Bubble-LED-Chip 5082-7415 von Hewlett Packard (kurz HP) und einer Real-time-clock (kurz RTC, konkret das Modell DS3231) lässt sich auf Arduino-Basis eine einfache Retrouhr im Stile der 70er Jahre basteln. Die Schaltung benötigt neben dem LED-Chip nur noch einige Widerstände und npn-Transistoren etwa vom Typ BC547.

Diese Bubble-LED-Chips wurden früher zum Beispiel in Taschenrechnern eingesetzt. Ich habe meinen Chip auf ebay für rund 14 Euro erstanden.

Bildquelle: https://tronixstuff.com/2025/04/11/hewlett-packard-5082-7415-led-display-from-1976/

 


Arduino-Code:

#include <Wire.h>

#define DS3231_I2C_ADDRESS 104

// SCL - pin A5
// SDA - pin A4
// To set the clock, run the sketch and use the serial monitor.
// Enter T1124154091014; the code will read this and set the clock. See the code for full details.
//

byte seconds, minutes, hours, day, date, month, year;
byte seconds_e, minutes_e, minutes_z, hours_e, hours_z;
char weekDay[4];

byte tMSB, tLSB;
float temp3231;

int Anzeigendauer;



//==============================
//=========== SETUP ============
//==============================

void setup()
   {
    Wire.begin();
    Serial.begin(9600);
    
    for (int i = 2; i < 14;i++)
       {
        pinMode(i, OUTPUT);
       }
       
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(11,LOW);
    digitalWrite(12,LOW);
    digitalWrite(13,LOW);      
    
    Anzeigendauer = 4;
   }

//======================================
//=========== HAUPTSCHLEIFE ============
//======================================

void loop()
   {
    watchConsole();
  
    get3231Date();
 
    /*
    Serial.print(weekDay);
    Serial.print(", ");
    Serial.print(date, DEC);
    Serial.print("/");
    Serial.print(month, DEC);
    Serial.print("/");
    Serial.print(year, DEC);
    Serial.print(" - ");
    Serial.print(hours, DEC);
    Serial.print(":");
    Serial.print(minutes, DEC);
    Serial.print(":");
    Serial.print(seconds, DEC);
 
    Serial.print(" - Temp: ");
    Serial.println(get3231Temp());
    */
    
    
    // Bestimmung der Einer- und Zehnerstellen der Minuten und Stunden
    // ===============================================================
    
    seconds_e = (seconds%10);
    minutes_e = (minutes%10);
    minutes_z = (minutes%100)/10;
    hours_e = (hours%10);
    hours_z = (hours%100)/10;
    
    
    if (hours_z > 0)
       {
        Anzeige(hours_z);     // Darstellung der Stunden-Zehnerstelle
    
        digitalWrite(9,HIGH);
        delay(Anzeigendauer);
        digitalWrite(9,LOW);
       }
    
    Anzeige(hours_e);     // Darstellung der Stunden-Einerstelle
    
    digitalWrite(10,HIGH);
    delay(Anzeigendauer);
    digitalWrite(10,LOW);
    
    
    if ((seconds_e%2) == 0)   // Darstellung eines Querstrichs alle geraden Sekunden
       {
        Anzeige(16);
    
        digitalWrite(11,HIGH);
        delay(Anzeigendauer);
        digitalWrite(11,LOW);
       }
    
    Anzeige(minutes_z);      // Darstellung der Minuten-Zehnerstelle
    
    digitalWrite(12,HIGH);
    delay(Anzeigendauer);
    digitalWrite(12,LOW);
    
    Anzeige(minutes_e);      // Darstellung der Minuten-Einerstelle
    
    digitalWrite(13,HIGH);
    delay(Anzeigendauer);
    digitalWrite(13,LOW);
   
 }


void Anzeige(int Ziffer)
   {
    switch (Ziffer)
       {
        case 0:   // Darstellung der Ziffer 0
        digitalWrite(2,HIGH);
        digitalWrite(3,HIGH);
        digitalWrite(4,HIGH);
        digitalWrite(5,HIGH);
        digitalWrite(6,HIGH);
        digitalWrite(7,HIGH);
        digitalWrite(8,LOW);
        break;

        case 1:   // Darstellung der Ziffer 1
        digitalWrite(2,LOW);
        digitalWrite(3,HIGH);
        digitalWrite(4,HIGH);
        digitalWrite(5,LOW);
        digitalWrite(6,LOW);
        digitalWrite(7,LOW);
        digitalWrite(8,LOW);
        break;

        case 2:   // Darstellung der Ziffer 2
        digitalWrite(2,HIGH);
        digitalWrite(3,HIGH);
        digitalWrite(4,LOW);
        digitalWrite(5,HIGH);
        digitalWrite(6,HIGH);
        digitalWrite(7,LOW);
        digitalWrite(8,HIGH);
        break;

        case 3:   // Darstellung der Ziffer 3
        digitalWrite(2,HIGH);
        digitalWrite(3,HIGH);
        digitalWrite(4,HIGH);
        digitalWrite(5,HIGH);
        digitalWrite(6,LOW);
        digitalWrite(7,LOW);
        digitalWrite(8,HIGH);
        break;

        case 4:   // Darstellung der Ziffer 4
        digitalWrite(2,LOW);
        digitalWrite(3,HIGH);
        digitalWrite(4,HIGH);
        digitalWrite(5,LOW);
        digitalWrite(6,LOW);
        digitalWrite(7,HIGH);
        digitalWrite(8,HIGH);
        break;

        case 5:   // Darstellung der Ziffer 5
        digitalWrite(2,HIGH);
        digitalWrite(3,LOW);
        digitalWrite(4,HIGH);
        digitalWrite(5,HIGH);
        digitalWrite(6,LOW);
        digitalWrite(7,HIGH);
        digitalWrite(8,HIGH);
        break;

        case 6:   // Darstellung der Ziffer 6
        digitalWrite(2,HIGH);
        digitalWrite(3,LOW);
        digitalWrite(4,HIGH);
        digitalWrite(5,HIGH);
        digitalWrite(6,HIGH);
        digitalWrite(7,HIGH);
        digitalWrite(8,HIGH);
        break;

        case 7:   // Darstellung der Ziffer 7
        digitalWrite(2,HIGH);
        digitalWrite(3,HIGH);
        digitalWrite(4,HIGH);
        digitalWrite(5,LOW);
        digitalWrite(6,LOW);
        digitalWrite(7,LOW);
        digitalWrite(8,LOW);
        break;

        case 8:   // Darstellung der Ziffer 8
        digitalWrite(2,HIGH);
        digitalWrite(3,HIGH);
        digitalWrite(4,HIGH);
        digitalWrite(5,HIGH);
        digitalWrite(6,HIGH);
        digitalWrite(7,HIGH);
        digitalWrite(8,HIGH);
        break;

        case 9:   // Darstellung der Ziffer 9
        digitalWrite(2,HIGH);
        digitalWrite(3,HIGH);
        digitalWrite(4,HIGH);
        digitalWrite(5,HIGH);
        digitalWrite(6,LOW);
        digitalWrite(7,HIGH);
        digitalWrite(8,HIGH);
        break;

        case 16:   // Darstellung des Querstrichs
        digitalWrite(2,LOW);
        digitalWrite(3,LOW);
        digitalWrite(4,LOW);
        digitalWrite(5,LOW);
        digitalWrite(6,LOW);
        digitalWrite(7,LOW);
        digitalWrite(8,HIGH);
        break;
        
       }
     
   }



// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
   {
    return ( (val/10*16) + (val%10) );
   }


void watchConsole()
   {
    if (Serial.available())
       {      // Look for char in serial queue and process if found
        if (Serial.read() == 84)
           {      //If command = "T" Set Date
            set3231Date();
            get3231Date();
            Serial.println(" ");
           }
       }
   }
 
 
void set3231Date()
   {
    //T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year)
    //T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99)
    //Example: 02-Okt-15 @ 19:57:11 for the 3rd day of the week -> T1157193021015

    seconds = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.  
    minutes = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
    hours   = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
    day     = (byte) (Serial.read() - 48);
    date    = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
    month   = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
    year    = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
    
    Wire.beginTransmission(DS3231_I2C_ADDRESS);
    Wire.write(0x00);
    Wire.write(decToBcd(seconds));
    Wire.write(decToBcd(minutes));
    Wire.write(decToBcd(hours));
    Wire.write(decToBcd(day));
    Wire.write(decToBcd(date));
    Wire.write(decToBcd(month));
    Wire.write(decToBcd(year));
    Wire.endTransmission();
   }


void get3231Date()
   {
    // send request to receive data starting at register 0
  
    Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
    Wire.write(0x00); // start at register 0
    Wire.endTransmission();
    Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes

    if(Wire.available())
       {
        seconds = Wire.read(); // get seconds
        minutes = Wire.read(); // get minutes
        hours   = Wire.read();   // get hours
        day     = Wire.read();
        date    = Wire.read();
        month   = Wire.read(); //temp month
        year    = Wire.read();
       
        seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); // convert BCD to decimal
        minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111)); // convert BCD to decimal
        hours   = (((hours & B00110000)>>4)*10 + (hours & B00001111)); // convert BCD to decimal (assume 24 hour mode)
        day     = (day & B00000111); // 1-7
        date    = (((date & B00110000)>>4)*10 + (date & B00001111)); // 1-31
        month   = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
        year    = (((year & B11110000)>>4)*10 + (year & B00001111));
       }
    else
       {
        //oh noes, no data!
       }
 
    switch (day)
       {
        case 1:
        strcpy(weekDay, "Mo");
        break;
        case 2:
        strcpy(weekDay, "Di");
        break;
        case 3:
        strcpy(weekDay, "Mi");
        break;
        case 4:
        strcpy(weekDay, "Do");
        break;
        case 5:
        strcpy(weekDay, "Fr");
        break;
        case 6:
        strcpy(weekDay, "Sa");
        break;
        case 7:
        strcpy(weekDay, "So");
        break;
       }
   }



float get3231Temp()
   {
    //temp registers (11h-12h) get updated automatically every 64s
  
    Wire.beginTransmission(DS3231_I2C_ADDRESS);
    Wire.write(0x11);
    Wire.endTransmission();
    Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
 
    if(Wire.available())
       {
        tMSB = Wire.read(); //2's complement int portion
        tLSB = Wire.read(); //fraction portion
   
        temp3231 = (tMSB & B01111111); //do 2's math on Tmsb
        temp3231 += ( (tLSB >> 6) * 0.25 ); //only care about bits 7 & 8
       }
    else
       {
        //oh noes, no data!
       }
   
    return temp3231;
   }