• .
  • Willkommen im Forum!
  • Alles beim Alten...
  • Du hast kaum etwas verpasst ;-)
  • Jetzt noch sicherer mit HTTPS
Hallo, Gast! Anmelden Registrieren


Panaplex time
#21
Vielleicht funktioniert er ja mit Bootstrap. Also 5V über Diode an Vin, Vout ebenfalls über Diode vom Ausgang an Vin.
 
Reply
#22
Möglicherweise. Aber bis 12V am Ausgang sollte er sowieso kein Problem haben, da mein 180V-Wandler erst bei 12V Strom saugt. Zwei DC-DC-Wandler hintereinander war vielleicht sowieso nicht meine beste Idee...

Ich glaub, ich nehme eine konventionelle, schwere Lösung. Alle Module der Steuerung durften heute mal "probeliegen". Es passt alles auf 90x150 mm:
   

Patchwork vom Feinsten  Weih .
 
Reply
#23
Jetzt weiss ich wieder, warum ich den Trafo noch nie verwendet habe. Leerlaufspannung am Ladeelko 37V! Das ist jenseits der Spezifikationen der nachgeschalteten Wandler. Also muss ein stabilerer (und grösserer) Ringkerntrafo ran, was die Platzplanung auf der Leiterplatte umwirft.

Mit 27V Leerlaufspannung bleibt es nun unter dem Limit von 30V, und die Spannungsversorgung steht.
- 180V / 30mA
- 5V / xA
- 3,7V Backup aus einer 18650 Zelle

   

Die Ladeschaltung aus Fernost für die Batterie war auf 1A Ladestrom eingestellt. Dabei waren die Chips auf dem Platinchen am Kochen. Ich brauche keine Schnellladung bei dem Projekt. Nach DB-Studium und mühsamem Austausch von Hühnerfutter lädt es nun mit nur 130mA. Alles bleibt kalt.

   
 
Reply
#24
Der "Designer" hat sich dabei auf das "Thermal Goldback" verlassen. Big Grin
 
Reply
#25
Und... noch den Dauertest unter Realbedingungen  Big Grin :

   

(24.09.2020, 02:55 PM)christianw. schrieb: Der "Designer" hat sich dabei auf das "Thermal Goldback" verlassen. Big Grin
Funktioniert ja, vielleicht muss das so sein. Ich steh mehr auf maximal handwarm Smile .
 
Reply
#26
Goldback = Foldback.. ! Big Grin
 
Reply
#27
Ich hab tatsächlich versucht, das zu googlen  lachend  motz  lachend .

Die Schaltpläne sind komplett (wobei Teil 1 eher ein Blockschaltbild ist). Man vergebe mir die Unübersichtlichkeit, bin Kicad-rookie.

Platine 1, zusammengestückelt aus Modulen:
   

Und, damit alles beisammen ist, die Schaltung der Anzeigeplatine:
   

Vielleicht sollte ich mich mal auf die Suche nach der Programmierung begeben, ich glaub 2014 war ich daran zugange...
 
Reply
#28
Wenn es dich weiter interessiert, KiCaD kann auch Subsheets, also Unterseiten für z.b. Funktionsblöcke. Die lassen sich auch dublizieren.
 
Reply
#29
Ja, das ist ein interessantes Konzept, was ich gerne ausprobieren würde. Bei diesem Projekt bin ich aber "durch"... Für grössere Projekte, und wenn man öfter Schaltpläne zeichnet, ist das bestimmt klasse. Wenn ich das beruflich machen würde, wäre "Funktionsblock" eines meiner Lieblingswörter  Big Grin .

Bin gerade bei mehrlagiger Steampunk-Verdrahtung der Lochrasterplatine  Smile .
 
Reply
#30
Fertig verdrahtet  Weih  lachend :
   

Das war sehr meditativ. Die Steuerplatine ist fertig, eine Rohfassung der Software geladen, die Uhr tickt.
   

Als nächstes eine Miniplatine für den Drehencoder zum Stellen. Bald  Confused .
 
Reply
#31
Herzlichen Glückwunsch. Smile

Als nächstes dann Mal so eine Klackeranzeige vom Bahnhof? So eine mit Pixeln wie man sie aus Funk und Fernsehen kennt?
 
Reply
#32
An das nächste mal denke ich noch nicht, bin ja erst halb durch. Und meine grosse Schwäche ist das Finish...
 
Reply
#33
Die Software ist fertig (soweit das geht ohne einen Test an der nicht vorhandenen Displayplatine). Falls jemand sowas gerne liest  klappe :
Code:
// 2020-09-25: Panaplex-Uhr mit hochgenauer RTC
// Version 0.1
// von kahlo (kahlo@stromrichter.org)
// Hardware: Teensy 2.0 ( https://www.pjrc.com/teensy/index.html )
// Hardware: Chronodot ( http://www.adafruit.com/products/255 )
// Hardware: Babcock SP-101 Panaplex displays ( https://www.industrialalchemy.org/articleview.php?item=2014 )
// Hardware: Drehencoder mit Druckschalter
// Programmierumgebung: Arduino ( http://arduino.cc/ )

#include <Wire.h>

volatile boolean one_sec_flag = true;
volatile boolean ten_sec_flag = true;
volatile boolean one_min_flag = true;
volatile boolean button_down = false;

volatile byte one_sec = 0;
volatile byte ten_sec = 0;
byte one_min = 0;
byte ten_min = 0;
byte one_hr = 0;
byte ten_hr = 0;

int SQW = 7;                  // 1Hz Rechteck-Signal vom Chronodot an Pin 7
volatile int Pushbutton = 8;  // Druckschalter des Drehenkoders ist an Pin 8, der 2. Kontakt an Masse
int PB_X = 22;                // Drehschalter des Drehenkoders sind an Pin 22 und 23, der 3. Kontakt an Masse
int PB_Y = 23;
boolean BX;                   // Drehschalter
boolean BY;                   // Drehschalter
boolean BX_old;               // Drehschalter

volatile int set_level = 0;   // Mode of operation (0-normal, 1-set hours, 2-set minutes)
int set_change = 0;
int seconds = 0;
int minutes = 0;
int hours = 0;

int glow_M = 10;   // Pin10 Blank minutes and seconds beim Stellen der Stunde
int glow_H = 9;    // Pin 9 Blank hours beim Stellen der Minute
int LED_Pin = 11;  // Pin 11 steuert den internen LED-Punkt auf dem Teensy-Bord
boolean LED_status = LOW;


void setup()
{
 DDRB = B00001111;   // Definiert B0..B3 als Output, B4..B7 als Input
                     // Das werden die BCD-Lines zum Display
 Wire.begin();
 Wire.beginTransmission(104);  // address DS3231
 Wire.write(0x0E);             // select register
 Wire.write(0b01000000);       // register bitmap, schaltet das 1Hz-Rechteck ein (siehe DB vom DS3231)
 Wire.endTransmission();

 pinMode(21, OUTPUT); // Definiert F0,F1,F4..F7 als Output, das sind die 6 Latches
 pinMode(20, OUTPUT);
 pinMode(19, OUTPUT);
 pinMode(18, OUTPUT);
 pinMode(17, OUTPUT);
 pinMode(16, OUTPUT);
 
 pinMode(glow_H, OUTPUT);                   // Pin10 für blanking beim Stellen der Stunde
 pinMode(glow_M, OUTPUT);                   // Pin 9 für blanking beim Stellen der Minute
 pinMode(LED_Pin, OUTPUT);
 pinMode(SQW, INPUT_PULLUP);                // Pin7 als Eingang definieren und den internen Pullup aktivieren
 pinMode(Pushbutton, INPUT_PULLUP);         // Pin8 als Eingang definieren und den internen Pullup aktivieren
 pinMode(PB_X, INPUT_PULLUP);               // Pin22 als Eingang definieren und den internen Pullup aktivieren
 pinMode(PB_Y, INPUT_PULLUP);               // Pin23 als Eingang definieren und den internen Pullup aktivieren  
 attachInterrupt(2, Hz_interrupt, FALLING); // Interrupt 2 an Pin 7 aktivieren
 attachInterrupt(3, push, CHANGE);
 BX = digitalRead(PB_X);
 BX_old = digitalRead(PB_X);
 digitalWrite(glow_H, HIGH);
 digitalWrite(glow_M, HIGH);
}
 
void loop()
{
 switch (set_level) {
   case 0: // normal operation
     if (one_sec_flag == true) {
       display_one_sec();
       one_sec_flag = false;
       digitalWrite(LED_Pin, LED_status); // 2s Blinker auf dem Teensy
       LED_status = !LED_status;          // 2s Blinker auf dem Teensy
       if (ten_sec_flag == true) {
         display_ten_sec();
         ten_sec_flag = false;
         if (one_min_flag == true) {
           get_time();            // alle Minute wird die volle Zeitangabe aus der RTC geklaubt
           display_one_min();
           display_ten_min();
           display_one_hr();
           display_ten_hr();
           LED_status = HIGH;      // Beim Minutenwechsel soll die LED angehen (nicht aus...)
           one_min_flag = false;
         }
       }
     }
     break;
   case 1: // set hours
     detachInterrupt(2);            // Interrupt 2 an Pin 7 deaktivieren (1Hz-Interrupt)
     digitalWrite(glow_M, LOW);     // Minuten- und Sekundendisplay abschalten
     hours = (ten_hr * 10) + one_hr;
     BX = digitalRead(PB_X);
     if (BX != BX_old) {            // Drehschalter wurde gedreht
       delayMicroseconds(1000);     // Prellschutz
       BX = digitalRead(PB_X);
       if (BX != BX_old) {          // Drehschalter wurde wirklich gedreht... ;)
         set_change = 1;
         hours = (ten_hr * 10) + one_hr;
         BY = digitalRead(PB_Y);    // Leitung A hat ausgelöst, wie sieht Leitung B aus?
         if (BX != BY) {            // Linksdrehung!
           if (hours < 23) { hours++;} else { hours = 0;}
         }
         else {                     // Rechtsdrehung!
           if (hours > 0) { hours--;} else { hours = 23;}
 }
         ten_hr = hours/10;
         one_hr = hours-(ten_hr*10);    
         display_one_hr();
         display_ten_hr();
         BX_old = BX;
       }
     }
     break;
   case 2:  // set minutes
     digitalWrite(glow_M, HIGH);    // Minuten- und Sekundendisplay anschalten
     digitalWrite(glow_H, LOW);     // Stundendisplay abschalten
     BX = digitalRead(PB_X);
     if (BX != BX_old) {            // Drehschalter wurde gedreht
       delayMicroseconds(1000);     // Prellschutz
       BX = digitalRead(PB_X);
       if (BX != BX_old) {          // Drehschalter wurde wirklich gedreht... ;)
         set_change = 2;
         minutes = (ten_min * 10) + one_min;
         BY = digitalRead(PB_Y);    // Leitung A hat ausgelöst, wie sieht Leitung B aus?
         if (BX != BY) {            // Linksdrehung!
           if (minutes < 59) { minutes++;} else { minutes = 0;}
         }
         else {                     // Rechtsdrehung!
           if (minutes > 0) { minutes--;} else { minutes = 59;}
 }
         ten_min = minutes/10;
         one_min = minutes-(ten_min*10);    
         display_one_min();
         display_ten_min();
         BX_old = BX;
       }
     }
     break;
   case 3:  // set seconds to 0 and goto normal operation
     seconds = 0;
     set_time();
     get_time();
     digitalWrite(glow_H, HIGH);
     digitalWrite(glow_M, HIGH);
     set_level = 0;
     attachInterrupt(2, Hz_interrupt, FALLING);
 }  
}
 
void get_time()
{
 Wire.beginTransmission(104);
 Wire.send(0);              //set register to 0
 Wire.endTransmission();
 Wire.requestFrom(104, 3);  //get 3 bytes (seconds,minutes,hours);
 seconds = Wire.receive();
 minutes = Wire.receive();
 hours = Wire.receive();

 one_sec = (seconds & 0b00001111);      // convert BCD to pseudodecimal
 ten_sec = ((seconds & 0b11110000)>>4); // convert BCD to pseudodecimal
 one_min = (minutes & 0b00001111);      // convert BCD to pseudodecimal
 ten_min = ((minutes & 0b11110000)>>4); // convert BCD to pseudodecimal
 one_hr = (hours & 0b00001111);         // convert BCD to pseudodecimal
 ten_hr = ((hours & 0b00110000)>>4);    // convert BCD to pseudodecimal
}

void display_ten_sec()
{
 PORTB = ten_sec;
 digitalWrite(20, 0);     // Latch2 öffnen und die Zehner schreiben
 digitalWrite(20, 1);     // Latch2 schliessen
}

void display_one_sec()
{
 PORTB = one_sec;
 digitalWrite(21, 0);     // Latch1 öffnen und die Einer schreiben
 digitalWrite(21, 1);     // Latch1 schliessen
}

void display_ten_min()
{
 PORTB = ten_min;
 digitalWrite(18, 0);     // Latch2 öffnen und die Zehner schreiben
 digitalWrite(18, 1);     // Latch2 schliessen
}

void display_one_min()
{
 PORTB = one_min;
 digitalWrite(19, 0);     // Latch1 öffnen und die Einer schreiben
 digitalWrite(19, 1);     // Latch1 schliessen
}

void display_ten_hr()
{
 PORTB = ten_hr;
 digitalWrite(16, 0);      // Latch4 öffnen und die Zehner schreiben
 digitalWrite(16, 1);      // Latch4 schliessen
}

void display_one_hr()
{
 PORTB = one_hr;
 digitalWrite(17, 0);     // Latch3 öffnen und die Einer schreiben
 digitalWrite(17, 1);     // Latch3 schliessen
}

void Hz_interrupt()
{
 one_sec_flag = true;
 if (one_sec < 9) {
   one_sec++;
 } else {
   one_sec = 0;
   ten_sec_flag = true;
   if (ten_sec < 5) {
     ten_sec++;
   } else {
     ten_sec = 0;
     one_min_flag = true;
   }
 }
}

void push() // ISR
{
 delayMicroseconds(10000);              // Das funktioniert in einer ISR im Gegensatz zu delay
 if (digitalRead(Pushbutton) == 0) {    // Wirklich gedrückt? Prellschutz.
   button_down = true;
   set_level++;  // 0 - normal, 1 - set hours, 2 - set minutes, 3 - set seconds to 0 and goto normal operation
 }
 while (button_down == true) {
   if (digitalRead(Pushbutton) == 1) {  // Wieder losgelassen?
     delayMicroseconds(10000);
 if (digitalRead(8) == 1) {           // Wirklich losgelassen?
button_down = false;
 }
   }
 }
}

void set_time()
{
 switch(set_change) {
   case 0:  // Keine Änderung?
     break;
   case 1:  // Nur an der Stunde gedreht - Minuten und Sekunden unverändert
     Wire.beginTransmission(104);
     Wire.send(2);
     Wire.send(decToBcd(hours));
     Wire.endTransmission();
     break;
   case 2:  // Alles verstellt - alles gestellt...
     Wire.beginTransmission(104);
     Wire.send(0);
     Wire.send(decToBcd(seconds));
     Wire.send(decToBcd(minutes));
     Wire.send(decToBcd(hours));
     Wire.endTransmission();
 }
 set_change = 0;
}

byte decToBcd(byte val)
{
 return ( (val/10*16) + (val%10) );
}
Sorry for the Mischmasch of English und Deutsch  Weih . Bin schon länger aus D weg, und Englisch ist manchmal einfach knackiger.
 
Reply
#34
Hat jemand von euch einen guten Tip für einen Platinenservice? Hab ich noch nie gemacht...
--
Edit: Ich habe ALLPCB probiert. 5 Platinen muss man abnehmen... Soviele Panaplex-Displays habe ich gar nicht. Und wenn ein Fehler drin ist, dann ist's 5mal falsch lachend .
 
Reply
#35
Ich mag PCBCart...die Proto-Platinen sind mMn. qualitativ hochwertig, und auch mit den Ingenieuren am anderen Ende (der Welt) hatte ich bisher nur gute Erfahrungen.
Wenn das PCB ohne Änderungen nochmal bestellt wird, fällt meines Wissens nach auch ein bestimmer Anteil Einmalkosten weg.

(Edit: grad nochmal gecheckt, die machen das auch erst ab 5. Nehme von da her alles zurück.)
 
Reply
#36
JLCPCB kann ich empfehlen. Ich denke Christian wird mir ebenfalls zustimmen.
 
Reply
#37
Ja, JLC wäre auch meine Empfehlung, die machen auch schwarz matt ohne (nennenswerten) Aufpreis.
 
Reply
#38
Ach menno, wäre ich mal nicht so ungeduldig gewesen. JLC ist echt besser (Preis, Lieferzeit, Discount on first order).

motz

Rolleyes

Big Grin
 
Reply
#39
jau, bin auch seit einiger Zeit bei JLCPCB. Schnell, zuverlässig, guter e-mail contact, Preis & Qualität ok. Was will man mehr?
...mit der Lizenz zum Löten!
 
Reply
#40
JLCPCB hätte ich auch gesagt....wenn du gewartet hättest.  Tongue
    Don't worry about getting older.  You're still gonna do dump stuff...only slower
 
Reply