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 ...).