23.09.2020, 11:51 AM 
(Dieser Beitrag wurde zuletzt bearbeitet: 23.09.2020, 11:54 AM von christianw..)
	
	
	
		Vielleicht funktioniert er ja mit Bootstrap. Also 5V über Diode an Vin, Vout ebenfalls über Diode vom Ausgang an Vin.
	
	
	
	
| 
				
				 
					Panaplex time
				 
			 | 
		
	
	
  
  
 .
 .
 .
	
 :// 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) );
}
 .