Einzelnen Beitrag anzeigen
Alt 30.01.2011, 21:05   #18
Niggoh
Benutzer
 
Threadstarter
 
Registriert seit: 02.04.2010
Ort: Nürnberg
Beiträge: 712
Standard Update: Magnetventilsteuerung

Inzwischen habe ich mein Projekt ein wenig ausgeweitet und noch ein Magnetventil integriert, um die Tropfen einfacher kontrollieren zu können. Da die Ströme, die beim Schalten des Magnetventils fließen, das Arduino zerstören würden, ist dafür eine kleine Zusatzschaltung notwendig, die allerdings für sich genommen schon komplexer ist, als die Lichtschranke.

Die Selbstentwicklung wäre über meine bescheidenen Elektronikkenntnisse hinausgegangen. Zum Glück gibt es Menschen mit mehr Ahnung, so zum Beispiel Pixelmagier, dessen Schaltung ich 1:1 übernommen habe (im Original hier zu finden). Spätestens an dieser Stelle macht es dann aber leider nicht mehr viel Sinn, mit Lüsterklemmen zu arbeiten.
Ich habe die Schaltung zum Testen auf ein Breadboard gesteckt und dann auf eine kleine Platine gelötet. Dazu habe ich erstmalig in meinem Leben einen Lötkolben in die Hand genommen, hat trotzdem keine halbe Stunde gedauert. Wie das mit dem Löten funktioniert, wird in diesem Video recht gut erklärt, sofern man der englischen Sprache mächtig ist.

Als Ventil habe ich das billigste 12V Gleichstromventil in einem Online-Auktionshaus gekauft, die restlichen Teile kamen von einem großen deutschen Elektronikhändler, der auch einige Ladengeschäfte betreibt. Außerdem benötigt man eine 12V Gleichstromquelle, da bin ich auf ein Netzteil umgestiegen, weil ich keine Lust mehr auf Batterien hatte. Theoretisch wären aber z.B. auch 8 AA-Batterien denkbar, auch dafür gibt es entsprechende Batteriefächer.

Die eigentlich Arbeit war dann, das zugehörige Arduino-Programm zu schreiben. Das wurde deutlich länger, weil die Verzögerung nicht mehr mittels delay() implementiert werden kann, da ansonsten die Lichtschranke nicht schalten kann, während die Tropfenverzögerung am Ventil stattfindet. So ganz komfortabel ist auch dieses Programm nicht, aber es funktioniert.
Ein paar Bemerkungen: die Pins für Ventil und Kamera habe ich gegenüber der ursprünglichen Version verändert, ebenso einige der Variablennamen. Entweder müssen also die Kabel an andere Stellen gesteckt werden oder die Pin-Belegung (im Programm Zeile 3 und 4) muss geändert werden. Die Lichtschranke kalibriert sich jetzt in den ersten zwei Sekunden Programmlaufzeit und legt dann automatisch einen Schwellenwert fest. In der Hauptprogrammschleife wird ganz zu Anfang eine Boolsche Variable auf true gesetzt, diese könnte man bei Bedarf dazu nutzen, die Tropfen nur auf Knopfdruck fallen zu lassen, anstatt alle 10 Sekunden, wie es derzeit implementiert ist. Dazu müsste man dann die Schaltung noch um einen Knopf und einen Widerstand erweitern, was kein großes Problem sein dürfte.

Hier der Quelltext:

Code:
// KONSTANTEN
const int lichtschranken_pin = A0;
const int ventil_pin = 12;
const int kamera_pin = 13;

// VARIABLEN
// Alle Zeiten in Millisekunden angegeben

// Zeitvariablen initalisieren
// Auslöseverzögerung Kamera
long aktuellezeit_ausloeseverzoegerung = 0;
long startzeit_ausloeseverzoegerung = 0;
// Ventil
long aktuellezeit_ventil = 0;
long startzeit_ventil = 0;

// Ventilöffnungszeiten festlegen
int tropfenzeit_1 = 150;
int verschlusszeit_1_2 = 70;
int tropfenzeit_2 = 150;
int verschlusszeit_2_3 = 70;
int tropfenzeit_3 = 150;
int gesamtzeit_tropfserie = tropfenzeit_1 + verschlusszeit_1_2 + tropfenzeit_2 + verschlusszeit_2_3 + tropfenzeit_3 + 500; // für die Inaktivzeit der Lichtschranke, 500 ms Sicherheitsreserve, damit die Lichtschranke nicht durch den dritten Tropfen doch wieder aktiviert werden kann

// Zeit zwischen den Tropfenserien festlegen
int pausenzeit = 10000;

// Auslöseverzögerung festlegen
int ausloeseverzoegerung = 288;

// Aktivierungszeit für Kameraauslöser festlegen
int ausloeser_aktivzeit = 200;

// Lichtschranken-Schwellenwert festlegen
int lichtschranke_messwert;
int lichtschranke_maximum;
int lichtschranke_minimum;
int lichtschranke_schwellenwert;
float lichtschranke_schwellenwertfaktor = 0.85; // Faktor, mit dem der maximale Messwert der Lichtschranke multipliziert wird, um den Schwellenwert zu errechnen, muss unbedingt kleiner als 1 sein!

// Statusvariable Lichtschranke
boolean lichtschranke_unterbrochen = false;

// Statusvariable Kameraauslöser
boolean kamera_ausloeser_aktiv = false;

// Satusvariable Ventil
boolean ventil_offen = false;

// Statusvariable Tropfserie
boolean tropfserie_laeuft = false;

// Statusvariable Tropfen ausgelöst
boolean tropfen_ausgeloest = false;

// Ventilzeiten in Absolutwerte umrechnen
int endzeit_offen_1 = tropfenzeit_1;
int endzeit_geschlossen_1_2 = endzeit_offen_1 + verschlusszeit_1_2;
int endzeit_offen_2 = endzeit_geschlossen_1_2 + tropfenzeit_2;
int endzeit_geschlossen_2_3 = endzeit_offen_2 + verschlusszeit_2_3;
int endzeit_offen_3 = endzeit_geschlossen_2_3 + tropfenzeit_3;
int endzeit_pause = endzeit_offen_3 + pausenzeit;

// Eingabevariable initialisieren
int eingabe;

void setup() {
  // Ausgangspins initialisieren
  pinMode(ventil_pin, OUTPUT); 
  pinMode(kamera_pin, OUTPUT);
  // Serielle Verbindung zum Computer initialisieren für Textausgabe
  Serial.begin(9600);
  Serial.println("Lichtschranke wird kalibiert...");
  // Die ersten zwei Sekunden die Lichtschranke kalibrieren
  while (millis() < 2000) {
    lichtschranke_messwert = analogRead(lichtschranken_pin);
    // Maximalwert speichern
    if (lichtschranke_messwert > lichtschranke_maximum) {
      lichtschranke_maximum = lichtschranke_messwert;
    }
    // Minimalwert speichern, nur fuer den Fall, dass wir den Schwellenwert irgendwann mal anders berechnen wollen
    if (lichtschranke_messwert < lichtschranke_minimum) {
      lichtschranke_minimum = lichtschranke_messwert;
    }
  }
  lichtschranke_schwellenwert = lichtschranke_maximum * lichtschranke_schwellenwertfaktor;
  Serial.print("Leerwert der Lichtschranke: ");
  Serial.println(lichtschranke_maximum);
  Serial.print("Schwellenwert der Lichtschranke: ");
  Serial.println(lichtschranke_schwellenwert);
}

void loop() {
  tropfen_ausgeloest = true;

  // Tropfserie fallen lassen falls ausgelöst
  if (tropfen_ausgeloest == true) {
    aktuellezeit_ventil = millis();
    if (aktuellezeit_ventil - startzeit_ventil < endzeit_offen_1 && ventil_offen == false) {
      digitalWrite(ventil_pin, HIGH);
      ventil_offen = true;
      tropfserie_laeuft = true;
      Serial.println("Tropfen 1 Start, Ventil offen");
    }
    else if (aktuellezeit_ventil - startzeit_ventil > endzeit_offen_1 && aktuellezeit_ventil - startzeit_ventil < endzeit_geschlossen_1_2 && ventil_offen == true) {
      digitalWrite(ventil_pin, LOW);
      ventil_offen = false;
      Serial.println("Tropfen 1 Ende, Ventil geschlossen");    
    }
    else if (aktuellezeit_ventil - startzeit_ventil > endzeit_geschlossen_1_2 && aktuellezeit_ventil - startzeit_ventil < endzeit_offen_2 && ventil_offen == false) {
      digitalWrite(ventil_pin, HIGH);
      ventil_offen = true;
      Serial.println("Tropfen 2 Start, Ventil offen");
    }
    else if (aktuellezeit_ventil - startzeit_ventil > endzeit_offen_2 && aktuellezeit_ventil - startzeit_ventil < endzeit_geschlossen_2_3 && ventil_offen == true) {
      digitalWrite(ventil_pin, LOW);
      ventil_offen = false;
      Serial.println("Tropfen 2 Ende, Ventil geschlossen");        
    }
    else if (aktuellezeit_ventil - startzeit_ventil > endzeit_geschlossen_2_3 && aktuellezeit_ventil - startzeit_ventil < endzeit_offen_3 && ventil_offen == false) {
      digitalWrite(ventil_pin, HIGH);
      ventil_offen = true;
      Serial.println("Tropfen 3 Start, Ventil offen");
    }
    else if (aktuellezeit_ventil - startzeit_ventil > endzeit_offen_3 && aktuellezeit_ventil - startzeit_ventil < endzeit_pause && ventil_offen == true) {
      digitalWrite(ventil_pin, LOW);
      ventil_offen = false;
      Serial.println("Tropfen 3 Ende, Ventil geschlossen");    
    }
    else if (aktuellezeit_ventil - startzeit_ventil > endzeit_pause) {
      startzeit_ventil = aktuellezeit_ventil;
      tropfserie_laeuft = false;
      lichtschranke_unterbrochen = false;
      Serial.println("Ende der Pause, Startzeit aktualisiert, Lichtschranke wieder scharf");
    }
  }
  
  // Lichtschranke abfragen
    lichtschranke_messwert = analogRead(lichtschranken_pin);
    if (lichtschranke_messwert < lichtschranke_schwellenwert && lichtschranke_unterbrochen == false) {
      Serial.println("Lichtschranke unterbrochen");
      lichtschranke_unterbrochen = true;
      startzeit_ausloeseverzoegerung = millis();
    }
    // Verzögerungszeit abwarten, dann Kamera-Auslöser aktivieren
    aktuellezeit_ausloeseverzoegerung = millis();
    if (aktuellezeit_ausloeseverzoegerung - startzeit_ausloeseverzoegerung > ausloeseverzoegerung && aktuellezeit_ausloeseverzoegerung - startzeit_ausloeseverzoegerung < ausloeseverzoegerung + ausloeser_aktivzeit && kamera_ausloeser_aktiv == false && lichtschranke_unterbrochen == true) {
      digitalWrite(kamera_pin, HIGH);
      kamera_ausloeser_aktiv = true; 
      Serial.println("Kamera-Ausloeser aktiviert");
    }
    // Aktivzeit des Auslösers abwarten, dann Kamera-Auslöser deaktivieren
    else if (aktuellezeit_ausloeseverzoegerung - startzeit_ausloeseverzoegerung > ausloeseverzoegerung + ausloeser_aktivzeit && aktuellezeit_ausloeseverzoegerung - startzeit_ausloeseverzoegerung < gesamtzeit_tropfserie && kamera_ausloeser_aktiv == true) {
      digitalWrite(kamera_pin, LOW);
      kamera_ausloeser_aktiv = false;
      Serial.println("Kamera-Ausloeser deaktiviert");
    }
}
Ich werde auch hierzu noch ein Fototutorial erstellen. Die zusätzlichen Kosten belaufen sich auf unter 20 Euro, wovon etwa 15 auf das Ventil entfallen.

Vorab erstmal für die bastelfreudigeren Menschen unter uns eine Fritzing Skizze und ein Foto von meinem Breadboard, die selbige korrigiert. In Fritzing gibts den von Pixelmagier vorgeschlagenen Optokoppler nicht, deswegen musste ich einen anderen einmalen (mit gestrichelter Linie umrandet). Der von Pixelmagier vorgeschlagene Optokoppler muss wie gezeigt eingesetzt werden, man beachte die kleine Aussparung, die ich unauffällig rot umrandet habe. Die 2 AA-Batterien sollen die 12V Gleichspannungsquelle darstellen. Pluspol rotes Kabel, Minuspol schwarzes Kabel. Das Magnetventil ist das lustige Ding unten in der Mitte, die Polung der Anschlüsse ist zumindest bei dem von mir gekauften Ventil egal.

Ich freue mich über alle Nachbauten, übernehme aber nach wie vor keine Verantwortung für Schäden und Fehlfunktionen. Bei mir funktioniert es aber und mein Haus steht auch noch. Nett wäre natürlich auch, wenn diejenigen, die die Idee noch erweitert oder verändert haben, Fotos und Anregungen hier posten würden.

Beispielfotos, die mit dem System geschossen wurden z.B. hier.
Angehängte Grafiken
Dateityp: jpg magnetventilschaltung_Steckplatine.jpg (145,9 KB, 1195x aufgerufen)
Dateityp: jpg optokoppler.jpg (215,8 KB, 784x aufgerufen)
Niggoh ist offline   Mit Zitat antworten
Werbung
Zu viel Werbung? Hier kostenlos bei DSLR-Forum.de registrieren!