Erkennung von Abstand zwischen zwei bewegten Teilen mittels IR-Sensor

@StefanL38: Jetzt bin ich wieder in der schon an anderer Stelle beschriebenen Zwickmühle, denn ich habe zur Ordnung meiner Gedanken ein Programm geschrieben, um mich in die Problematik einzudenken. Andere würden Grafiken malen oder Ablaufdiagramme schreiben.

Soll ich dieses Programm geheim halten?

Meine Entscheidung, ich zeige das Programm und überlasse es dem TO, etwas davon zu nehmen oder auch nicht.

Als Fan der MobaTools nutze ich diese und eine Schrittkette (= finite state machine; = endlicher Automat) mit switch/case realisiert. Da kann ich einfacher denken :roll_eyes:

Getestet mit UNO, DRV8825 und einem Schrittmotor:

//#define DEBUGGING                     // Einkommentieren für die Serielle Ausgabe
#ifdef DEBUGGING
#define DEBUG_B(...) Serial.begin(__VA_ARGS__)
#define DEBUG_P(...) Serial.print(__VA_ARGS__)
#define DEBUG_L(...) Serial.println(__VA_ARGS__)
#else
#define DEBUG_B(...)
#define DEBUG_P(...)
#define DEBUG_L(...)
#endif

#include <MobaTools.h>
MoToStepper Step(200, STEPDIR);          // Schritte pro Umdrehung

const byte stepPin = 2;          // X.STEP
const byte dirPin = 5;           // X.DIR
const byte sensorPin = 9;
const uint32_t mindestZeit = 2000;
uint32_t detectTime;
uint32_t jetzt;

void setup() {
  DEBUG_B(115200);
  DEBUG_L(F("Start ..."));
  pinMode(sensorPin, INPUT_PULLUP);       //Sensor eingang
  Step.attach( stepPin, dirPin );         // stepPin, dirPin
  Step.setSpeed( 3000 );                  // = 300 U/Min
  Step.setRampLen( 50 );                  // Beschleunigung
  Step.setZero();                         // Referenzpunkt setzen
  Step.rotate( 1 );                       // Richtung ist immer vorwärts
}

void loop()
{
  jetzt = millis();
  static byte schritt = 0;
  switch ( schritt )
  {
    case 0:
      if (digitalRead(sensorPin) == LOW)         // Sensor detektiert etwas
      {
        serMon( schritt, "Zeit gestartet" );
        detectTime = jetzt;
        schritt++;
      }
      break;
    case 1:
      if (digitalRead(sensorPin) == HIGH)         // Sensor detektiert etwas
      {
        serMon( schritt, "Teil Ende erkannt" );
        schritt++;
      }
      break;
    case 2:
      if (digitalRead(sensorPin) == LOW)         // Sensor detektiert etwas
      {
        serMon( schritt, "Teil Ende erkannt, Zeitdiff: \t", jetzt - detectTime );
        if (jetzt - detectTime >= mindestZeit)  // letzte detektZeit ist zu kurz? ...
        {
          serMon( schritt, "Zeit überschritten, Motor dreht weiter" );
          Step.rotate( 1 );                        // Richtung ist immer vorwärts
          detectTime = jetzt;
          schritt = 1;
        } else {
          serMon( schritt, "Zeit unterschritten, Motor Halt" );
          Step.rotate( 0 );                        // Anhalten mit Rampe
          Step.setZero();                          // Referenzpunkt setzen, wohl nicht benötigt, aber der Positionszähler läuft dann nicht über
          schritt++;
        }
      }
      break;
    case 3:
      if (jetzt - detectTime >= mindestZeit)  // letzte detektZeit ist zu kurz? ...
      {
        serMon( schritt, "Zeit erreicht, Motor Start" );
        Step.rotate( 1 );                        // Richtung ist immer vorwärts
        detectTime = jetzt;
        schritt = 1;
      }
      break;
    default:
      schritt = 0;
  }
}

void serMon(byte s, const char * text)
{
  serMon( s, text, 0 );
}

void serMon(byte s, const char * text, const uint32_t diff)
{
  DEBUG_P(jetzt);
  DEBUG_P(F("\tSchritt: "));
  DEBUG_P(s);
  DEBUG_P('\t');
  DEBUG_P(text);
  if (diff)
  {
    DEBUG_P('\t');
    DEBUG_P(diff);
  }
  DEBUG_L();
}

Bitte ausprobieren, fragen oder verwerfen.

Bei den MobaTools gibt es auch Zeitgeber, die ich wegen der Vergleiichbarkeit nicht genutzt habe.

"Hier stehe ich, ich kann nicht anders." Luthers berühmte Worte, die er wohl nie gesagt hat.