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) );
}