Zeit Überwachung der Endanschläge für einen Schrapperboden

Hallo zusammen

Nach etlichen erfolglosen Versuchen mit diversen Varianten bitte ich euch um Hilfe.
Geht das überhaupt und könnt ihr mir einen Anstoss geben auf welche weise.

Für unseren Kratzboden im Sandstrahlraum hätte ich gerne eine Überwachung gegen Verstopfung. Das ist keine Sicherheitsrelevante Überwachung. Und benötigt nur ein Code als Abfuhrmittel.

Erklärung zur Funktion:
8 Pneumatik Zylinder treiben Schrapper Rechen an. Gesteuert über ein Blinker Zeitrelais.
Die oberen 7 schieben den Sand in den einen Unteren, der das ganze dann zum Becherwerk schiebt. Die Überwachung müsste nur für den einen unteren sein, der schon öfters verstopft ist.

Nun zum angedachten Ablauf:
Über einen Endanschlag und einer Vorgabe Zeit, die oberen 7 Ein oder Ausschalten.
Mit dem angefügten Code funktioniert die Abschaltung sehr gut, wenn die Zeit überschritten wurde. Jedoch sollte jetzt beim nächsten Kontakt mit dem Endanschlag das Relais nicht gleich auf HIGH gehen, sondern erst geprüft werden, ob die Zeit wieder innerhalb der Vorgabezeit liegt.

Taktzeit ist ca. 2000ms Vorgabezeit ca. 2500ms

Für Tipps bin ich jetzt schon dankbar.

Gruss Marcel

[code]
const byte relaisPin = 0; // Pin für Relaisboard (OUTPUT)
const byte schaltPin = 1; // Pin für Endschalter (INPUT)
const int potiPin = A1;   // Pin für Poti (INPUT) Externe einstellung der Zeitlimite - Relais Aus

void setup() {
  pinMode(schaltPin, INPUT);
  pinMode(relaisPin, OUTPUT);
}

void loop() {
  int potiWert = analogRead(potiPin);
  static uint32_t previousMillis = 0;

  if (digitalRead(schaltPin) == HIGH) {
    previousMillis = millis();
  }
  if (millis() - previousMillis > 5 * potiWert && digitalRead(relaisPin) == HIGH) {
    digitalWrite(relaisPin, LOW);
  }
  if (millis() - previousMillis < 5 * potiWert && digitalRead(relaisPin) == LOW) {
    digitalWrite(relaisPin, HIGH);
  }
}
[/code]

Hallo Marcel,
na ja, Du musst halt die Vorgabezeit mit den Sketch aufnehmen und die Zeit zwischen 2 Schalter Betätigungen ausrechnen. Diesen Wert dann mit der Vorgabezeit vergleichen und gegebenenfalls die Differenz warten.

An was für einem Controller?
Die Arduinos haben 0 und 1 für die Serielle Kommunikation RX/TX belegt....

Was genau ist das "Blinker Zeitrelais"?
Ist das ein vom Arduino völlig unabhängiges Relais das durch simples an den Strom anschliessen von alleine Ein/Aus schaltet = von alleine blinkt?
oder
ist das ein Stück Programmcode das auch auf dem Arduino läuft?

Kann jeder der sieben oberen Schrapper-Rechen für sich ohne Synchronisation so vor/zurück vor sich hin rechen oder müssen die synchronisiert sein?

Der unterste Schrapper-Rechen hat

  • einen Endanschlagsschalter für vorne
    und
  • einen Endanschlagsschalter für hinten

Im Falle von Verstopfung kann sich der unterste Schrapper-Rechen nicht mehr bis zum Endanschlag bewegen.

Und du willst jetzt die Verstopfung vom Programm erfassen lassen, dadurch das es eine Zeitüberwachung gibt die folgendermaßen funktioniert:
Der Schrapper-Rechen befindet sich ganz hinten, das heißt hinterer Endschalter ist betätigt.
Jetzt wird die Pneumatik auf Schrapper-Rechen nach vorne schieben geschaltet und die Zeitüberwachung beginnt. Wenn nach einer Zeit von 2500 Millisekunden der vordere Endschalter nicht betätigt ist, dann soll die Steuerung eine Meldung ausgeben
"Zeitüberwachung vordere Endlage nicht erreicht"

Und in der gleichen Art und Weise auch für die hinteren Endlagenschalter
wenn Schrapp-Rechen ganz vorne ist und der Schrapp-Rechen auf "bewege dich nach hinten" geschaltet wird Zeitüberwachung starten. Wenn hinterer Endschalter nach 2500 millisekunden noch nicht geschaltet hat dann soll die Steuerung eine Meldung ausgeben
"Zeitüberwachung hintere Endlage nicht erreicht"

Ist das eine zutreffende Beschreibung der Funktionalität die du haben möchtest?

In dem Code den du gespostet hast gibt es nur einen Relais-Pin und einen Schaltpin
Heißt das dass du nur eine Endlage so überwachen willst?
Oder
heißt das es gibt 16 Arduinos wobei auf jedem Arduino dieses Programm für einen Endschalter läuft?
oder
noch etwas anderes?

vgs

Hallo gfenner

Bilder sagen mehr als 1000 Worte.

Hallo zusammen

@my xy projekt
Der Controller ist ein Digispark / Joy-IT

@stefanL38
Es ist nur ein einziger Blinker, der ist von Finder 87.31 und dieser gibt den Takt für die Ventileinheiten an.

Eine Unterbrechung der oberen Rechen würde bei der Ventileinheit geschehen.
Geplant habe ich eine einseitige Endlagen Kontrolle, das sollte doch reichen? Rein Programm technisch.

Bis anhin wird eine Verstopfung erst bemerkt, wenn gar nichts mehr geht.
Ich glaube, wenn hier eine frühzeitige Abschaltung der Oberen Rechen und
natürlich auch den Strahlvorgang unterbricht. Sollte es reichen für den unteren Rechen
dass er den Sand los wird und wieder in die Vorgabe Zeit kommt.

Die Blinker Zeit ist natürlich etwas länger eingestellt als die Zylinder pro hub benötigen.
Dadurch gibt es eine kurze Verweilzeit in den Endpositionen.

Besten dank

Gruss Marcel

Ein Schema und Bilder werde ich morgen noch einstellen.

1 Like

Noch eine Frage:

wird vom Digispark IO-pin mit Namen

const byte relaisPin = 0; // Pin für Relaisboard (OUTPUT)

das Relais geschaltet, dass den untersten Zylinder raus/reinfährt?
vgs

So jetzt habe ich ein Programm geschrieben dass die Zeitüberwachung realisiert.
Achtung alteingesessene Hasen: die State-Machine nennt sich eingedeutscht Schrittkette.

Bestimmte Detaildaten haben in der Beschreibung gefehlt. Da habe ich jetzt Annahmen getroffen.

Der Relais-Pin heißt jetzt "ZylVorPin" Annahme von diesem Relais wird der untererste Zylinder gesteuert.

Marcel hat was von Ventil-Insel abschalten geschrieben. Dafür gibt es jetzt auch einen IO-pin

Die Steuerung / Überwachung hat zwei unterschiedliche Abläufe

  1. Normalablauf keine Verstopfung Ventil-Insel ist eingeschaltet alle Schrappen-Rechen sind aktiv Der unterste arbeitet mit Zeitüberwachung. Wenn Endschalter nach Maximalzeit nicht geschaltet hat umschalten auf 2.

  2. Endschalter hat nicht geschaltet = Verstopfung =>

  • Ventil-Insel ausschalten
  • Der unterste arbeitet ohne Überwachung überprüft aber bei jedem nach vorne fahren des Rechens ob der Endschalter betätigt wird
    Wenn das der Fall ist umschalten auf Normalbetrieb 1.

Das Ganze ist über eine Schrittkette programmiert in der wie der Name schon sagt bestimmte Schritte nacheinander durchlaufen werden.
Das Schöne an Schrittketten (state-machines) ist, dass der Code nicht-blockierend ist und man ihn sehr leicht erweitern / abändern kann und die Anzahl If-bedingungen durch das switch-case auf das notwendige Minimum reduziert ist

Man könnte mit cleverer Programmierung noch 2,3 Schritte einsparen, dann wird der Code aber schwerer zu verstehen. Deshalb lieber 3 Schritte mehr und dafür leicht verständlich.


const byte ZylVorPin = 0; // Pin für Relaisboard (OUTPUT)
const byte schaltPin = 1; // Pin für Endschalter (INPUT)
const int potiPin = A1;   // Pin für Poti (INPUT) Externe einstellung der Zeitlimite - Relais Aus
const byte VentileAbschaltenPin = 2;

const byte betaetigt = HIGH;
const byte eingeschaltet = HIGH;
const byte ausgeschaltet = LOW;

const byte sk_leerLauf            = 0;
const byte sk_Zylinder_vor        = 1;
const byte sk_warte_auf_Endlage   = 2;
const byte sk_Endlage_erreicht    = 3;
const byte sk_Zylinder_zurueck    = 4;
const byte sk_warten_bis_zurueck  = 5;

const byte sk_Ventileinheit_aus   = 6;
const byte sk_frei_rechen         = 7;
const byte sk_frei_rechen_warten  = 8;

byte SchrittNr = sk_leerLauf;

unsigned long ZylinderTimer;
unsigned long MaximalZeitVor;
unsigned long MaximalZeitZurueck;

void setup() {
  pinMode(schaltPin, INPUT);
  pinMode(ZylVorPin, OUTPUT);
  pinMode(VentileAbschaltenPin, OUTPUT);
  
  digitalWrite(VentileAbschaltenPin, eingeschaltet);
}

void loop() {
  int potiWert = analogRead(potiPin);

  MaximalZeitVor     = 5 * potiWert;
  MaximalZeitZurueck = 5 * potiWert;

  Schrittkette_Schieber_Unten();
}


void Schrittkette_Schieber_Unten() {
  switch (SchrittNr) {

    case sk_leerLauf:
      // mache gar nichts
      break; // springe sofort zu switch-ENDE

    case sk_Zylinder_vor:
      digitalWrite(ZylVorPin, HIGH);
      ZylinderTimer = millis();
      SchrittNr = sk_warte_auf_Endlage;
      break; // springe sofort zu switch-ENDE

    case sk_warte_auf_Endlage:
      // wenn Endschalter nach Ablauf der Maximalzeit
      // immer noch nicht geschaltet hat => Verstopfung
      if ( TimePeriodIsOver(ZylinderTimer, MaximalZeitVor) ) {
        // obere Rechen abschalten (und dann unten freirechen)
        SchrittNr = sk_Ventileinheit_aus;
        break; // springe sofort zu switch-ENDE
      }
      // Endlage erreicht = alles IO
      if (digitalRead(schaltPin) == betaetigt) {
        SchrittNr = sk_Endlage_erreicht;
      }
      break; // springe sofort zu switch-ENDE


    case sk_Endlage_erreicht:
      digitalWrite(ZylVorPin, LOW); // Zylinder zurueck fahren
      ZylinderTimer = millis();
      SchrittNr = sk_warten_bis_zurueck;
      break; // springe sofort zu switch-ENDE


    case sk_warten_bis_zurueck:
      if ( TimePeriodIsOver(ZylinderTimer, MaximalZeitZurueck) ) {
        SchrittNr = sk_Zylinder_vor;
      }
      break; // springe sofort zu switch-ENDE


    case sk_Ventileinheit_aus:
      digitalWrite(VentileAbschaltenPin, LOW);
      SchrittNr = sk_frei_rechen;
      break; // springe sofort zu switch-ENDE

    case sk_frei_rechen:
      if ( digitalRead(ZylVorPin) == HIGH) { // wenn Zylinder vorne
        digitalWrite(ZylVorPin, LOW);        // Zylinder zurück
      }
      else { // wenn Zylinder zurück
        digitalWrite(ZylVorPin, HIGH); // Zylinder vor
      }
      ZylinderTimer = millis();
      SchrittNr = sk_frei_rechen_warten;
      break; // springe sofort zu switch-ENDE

    case sk_frei_rechen_warten:
      if ( TimePeriodIsOver(ZylinderTimer, MaximalZeitVor) ) {
        SchrittNr = sk_frei_rechen;
      }

      // wenn Endlage geschaltet hat = KEINE Verstopfung mehr
      if ( digitalRead(schaltPin) == HIGH ) {
        digitalWrite(VentileAbschaltenPin, eingeschaltet); // obere Rechen wieder einschalten
        SchrittNr = sk_Endlage_erreicht; // mit Normal Steuerung weiter machen
      }
      break; // springe sofort zu switch-ENDE

  } // switch-ENDE
}

// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

vgs

1 Like

Hallo zusammen

Als erstes möchte ich ein grosses Dankeschön aussprechen.
Sehr tolles und informatives Forum.

@StefanL38 mit deinem Code hatte ich leider keinen Erfolg.
Ich habe dann noch einen Nano und Uno zum Ausprobieren zugelegt,
dachte das liegt am Digispark. Besten Dank nochmals.

Meinem Sohn ist dann ein Kumpel eingefallen der Programmierer
ist und sich das mal ansehen würde. Nach einigen Erklärungen
und Ablauf Skizzen, ist der Code nun fertig.
Anbei der Code und Schema, falls jemand mal das gleiche benötigt.

Gruss Marcel

[code]
const byte relaisPin = 0; // Pin für Relaisboard (OUTPUT)
const byte schaltPin = 1; // Pin für Endschalter (INPUT)
const int potiPin = A1;   // Pin für Poti (INPUT) / Für Externe Einstellung der Zeitlimite

void setup() {
  pinMode(schaltPin, INPUT);
  pinMode(relaisPin, OUTPUT);
}

static uint32_t previousMillis = 0;
static uint32_t currentMillis = 0;
static uint32_t vorgabeZeit = 0;     // diese Zeit bestimmt, ob erfüllt oder nicht erfüllt
static uint32_t vergangeneZeit = 0;
static uint32_t vorherigeZeit = 0;
static uint32_t potiWert = 0;
int schalterstatus = HIGH;
uint32_t debouncingCounter = 0;

const uint32_t zyklenAnzahl = 200;  // Diese Zahl eventuell anpassen, je nach Arduino Clock und verwendetem Schalter
const uint32_t potiFaktor = 5;      // Faktor Einstellung. Um den PotiWert zu erhöhen.

void loop() {

  potiWert = analogRead(potiPin);       // Potiwert ist die erlaubte Zeit in ms, welche nicht Überschritten werden darf
  vorgabeZeit = potiWert * potiFaktor;  // Benennung einer Variablen für (PotiWert inkl. Faktor)
  schalterstatus = LOW;                 // Schalterstatus wird zurückgesetzt

  if (digitalRead(schaltPin) == HIGH) {  // Wenn der Endschalter betätigt wurde...
    debouncingCounter = 0;               // stelle den Counter auf Null
  } else {                               // wenn nicht betätigt....
    debouncingCounter++;                 // erhöht bei jedem Durchgang um 1 / wird für einen vergleich mit der ZyklenAnzahl benötigt
  }

  if (debouncingCounter == zyklenAnzahl) {  // Wenn der Endschalter in der gewählten ZyklenAnzahl (wie als Zeit) nicht betätigt wurde,
    schalterstatus = HIGH;                  // zählen wir dies als schaltvorgang
  }

  currentMillis = millis();
  vergangeneZeit = currentMillis - previousMillis;

  if (schalterstatus == HIGH) {       // Wenn der Endschalter betätigt wird, passiert folgendes ....
    vorherigeZeit = vergangeneZeit;
    previousMillis = currentMillis;   // previousMillis wird auf die aktuelle Zeit gesetzt
    vergangeneZeit = 0;               // vergangeneZeit wird auf 0 zurückgesetzt
  }

  if (vergangeneZeit > vorgabeZeit) {    // Wenn die vergangeneZeit grösser als die vorgabeZeit ist
    digitalWrite(relaisPin, LOW);        // dann schalte das Relais der Oberen Zylinder Aus
  } else {                               // wenn Zeit kleiner, dann weiter..
    if (vorherigeZeit < vorgabeZeit) {   // Wenn die vorherigeZeit kleiner als die vorgabeZeit ist
      digitalWrite(relaisPin, HIGH);     // dann schalte das Relais der Oberen Zylinder Ein
    }
  }

  schalterstatus = LOW;
}
[/code]

Und das Schema

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.