Projekt zur Ermittlung der Dauerbetriebseigenschaften unterschiedlicher Sensoren

Hayley_Hay: Der von mir als Referenz zu untersuchende Schwimmerschalter benötigt mindestens 24 V.

24V AC halte ich für keine gute Idee, da der Arduino mit Wechselspannung nichts anfangen kann. Mit galvanisch getrennten 24 V DC sollte es gehen. Wobei es mich immer etwas nervös macht, wenn GND vom Netzteil geschaltet wird. Möglicherweise ja so:

                  Pin7
                   │
24V ─── S1 ─── R1 ─┴─ R2 ─── GND

agmue: 24V AC halte ich für keine gute Idee, da der Arduino mit Wechselspannung nichts anfangen kann.

Danke! Das ist natürlich ein Fehler im Schaltplan.

                  Pin7
                   │
24V ─── S1 ─── R1 ─┴─ R2 ─── GND

Das klingt gut, dann mach ich das so. edit: Dann habe ich aber keine 24 V mehr für den Schalter, wenn ich da noch 1kOhm davorhänge...

Hayley_Hay: Dann habe ich aber keine 24 V mehr für den Schalter, wenn ich da noch 1kOhm davorhänge...

Wenn Du den Schalter öffnest, hast Du 24V an den Kontakten. R1 und R2 spielen da keine Rolle. Oder benötigst Du einen minimalen Strom?

agmue: Wenn Du den Schalter öffnest, hast Du 24V an den Kontakten. R1 und R2 spielen da keine Rolle. Oder benötigst Du einen minimalen Strom?

Ich denke nicht, zumindest steht auf dem Schalter nichts davon. Aber wenn er schließt habe ich ja keine 24 V mehr, oder habe ich da etwas übersehen?

Hayley_Hay: Aber wenn er schließt habe ich ja keine 24 V mehr, ...

Hoffentlich!

Hayley_Hay: ... zumindest steht auf dem Schalter nichts davon.

Auf Schaltern steht üblicherweise, welche Spannung und welchen Strom sie maximal schalten können.

Im Datenblatt finden sich dann auch Angaben zur Legierung der Kontakte und den dadurch bedingten minimalen Spannungen und Strömen. Wenn man mit einem Schütz versucht, 1 µA / 5 V zu schalten, können sich Oxidschichten bilden, die nicht mehr durchschlagen werden. Wenn Du solche Dinge berücksichtigen möchtest, mußt Du schon Spezialisten des Fachs befragen und einen Link zum Datenblatt gleich dazu liefern.

agmue: Hoffentlich! Auf Schaltern steht üblicherweise, welche Spannung und welchen Strom sie maximal schalten können.

Im Datenblatt finden sich dann auch Angaben zur Legierung der Kontakte und den dadurch bedingten minimalen Spannungen und Strömen. Wenn man mit einem Schütz versucht, 1 µA / 5 V zu schalten, können sich Oxidschichten bilden, die nicht mehr durchschlagen werden. Wenn Du solche Dinge berücksichtigen möchtest, mußt Du schon Spezialisten des Fachs befragen und einen Link zum Datenblatt gleich dazu liefern.

Ich denke, der Schalter benötigt eine Minimalspannung, da es sich nicht um einen einfachen mechanischen Schalter handelt, sondern sich in dem Schwimmer irgend eine Elektronik befindet. Ich habe bereits versucht, ihn an den 5V vom Arduino zu betreiben, aber das hat nicht funktioniert oder das Programm abstürzen lassen. Wenn ich also richtig liege, dass bei der von Dir vorgeschlagenen Schaltung nur noch 19 V anliegen, wird vermutlich wieder das selbe passieren. Aber ich werde es morgen einfach mal ausprobieren. Vielen Dank bis hierher!

Hayley_Hay: ... irgend eine Elektronik ...

Meine Aussagen beziehen sich genau auf das, was Du im Schaltplan eingezeichnest hast: einen Schalter als Öffner.

agmue: Meine Aussagen beziehen sich genau auf das, was Du im Schaltplan eingezeichnest hast: einen Schalter als Öffner.

Ah, ok. Das war dann schon wieder mein Fehler. Ich habe hier nur einen Schließer, ursprünglich war es ein Öffner.

edit: Also wäre wohl die ursprüngliche Variante, ergänzt um eine Sperrdiode zwischen Arduino und Schalter eine günstige, sichere Möglichkeit?

Ob Öffner oder Schließer ist nicht problematish, aber "... irgend eine Elektronik ..." schon. Da halte ich mich komplett zurück.

agmue: Ob Öffner oder Schließer ist nicht problematish, aber "... irgend eine Elektronik ..." schon. Da halte ich mich komplett zurück.

Ok, aber mehr kann ich auch aus dem Datenblatt nicht entnehmen. Die Elektronik ist eine Vermutung, denn wenn es nur ein Schalter wäre würde er ja auch an 5 V funktionieren und die Angabe 24 V - 230 V wäre nicht sinnvoll.

Ich melde mich mal wieder hier mit einem kleinen Update:

Die Übertragung der Daten läuft jetzt stabil über den seriellen Monitor des RasPi, das Skript zur Erstellung der Datenbank funktioniert leider nicht zuverlässig. Trotzdem habe ich so schon einige Stunden an Datenaufzeichnung zusammenbekommen.

Die Steuerung mittels des einen Arduino läuft prinzipiell ebenfalls wie gewünscht (Abfahren des Programms Pumpen - Pause - Pumpen ... Belüften ). Allerdings bleibt es regelmäßig über Nacht stehen, scheinbar (bisher drei Mal) immer an der selben Stelle zum Ende des einen Pumpzyklus nach ca. 28 000 s Gesamtlaufzeit. Ich komme leider nicht dahinter, woran es liegen könnte, zumal ich frühere, einfachere Versionen bereits länger laufen lassen konnte, ohne dass es zu einem Abbruch kam. Blöderweise habe ich dafür keine ordentliche Versionierung.

Vielleicht kommt es irgendwo zu einem Überlauf oder dergleichen? Ich lasse mal den Code hier, vielleicht hat ja jemand eine Idee? Das Problem tritt natürlich nur im Modus 'Programm' auf.

#include
#include 
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Belegung der Ein- und Ausgaenge, Relais und Switches, Zustandsvariablen

const byte RY_V1_pin = 3;  // Verdichter
byte RY_V1_state;

const byte RY_M1_pin = 5;  // Magnetventil 1
byte RY_M1_state;

const byte RY_M2_pin = 7;  // Magnetventil 2
byte RY_M2_state;

const byte RY_M3_pin = 9;  // Magnetventil 3
byte RY_M3_state;

const byte SW1_pin = 4;    // Schalter 1
bool SW1_status;
const byte SW2_pin = 6;    // Schalter 2
bool SW2_status;
const byte SW3_pin = 8;    // Schalter 3
bool SW3_status;

const byte trig_A = 2;
const byte trig_B = 13;

bool A_state;
bool B_state;


// Zeit
const unsigned int long pump_intervall = 315000;
const unsigned int long pause_intervall = 20000;
const unsigned int long air_intervall = 30000;

unsigned int long remaining_time;
unsigned int long elapsed_time;

unsigned int long Millis;
unsigned int long Intervall;

unsigned int long schreib_timestore;
const int long schreib_intervall = 1000;


void setup() {
  Wire.begin();
  Serial.begin(9600);

  pinMode(trig_A, OUTPUT);
  pinMode(trig_B, OUTPUT);

  pinMode(RY_M3_pin, OUTPUT);
  digitalWrite(RY_M3_pin, HIGH);

  pinMode(RY_M2_pin, OUTPUT);
  digitalWrite(RY_M2_pin, HIGH);

  pinMode(RY_M1_pin, OUTPUT);
  digitalWrite(RY_M1_pin, HIGH);

  pinMode(RY_V1_pin, OUTPUT);
  digitalWrite(RY_V1_pin, HIGH);

  pinMode(SW1_pin, INPUT);
  pinMode(SW2_pin, INPUT);
  pinMode(SW3_pin, INPUT);
  digitalWrite(SW1_pin, HIGH);
  digitalWrite(SW2_pin, HIGH);
  digitalWrite(SW3_pin, HIGH);

  lcd.init();
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Pumpen/Belueften");
  lcd.setCursor(0, 1);
  lcd.print("Funktion waehlen");
}

void dig_Write() {
  digitalWrite(RY_V1_pin, RY_V1_state);
  digitalWrite(RY_M1_pin, RY_M1_state);
  digitalWrite(RY_M2_pin, RY_M2_state);
  digitalWrite(RY_M3_pin, RY_M3_state);
  digitalWrite(trig_A, A_state);
  digitalWrite(trig_B, B_state);
}

enum ZUSTAENDE {
  A_to_B, pause_1 , B_to_A, pause_2, pause_0, air
};

byte curr_state = pause_2;
byte next_state = A_to_B;
byte prev_state = B_to_A;

const int rounds = 2;
int count_rounds = 0;
int count_global = 0;

void A_B () {
  RY_V1_state = LOW;
  RY_M1_state = LOW;
  RY_M2_state = HIGH;
  RY_M3_state = HIGH;
  A_state = 1;
  B_state = 0;
  dig_Write();
  Millis = millis();
  curr_state = A_to_B;
  return;
}

void B_A () {
  RY_V1_state = LOW;
  RY_M1_state = HIGH;
  RY_M2_state = LOW;
  RY_M3_state = HIGH;
  A_state = 0;
  B_state = 1;
  dig_Write();
  Millis = millis();
  curr_state = B_to_A;
  return;
}

void Air () {
  RY_V1_state = LOW;
  RY_M1_state = HIGH;
  RY_M2_state = HIGH;
  RY_M3_state = LOW;
  A_state = 1;
  B_state = 1;
  dig_Write();
  Millis = millis();
  curr_state = air;
  return;
}

void pause () {
  RY_V1_state = HIGH;
  RY_M1_state = HIGH;
  RY_M2_state = HIGH;
  RY_M3_state = HIGH;
  curr_state = pause_0;
  A_state = 0;
  B_state = 0;
  dig_Write();
  Millis = millis();
  return;
}

void programm() {
  if (millis() - Millis >= Intervall) {
    switch (next_state) {

      case A_to_B:
        count_rounds++;
        count_global++;
        prev_state = curr_state;
        A_B();
        next_state = pause_1;
        Intervall = pump_intervall;
        break;

      case pause_1:
        pause();
        prev_state = curr_state;

        next_state = B_to_A;
        Intervall = pause_intervall;
        break;

      case B_to_A:
        prev_state = curr_state;
        B_A();
        next_state = pause_2;
        Intervall = pump_intervall;
        break;

      case pause_2:
        prev_state = curr_state;
        pause();
        if (count_rounds <= rounds)
        {
          next_state = A_to_B;
        }
        else {
          next_state = air;
        }
        Intervall = pause_intervall;
        break;

      case air:
        prev_state = curr_state;
        Intervall = air_intervall;
        Air();
        count_rounds = 0;
        next_state = pause_2;
    }
  }
}

unsigned int long switches_last_millis;
const unsigned int long switches_intervall = 50;

bool readingSwitches() {
  if(millis()- switches_last_millis < switches_intervall) return;
  switches_last_millis += switches_intervall;

  SW1_status = digitalRead(SW1_pin);
  SW2_status = digitalRead(SW2_pin);
  SW3_status = digitalRead(SW3_pin);
  return;
}

void schreiben() {
  if (millis() - schreib_timestore >= schreib_intervall) {
    schreib_timestore = millis();
    Serial.print(millis());
    Serial.print(",");
    Serial.print(curr_state);
    Serial.print(",");
    Serial.print(elapsed_time);
    Serial.print(",");
    Serial.print(RY_V1_state);
    Serial.print(",");
    Serial.print(RY_M1_state);
    Serial.print(",");
    Serial.print(RY_M2_state);
    Serial.print(",");
    Serial.print(RY_M3_state);
    Serial.println("");
  }
}

unsigned int display_last_millis;
const unsigned int display_intervall = 1000;

void Display() {
  if(millis()- display_last_millis < display_intervall) return;
  display_last_millis += display_intervall;

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Runde ");
  lcd.print(count_global);
  lcd.print(" ");
  if (curr_state == 4) {
    lcd.print("- Pause");
  }
  if (curr_state == 0) {
    lcd.print("- A->B");
  }
  if (curr_state == 2) {
    lcd.print("- B->A");
  }
  if (curr_state == 5) {
    lcd.print("- Air");
  }
  lcd.setCursor(0, 1);
  if (next_state == pause_1 || next_state == pause_2 || next_state == pause_0) {
    lcd.print("Pause in ");
  }
  if (next_state == A_to_B) {
    lcd.print("A->B in ");
  }
  if (next_state == B_to_A) {
    lcd.print("B->A in ");
  }
  if (next_state == air) {
    lcd.print("Air in ");
  }
  lcd.print(remaining_time);
  lcd.print(" s");
}


void loop() {
  schreiben();

  elapsed_time = (millis() - Millis) / 1000;
  remaining_time = Intervall / 1000 - elapsed_time;

  readingSwitches();

  if (SW1_status == HIGH && SW2_status == HIGH && SW3_status == HIGH) {  // Schalter 1+2+3
    programm();
  }

  if (SW1_status == HIGH && SW2_status == HIGH && SW3_status == LOW) {   // Schalter 1+2
    A_B();
  }

  if (SW1_status == HIGH && SW2_status == LOW && SW3_status == HIGH) {   // Schalter 1+3
    B_A();
  }

  if (SW1_status == HIGH && SW2_status == LOW && SW3_status == LOW) {    // Schalter 1
    Air();
  }

  if (SW1_status == LOW && SW2_status == LOW && SW3_status == LOW) { // kein Schalter
    pause();
    //}
  }
  if (SW1_status == LOW && SW2_status == LOW && SW3_status == HIGH) {
    pause();
  }

  if (SW1_status == LOW && SW2_status == HIGH && SW3_status == HIGH) {
    pause();
  }

  Display();
}
unsigned int display_last_millis;
const unsigned int display_intervall = 1000;

Wenn ich int im Zusammenhang mit millis() sehe, werde ich skeptisch.

agmue: unsigned int display_last_millis; const unsigned int display_intervall = 1000;

Wenn ich int im Zusammenhang mit millis() sehe, werde ich skeptisch.

Danke! Das stell ich mal ab und schau, was die Nacht bringt...

Hallo, kann mich da agmue nur anschliessen. alle Variable die bei Berechnungen und abfragen mit millis() benutzt werden solltest Du erst mal als

unsigned long Mllis // deklarieren

bei abfragen mit festen Werten im code den Wert mit UL kennzeichnen z.B

if millis()-Millis >=1000UL

So, ich habe alle entsprechenden Variablen und Konstanten in unsigned long geändert - leider ist das Programm wieder stehen geblieben (dieses Mal nach 34000 s und mit dem Unterschied, dass nun wieder das Start-Display gezeigt wurde, wo vorher nur das "R" von Runde ... angezeigt wurde) :(

Hallo 34000s ist ja Mal gerade ein knapper halber Tag. Da wirst du als nächstes ein paar Serielleptint Anweisungen einbauen müssen um die die Zeitvariablen und Statuswerte ansehen zu können.

Ich denke mal Bein Eintritt und Austritt in deine Funktionen wäre eine gute Stelle

Anscheinend rennt das Programm durch ohne das eine swich Case ausgeführt wird .

Heinz

Rentner: Anscheinend rennt das Programm durch ohne das eine swich Case ausgeführt wird .

Wie meinst Du das? Kannst Du das etwas erläutern? Meinst Du, ein Case wird übersprungen?

Hallo,

na ja , Du schreibst das Program bleibt stehen, daraus folgere ich das nichts mehr passiert , nichts mehr geschaltet wird an der Maschine. Was mich etwas wunder ist jetzt allerdings das in dem Fall ja eigendlich der aktuelle Zustand erhalten bleiben müsste. D.h irgendwas läüft immer weiter ohne das es mit dem nächsten Schritt abgeschaltet wird. Das wäre ja schlimm- Das Ding läuft dann ohne jede Kontrolle vor sich hin. Oder ist das gerade immer ein Zustand in dem eh alles ausgeschaltet ist. ? Also passiert das immer nur am Ende eines Maschinenzyklus oder auch mitten drin. ?

die angegeben 28000 oder 34000s entnimmst Du den in der Funktion schreiben mit ausgegebenen millis() nehme ich mal an. ??

Eigendlich ist es ja so wenn das Startdisplay angezeigt wird ist das Programm ja anscheinend aus dem "Programm modus der “Automatik” rausgefallen, ?? ich blicke da aber auch nicht so ganz durch was Dein programm da so macht und wann anzeigt.

Dann hab ich noch mal eine Frage zur Hardware. Ich hab gesehen das die Schalter positiv schaltend abgefragt werden. Wie sind die Schalter beschaltet. Welche Widerstände (Pull-down) sind da mit verschaltet. ? Ist das ganze halbwegs sicher ? , oder ist dein eigendliches Problem ehr die EMV ?

wie Du siehst Fragen über Fragen

Gruß Heinz

Hi

Hatte hier ebenfalls sporadische Hänger - bei mir wurde aber von einer CAN-Nachricht (maximal 8 Byte lang) die Länge ermittelt und diese Anzahl an Bytes in den vorhandenen Puffer geschrieben. Blöd, wenn vom CAN-Modul eine 12 Byte lange Nachricht angeboten wird ... (so richtig gefunden habe ich den Fehler nicht wirklich, tendiere auf Spannungseinbrüche, ausgebessert habe ich im Programm durch Begrenzen der Nachrichtenlänge und Kondensatoren in der Spannungsversorgung - ca. 24h bis jetzt fehlerfrei)

MfG

Hallo noch mal!

Das Programm läuft jetzt seit einigen Tagen durch, nachdem ich beim letzten case (air) noch ein break; hinzugefügt habe.

Rentner: Dann hab ich noch mal eine Frage zur Hardware. Ich hab gesehen das die Schalter positiv schaltend abgefragt werden. Wie sind die Schalter beschaltet. Welche Widerstände (Pull-down) sind da mit verschaltet. ? Ist das ganze halbwegs sicher ? , oder ist dein eigendliches Problem ehr die EMV ?

Ja, das stimmt. Das hab ich ganz am Anfang so gemacht ohne Nachzudenken, und aus Bequemlichkeit habe ich es so gelassen. Probleme mit der EMV sind inzwischen nur noch minimal, der Bildschirm des angeschlossenen RasPi geht kurz aus wenn ein Relais schaltet.

Also, vielen Dank wieder mal bis hier her!