1 Röhre Nixie Uhr

halle community,

seid einiger zeit beschäftigt mich das thema Nixie tubes und irgendwie hänge ich in meinem kopf selbst fest,

ich habe vor einiger zeit einige anleitung gefunden so eine uhr zu bauen (6 röhren mit 6 Chips, oder 6 röhren mit 6 chips und 3 74hc595)
nach einigen versuchen wusste ich zwar wie das funktioniert aber irgendwie erscheint es mir falsch einfach nur zu kopieren ich will es ehr verstehen.

so nun zu meiner frage also ich habe einen uno und einen k155id1 chip und eine röhre

die belegung und steuerung des chips ist klar

allerding ist mir nicht klar wie ich mit einer rtc1307 zb die zeit ausgeben soll....
es ist wie eine barikade im kopf....

hier mal mein code zur steuerung des chips.....

ich hoffe ihr könnt mir helfen denn dieser knoten im kopf macht mich wahnsinnig

void setup() {
  
  //D2 => D
  //D3 => C
  //D4 => B
  //D5 => A
    DDRD = DDRD | B00111100;

 //                       DCBA
 //                0- B00 0000 00
 //                1- B00 0001 00
 //                2- B00 0010 00
 //                3- B00 0011 00
 //                4- B00 0100 00
 //                5- B00 0101 00
 //                6- B00 0110 00
 //                7- B00 0111 00
 //                8- B00 1000 00
 //                9- B00 1001 00

                 
}

void loop() {
  int i;                      //Jede Sekunde wird der Zustand eins weiter geschalten von 0 bis 9
  while(true){
    ausgabe(i);
    delay(1000);
    i++;
    if (i >= 10){
      i = 0;
    }
  }
}

void ausgabe(int eingabe){
  switch (eingabe){
    case 0: PORTD = B00000000; //                00 0000 00
   // delay(333);      
            break;
    case 2: PORTD = B00001000; //                00 0010 00
  //  delay(333);       
            break;
    case 3: PORTD = B00001100; //                00 0011 00
   // delay(333);        
            break;
    case 4: PORTD = B00010000; //               00 0100 00
   // delay(333);        
            break;
    case 5: PORTD = B00010100; //               00 0101 00
   // delay(333);        
            break;
    case 6: PORTD = B00011000; //               00 0110 00
  //  delay(333);        
            break;
    case 7: PORTD = B00011100; //               00 0111 00
   // delay(333);        
            break;
    case 8: PORTD = B00100000; //               00 1000 00
   // delay(333);       
            break;
    case 9: PORTD = B00100100; //               00 1001 00
   // delay(333);       
            break;
        default: break;
  }  
}

Ich als Nixie Uhren Fan muss mal was dazu schreiben.
Also erstes musst du dich von der DS1307 lösen und eine DS3231 nehemen da die 1307 sehr gerne sehr falsch läuft.
Ich habe sie selber in mehreren meiner Uhren drin und nur in meiner Nixie Uhr läuft sie halbwegs genau in den anderen Uhren habe ich bis zu 2-3min im Monat!!! falsch.

Herangehensweise:

  1. Lernen RTC Uhr auslesen mit Ausgabe auf dem seriellen Port.
  2. Konzept der Darstellung er arbeiten.
  3. Konzept erst mit serieller Augabe testen
  4. Umsetzten auf die BCD- Darstellung

Mein Vorschlag:
Die 4 Ziffern werden mit kurzen abständen hintereinder auf der Röhre dargestllt (z.B. 500ms pause zwischen den Angezeigen stellen dann 3-4s pause und wiederholung.

Da der k155id1 mit BCD Code angesteuert wird (einfache Binärzahl von 0 bis9) kannst Du einfach 4 Bits um 2 Bit verschieben und mittels OR mit den Port verknüpfen. So braucht es nur 1 Zeile und nicht den ganzen Switch-Block.

Das Setzen / Auslesen der RTC wird in vielen Beispielen beschrieben und es gibt auch viele Bibliotheken dazu.
Einfach ein bißchen suchen.

Dann extrahierst Du aus den Minuten und Stunden die einzelnen Ziffern und stellst diese nacheinander dar.

Grüße Uwe

hallo uwe du meinst odieren???
ja ich habe davon schoneinmal gehört
als beispiel: 00000001 <<4 00010000?
habe ich das so richtig verstanden?
das erscheint mir aber im ersten moment doch recht schwierig wenn ich mir vorstelle wie das aussehen sollte

zumal verstehe ich nicht wie ich da aus 00000000 für die null 00001100 für die 3 machen soll…

das thema rtc ist glaube zum "verstehen gerade ersteinmal nebensache oder sehe ich das falsch? auf eine andere kann ich doch später umsteigen

als ausgabe hatte ich mir das mal so gedacht

stunden_zehner = tm.Hour / 10; //aufteilung der Stunden erste zahl
stunden_einer = tm.Hour - stunden_zehner *10; //aufteilung der Stunden zweite zahl

minuten_zehner = tm.Minute / 10; //aufteilung der Minuten erste zahl
minuten_einer = tm.Minute - minuten_zehner * 10; //aufteilung der Minuten zweite zahl

sekunden_zehner = tm.Second / 10; //aufteilung der Sekunden erste zahl
sekunden_einer = tm.Second - sekunden_zehner * 10; //aufteilung der Sekunden zweite zahl

gibt es denn ein beispiel wo ich das eventuell besser verstehen lerne? denn die ausgabe im monitor ist ja recht simpel aber sobald ich das auf ein anderes medium übertragen möchte blockiert es

Verwende %.

stunden_zehner = tm.Hour / 10; //aufteilung der Stunden erste zahl
stunden_einer = tm.Hour %10; //aufteilung der Stunden zweite zahl

Da Du die Pins 2 bis 5 des Ports D verwendest:

PORTD = PORTD & B11000011 | (stunden_zehner << 2); //Bit löschen und neu schreien

zumal verstehe ich nicht wie ich da aus 00000000 für die null 00001100 für die 3 machen soll…

Das verstehe ich dann nicht. Wieso mußt Du von 0 auf 3 kommen?

Ich würde die Sekunden nicht anzeigen da 6 Ziffern nacheinander die Lesbarkeit sehr reduziert.

Grüße Uwe

ich glaube du verstehst mich gerade falsch

was ich meine ist wen die zahl Null 0000 wie mache ich eine 0110 daraus

Das hast du doch schon in deinem Eingangspost mit dem switch case aus deinem Post gemacht. Ist für Anfänger das einfachste.
Du definierst 10 cases und für die Ziffern 0-9. Die schreiben die dann in ein “Byte” dein Bitmuster.
Gruß
DerDani

byte ausgabe(int eingabe){
byte puffer;
  switch (eingabe){
    case 0: puffer=B0000; //                00 0000 00
            break;
    case 1:
            puffer=B0001;
            break;
    case 2: puffer = 0010; //                00 0010 00
           break;
    case 3: puffer = B1100; //                00 0011 00
            break;
    case 4: puffer = B0100; //               00 0100 00
           break;
    case 5: puffer = B0101; //               00 0101 00
            break;
    case 6: puffer = B0110; //               00 0110 00
            break;
    case 7: puffer = B0111; //               00 0111 00
            break;
    case 8: puffer = B1000; //               00 1000 00
            break;
    case 9: PORTD = B1001; //               00 1001 00
            break;
        default: break;
  }
return puffer;
}

Diese funktion gibt die wenn du die Ziffer übergibst das Darstellungsmuster an

PORTD=(ausgabe(stunden_zehner)<<2);

Gruß
DerDani

Ich habe zufällig das gleiche Equipment aufgebaut… Projekt ist allerdings schon fertig.

Vielleicht hilfts ja.

Da ist noch ein bisschen sonst nutzloses bitshifting bei, so konnte ich einfach den Autorouter drüberschicken und dann die 4 BCD Pins zuweisen. (Singlelayer @home einfacher.)

EDIT: ist schon älter der Code :slight_smile: Ich sehe gerade das ich mir 2 Funktionen mit MSBfirst hätte sparen können… ich war da gerade in der Bitshifting Lernphase… wohl etwas zu eifrig :wink:

#include <DS3232RTC.h> //http://github.com/JChristensen/DS3232RTC
#include <Time.h> //http://www.arduino.cc/playground/Code/Time
#include <Wire.h> //http://arduino.cc/en/Reference/Wire (included withArduino IDE)

int latchPin = 10;
int clockPin = 11;
int dataPin = 12;
int enablePin = 9;
int hour_adjust=8;
void setup() {

  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(enablePin, OUTPUT);
  pinMode(hour_adjust, INPUT);
  digitalWrite(latchPin, 0);
  digitalWrite(enablePin, 1); //make sure data isn't latched
  digitalWrite(hour_adjust, HIGH); 
  if(digitalRead(hour_adjust)==HIGH)
    setSyncProvider(RTC.get);
  else
    setSyncProvider(wintertime);
  if (timeStatus() != timeSet)
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");
  setSyncInterval(30);
  // RTC.set(1516773120+60);
}
time_t wintertime(){
  time_t time=RTC.get()+3600;
  return time;
}
long mylastmillis=0;
// long myinterval=30000;
int mylasthour=0;
int mylastminute=0;
void loop() {


  mylastmillis=millis();
  if(mylasthour!=hour()|| mylastminute!=minute())            
  {
    settime(hour(), minute(), 0);
    mylasthour=hour();
    mylastminute=minute();
  }
}


void settime(unsigned int Stunden, unsigned int Minuten, unsigned int temp) {
  shiftOut(dataPin, clockPin, LSBFIRST,swapNibbles(reverse(mysort(uint2bcd(Minuten)))));
  shiftOut(dataPin, clockPin, LSBFIRST,swapNibbles(reverse(mysort(uint2bcd(Stunden)))));
  digitalWrite(latchPin, 1);                // flick the latch to putthe data on the output pins
  delay(100);
  digitalWrite(latchPin, 0);
  delay(100);
}
unsigned char reverse(unsigned char b) {
  b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
  b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
  b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
  return b;
}
static unsigned int uint2bcd(unsigned int ival)
{
  return ((ival / 10) << 4) | (ival % 10);
}
int MeineFolge[9] = {
  2, 1, 0, 3, 6, 5, 4, 7};
unsigned int mysort(unsigned int ival)
{
  uint8_t mytempival = 0;
  for (int i = 0; i < 7; i++) {
    if (bitRead(ival, i) == 1) {
      bitWrite(mytempival, MeineFolge[i], 1);

    }
  }

  return mytempival;
}
unsigned char swapNibbles(unsigned char x)
{
  return ( (x & 0x0F) << 4 | (x & 0xF0) >> 4 );
}

phillert:
ich glaube du verstehst mich gerade falsch

was ich meine ist wen die zahl Null 0000 wie mache ich eine 0110 daraus

Hast Du die Kathoden der NIXIE zufällig an die Ausgänge des k155id1 geschaltet? Ansonsten verstehe ich nicht wieso Du eine 3 brauchst um null darzustellen.

Ansonsten macht man das am einfachsten mit einem Array um von einer Zahl (inputzahl) zur anderen (outputzahl) zu kommen und keine Regel dahintersteht. Da braucht es nicht 35 Zeilen switch.

feld[10] = {1,2,3,5,6,7,9,0,4,8}; // 0->1; 1->2;.. 4->6; ecc
outputzahl = feld [inputzahl];

Grüße Uwe

wie müsste denn der code aussehen damit ich eine 1 röhren uhr hinbekomme....
ich hänge mich absolut an dem code auf
ich denke ich habe das problem das ich das mit der ausgabe der zeichen nicht wirklich verstehe

mir würde erstmal genügen wenn ich weiß wie ich mein switch case als grundlage nutzen könnte

Ach moment, Du willst eine Uhr mit 1 Röhre programmieren

EDIT: Ich habe 4094 benutzt, die reichen für Logik Level immer..
Hier nochmal mein ganzes Projekt: Nixie Projekt

Oder eine 1 Röhren Anzeige von 1 Ziffer? Siehe an meinem Beispielcode.. Shiftout für das zweite Schieberegister rausnehmen, ist dann nur für 1!

mach doch lieber 1 Uhr mit 2 Ziffern und einem HC595.. das ist sogar einfacher.

  1. interne Uhr mit der RTC Synchronisieren. (mit der richtigen lib automatisch)

  2. immer wenn sich Sekunden ändern if(oldsec!=second()tueblabla) einen neuen Shiftout auf die HC595.

  3. 2 Röhren sind einfacher, da man einen zweistelligen INT nach Dual-BCD casten und diesen direkt schieben kann. (Im optimalen Fall, siehe bin2bcd in meinem Beispielcode)

  4. Bis auf wenige optimierugnen die einen dann wieder fordern fertig.

ich denke ich habe das problem das ich das mit der ausgabe der zeichen nicht wirklich verstehe

Du möchtest sowas machen:

Der 74141 aka k155id1 hat 10 Ausgänge, einen für jede Kathode der Nixie. Die Anode geht über einen Strombegrenzungswiderstand auf die Versorgungsspannung (Je nach Nixietyp zwiscehn 150-250V DC)
Der 74141 aka k155id1 hat 4 Eingänge. Auf diese gibst d 4 Bit den BCD Code (Binärzahl von 0 bis 9).
Du brauchst einen 74141 aka k155id1 pro NIXIE. Bei einer NIXIE also einen 74141 aka k155id1.

Der Arduino liest die RTC und gibt nach der Sequenz die Du willst die Einer und Zehnerstellen der Minuten und Stunden nacheinander mit Pausen aus. Der Arduino hat genug Ausgänge um direkt den 74141 aka k155id1 anzusteuern. Bei 4 oder 6 Ziffern bzw 74141 aka k155id1 brauchst Du dann Port Expander oder Shiftregister für die benötigte Anzahl von Ausgängen.

Grüße Uwe

Der TO hat nur verkehrt gefragt konnte ich jetzt feststellen.

Er wollte lediglich wissen wie der von ihm im Eröffnunfsfred gezeigte Beispielcode funktioniert weil er nicht hinterkommt.. bitte an nur einer Röhre.

Darauf könnte man antworten:

Das ist kein direkter Arduino Code, siehe andere Tutorials:

AVR-GCC Grundlagen IO Port

EDIT: Ich bin da am Anfang auch etwas durcheinander gekommen weil ja D4-D7 gleichzeitig im Mapping auch D4-D7 sind und ich dachte da wäre der HC595 dran :-X :-X

Nochmal als Beispiel für den TO, das passt halt nur von D4-D7, für Pins 9,10,11 müsste aus DDRD/PORTD folgendes werden DDRB/PORTB (PD=PORT D, PB= Port B)

Atmega168PinMap2.png

Atmega168PinMap2.png