Erkennung von Abstand zwischen zwei bewegten Teilen mittels IR-Sensor

Sehr gut, aber eine Lichtschranke wäre einfacher :roll_eyes:

Mein Kommentar ist nicht ganz eindeutig, versuche es mal mit der Invertierung der Logik:

    case 0:
      if (isDetect == HIGH)         // Sensor detektiert etwas
...
    case 1:
      if (isDetect == LOW)         // Sensor detektiert nichts
...
    case 2:
      if (isDetect == HIGH)         // Sensor detektiert etwas

Besser?

Hallo Herman,

Aus dieser Aussage weiß man nur dass es nicht so funtkioniert wie es sollte
Aber du gibt keinerlei Details an WAS es denn macht.
Wenn du diese Details mitteilst dann kann man wesentlich besser analysieren.
Poste die Details der neuesten Version
a. als verbale Beschreibung
b. das was der serielle Monitor ausgibt als Code-Section.

Ansonsten empfehle ich dir lieber 5 Minuten in die sorgfälte Formulierung der Variablennamen zu investieren und dann das Programm schnell analysieren zu können.

Einschub: Das folgende trifft möglicherweise gar nicht auf dich zu dann wäre das prima.

Lieber 5 Minuten pro Variable überlegen wie nenne ich die genau als 50 Minuten Zeit zu verplempern mit schlecht gewählten Variablennamen und 10 bis 20 "Schnellversuchen" probiere ich mal ....

Ein Variablename wie "TEIL" sagt überhaupt nichts darüber aus welches Teil.
Teil 1? oder Teil 2?
Ausserdem geht es darum den Anfang bzw. das Ende von Teilen zu detektieren. Dazu sagt "TEIL" auch nichts aus.

Bei "detect" ist das ähnlich. Es wurde etwas detektiert. Ja schön und was?

Ebenso bei Zahl = 1 und Zahl = 2

Was bedeutet das wenn "Zahl" = 1 ist ???
Was bedeutet es wenn "Zahl" = 2 ist ???

Im Moment mag das mit diesen Variablennamen gerade noch so gehen.
Sobald noch drei bis vier Variablen dazukommen wirst du in zwei Wochen deinen eigenen Code nicht mehr verstehen.

Deshalb selbst-erklärende Namem für alle Variablen und für alle functions.
Bei diesem überlegen wird einem auch der Programmablauf was man wirklich braucht klarer.

Bei so nichtssagenden Variablennamen wie "TEIL" habe ich auch keine Lust mir das erst einmal ales zu "übersetzen" was das bedeutet.

Mit den selbsterklärenden Namen braucht man dann auch keine erklärenden Kommentare mehr weil die Erklärung ja schon im Namen selbst gegeben ist.

Also überarbeite das Programm einmal entsprechend.
vgs

das widerspricht sich mit dem hier

Ich würde hier sogar so weit gehen zwei Konstanten zu definieren die Klartext sprechen

#define TeilVorhanden LOW
#define KeinTEIL HIGH

damit werden die Bedingungen dann
if (digitalRead(sensorPin) == TeilVorhanden ) // kein Kommentar mehr notwendig

if (digitalRead(sensorPin) == KeinTEIL ) // kein Kommentar mehr notwendig

und der Klartext stupst einen dann auch viel eher auf logische Fehler
vgs

Es ist eine "Lichtschranke" nur eben Reflexion Lichtschranke.
Du meinst Lichtschranke - Sender - Empfänger == sogenannte Durchgangsstrahl Lichtschranke.
Jedoch wem man die gut einstellt und benutzt Reflexion Spiegel, Folie sollte auch besser funktionieren
Grüße

Ja, ich meinte etwas, was durchgehend ein Signal sendet und empfängt, ohne erst ein Triggersignal zu benötigen, denn dadurch ist KY-23 zeitweise blind.

IR Diode + Fototransistor in TO18 (haben kleineren Empfangswinkel) reicht auch.

Vollkommen Recht !!!

Vielleich mal mit dieser Variante versuchen:

int Led = 13 ;// Deklaration des LED-Ausgangspin

const byte sen = 9;
const unsigned long minStepTime = 50;
const unsigned long minWaitTime = 2000;

struct object_type {
    boolean       Found = false;
    unsigned long Time        = 0;
    unsigned long WaitTime    = 0;
  };

object_type object;  

struct motor_type {
    unsigned long lastStep;
    byte dirPin;
    byte stepPin;
    boolean Stopped;
};

motor_type motor = {
  0,
  5,
  2,
  false
};

void setup ()
{
  Serial.begin(115200);
  pinMode(motor.stepPin, OUTPUT);   // Step Signal fuer Geschw.
  pinMode(motor.dirPin, OUTPUT);    //Dir -> direction
  pinMode (Led, OUTPUT) ; // Initialisierung Ausgangspin
  pinMode (sen, INPUT) ; // Initialisierung Sensorpin
  digitalWrite(motor.dirPin, LOW);
}

  
void loop ()
{
  
  if (ObjectDetected()) HandleObject();
                   else object.Found = false;
  if (millis()-object.Time < object.WaitTime) Wait();
                                         else GoOn();                 
}

boolean ObjectDetected(){
  static byte          lastState = LOW;
  static unsigned long lastChangeTime = 0;
  byte value = digitalRead(sen);
  if (value != lastState) lastChangeTime = millis();
  lastState = value;
  if (millis() - lastChangeTime > 5) {
     return !lastState;     
   } return false;
}

void HandleObject(){
   if (!object.Found) {           // Falls bisher noch nicht erkannt
             object.Found = true;   
             unsigned long delta = millis()- object.Time; 
             if (delta < minWaitTime) object.WaitTime = minWaitTime-delta;
                                 else object.WaitTime = 0;
            object.Time = millis(); // dann jetzt die Zeit nehmen
          Serial.print("Objekt erkannt\t");
          Serial.println(object.WaitTime);
        }
 }


void Wait(){
    if (!motor.Stopped) {
        digitalWrite (Led, HIGH);
        Serial.print(millis());
        Serial.println("\t...WARTEN...");
        motor.Stopped = true;
    }
}

void GoOn(){
    if (motor.Stopped) {
        digitalWrite (Led, LOW);
        Serial.print(millis());
        Serial.println("\t...weiter...");
        motor.Stopped = false;
      }
    MoveMotor();  
}

void MoveMotor(){
  if (millis()-motor.lastStep > minStepTime) {
     motor.lastStep = millis();
    digitalWrite(motor.stepPin, HIGH);
    delayMicroseconds(471);
    digitalWrite(motor.stepPin, LOW);
    delayMicroseconds(471); 
  }
}
  • Die Zeit zwischen zwei Steps lässt sich über minStepTime einstellen.
  • Die Zeit zwischen zwei Objekten über minWaitTime.
  • Die Abfrage des Sensors habe ich mal vorsichtshalber mit 5 ms "debounced".

Das meiste konnte ich mit einem eigenen Aufbau prüfen, allerdings nur mit der Arduino Stepper-Lib, da ich kein A4988-Shield besitze, Dies habe ich dann in Wokwi umgesetzt (wo der Objekterkenner allerdings durch einen Taster simuliert wird):

https://wokwi.com/projects/333389749240726099

EDIT: Und hier eine Version, die auf der Zeit basiert, zu der das vorhergehende Teil den Sensor passiert hat und zudem das erste Teil nach Start des Sketches ohne Halt behandelt.

int Led = 13 ;// Deklaration des LED-Ausgangspin

const byte sen = 9;
const unsigned long minStepTime = 50;
const unsigned long minWaitTime = 2000;

struct object_type {
    boolean       Found = false;
    boolean       First = true;
    unsigned long Time        = 0;
    unsigned long WaitTime    = 0;
  };

object_type object;  

struct motor_type {
    unsigned long lastStep;
    byte dirPin;
    byte stepPin;
    boolean Stopped;
};

motor_type motor = {
  0,
  5,
  2,
  false
};

void setup ()
{
  Serial.begin(115200);
  pinMode(motor.stepPin, OUTPUT);   // Step Signal fuer Geschw.
  pinMode(motor.dirPin, OUTPUT);    //Dir -> direction
  pinMode (Led, OUTPUT) ; // Initialisierung Ausgangspin
  pinMode (sen, INPUT) ; // Initialisierung Sensorpin
  digitalWrite(motor.dirPin, LOW);
}

  
void loop ()
{
  
  if (ObjectDetected()) HandleObject();
                   else HandleNoObject();
  if (millis()-object.Time < object.WaitTime) Wait();
                                         else GoOn();                 
}

boolean ObjectDetected(){
  static byte          lastState = LOW;
  static unsigned long lastChangeTime = 0;
  byte value = digitalRead(sen);
  if (value != lastState) lastChangeTime = millis();
  lastState = value;
  if (millis() - lastChangeTime > 5) {
     return !lastState;     
   } return false;
}

void HandleNoObject(){
   if (object.Found) object.Time = millis();
   object.Found = false;
}

void HandleObject(){
   if (!object.Found) {           // Falls bisher noch nicht erkannt
             object.Found = true;   
             unsigned long delta = millis()- object.Time; 
             if (delta < minWaitTime) object.WaitTime = minWaitTime-delta;
                                 else object.WaitTime = 0;
             if (object.First) {
                object.First = false;
                object.WaitTime = 0;
             }                    
          Serial.print("Objekt erkannt\t");
          Serial.println(object.WaitTime);
        }
 }


void Wait(){
    if (!motor.Stopped) {
        digitalWrite (Led, HIGH);
        Serial.print(millis());
        Serial.println("\t...WARTEN...");
        motor.Stopped = true;
    }
}

void GoOn(){
    if (motor.Stopped) {
        digitalWrite (Led, LOW);
        Serial.print(millis());
        Serial.println("\t...weiter...");
        motor.Stopped = false;
      }
    MoveMotor();  
}

void MoveMotor(){
  if (millis()-motor.lastStep > minStepTime) {
     motor.lastStep = millis();
    digitalWrite(motor.stepPin, HIGH);
    delayMicroseconds(471);
    digitalWrite(motor.stepPin, LOW);
    delayMicroseconds(471); 
  }
}

siehe auch https://wokwi.com/projects/333432193768489556

Der wesentliche Unterschied zwischen erster und zweiter Version ist, dass

  • in der ersten Version die Wartezeit zwischen den Zeitpunkten der Eintritte in den Strahlengang des Sensors verwendet wird,
  • in der zweiten Version die Wartezeit zwischen dem Zeitpunkt des Austritts des vorhergehenden Objektes und dem Eintritt des folgenden Objektes angewandt wird.

Damit sollte in der zweiten Version die Wartezeit unabhängig von der Länge des vorhergehenden Objektes sein ... (ausgenommen der Fall, dass das Teil für den Durchlauf genauso lange wie oder länger als die Wartezeit benötigt ...).

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