Akkorduhr

Stunden




void printStdSchritt( byte schritt ) {
  static const char *schrittTexte[] = {"REF_STD_KELLE", "REF_STD_GEFUNDEN", "REF_STD", "REF_STD_SUCHEN", "WARTEN_STD", "STD_KELLE_RUNTER", "S_ZEIT", "STD_KELLE_RAUF" };
  
}

// Rückgabe wert ist die aktuelle Position ( wenn im Zustand WARTEN )
// oder -1 wenn in Bewegung
int stundenRing() {
  byte minute, hour;
 static byte altStunden = 12, posStunden = 0;
  enum class Schritt : byte {REF_CHK_KELLE,REF_FREI_KELLE,REF_STD_KELLE, REF_STD_GEFUNDEN, REF_STD, REF_STD_SUCHEN, WARTEN_STD, STD_KELLE_RUNTER, STD_ZEIT, STD_KELLE_RAUF};
  static Schritt schritt = Schritt::REF_CHK_KELLE, altSchritt = Schritt::REF_STD;
#ifdef DEBUG
  if ( schritt != altSchritt ) {
    // Debugging: Ausgabe wenn Statuswechsel
    printStdSchritt((byte)schritt);
    altSchritt = schritt;
  }
#endif

  // Erkennen der Referenzpunkte ( unabhängig von der FSM )
  // Kellen-Referenz
  if (Taster.pressed(refStdKellPin)) {   // Wenn Referenzpunkt erreicht, Bewegung anhalten und Nullpunkt setzen.
    StepMinuten.setZero(10);  // Nullpunkt etwas hinter den referenzpunkt setzen, um ihn auch bei Schrittverlusten sicher zu erreichen
    StepMinuten.write(NULLPOSMINUTEN);
    
  }
  // Ring-Referenz
  if (Taster.pressed(refStdPin)) {
    StepMinuten.setZero(NULLPOSMINUTEN);
    StepMinuten.write(0);
    
  }


  switch (schritt) {

     case Schritt::REF_CHK_KELLE:
      // Prüfen ob Kelle in der Lichtschranke steht
      digitalWrite(refMinPin, LOW);                 // Stepperspulen anschalten
      if ( Taster.state(refStdKellPin ) ) {
        // Kelle aus LS ausfahren
     
        StepMinuten.write(-90);
        schritt = Schritt::REF_FREI_KELLE;
      } else {
       
        // Kelle Refpunkt suchen
        schritt = Schritt::REF_STD_KELLE;
    }
      break;

   case Schritt::REF_FREI_KELLE:
      // LS freifahren
      // etwas über LS Grenze hinausfahren
      if ( Taster.released(refMinPin) ) StepMinuten.doSteps(-300 );
      if ( !StepMinuten.moving() ) schritt = Schritt::REF_STD_KELLE;
      
      break;
   case Schritt::REF_STD_KELLE:

      StepMinuten.write(180);
      schritt = Schritt::REF_STD_GEFUNDEN;
       // Bewegung Kelle starten.
      break;

    case Schritt::REF_STD_GEFUNDEN:
      if (Taster.state(refStdKellPin)) {   // Wenn Referenzpunkt erreicht, (Kelle unten ) Referenzpunkt Ring suchen
       
        schritt = Schritt::REF_STD;
      }
      break;

    case Schritt::REF_STD:

  
      StepMinuten.write(390);
      schritt = Schritt::REF_STD_SUCHEN;
      break;

   case Schritt::REF_STD_SUCHEN:

      if (Taster.state(refStdPin)) {
       
        schritt = Schritt::WARTEN_STD;
      }
      break;
    case Schritt::WARTEN_STD:

      // Das Abschalten wurde bereits in STD_KELLE_RAUF gemacht

      if ( stellenAktiv ) {
        // im Einstellmodus wird das vorrücken über den Stelltaster ausgelöst
          posStunden = altStunden+Taster.clicked(stellStd);  // Bei einfach Klick wird eins, bei Doppelklick 2 addiert
          if ( posStunden > 11 ) posStunden = 0;
      } else {
       
        // im Normalbetrieb die Uhr abfragen
        readDS3231time(minute, hour);
        posStunden = hour > 11 ? hour - 12 : hour;     //posStunden = minute > 11 ? minute - 12 : minute; // nur zum Testen
      }
      if (altStunden != posStunden) {
        debug( "Std: "); displayTime(0, minute, hour);
        debug("altStunden: "); debug(altStunden); debug('\t'); debug("posStunden: "); debug(posStunden); debug('\n');
        altStunden = posStunden;
        digitalWrite(refMinPin, LOW);                 // Stepperspulen anschalten
        StepMinuten.write(0);                // Stundenkelle runter
        schritt = Schritt::STD_KELLE_RUNTER;
      }
      break;

    case Schritt::STD_KELLE_RUNTER:

   if (Taster.pressed(refStdKellPin)) {    // Referenzieren der Stundenkelle/Hochdrücker im Betrieb
        StepMinuten.setZero();
        }

   if (!StepMinuten.moving()) {
        // Ereignis: die Stundenkelle ist unten
        // Aktion: Beweegung des Stundenrings starten

        if (posStunden == 0) {
          StepMinuten.write(360);
          schritt = Schritt::STD_ZEIT;
        }
        else {
          StepMinuten.writeSteps(30 * posStunden);
          debug("Stunden-Winkel: "); debugln(30 * posStunden);
          // if (posStunden == 0) StepStunden.setZero();
          schritt = Schritt::STD_ZEIT;
        }
      }

      break;
    case Schritt::STD_ZEIT:

      if (!StepMinuten.moving()) {
        // Ereignis: Bewegung des Rings beendet
        // Aktion: Kelle hochfahren
        StepMinuten.write(-59);   // Stundenkelle hoch

        //if (posStunden == 0) StepStunden.setZero();

        schritt = Schritt::STD_KELLE_RAUF;
      }
      break;

    case Schritt::STD_KELLE_RAUF:
      if (!StepMinuten.moving())
      { // Ereignis: die Stundenkelle ist oben
        // Aktion: Stepper abschalten
        digitalWrite(refMinPin, HIGH);
        schritt = Schritt::WARTEN_STD;
      }
      break;
  }
  if ( schritt == Schritt::WARTEN_STD ) return altStunden;
  else return -1;
}

Weiss nicht wie man hier auf der neuen Seite quotet.

Hast Du denn jetzt eine kompilierbare Variante, bei der das Referenzieren funktioniert? Das fehlt mir irgendwie noch.

Wodurch werden denn die ‘Beater’ ausglöst? Im Grundsatz entspricht das ja in etwas der Stelle bei der Farbuhr, bei der die Kelle wieder hochgehoben wird. Also nachdem der Stepper auf die neue Minutenposition gestellt wurde. genau!
Verstehe ich das richtig, dass dann immer erst ein ‘fester’ Klöppel angeschlagen wird, und dann der auf der Minutenposition? Der feste Klöpel wird erst gleichzeitig mit dem Stundenklöpel angeschlagen und etwa 1 sekunde später zusammen mit dem Minutenklöpel.
Wenn ich mich recht erinnere, wolltest Du das aber auch nachträglich noch manuell auslösen können? Dann müsstest Du das in einer eigenen Schrittkette realisieren, die dann sowohl aus der Minuten-Kette, als auch manuel gestartet werden kann. jawohl so sollte es sein

Den gewünschten Text markieren, und dann auf den erscheinenden 'Zitat' -Button klicken. Damit dieser Button erscheint, muss man es aber erst im Profil freischalten ( unter Einstellungen->Oberfläche->Andere: 'Aktiviere Zitatantwort...' ).

Mhmm ... gibt bei mir aber auch noch Fehler und einige Warnungen :confused:

ups, die sollte aber keine Fehlermeldungen mehr bringen.

ino


// Debugging
#define DEBUG Serial // Diese Zeile als Kommentar, wenn keine Ausgabe auf dem seriellen Monitor gewünscht ist.
#ifdef DEBUG
#define debug(...) DEBUG.print(__VA_ARGS__)
#define debugln(...) DEBUG.println(__VA_ARGS__)
#define debugbegin(...) DEBUG.begin(__VA_ARGS__)
#define SECPERMIN 4  // Sekunden pro Minute - zur Beschleunignung beim Testen

#else
#define debug(...)
#define debugln(...)
#define debugbegin(...)
#endif

#include "Wire.h"
constexpr int DS3231_I2C_ADDRESS = 0x68; // Die Bibliothek möchte int!
#include <MobaTools.h>
MoToTimer Zeitlesen;

constexpr uint32_t PAUSE = 1000;


constexpr uint16_t NULLPOSMINUTEN = 200;  // Abstand Referenzpunkt ( LS ) zum Nullpunkt
constexpr uint16_t NULLPOSSTUNDEN = 100;

const byte dirPin       = 4;
const byte stepPin      = 5;
const byte enaPin       = 6;

//const byte refMinPin       = 2;





// Input-Pins ( Lichtschranken und Zeitsetz-Taster ) über MoToButtons verwalten
const byte inPins[] = { 2, 3, 4, 5, A1, A2, A3 };
const byte pinAnzahl = sizeof( inPins );
enum : byte { refMinPin, refStdPin, refMinKellPin, refStdKellPin, stellMin, stellStd, stellMode };
#define MAX8BUTTONS     // optional, spart Speicherplatz ( Standard ist maximal 16 Taster )
MoToButtons Taster ( inPins, pinAnzahl, 20, 2000 );  // Einrichten der Tasterverwaltung

//Variable für das Uhr stellen
boolean stellenAktiv;
const byte stellenLED = A0;

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

//Convertiert Dezimalzeichen in BCD Zeichen.
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Zeit von DS3231 holen
void readDS3231time( byte &minute, byte &hour)
{ // Die DS3231 wird nur jede 500ms abgefragt, sonst werden die
  // gespeicherten Zeiten zurückgegeben
  static byte DShour, DSmin, DSsec;
  if (!Zeitlesen.running()) {
    Zeitlesen.setTime( PAUSE );
    Wire.beginTransmission(DS3231_I2C_ADDRESS);
    Wire.write(0); // set DS3231 register pointer to 00h
    Wire.endTransmission();
    Wire.requestFrom(DS3231_I2C_ADDRESS, 3);
    // request three bytes of data from DS3231 starting from register 00h
    DSsec = bcdToDec(Wire.read() & 0x7f);
    DSmin = bcdToDec(Wire.read());
    DShour = bcdToDec(Wire.read() & 0x3f);

  }
   
#ifdef SECPERMIN
    if ( DSsec >= SECPERMIN && DSsec < 59 ) {
      DSsec = 59;
      Wire.beginTransmission(DS3231_I2C_ADDRESS);
      Wire.write(0);              // Start ab Register 0 (Sekunden )
      Wire.write(decToBcd(DSsec));    // Sekunden auf 59 setzen für vorzeitigen Minutensprung
      Wire.endTransmission();
    }
#endif
 
  hour = DShour;
  minute = DSmin;
}
// Anzeige im seriellen Monitor
void displayTime(byte second, byte minute, byte hour)
{
  char buf [10];
  snprintf ( buf, 10, "%02u:%02u:%02u", hour, minute, second );
  debugln(buf);  // send it to the serial monitor
}

const int STEPS_REVOLUTION = 200;
//Stepper einrichten ( 200 Schritte / Umdrehung - 1/4 Microstep )
MoToStepper StepMinuten( STEPS_REVOLUTION, STEPDIR );  // 200 Steps/ Umdrehung
MoToStepper StepStunden( STEPS_REVOLUTION, STEPDIR );  // 200 Steps/ Umdrehung



void setup() {
  Wire.begin();
  debugbegin(115200);
  debugln("\nStart");
  
  
  pinMode(stellenLED, OUTPUT);

  
  StepMinuten.attach( stepPin, dirPin );
  StepMinuten.attachEnable( enaPin, 6, LOW );        // Enable Pin aktivieren ( LOW=aktiv )
  StepMinuten.setSpeed( 3000 );
  StepMinuten.setRampLen(200 );
  StepMinuten.setZero(0);

  
delay(100);
}

void loop () {
  Taster.processButtons();
  int minutenPosition = minutenRing();
  int stundenPosition = stundenRing();


  // Verwaltung Einstellmode
  if (! stellenAktiv ) {
    // Wenn Taster lange gedrückt, in Stellmode schalten
    if ( Taster.longPress(stellMode) ) {
      stellenAktiv = true;
      debugln("Stellmode aktiv");
      digitalWrite( stellenLED, HIGH );
    }
  } else {
     // Das Beenden des Stellmode ist nur im Stillstand der Ringe möglich
    if ( Taster.shortPress(stellMode) ) {
      debug (F("minutenPosition=")); debugln(minutenPosition);
      debug(F("stundenPosition=")); debugln(stundenPosition);
      if ( minutenPosition >= 0 && stundenPosition >= 0 ) {
        debugln(F("Stellmode beenden"));
        debug("Std: "); debug(stundenPosition); debug(" - Min: "); debugln(minutenPosition * 5);

        // aktuelle Stunden und Minuten an RTC übertragen
        Wire.beginTransmission(DS3231_I2C_ADDRESS);
        Wire.write(0);              // Start ab Register 0 (Sekunden )
        Wire.write(decToBcd(0));    // Sekunden
        Wire.write(decToBcd(minutenPosition * 5)); // Minuten
        Wire.write(decToBcd(stundenPosition));    // Stunde
        Wire.endTransmission();
        digitalWrite( stellenLED, LOW );
        stellenAktiv = false;
      }
    }

}
}

Minuten


void printMinSchritt( byte schritt ) {
  static const char *schrittTexte[] = {"REF_CHK_SCHLITTEN", "REF_FREI_M", "REF_M_SUCHEN", "REF_FAHRT_M", "WARTEN_MIN", "M_ZEIT", "MIN_KLANG", };
  debug("Min: "); debugln( schrittTexte[schritt] );
}

// Rückgabe wert ist die aktuelle Position ( wenn im Zustand WARTEN )
// oder -1 wenn in Bewegung
int minutenRing() {
  byte minute, hour;
  static byte altMinuten = 12, posMinuten = 0;
  enum class Schritt : byte {REF_CHK_SCHLITTEN, REF_FREI_M, REF_M_SUCHEN, REF_FAHRT_M, WARTEN_MIN, M_ZEIT, MIN_KLANG};
  static Schritt schritt = Schritt::REF_CHK_SCHLITTEN, altSchritt = Schritt::REF_M_SUCHEN;
#ifdef DEBUG
  if ( schritt != altSchritt ) {
    // Debugging; Ausgabe wenn Statuswechsel
    printMinSchritt((byte) schritt);
    altSchritt = schritt;
  }
#endif

      //Referenzierung der Minuten unabhängig von der FSM

      if (Taster.pressed(refMinPin)) {
        StepMinuten.setZero(NULLPOSMINUTEN);
        StepMinuten.writeSteps(0);
        debugln(F("Referenz Minuten gefunden"));

        
      }
    
  switch (schritt) {
    case Schritt:: REF_CHK_SCHLITTEN:
      if (Taster.state(refMinPin)) {     // Prüfen ob Schlitten in der Lichtschranke steht
        debugln(F("Aus der Lichtschranke fahren")); 
        StepMinuten.writeSteps(4000 );      //aus der LS fahren
        if ( !StepMinuten.moving() )
 
        schritt = Schritt::REF_FREI_M;
      } else {
        
        schritt = Schritt::REF_M_SUCHEN;    // Referenzfahrt M-Schlitten
      }
      break;

   


      /*   // Auf UhrZeit warten:

         case Schritt::WARTEN_MIN:

           // Das Abschalten der Stepper wurde bereits in MIN_KELLE_RAUF gemacht

           if ( stellenAktiv ) {
             // im Einstellmodus wird das vorrücken über den Stelltaster ausgelöst
             posMinuten = altMinuten + Taster.clicked(stellMin); // Bei einfach Klick wird eins, bei Doppelklick 2 addiert
             if ( posMinuten > 11 ) posMinuten = 0;
           } else {
             // im Normalbetrieb die Uhr abfragen
             readDS3231time(minute, hour);
             posMinuten = minute / 5;
           }

           if (altMinuten != posMinuten) {
             // Ereignis: Zeitpunkt für den Bewegungsablauf ist gekommen
             // Aktion: Ablauf starten mit der Kellenbewegung
             debug( "Min: "); displayTime(0, minute, hour);

             debug(F("altMinuten: ")); debug(altMinuten); debug('\t'); debug("posMinuten: "); debug(posMinuten); debug('\n');
             altMinuten = posMinuten;
             digitalWrite(minDisPin, LOW);                 // Stepperspulen anschalten
             //        MinBeater.write(0);                // Minutenkelle runter
             schritt = Schritt::MIN_KLANG;
           }
           break;

         case Schritt::MIN_KLANG:

           if (!StepMinuten.moving()) {
             // Ereignis: die Minutenkelle ist unten
             // Aktion: Beweegung des Minutenrings starten
             if (posMinuten == 0) {
               StepMinuten.write(360);
               schritt = Schritt::M_ZEIT;
             }
             else {
               StepMinuten.write(30 * posMinuten);
               debug("Minuten-Winkel: "); debugln(30 * posMinuten);

               schritt = Schritt::M_ZEIT;
             }
           }

           break;
           /*case Schritt::M_ZEIT:

             if (!StepMinuten.moving() )
             { // Ereignis: Bewegung des Rings beendet
               // Aktion: Kelle hochfahren

               MinBeater.write(HIGH);           // Minutenkelle hoch

               // if (posMinuten == 0) StepMinuten.setZero();

               schritt = Schritt::WARTEN_MIN;
             }
             break; */


  }

  if ( schritt == Schritt::WARTEN_MIN ) return altMinuten;
  else return -1;
}

Stunden




void printStdSchritt( byte schritt ) {
  static const char *schrittTexte[] = {"REF_STD_KELLE", "REF_STD_GEFUNDEN", "REF_STD", "REF_STD_SUCHEN", "WARTEN_STD", "STD_KELLE_RUNTER", "S_ZEIT", "STD_KELLE_RAUF" };
  
}

// Rückgabe wert ist die aktuelle Position ( wenn im Zustand WARTEN )
// oder -1 wenn in Bewegung
int stundenRing() {
  byte minute, hour;
 static byte altStunden = 12, posStunden = 0;
  enum class Schritt : byte {REF_CHK_KELLE,REF_FREI_KELLE,REF_STD_KELLE, REF_STD_GEFUNDEN, REF_STD, REF_STD_SUCHEN, WARTEN_STD, STD_KELLE_RUNTER, STD_ZEIT, STD_KELLE_RAUF};
  static Schritt schritt = Schritt::REF_CHK_KELLE, altSchritt = Schritt::REF_STD;
#ifdef DEBUG
  if ( schritt != altSchritt ) {
    // Debugging: Ausgabe wenn Statuswechsel
    printStdSchritt((byte)schritt);
    altSchritt = schritt;
  }
#endif

  // Erkennen der Referenzpunkte ( unabhängig von der FSM )
  // Kellen-Referenz
  if (Taster.pressed(refStdKellPin)) {   // Wenn Referenzpunkt erreicht, Bewegung anhalten und Nullpunkt setzen.
    StepMinuten.setZero(10);  // Nullpunkt etwas hinter den referenzpunkt setzen, um ihn auch bei Schrittverlusten sicher zu erreichen
    StepMinuten.write(NULLPOSMINUTEN);
    
  }
  // Ring-Referenz
  if (Taster.pressed(refStdPin)) {
    StepMinuten.setZero(NULLPOSMINUTEN);
    StepMinuten.write(0);
    
  }


  switch (schritt) {

     case Schritt::REF_CHK_KELLE:
      // Prüfen ob Kelle in der Lichtschranke steht
      digitalWrite(refMinPin, LOW);                 // Stepperspulen anschalten
      if ( Taster.state(refStdKellPin ) ) {
        // Kelle aus LS ausfahren
     
        StepMinuten.write(-90);
        schritt = Schritt::REF_FREI_KELLE;
      } else {
       
        // Kelle Refpunkt suchen
        schritt = Schritt::REF_STD_KELLE;
    }
      break;

   case Schritt::REF_FREI_KELLE:
      // LS freifahren
      // etwas über LS Grenze hinausfahren
      if ( Taster.released(refMinPin) ) StepMinuten.doSteps(-300 );
      if ( !StepMinuten.moving() ) schritt = Schritt::REF_STD_KELLE;
      
      break;
   case Schritt::REF_STD_KELLE:

      StepMinuten.write(180);
      schritt = Schritt::REF_STD_GEFUNDEN;
       // Bewegung Kelle starten.
      break;

    case Schritt::REF_STD_GEFUNDEN:
      if (Taster.state(refStdKellPin)) {   // Wenn Referenzpunkt erreicht, (Kelle unten ) Referenzpunkt Ring suchen
       
        schritt = Schritt::REF_STD;
      }
      break;

    case Schritt::REF_STD:

  
      StepMinuten.write(390);
      schritt = Schritt::REF_STD_SUCHEN;
      break;

   case Schritt::REF_STD_SUCHEN:

      if (Taster.state(refStdPin)) {
       
        schritt = Schritt::WARTEN_STD;
      }
      break;
    case Schritt::WARTEN_STD:

      // Das Abschalten wurde bereits in STD_KELLE_RAUF gemacht

      if ( stellenAktiv ) {
        // im Einstellmodus wird das vorrücken über den Stelltaster ausgelöst
          posStunden = altStunden+Taster.clicked(stellStd);  // Bei einfach Klick wird eins, bei Doppelklick 2 addiert
          if ( posStunden > 11 ) posStunden = 0;
      } else {
       
        // im Normalbetrieb die Uhr abfragen
        readDS3231time(minute, hour);
        posStunden = hour > 11 ? hour - 12 : hour;     //posStunden = minute > 11 ? minute - 12 : minute; // nur zum Testen
      }
      if (altStunden != posStunden) {
        debug( "Std: "); displayTime(0, minute, hour);
        debug("altStunden: "); debug(altStunden); debug('\t'); debug("posStunden: "); debug(posStunden); debug('\n');
        altStunden = posStunden;
        digitalWrite(refMinPin, LOW);                 // Stepperspulen anschalten
        StepMinuten.write(0);                // Stundenkelle runter
        schritt = Schritt::STD_KELLE_RUNTER;
      }
      break;

    case Schritt::STD_KELLE_RUNTER:

   if (Taster.pressed(refStdKellPin)) {    // Referenzieren der Stundenkelle/Hochdrücker im Betrieb
        StepMinuten.setZero();
        }

   if (!StepMinuten.moving()) {
        // Ereignis: die Stundenkelle ist unten
        // Aktion: Beweegung des Stundenrings starten

        if (posStunden == 0) {
          StepMinuten.write(360);
          schritt = Schritt::STD_ZEIT;
        }
        else {
          StepMinuten.writeSteps(30 * posStunden);
          debug("Stunden-Winkel: "); debugln(30 * posStunden);
          // if (posStunden == 0) StepStunden.setZero();
          schritt = Schritt::STD_ZEIT;
        }
      }

      break;
    case Schritt::STD_ZEIT:

      if (!StepMinuten.moving()) {
        // Ereignis: Bewegung des Rings beendet
        // Aktion: Kelle hochfahren
        StepMinuten.write(-59);   // Stundenkelle hoch

        //if (posStunden == 0) StepStunden.setZero();

        schritt = Schritt::STD_KELLE_RAUF;
      }
      break;

    case Schritt::STD_KELLE_RAUF:
      if (!StepMinuten.moving())
      { // Ereignis: die Stundenkelle ist oben
        // Aktion: Stepper abschalten
        digitalWrite(refMinPin, HIGH);
        schritt = Schritt::WARTEN_STD;
      }
      break;
  }
  if ( schritt == Schritt::WARTEN_STD ) return altStunden;
  else return -1;
}

evtl. noch ds3231?

// Stellen der Uhrzeit der ds3231
/*void setDs3231() {
  rtcWriteTime();
}

//Funktion zum schreiben / setzen der Uhrzeit.
void rtcWriteTime(){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // Der Wert 0 aktiviert das RTC Modul.
  Wire.write(decToBcd(0));    // Sekunden
  Wire.write(decToBcd(30));   // Minuten
  Wire.write(decToBcd(9));    // Stunde                              
  Wire.write(decToBcd(0));    // Wochentag unberücksichtigt
  Wire.write(decToBcd(0));   // Tag unberücksichtigt
  Wire.write(decToBcd(0));   // Monat unberücksichtig
  Wire.write(decToBcd(0));    // Jahr unberücksichtig
  Wire.endTransmission();  
}

/*
//Convertiert Dezimalzeichen in BCD Zeichen.
byte decToBcd(byte val){
  return ( (val/10*16) + (val%10) );
}*/

Danke :wink:

Ok, ein paar Warnungen kommen zwar noch, dürfte aber am Stand der Dinge liegen :wink:
Aber sonst läuft es durch und gibt ein hochladbares Ergebnis. Hast Du das Referenzieren damit schonmal ausprobiert?
Kannst Du schon ein Bild deiner HW zeigen, dass man sich das besser vorstellen kann mit den Klöppeln?
Du hast auch noch nciht geschrieben, wie die Klöppel ausgelöst werden. ( Oder ich hab's übersehen ... )

Ich habe einen Versuchsaufbau mit einem Schrittmotor, da hab ichs schon ausprobiert. noch nicht an der Originalanlag. Warte noch auf Gabellichtschranken, welche ich bestellt habe.

Ich habe nur dieses bild der Maschine. Aber ich kann morgen noch ein besseres machen.!
Der Klöpel ist dieses schwarze Teil etwa in der mitte der Klangstäbe. Er sitzt auf einem Schlitten, welche von der Spindel nach rechts und links bewegt wird - angetrieben vom Schrittmotor ganz rechts. Ganz links ist der Grundtonschlklöpel zu sehen. Dieser schlägt immer auf die 1. Röhre bei jedem Klang, blaibt also an Ort und Stelle-

Eigentlich war die Idee auch über den Arduino. Der Klöpel besteht aus einem kleiner Motor mit einem Schläger und Feder, eigentlich wie bei einer Klingel, hier aber nur mit einem Schlag. Es braucht also nur einen kleinen Strom Impuls von etwa 0.5 Sekunden.

Über den Arduino war klar :wink: - das mit dem 0,5 Sec-Impuls war die Antwort auf meine Frage.

Hier noch ein besseres Foto vom Minutenklöpel.

Der Stundenklöpel liegt hinter den Klangstäben)und schlägt den Stundenschlag auf die gleiche Art und weise.

Und der Grundtonklöpel, welcher immer nur diesen Grundtonstab von der Seite her anschlägt

Sieht interessant aus. Und mal wieder viel Draht :laughing:

Ohne Draht läuft bei mir nix!! :laughing:

Die Betriebsspannung der Steuerung (5V) wollte ich mir mit einem Stepdown-Converter bereitstellen %product-title% - Conrad Electronic Schweiz
Meine Frage nun: Brauche ich da die Eingangs und Ausgangsfilter, welche im Datenblatt angegeben sind., oder kann ich die auch weg lassen?

So wie ich das Datenblatt verstehe, ja.