Big problem, bloody mess of code, desperated

Hi guys,

I have make a really nice project. I put an endless amount of time in it and it is working now. It ALMOST works. :frowning:
In this video you can see a 3D printed fish feeder which is driven by an ESP32. The components are:
stepper motor NEMA 17 (turning the wheel)
1LDR (to avoid collisions by accident)
1
fork light barrier (to set zero point/starting position) (not really seen in this video)
1*SG90 servo (for emptying the boxes)

insane fish feeder

So, my problem is, it seems to work fine. But after a few actions, the feeder does not move to zero position anymore and it ends up in not choosing the correct boxes anymore.

To be honest, I am a very bad coder. I put codes together from examples and often ask questions in this forum.
No the moment has come, I am lost in this bloody mess of a code.

Maybe there are some guys, who has the time and the patience to have a look at the code and give me advices what I have to change. Maybe there are things in this code which are not needed.
Here it is...

//letzte Änderung:  if (executed == false && lightVal > 500) von 300 auf 500 gesetzt, da es immer schon bei 400 war. scheint aber wohl netzteil abhängig zu sein.
//letzte Änderung 15.06.22:  Servo beschleunigt
#include <AccelStepper.h>
#include <Servo.h>
#include "WiFi.h"
#include <PubSubClient.h>
#include <WiFiUdp.h>
#include <NTPClient.h>                              // include NTPClient library
#include <time.h>                                   // time() ctime()

// Define NTP properties
#define NTP_ADDRESS  "de.pool.ntp.org"              // change this to whatever pool is closest (see ntp.org)
#define MY_TZ "CET-1CEST,M3.5.0/02,M10.5.0/03"      //Timezone
time_t now;                                         // this is the epoch
tm tm;                                              // the structure tm holds time information in a more convient way
String t = "";

#define dirPin 33
#define stepPin 32
#define motorInterfaceType 1
#define SERVO_PIN 26 // ESP32 pin GIOP26 connected to servo motor
String temp = "";  //temporär
String packet = "";
String received = "";
#define onoffpin 16  //servo on off pin
Servo servoMotor;

//WIFI
const char *ssid     = "fghjfghj";                              
const char *password = "fghjfghj";
const char* deviceName = "esp32_feeder";

String command;

const int MS1 = 14;
const int MS2 = 13;
const int MS3 = 12;
int MOTOR_STEPS = 200;

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

const int buttonPin = 4;     // the number of the pushbutton pin
int buttonState = 0;         // variable for reading the pushbutton status
#define LED1  18
#define LED2  5
#define LED3  23  //white
const int sensorPin = 35;  //photoelectric pin
int LDRValue;  //LDR Value
int lightInit;  // initial value
int lightVal;   // light reading
bool nulled = false;
bool executed = false;
bool going = false;
bool activated = true;

unsigned long previousMillisLED = 0;                // will store last time LED3 was updated
unsigned long intervalLED = 45000;                   // interval at which to switch off LED3 (milliseconds)


const int g1 = 280;
const int g2 = 175;
const int g3 = 65;
const int g4 = -40;
const int g5 = -145;

int counteryellow = 0;

const int MotorStepyellow[5] = {g1, g2, g3, g4, g5};

const int b1 = -250;
const int b2 = -360;
const int b3 = -460;
const int b4 = -570;
const int b5 = -675;

int counterblue = 0;

const int MotorStepblue[5] = {b1, b2, b3, b4, b5};

const int s1 = -786;
const int s2 = 705;
const int s3 = 600;
const int s4 = 490;
const int s5 = 380;
int counterblack = 0;

// Variables for publish counter via mqtt

String counterblack_str; 
String counterblue_str;
String counteryellow_str;
char black[5];
char blue[5];
char yellow[5];

const int MotorStepblack[5] = {s1, s2, s3, s4, s5};

char buffer[40]; // added for monitor reading


const char* mqtt_server = "192.168.178.44";
const int mqttPort = 1883;
const char* mqttUser = "dfghdghd";
const char* mqttPassword = "dfghdhg";
//mqtt ende

// WiFi connect timeout per AP. Increase when connecting takes longer.
const uint32_t connectTimeoutMs = 5000;
unsigned long previousMillis = 0;                   // will store last time updated
const long interval = 30000;                        // interval at which to run   muss 15000 sein
unsigned long previousMillisLED1 = 0;                // will store last time LED1 was updated
unsigned long intervalLED1 = 1000;                   // interval at which to blink (milliseconds)
int LED1State = LOW;


WiFiClient espClient;
PubSubClient client(espClient);


void nullposition() {
  //digitalWrite(LED3, HIGH); // 04062022
  stepper.enableOutputs();
  LDRValue = analogRead(A0); // read analog input pin 0
  lightVal = analogRead(sensorPin);
  Serial.println("check fork light barrier");
  Serial.println(lightVal);
  stepper.setMaxSpeed(200);
  if (executed == false && lightVal > 700) {
    stepper.runToNewPosition(-100);
    Serial.println("detection positive --> repositioning");
    executed = true;
  //  delay(2000);
  }
 

 lightVal = analogRead(sensorPin);
 LDRValue = analogRead(A0); // read analog input pin 0
  stepper.moveTo(4000);
  while (lightVal < 700 && nulled != true && LDRValue > 3000) {// Full speed up to 300
    stepper.run();
    lightVal = analogRead(sensorPin); // read the current light levels
LDRValue = analogRead(A0); // read analog input pin 0
  }

  stepper.stop(); // Stop as fast as possible: sets new target
  stepper.runToPosition();
  stepper.setCurrentPosition(0);  //set steppercounter to 0 aufter reaching endstop switch
  if (LDRValue > 3000) {
    Serial.println(LDRValue); // prints the value read
      Serial.println("moved on to null position"); // prints the value read
  nulled = true;
  
    Serial.println("null position set");
  Serial.println(stepper.currentPosition());
  }
  stepper.setMaxSpeed(200);
  stepper.disableOutputs();
LDRValue = analogRead(A0); // read analog input pin 0
  if (LDRValue < 3000) {
   Serial.println("light barrier interrupted");   
  Serial.println(LDRValue); // prints the value read
  Serial.println("move to empty position again"); 
  moveemptyposition();
  stepper.moveTo(4000);
  }
  
  // delay(10);
}


void setup() {
  Serial.begin(115200);
  servoMotor.attach(SERVO_PIN);  // attaches the servo on ESP32 pin
  lightInit = analogRead(sensorPin);
  Serial.println(lightInit);
  pinMode(onoffpin, OUTPUT);
  digitalWrite(onoffpin, LOW);
  pinMode(buttonPin, INPUT); //initialize the pushbutton pin as an input
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  digitalWrite(LED1, LOW); 
  digitalWrite(LED2, LOW); 
  digitalWrite(LED3, HIGH); 
  stepper.setPinsInverted(false, false, true);
  stepper.setEnablePin(25);
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(MS3, OUTPUT);
  digitalWrite(MS1, HIGH);
  digitalWrite(MS2, HIGH);
  digitalWrite(MS3, HIGH);

  setup_wifi();
  client.setServer(mqtt_server, mqttPort);
  client.setCallback(callback);
  reconnect();
  configTzTime(MY_TZ, NTP_ADDRESS);
  ntp();
  // Set the maximum speed and acceleration:
  stepper.setMaxSpeed(200);   //(1000)
  stepper.setAcceleration(800);  //(1000)
  nullposition();

}


void callback(char* topic, byte* payload, unsigned int length) {
  String sTopic = String(topic);
  Serial.print("topic empfangen: ");
  Serial.println(String(topic));


  if (sTopic == "aqua/feeder") {
activated = true;
 digitalWrite(LED3, HIGH); 
    temp = "";

    for (int i = 0; i < length; i++) {
      temp += ((char)payload[i]);
    }
    received = temp;
    Serial.println(received);
    moveposition();
  }

 
}

void setup_wifi() {


  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }

  Serial.println("Connected to the WiFi network");
}
void reconnect() {

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi not connected!");
    void setup_wifi();
  }
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    char clientid[25];
    snprintf(clientid, 25, "WIFI-Display-%08X", "12345"); //this adds the mac address to the client for a unique id
    Serial.print("Client ID: ");
    Serial.println(clientid);
    if (client.connect(clientid)) {
      Serial.println("connected");


      client.subscribe("aqua/feeder");

    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 1 second before retrying
      delay(1000);
    }
  }
}
void moveposition() {

  if (received == "blue") {
    if ( counterblue < 5 ) {
      MOTOR_STEPS = MotorStepblue[counterblue++];
      sprintf ( buffer, "Counter: %d \t MotoStepValues blue: %d", counterblue, MOTOR_STEPS);
      Serial.println(buffer);
if (counterblue == 5) {
  counterblue = 0;
}
    }
    else {
      Serial.println("bullshit");
    }
  }


  if (received == "yellow") {

    MOTOR_STEPS = MotorStepyellow[counteryellow++];
    sprintf ( buffer, "Counter: %d \t MotoStepValues yellow: %d", counteryellow, MOTOR_STEPS);
    Serial.println(buffer);
if (counteryellow == 5) {
  counteryellow = 0;
}
  }
  if (received == "black") {

    MOTOR_STEPS = MotorStepblack[counterblack++];
    sprintf ( buffer, "Counter: %d \t MotoStepValues black: %d", counterblack, MOTOR_STEPS);
    Serial.println(buffer);
if (counterblack == 5) {
  counterblack = 0;
}
  }
  if (received != "black" && received != "yellow" && received != "blue" ) {
    // nulled = false;
    MOTOR_STEPS = 0;
  }
  nulled = false;
  executed = false;
  nullposition();
  executed = true;

  stepper.enableOutputs();
  stepper.setMaxSpeed(200);   //(1000)
  stepper.setAcceleration(800);  //(1000)
  //MOTOR_STEPS = command.toInt();

  if (nulled == true) {
    Serial.println("fahren");
    stepper.moveTo(MOTOR_STEPS);
    while (stepper.currentPosition() != MOTOR_STEPS) {
      stepper.run();
      //Serial.println(stepper.currentPosition());
    }
    nulled = false;

    //stepper.disableOutputs();
  }
 if (received == "black" || received == "yellow" || received == "blue" ) {  
  empty();
 }
 else {
    nulled = false;
    executed = false;
  nullposition();
 }
}

void empty()
{
  digitalWrite(onoffpin, HIGH);
  // rotates from 110 degrees to 0 degrees
  /* for (int pos = 110; pos >= 0; pos -= 1) {
    servoMotor.write(pos);
    delay(20); // waits 15ms to reach the position - last value 20
  }
  for (int pos = 0; pos <= 110; pos += 1) {
    // in steps of 10 degree
    servoMotor.write(pos);
    delay(20); // waits 15ms to reach the position - last value 20
  }
  */
  for (int pos = 110; pos >= -50; pos -= 1) {
    servoMotor.write(pos);
    delay(1); // waits 15ms to reach the position - last value 20
  }
 
  for (int pos = -50; pos <= 110; pos += 1) {
    // in steps of 10 degree
    servoMotor.write(pos);
    delay(5); // waits 15ms to reach the position - last value 20
  }

   for (int pos = 110; pos >= -50; pos -= 1) {
    servoMotor.write(pos);
    delay(1); // waits 15ms to reach the position - last value 20
  }
 
  for (int pos = -50; pos <= 110; pos += 1) {
    // in steps of 10 degree
    servoMotor.write(pos);
    delay(5); // waits 15ms to reach the position - last value 20
  }

   for (int pos = 110; pos >= -50; pos -= 1) {
    servoMotor.write(pos);
    delay(3); // waits 15ms to reach the position - last value 20
  }
 
  for (int pos = -50; pos <= 110; pos += 1) {
    // in steps of 10 degree
    servoMotor.write(pos);
    delay(5); // waits 15ms to reach the position - last value 20
  }
  //delay(5000);

  moveemptyposition();
}

void moveemptyposition() {
   delay(500);
  stepper.enableOutputs();
  stepper.setMaxSpeed(200);   //(1000)
  stepper.setAcceleration(800);  //(1000)
  MOTOR_STEPS = stepper.currentPosition() - 350;
  stepper.moveTo(MOTOR_STEPS);
  while (stepper.currentPosition() != MOTOR_STEPS) {
    stepper.run();
   // Serial.println(stepper.currentPosition());

  }
  nulled = false;
  nullposition();
}

void loop() {

    unsigned long currentMillisLED = millis();

  if ((currentMillisLED - previousMillisLED > intervalLED)&& activated == true) {
    // save the last time you blinked the LED
    previousMillisLED = currentMillisLED;
  digitalWrite(LED3, LOW);
  digitalWrite(onoffpin, LOW);
  activated = false;
    }
  
  buttonState = digitalRead(buttonPin);
  if (Serial.available()) {

    command = Serial.readStringUntil('\n');
    command.trim();
    Serial.print("you have typed: ");
    Serial.println(command);
    if (command.equals("99")) {
      //Serial.println("go to null position");
      nulled = false;
      nullposition();

    }
    else if (command.equals("999")) {
      empty();
    }
    else  {
      moveposition();
    }

  }

  if (WiFi.status() == WL_CONNECTED) {                            //blink blue LED1 while wifi is connected

    unsigned long currentMillisLED1 = millis();

    if (currentMillisLED1 - previousMillisLED1 > intervalLED1) {
      // save the last time you blinked the LED1
      previousMillisLED1 = currentMillisLED1;
      LED1State = !LED1State;
      // if the LED1 is off turn it on and vice-versa:
      if (LED1State == HIGH) {
        digitalWrite(LED1, LOW);
        intervalLED1 = 3000;
      } else {
        digitalWrite(LED1, HIGH);
        intervalLED1 = 100;
      }
    }
  }

  if (buttonState == HIGH) {

counterblack = 0;
counterblue = 0;
counteryellow = 0;

    digitalWrite(LED2, HIGH);

  }
  else {
    digitalWrite(LED2, LOW);

  }


  reconnect();


  
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {

      Serial.print("counteryellow jetzt: ");
      Serial.println(counteryellow);
      Serial.print("counterblack jetzt: ");
      Serial.println(counterblack);
      Serial.print("counterblue jetzt: ");
      Serial.println(counterblue);
      Serial.println("publish werte zu smartphone");

      lightVal = analogRead(sensorPin);
        Serial.println("check fork light barrier in loop");
  Serial.println(lightVal);
ntp();
//Preparing for mqtt send

    counteryellow_str = String(counteryellow); //converting ftemp (the float variable above) to a string 
    counteryellow_str.toCharArray(yellow, counteryellow_str.length() + 1); //packaging up the data to publish to mqtt whoa...

    counterblack_str = String(counterblack); //converting Humidity (the float variable above) to a string
    counterblack_str.toCharArray(black, counterblack_str.length() + 1); //packaging up the data to publish to mqtt whoa...

    counterblue_str = String(counterblue); //converting Humidity (the float variable above) to a string
    counterblue_str.toCharArray(blue, counterblue_str.length() + 1); //packaging up the data to publish to mqtt whoa...
      
      client.publish("aqua/feeder/counteryellow", yellow);
      client.publish("aqua/feeder/counterblack", black);
      client.publish("aqua/feeder/counterblue", blue);
     // client.publish("aqua/feeder/zeit", t.c_str());
          
     previousMillis = currentMillis;
    }

  
  client.loop();

}


void convert2Json()
{
  // Temperature in Celsius

  packet = "";


  packet.concat(("{\"temp\": "));
  // packet.concat(temperature);


  packet.concat("}");
  Serial.println(packet);
  //client.publish("sensors/room/aqua", packet.c_str());
  Serial.println("sensors/room/aqua  published");
}

void ntp()
{
  //Seperate the components of the time/date for using it to trigger the event of setzero()".
  //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  time(&now);                               // read the current time
  localtime_r(&now, &tm);                   // update the structure tm with the current time
 /* Serial.print("year:");
  Serial.print(tm.tm_year + 1900);          // years since 1900
  Serial.print("\tmonth:");
  Serial.print(tm.tm_mon + 1);              // January = 0 (!)
  Serial.print("\tday:");
  Serial.print(tm.tm_mday);                 // day of month
  Serial.print("\thour:");
  Serial.print(tm.tm_hour);                 // hours since midnight  0-23
  Serial.print("\tmin:");
  Serial.print(tm.tm_min);                  // minutes after the hour  0-59
  Serial.print("\tsec:");
  Serial.print(tm.tm_sec);                  // seconds after the minute  0-61*
  Serial.print("\twday");
  Serial.println(tm.tm_wday);               // days since Sunday 0-6
*/
  //  date = String(tm.tm_mday) + "." + String(tm.tm_mon + 1) + "." + String(tm.tm_year + 1900);
  // savedate = String(tm.tm_mon + 1) + String(tm.tm_year + 1900) + ".csv";
  t = String(tm.tm_hour) + ":" + String(tm.tm_min) + ":" + String(tm.tm_sec);

  if (tm.tm_isdst == 1)                     // Daylight Saving Time flag
    Serial.print("\tDST");
  else
    Serial.print("\tstandard");
  Serial.println();

}
#define onoffpin 16  //servo on off pin

Please tell me that you are not powering the servo directly from an Arduino pin

Looking at code can only tell one what it actually does, so you will first need to describe, in words not code, exactly what it's supposed to do.

So, if I understand... your feeder receives a command (a colour) via wifi and based on that dispenses food of that colour into the fish tank.

Once it has dispensed the food, it should return to "position 0".

Your problem is that after a few commands (is it always the same number of commands?) it does not return to "position 0"... and after that it does not function correctly?

Is the routine nullpostion() the thing that sets it to "position 0" ?

How do you know you are at "position 0"?

What does the LDR do?

I can confirm that. I do not powering the servo and also the stepper directly from an esp32 pin.

Ok, you are right.

The ESP32 connects to wifi and to a mqtt broker to get the commands "blue" "yellow" and "black" by mqtt. Triggert by a google calendar and node-red. node-red is sending the mqtt message. Of course you can send such a message manually by using some kind of mqtt client for testing purposes.

I try to describe what it is doing excatly.

First of all, the stepper is not in holding mode during no command is executing. so you can turn the wheel by hand at every time.
That means, before a command can be executed, I have to set the wheel to a null position which is defined by a fork light barrier and a little tile which is moving into it and instantly stop there. Here is a picture of that:
tile

If the wheel was not moved and nonetheless the fork light barrier is detecting the little tile, it have to move just some steps forward and the go to null again. The reason is, that if someone or something has moved the wheel just a little bit the light barrier is still blocked but the device is in reality not at null position anymore and this could cause problems when turning to empty position and so on. For that reason the go to null position process has to executed everytime a command is received.

After nulled, the wheel is moving to one of the boxes. There are 5 boxes of each color and a counter defines which box has to be emptied. This is working.

The empty-process is like this:
move the servo several times (in the past sometimes a box jammed)
spin the wheel counterclockwise (actual steps minus 350) to get the box in its up-position again
move to nullposition

There is an LDR sensor at the place where the boxes are emtying. That's to avoid crashing the device when it moves to nullposition and a box did not stay in its up-position by accident.
In this case the device instantly stops and try to do the minus 350 steps again to get the box up to its up-position.
THen it should go to nullposition again.
This case normaly can't happens unless someone maniulates by hand. but for security reasons it is implemented.

Ok, my problem is, that after a few boxes were emptied, the device does not go to nullposition anymore. It just spins about 300 steps in the correct direction but did not reach the light fork barrier. And also from this point, the nulling process BEFORE each command execution does not work properly anymore. I have no clue why.

[note: I think all of the "executed false/true" commands are probably not necessary and of course the "void convert2Json()" part is actually not in use. but that should not matter]

I hope this question is answered now by the long text. The nullposition has to set everytime again because it might be happen that someone spin the wheel between the feeding intervalls.
Feeding happens two times a day.
Typically the first error appears at the 4th feeding.
today 1 PM yellow
today 8 PM blue
tomorrow 1 PM yellow
tomorrow 8 PM blue <-- typically first error. but not 100% sure if that's always the case.
At my table by trying to reproduce this, it is most time this 4th empty action.

the first 3 are always fine. that seems to be sure

Does nullPosition() get called when it fails?

Do you see

  Serial.println("check fork light barrier");
  Serial.println(lightVal);

in the log?

If so then then problem is likely in nullPosition().

seems like a lot of code to debug by inspection

i'd suggest working on a much small piece of code that exercises pieces of code based on serial commands to verify the function and sub-functions that operate the feeder.

One should not expect a MG90 plastic geared servo to go to 0 position reliably. Over time those plastic gears wear out and the ability of the servo to find the 'exact' position gets worse.

What does this mean,

?

I have made a new video where you can see the error. It starts after the 3rd blue empty action. the device did not go to null. you can see it the the tile did not move to the fork light barrier.
after that, the following yellow action goes wrong. So:
1.) why the heck did it not go to null position
2.) not going to null position shoudl not matter cause before executing every command regardless it should do the nullpositioning process. THis also did not work.

here ist the log output:

topic empfangen: aqua/feeder
yellow
Counter: 1 	 MotoStepValues yellow: 280
check fork light barrier
893
detection positive --> repositioning
3390
moved on to null position
null position set
0
fahren
check fork light barrier
397
3381
moved on to null position
null position set
0
counteryellow jetzt: 1
counterblack jetzt: 0
counterblue jetzt: 0
publish werte zu smartphone
check fork light barrier in loop
928
	DST
topic empfangen: aqua/feeder
blue
Counter: 1 	 MotoStepValues blue: -250
check fork light barrier
906
detection positive --> repositioning
3376
moved on to null position
null position set
0
fahren
check fork light barrier
389
3362
moved on to null position
null position set
0
topic empfangen: aqua/feeder
yellow
Counter: 2 	 MotoStepValues yellow: 175
check fork light barrier
895
detection positive --> repositioning
3393
moved on to null position
null position set
0
fahren
check fork light barrier
373
counteryellow jetzt: 2
counterblack jetzt: 0
counterblue jetzt: 1
publish werte zu smartphone
check fork light barrier in loop
409
	DST
topic empfangen: aqua/feeder
blue
Counter: 2 	 MotoStepValues blue: -360
check fork light barrier
406
3389
moved on to null position
null position set
0
fahren
check fork light barrier
400
3383
moved on to null position
null position set
0
topic empfangen: aqua/feeder
yellow
Counter: 3 	 MotoStepValues yellow: 65
check fork light barrier
906
detection positive --> repositioning
3317
moved on to null position
null position set
0
fahren
check fork light barrier
400
3385
moved on to null position
null position set
0
counteryellow jetzt: 3
counterblack jetzt: 0
counterblue jetzt: 2
publish werte zu smartphone
check fork light barrier in loop
916
	DST
topic empfangen: aqua/feeder
blue
Counter: 3 	 MotoStepValues blue: -460
check fork light barrier
897
detection positive --> repositioning
3385
moved on to null position
null position set
0
fahren
check fork light barrier
402
topic empfangen: aqua/feeder
yellow
Counter: 4 	 MotoStepValues yellow: -40
check fork light barrier
403
light barrier interrupted
1344
move to empty position again
check fork light barrier
400
3383
moved on to null position
null position set
0
fahren
check fork light barrier
400
3388
moved on to null position
null position set
0
Attempting MQTT connection...Client ID: WIFI-Display-3F4010E1
connected
counteryellow jetzt: 4
counterblack jetzt: 0
counterblue jetzt: 3
publish werte zu smartphone
check fork light barrier in loop
896
	DST
topic empfangen: aqua/feeder
blue
Counter: 4 	 MotoStepValues blue: -570
check fork light barrier
875
detection positive --> repositioning
3391
moved on to null position
null position set
0
fahren
check fork light barrier
387
3384
moved on to null position
null position set
0
Attempting MQTT connection...Client ID: WIFI-Display-3F4010E1
connected
topic empfangen: aqua/feeder
yellow
Counter: 5 	 MotoStepValues yellow: -145
check fork light barrier
899
detection positive --> repositioning
3387
moved on to null position
null position set
0
fahren
check fork light barrier
397
3386
moved on to null position
null position set
0
counteryellow jetzt: 0
counterblack jetzt: 0
counterblue jetzt: 4
publish werte zu smartphone
check fork light barrier in loop
927
	DST
topic empfangen: aqua/feeder
blue
Counter: 5 	 MotoStepValues blue: -675
check fork light barrier
898
detection positive --> repositioning
3381
moved on to null position
null position set
0
fahren
check fork light barrier
384
3389
moved on to null position
null position set
0
counteryellow jetzt: 0
counterblack jetzt: 0
counterblue jetzt: 0
publish werte zu smartphone
check fork light barrier in loop
921

you can see the line

check fork light barrier
403

this value is normaly around 900 but because the fork light barrier is not blocked, it is 403.

video:
feeder starts sucking at 1:56

the wheel is driven by a stepper not by the servo. the servo moves to empty the boxes.

sucking feeder

the not blocked catched my attention.

I have used some of this fork-light-barriers too and made this observation:

for a green plastic 1 mm thick tile the lightbarrier was not blocked
I had to glue aluminium-foil on the tile to make it work reliably
This green-plastic tile was transparent enough for the infrared-light to make the lightbarrier switch to "un-interrupted beam even with the tile in the fork !

So if you simply put black adhesive tape or aluminium on the tile you could test if this is the reason why it is not working reliably.

If it is something else serial debugging or in your case maybe sending UDP-messages is the way to go to print out much more details to see what is going on in your code

I use two macros that keep adding the debug-code short. In a single line of code it prints a fixed text the name of a variable and the value of the variable.

There is a variant of the macro that can be used in fast running loops which will print only after a user-defined time-intervall

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * 

https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298
#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope

#define dbgi(myFixedText, variableName,timeInterval) \
  do { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  } while (false);
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a 
// Serial.print is executed
// end of macros dbg and dbgi
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * 

best regards Stefan