"Klotür" Problem

Hallo Leute,

ich Bastel an einer Modelleisenbahn H0 Toilettentür. Mit Licht, Geräusch und Servo.
Ich hatte es irgendwie schon am laufen, aber leider funktioniert es nicht mehr so richtig.
Vielleicht hat sich ja ein Fehler in der Programmierung eingeschlichen.
Wenn da mal jemand drüber schauen kann wäre das toll.
Das ist mein erstes Arduino Projekt ich habe das Programm auf einen Uno und Mega vergeblich zu 100% zuverlässig laufen lassen. . Mal ging es gar nicht dann nur 2-3 mal.

Gruss
Andy aus Recklinghausen

/*
 * Toilettentür-Steuerung mit Sound für Modellbahnanlage H0 
 * 
 * Verbautes Material:
 * Toilette & Figur von NOCH Art Nr. 15560
 * Soundmodul: ISD 1820 Plus an 5V, Minus an GND, Eingang  P-L des Moduls an Pin 13
 * Innenbeleuchtung: Kathode der SMD LED über 470R  am Collektor BC 547, Anode an 5V, 
 * BC547 Emitter an GND, Basis über 1K an Pin7
 * 9 Gramm Micro Servo als Türöffner Signal an Pin 9   5V  & GND angeschlossen
 * Reedkontakt: Mini Reed KY-21 Plus an 5V Minus an GND Signal an Pin 3
 * Im letzten Wagon befindet sich ein Neodym Magnet der den Kontakt auslöst.
 * 
 * Ablauf:
 * Nach 2 Runden(+ 5 Sek. wartezeit) des Zuges wird das Toilettenhäuschen "besetzt" und das Licht geht an.
 * Nach 4 Runden (+ 2 Sek. wartezeit) des Zuges  bewegt sich die Tür weil es kräftige Geräusche im Toilettenhaus gibt ;-)
 * Nach 10 Runden  wird durch den "Zugwind" die Tür aufgeschlagen ,und die Person im Toilettenhäuschen macht sich bemerkbar und schließst dann die Tür wieder. 
 * Nach 12 Runden "verlässt" sich das Klohaus und macht das Licht aus.
 * Nach 15 Runden beginnt alles von vorne.
 * 
 * 29.03.2016 Andy.Oldy
 * 
 * 
 * 
 * 
 * 
 * 
 */
int Kontakt         = 2;      // Zustand der Taste auf 2 setzen
int Reed_Eingang    = 2;      // Reedkontakt an Pin 2. 
int Sound           = 13;     // Soundmodul P-E an Pin 13 
int LED             = 7;      // LED an Pin 7
int count           = 0;      // Zähler auf 0 stellen
int TasterStatus    = 0;      // Tasten Status auf 0
byte auf            =30;      // Servowert für Tür auf
byte zu             =120;     // Servowert für Tür zu


#include <Servo.h>            // Bilbliothek Servo einbinden

Servo servo1;                 // Servobezeichnung = servo1

void setup() {
   Serial.begin(9600);
 
 
  servo1. attach (9);                        // Servo an PIN 9 
  servo1.write (120);                        // Tür schließen 
  pinMode[Reed_Eingang, INPUT];              // Reedkontakt  = Pin 2    = Eingang
  pinMode[Sound, OUTPUT];                    // Soundmodul   = Pin 13   = Ausgang
  pinMode[LED, OUTPUT];                      // LED          = Pin 7    = Ausgang
}

void loop() {

  if (count>15)  {count=0;}                        // Zähler zurücksetzen wenn bis 15 gezählt wurde.
  
    Kontakt = digitalRead(Reed_Eingang);           // Reedkontakt einlesen (Öffner)                            
                                             
    if(Kontakt == LOW)                             // Wenn Reedkontakt = LOW- Tasterstatus auf 1 setzen
    {TasterStatus = 1;}
    if (Kontakt == HIGH && TasterStatus ==1)       // Erst wenn Reed wieder geöffnet  weiterzählen
      
{                   
  count++;                                          // Zähler eins höher zählen
  TasterStatus =0;                                  // TasterStatus wiederauf 0 setzen
  
  }                                
                                    
                                               


    if(count==2)                                     // Bei 1 durchgang LED EIN
{                 delay(100);                       // 5 Sekunden warten damit alles nicht an der selber Stelle passiert
      digitalWrite(LED,HIGH);                         // LED einschalten = Toilette besetzt
      
   }

   
   if (count==3)                                    // Bei 3 durchgängen kurzer Ton, Tür wackelt & Zähler eins höher stellen
                                                    
   {                    delay(2000);                // 2 Sekunden warten damit alles nicht an der selber Stelle passiert
    digitalWrite(Sound,HIGH);                       // Sound abspielen
  
       servo1.write (115);                          // Tür geht bisschen auf und zu 
                          delay(100);
      servo1.write (120);
                          delay(50);
      servo1.write (108);
                          delay(80);
      servo1.write (120);
                          delay(50);
      servo1.write (112);
                          delay(80);
      servo1.write (122);
                        
      
    count++;                                         // Zähler eins höher damit ohne weiteren Reedkontakt dieses nicht wiederholt wird
     
                         delay(700);                // 700 mSekunden warten -> Dauer des kurzen Tons                
    digitalWrite(Sound,LOW);                        // Soundmodul abschalten
    }

    

    if(count==6)                                    // Bei 6 Durchgängen langer Ton, Tür auf/Tür zu & Zähler eins höher stellen
{
   
  digitalWrite(Sound,HIGH);                         // Sound abspielen
                    delay (200);                    // Kurz warten damit Tür nicht zu früh aufgeht
  servo1.write (30);                                // Tür öffnen
                    delay(2900);                    // 2,5 Sekunden warten = länge des Sounds der abgespielt werden soll
                    
  servo1.write (120);                               // Tür schließen
                     delay(700);                    // 700 ms  warten = bis der Sound zu Ende abgespielt wurde
  
  count++;                                          // Zähler eins höher damit ohne weiteren Reedkontakt dieses nicht wiederholt wird
  
  digitalWrite(Sound,LOW);                          // Soundmodul abschalten
}



 if (count==8)                                     // Bei 8 Durchgängen
{ digitalWrite(LED,LOW);}                           // Licht ausschalten


    
}
  pinMode[LED, OUTPUT];

Was sind das für komische eckige Klammern da?

Ablaufsteuerung
Offensichtlich versuchst du eine Ablaufsteuerung zu basteln.
Mich stören die delay() und die vielen Verschachtlungen.
Und ebenso offensichtlich, kommst du damit auch durcheinander....

Meine Standardantwort zu Ablaufsteuerungen:
Eine Stichworte Sammlung für Google Suchen:
Endlicher Automat,
State Machine,
Multitasking,
Coroutinen,
Ablaufsteuerung,
Schrittkette,
BlinkWithoutDelay,

Blink Without Delay
Der Wachmann

Multitasking Macros
Intervall Macros

Ändere mal die loop Funktion zum Testen so ab:

void loop() {
digitalWrite(LED,digitalRead(Reed_eingang));
}

Beobachte dann die LED bei unbetätigtem und bei betätigtem Reed-Kontakt:

Wann ist die LEDan und wann ist sie aus?

Ist sie bei betätigtem Reedkontakt an? Oder aus?

D.h. wenn Dein Modellzug seine Runden dreht: Ist die LED aus und blinkt kurz auf, wenn der Zug drüberfährt?

Oder umgekehrt: Ist die LEDan und geht kurz aus, wenn der Zug drüberfährt?

Hallo Leute,
danke schon mal für Eure Hilfe,

@ jurs: ich habe das nun geändert. Solange der Reedkontakt betätigt ist leuchtet die LED, ist der Kontakt nicht betätigt dann ist die LED aus.

Meint ihr ich müsste das ganz anders aufzíehen? OK dann muss ich mich wohl noch etwas einlesen.

Im Grunde ist es ja ganz einfach (naja für mich anscheinend nicht :wink:
Immer beim betätigen des Kontakts soll etwas geschaltet werden, damit das nicht immer an der "selben Stelle" des Zuges passiert dachte ich ich mal da mal eine kurze Pause rein damit es "spanender" wird.

Gruss
Andy

AndyOldy:
damit das nicht immer an der "selben Stelle" des Zuges passiert dachte ich ich mal da mal eine kurze Pause rein damit es "spanender" wird.

Dann schau Dir mal randomSeed(analogRead(unbelegter Analog-Pin)); ins Setup rein, um den Startwert für den Zufall "zufälliger" zu machen und mit random(min, max) und millis() eine Verzögerung bauen.

Gruß Tommy

Hallo Tommy,

danke für den Hinweis, aber da muss ich mich dann wohl doch intensiver einlesen als zuerst gedacht.
Dachte das könnte ich alles mit einfacheren mitteln hinbekommen.

Aber toll wie schnell ihr hier mit geantwortet habt KLASSE

Gruss
Andy

Du kannst Dir ja den Zufall als Version 2 vornehmen. Da hast Du erst mal die Tür und kannst das dann ausbauen.

Gruß Tommy

...und randomSeed(analogRead(unbelegter Analog-Pin)); als Version 3 :wink:

Was einfacheres als einen Aufruf von random(min,max); kann ich mir nicht vorstellen.

In seinem Programm ist da evtl. noch etwas mehr drin.

Gruß Tommy

Ja, z.B. die Zeile

int Kontakt         = 2;      // Zustand der Taste auf 2 setzen

die zwar nicht weiter stört, man aber nicht ganz so Ernst nehmen sollte :wink:

Der Trick, dasscountnicht nur Rundenzähler ist, sondern oft auch einfach "vorige Sequenz zu Ende" signalisiert, ist interessant.
Ein schönes Beispiel, dass man mit delay() oft auch ziemlich weit kommt :stuck_out_tongue:
Wenn "Sequenz fertig abspielen" Vorrang haben soll vor evtl. sonst zu früh startenden neuen Runden, um so besser.

   delay(100);  // 5 Sek. warten damit alles nicht an der selber Stelle passiert

lässt sich aber wirklich sehr einfach durch

   delay(random(1000,2000));  // zufällig 1 .. 2 Sekunden warten

ersetzen, oder?

Meint ihr ich müsste das ganz anders aufzíehen?

Orthodoxe Programmierer graust es natürlich vor den vielen delay(), aber im Prinzip solltest du die Aufgabenstellung auch so hinbekommen.

Bei "Manchmal geht's, manchmal nicht" kann dir natürlich keiner helfen :wink:

Kannst ja mal, immer wenn du per Reedkontakt count++; machst, eine Serial.print Meldung ausgeben.
Muss evtl. doch "entprellt" werden. ( Auf ein delay mehr, wenn nichts zu tun ist, kommt es ja nicht an. )

Hallo Leute,
kurze Rückmeldung von mir.

Problem ist gelöst, ein Kabel vom Reedkontakt hatte einen Kabelbruch.

Vielen Dank für Eure mithilfe

Gruss
Andy