Problema con movimiento de motores paso a paso + CNC shield

He creado un programa en el que mediante conexión serial, se envían unas coordenadas obtenidas mediante visión artificial desde una placa Raspberry Pi a una Arduino. He descartado todos los problemas de conexión ya que recibo todos los datos. El problema es a la hora de introducir una función de movimiento de motores (en los ejes X, Y), la placa Arduino, en el caso de tener 10 pares de coordenadas, a las sexta por ejemplo deja de funcionar.

¿Alguien sabe por qué puede suceder esto?

Sin ver el código es difícil ayudarte.
Por favor adjunta el código de acuerdo a las Normas del Foro en Español, punto 7.
Antes de copiarlo usa la opción Autoformato del menú Herramientas de la IDE así nos facilitas su lectura.

Adjunto el código. Se trata de una aplicación de pick and place:

// Definir el tamaño máximo del array de datos
#define MAX_DATOS 25
#include <AccelStepper.h>

// Configuración de los pines para el CNC Shield
#define X_STEP_PIN 2
#define X_DIR_PIN 5
#define Y_STEP_PIN 3
#define Y_DIR_PIN 6
#define Z_STEP_PIN 4
#define Z_DIR_PIN 7

// Configuración de las dimensiones del sistema
const float stepsPerRevolution = 200;  // Número de pasos por revolución del motor
const float microstepping = 8;         // Factor de microstepping del controlador

// Crear objetos AccelStepper para los tres motores
AccelStepper stepperX(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN);
AccelStepper stepperY(AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN);
AccelStepper stepperZ(AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN);

// Coordenadas objetivo en el espacio cartesiano
float targetX = 0.0;
float targetY = 0.0;
float targetZ = 0.0;

// Definir la estructura para almacenar los datos de cada objeto
struct Objeto {
  String tipo;
  int coordenadaX;
  int coordenadaY;
};

// Declarar el array para almacenar los datos de los objetos
Objeto objetos[MAX_DATOS];
// Variable para rastrear el número de objetos recibidos
int numeroObjetos = 0;


float Z = 100.00;
float X;
float Y;

void recibirDatosObjetos() {
  // Variable para rastrear el número de objetos recibidos
  while (Serial.available()) {
    String input = Serial.readStringUntil('\n');
    if (input.length() > 0) {
      // Dividir la cadena de entrada en el tipo de objeto, coordenada X y coordenada Y
      int comma1 = input.indexOf(',');
      int comma2 = input.indexOf(',', comma1 + 1);
      if (comma1 != -1 && comma2 != -1) {
        String tipo = input.substring(0, comma1);
        int coordenadaX = input.substring(comma1 + 1, comma2).toInt();
        int coordenadaY = input.substring(comma2 + 1).toInt();

        // Crear un nuevo objeto y asignar los datos recibidos
        Objeto nuevoObjeto;
        nuevoObjeto.tipo = tipo;
        nuevoObjeto.coordenadaX = coordenadaX;
        nuevoObjeto.coordenadaY = coordenadaY;

        // Añadir el objeto al array
        objetos[numeroObjetos] = nuevoObjeto;

        // Incrementar el contador de objetos
        numeroObjetos++;
        Serial.print(numeroObjetos  );


        // Verificar si se ha alcanzado el tamaño máximo del array
        if (numeroObjetos >= MAX_DATOS) {
          break; // Salir del bucle si se alcanza el tamaño máximo
        }
      }
    }
  }
}


void procesarDatosObjetos() {
  for (int i = 0; i < numeroObjetos; i++) {
    // Obtener el objeto actual
    Objeto objetoActual = objetos[i];

    // Realizar las operaciones deseadas con los datos del objeto
    // Por ejemplo, imprimir el tipo y las coordenadas
    Serial.print("Objeto ");
    Serial.print(i + 1);  // Sumamos 1 para mostrar el número de objeto correcto
    Serial.print(": Tipo=");
    Serial.print(objetoActual.tipo);
    Serial.print(", Coordenada X=");
    Serial.print(objetoActual.coordenadaX);
    Serial.print(", Coordenada Y=");
    Serial.println(objetoActual.coordenadaY);

    float X = objetoActual.coordenadaX;
    float Y = objetoActual.coordenadaY;
    float Z = 0.0;  // Ajusta el valor de Z según sea necesario

    moveToCoordinates(X, Y, Z);
  }
  if (numeroObjetos >= MAX_DATOS) {
    Serial.print(" Se han realizado todos los movimientos.");
  }
  // Reiniciar el contador de objetos para la próxima recepción de datos
  numeroObjetos = 0;

}

void moveToCoordinates(float X, float Y, float Z) {
  long targetXSteps = 2 * X / (0.01 * microstepping);
  long targetYSteps = 2 * Y / (0.01 * microstepping);
  long targetZSteps = 2 * Z / (0.01 * microstepping);

  stepperX.moveTo(targetXSteps);
  stepperY.moveTo(targetYSteps);
  stepperZ.moveTo(targetZSteps);

  while ((stepperX.isRunning() || stepperY.isRunning() || stepperZ.isRunning()) && millis() - startTime < timeout) {
    stepperX.run();
    stepperY.run();
    stepperZ.run();
  }

  Serial.println("¡Movimiento completado!");

}


void setup() {
  // Inicializar los motores, habilitar el driver
  stepperX.setEnablePin(8);
  stepperY.setEnablePin(8);
  stepperZ.setEnablePin(8);
  // cambiar sentido de X
  stepperX.setPinsInverted(true, false, false);  // Invertir los pines si es necesario
  stepperY.setPinsInverted(false, false, true);
  stepperZ.setPinsInverted(false, false, true);

  // Establecer la configuración de aceleración y velocidad máxima de los motores
  stepperX.setMaxSpeed(1000.0);
  stepperX.setAcceleration(500.0);
  stepperY.setMaxSpeed(1000.0);
  stepperY.setAcceleration(500.0);
  stepperZ.setMaxSpeed(1000.0);
  stepperZ.setAcceleration(500.0);

  // Habilitar los motores
  stepperX.enableOutputs();
  stepperY.enableOutputs();
  stepperZ.enableOutputs();
  Serial.begin(9600); // Iniciar comunicación serial a 9600 bps
}

void loop() {
  recibirDatosObjetos();
  procesarDatosObjetos();
}

Editado por moderador

Moderador:
Por favor, lee las Normas del foro y edita tu código/error usando etiquetas de código.
Ve a edición, luego selecciona todo el código que has publicado, lo cortas y click en (<CODE/>)
Si no entiendes mira otros hilos y observarás como debe verse un código o los errores de compilación.

Estas a 9600bps, sube la velocidad en la PI y en Arduino.
Esto no quita que debes editar.

Buenas noches, soy nueva en esto de los foros, espero que esta vez lo haya subido correctamente.

// Definir el tamaño máximo del array de datos
#define MAX_DATOS 25
#include <AccelStepper.h>

// Configuración de los pines para el CNC Shield
#define X_STEP_PIN 2
#define X_DIR_PIN 5
#define Y_STEP_PIN 3
#define Y_DIR_PIN 6
#define Z_STEP_PIN 4
#define Z_DIR_PIN 7

// Configuración de las dimensiones del sistema
const float stepsPerRevolution = 200;  // Número de pasos por revolución del motor
const float microstepping = 8;         // Factor de microstepping del controlador

// Crear objetos AccelStepper para los tres motores
AccelStepper stepperX(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN);
AccelStepper stepperY(AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN);
AccelStepper stepperZ(AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN);

// Coordenadas objetivo en el espacio cartesiano
float targetX = 0.0;
float targetY = 0.0;
float targetZ = 0.0;

// Definir la estructura para almacenar los datos de cada objeto
struct Objeto {
  String tipo;
  int coordenadaX;
  int coordenadaY;
};

// Declarar el array para almacenar los datos de los objetos
Objeto objetos[MAX_DATOS];
// Variable para rastrear el número de objetos recibidos
int numeroObjetos = 0;


float Z = 100.00;
float X;
float Y;

void recibirDatosObjetos() {
  // Variable para rastrear el número de objetos recibidos
  while (Serial.available()) {
    String input = Serial.readStringUntil('\n');
    if (input.length() > 0) {
      // Dividir la cadena de entrada en el tipo de objeto, coordenada X y coordenada Y
      int comma1 = input.indexOf(',');
      int comma2 = input.indexOf(',', comma1 + 1);
      if (comma1 != -1 && comma2 != -1) {
        String tipo = input.substring(0, comma1);
        int coordenadaX = input.substring(comma1 + 1, comma2).toInt();
        int coordenadaY = input.substring(comma2 + 1).toInt();

        // Crear un nuevo objeto y asignar los datos recibidos
        Objeto nuevoObjeto;
        nuevoObjeto.tipo = tipo;
        nuevoObjeto.coordenadaX = coordenadaX;
        nuevoObjeto.coordenadaY = coordenadaY;

        // Añadir el objeto al array
        objetos[numeroObjetos] = nuevoObjeto;

        // Incrementar el contador de objetos
        numeroObjetos++;
        Serial.print(numeroObjetos  );


        // Verificar si se ha alcanzado el tamaño máximo del array
        if (numeroObjetos >= MAX_DATOS) {
          break; // Salir del bucle si se alcanza el tamaño máximo
        }
      }
    }
  }
}


void procesarDatosObjetos() {
  for (int i = 0; i < numeroObjetos; i++) {
    // Obtener el objeto actual
    Objeto objetoActual = objetos[i];

    // Realizar las operaciones deseadas con los datos del objeto
    // Por ejemplo, imprimir el tipo y las coordenadas
    Serial.print("Objeto ");
    Serial.print(i + 1);  // Sumamos 1 para mostrar el número de objeto correcto
    Serial.print(": Tipo=");
    Serial.print(objetoActual.tipo);
    Serial.print(", Coordenada X=");
    Serial.print(objetoActual.coordenadaX);
    Serial.print(", Coordenada Y=");
    Serial.println(objetoActual.coordenadaY);

    float X = objetoActual.coordenadaX;
    float Y = objetoActual.coordenadaY;
    float Z = 0.0;  // Ajusta el valor de Z según sea necesario

    moveToCoordinates(X, Y, Z);
  }
  if (numeroObjetos >= MAX_DATOS) {
    Serial.print(" Se han realizado todos los movimientos.");
  }
  // Reiniciar el contador de objetos para la próxima recepción de datos
  numeroObjetos = 0;

}

void moveToCoordinates(float X, float Y, float Z) {
  long targetXSteps = 2 * X / (0.01 * microstepping);
  long targetYSteps = 2 * Y / (0.01 * microstepping);
  long targetZSteps = 2 * Z / (0.01 * microstepping);

  stepperX.moveTo(targetXSteps);
  stepperY.moveTo(targetYSteps);
  stepperZ.moveTo(targetZSteps);

  while ((stepperX.isRunning() || stepperY.isRunning() || stepperZ.isRunning()) && millis() - startTime < timeout) {
    stepperX.run();
    stepperY.run();
    stepperZ.run();
  }

  Serial.println("¡Movimiento completado!");

}


void setup() {
  // Inicializar los motores, habilitar el driver
  stepperX.setEnablePin(8);
  stepperY.setEnablePin(8);
  stepperZ.setEnablePin(8);
  // cambiar sentido de X
  stepperX.setPinsInverted(true, false, false);  // Invertir los pines si es necesario
  stepperY.setPinsInverted(false, false, true);
  stepperZ.setPinsInverted(false, false, true);

  // Establecer la configuración de aceleración y velocidad máxima de los motores
  stepperX.setMaxSpeed(1000.0);
  stepperX.setAcceleration(500.0);
  stepperY.setMaxSpeed(1000.0);
  stepperY.setAcceleration(500.0);
  stepperZ.setMaxSpeed(1000.0);
  stepperZ.setAcceleration(500.0);

  // Habilitar los motores
  stepperX.enableOutputs();
  stepperY.enableOutputs();
  stepperZ.enableOutputs();
  Serial.begin(9600); // Iniciar comunicación serial a 9600 bps
}

void loop() {
  recibirDatosObjetos();
  procesarDatosObjetos();
}

Aún no he cambiado la velocidad de la Pi y la Arduino, pero en esencia, el código es este.

Si como te pedí compruebas otros hilos verás que si, que ahora luce como corresponde y ser nuevo no es excusa.

Según mi compilador estas dos variables globales no estan definidas.

He corregido tu código y esto funciona con un ingreso de datos como este
1, 45,34, 2, 12,59, 3, 36, 56, 4, 83, 82, 5, 43, 56, 6, 82, 22, 7, 90, 21, 8, 12, 44

// Definir el tamaño máximo del array de datos
#define MAX_DATOS 25
#include <AccelStepper.h>

// Configuración de los pines para el CNC Shield
#define X_STEP_PIN 2
#define X_DIR_PIN 5
#define Y_STEP_PIN 3
#define Y_DIR_PIN 6
#define Z_STEP_PIN 4
#define Z_DIR_PIN 7

// Configuración de las dimensiones del sistema
const float stepsPerRevolution = 200;  // Número de pasos por revolución del motor
const float microstepping = 8;         // Factor de microstepping del controlador

// Crear objetos AccelStepper para los tres motores
AccelStepper stepperX(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN);
AccelStepper stepperY(AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN);
AccelStepper stepperZ(AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN);

// Coordenadas objetivo en el espacio cartesiano
float targetX = 0.0;
float targetY = 0.0;
float targetZ = 0.0;

// Definir la estructura para almacenar los datos de cada objeto
struct Objeto {
  String tipo;
  int coordenadaX;
  int coordenadaY;
};

// Declarar el array para almacenar los datos de los objetos
Objeto objetos[MAX_DATOS];
// Variable para rastrear el número de objetos recibidos
int numeroObjetos = 0;


float Z = 100.00;
float X;
float Y;

unsigned long startTime, timeout = 10000UL;

void recibirDatosObjetos() {
  String input = "";
  int comma1;
  int comma2;
  int longitud, longitudAnt = 100;
  // Variable para rastrear el número de objetos recibidos
  while (Serial.available()) {
    input = Serial.readStringUntil('\n');
    longitud = input.length();
    
    while (longitud < longitudAnt) {
      // Dividir la cadena de entrada en el tipo de objeto, coordenada X y coordenada Y
      comma1 = input.indexOf(',');
      comma2 = input.indexOf(',', comma1 + 1);
      if (comma1 != -1 && comma2 != -1) {
        String tipo = input.substring(0, comma1);
        int coordenadaX = input.substring(comma1 + 1, comma2).toInt();
        int coordenadaY = input.substring(comma2 + 1).toInt();
        Serial.println("Tipo  :"+String(tipo));
        Serial.println("CoorX :"+String(coordenadaX));
        Serial.println("CoorY :"+String(coordenadaY));

        // Crear un nuevo objeto y asignar los datos recibidos
        Objeto nuevoObjeto;
        nuevoObjeto.tipo = tipo;
        nuevoObjeto.coordenadaX = coordenadaX;
        nuevoObjeto.coordenadaY = coordenadaY;

        // Añadir el objeto al array
        objetos[numeroObjetos] = nuevoObjeto;

        // Incrementar el contador de objetos
        numeroObjetos++;
        Serial.print(numeroObjetos );

        // Verificar si se ha alcanzado el tamaño máximo del array
        if (numeroObjetos >= MAX_DATOS) {
          //break; // Salir del bucle si se alcanza el tamaño máximo
          Serial.println("Error alcancé el maximo de datos");
        }
        
        input = input.substring(input.indexOf(',', comma2 + 1) + 1, input.length());
        longitudAnt = longitud; // feo pero funciona
        longitud = input.length();
        Serial.print(" input restante : " + input);
        Serial.println(" length " + String(longitud));
      }
    }
  }
}
//1, 45,34, 2, 12,59, 3, 36, 56, 4, 83, 82

void procesarDatosObjetos() {
  for (int i = 0; i < numeroObjetos; i++) {
    // Obtener el objeto actual
    Objeto objetoActual = objetos[i];

    // Realizar las operaciones deseadas con los datos del objeto
    // Por ejemplo, imprimir el tipo y las coordenadas
    Serial.print("Objeto ");
    Serial.print(i + 1);  // Sumamos 1 para mostrar el número de objeto correcto
    Serial.print(": Tipo=");
    Serial.print(objetoActual.tipo);
    Serial.print(", Coordenada X=");
    Serial.print(objetoActual.coordenadaX);
    Serial.print(", Coordenada Y=");
    Serial.println(objetoActual.coordenadaY);

    float X = objetoActual.coordenadaX;
    float Y = objetoActual.coordenadaY;
    float Z = 0.0;  // Ajusta el valor de Z según sea necesario

    moveToCoordinates(X, Y, Z);
  }
  if (numeroObjetos >= MAX_DATOS) {
    Serial.print(" Se han realizado todos los movimientos.");
  }
  // Reiniciar el contador de objetos para la próxima recepción de datos
  numeroObjetos = 0;

}

void moveToCoordinates(float X, float Y, float Z) {
  long targetXSteps = 2 * X / (0.01 * microstepping);
  long targetYSteps = 2 * Y / (0.01 * microstepping);
  long targetZSteps = 2 * Z / (0.01 * microstepping);

  stepperX.moveTo(targetXSteps);
  stepperY.moveTo(targetYSteps);
  stepperZ.moveTo(targetZSteps);

  while ((stepperX.isRunning() || stepperY.isRunning() || stepperZ.isRunning()) && millis() - startTime < timeout) {
    stepperX.run();
    stepperY.run();
    stepperZ.run();
  }

  Serial.println("¡Movimiento completado!");

}


void setup() {
  // Inicializar los motores, habilitar el driver
  stepperX.setEnablePin(8);
  stepperY.setEnablePin(8);
  stepperZ.setEnablePin(8);
  // cambiar sentido de X
  stepperX.setPinsInverted(true, false, false);  // Invertir los pines si es necesario
  stepperY.setPinsInverted(false, false, true);
  stepperZ.setPinsInverted(false, false, true);

  // Establecer la configuración de aceleración y velocidad máxima de los motores
  stepperX.setMaxSpeed(1000.0);
  stepperX.setAcceleration(500.0);
  stepperY.setMaxSpeed(1000.0);
  stepperY.setAcceleration(500.0);
  stepperZ.setMaxSpeed(1000.0);
  stepperZ.setAcceleration(500.0);

  // Habilitar los motores
  stepperX.enableOutputs();
  stepperY.enableOutputs();
  stepperZ.enableOutputs();
  Serial.begin(9600); // Iniciar comunicación serial a 9600 bps
}

void loop() {
  recibirDatosObjetos();
  procesarDatosObjetos();
}

Salida por pantalla

Tipo  :1
CoorX :45
CoorY :34
1 input restante :  2, 12,59, 3, 36, 56, 4, 83, 82, 5, 43, 56, 6, 82, 22, 7, 90, 21, 8, 12, 44 length 75
Tipo  : 2
CoorX :12
CoorY :59
2 input restante :  3, 36, 56, 4, 83, 82, 5, 43, 56, 6, 82, 22, 7, 90, 21, 8, 12, 44 length 65
Tipo  : 3
CoorX :36
CoorY :56
3 input restante :  4, 83, 82, 5, 43, 56, 6, 82, 22, 7, 90, 21, 8, 12, 44 length 54
Tipo  : 4
CoorX :83
CoorY :82
4 input restante :  5, 43, 56, 6, 82, 22, 7, 90, 21, 8, 12, 44 length 43
Tipo  : 5
CoorX :43
CoorY :56
5 input restante :  6, 82, 22, 7, 90, 21, 8, 12, 44 length 32
Tipo  : 6
CoorX :82
CoorY :22
6 input restante :  7, 90, 21, 8, 12, 44 length 21
Tipo  : 7
CoorX :90
CoorY :21
7 input restante :  8, 12, 44 length 10
Tipo  : 8
CoorX :12
CoorY :44
8 input restante :  8, 12, 44 length 10
Objeto 1: Tipo=1, Coordenada X=45, Coordenada Y=34
¡Movimiento completado!
Objeto 2: Tipo= 2, Coordenada X=12, Coordenada Y=59
¡Movimiento completado!
Objeto 3: Tipo= 3, Coordenada X=36, Coordenada Y=56
¡Movimiento completado!
Objeto 4: Tipo= 4, Coordenada X=83, Coordenada Y=82
¡Movimiento completado!
Objeto 5: Tipo= 5, Coordenada X=43, Coordenada Y=56
¡Movimiento completado!
Objeto 6: Tipo= 6, Coordenada X=82, Coordenada Y=22
¡Movimiento completado!
Objeto 7: Tipo= 7, Coordenada X=90, Coordenada Y=21
¡Movimiento completado!
Objeto 8: Tipo= 8, Coordenada X=12, Coordenada Y=44
¡Movimiento completado!

Buenos días, sigo teniendo el mismo problema, adjunto el código PI junto al resultado que aparece por pantalla de la PI y a continuación para Arduino he utilizado su código, y muestro por pantalla (se puede observar que lleva un punto en el que la palabra 'length' se corta, aquí es cuando se bloquea el movimiento. En el caso de tener por ejemplo 20 objetos identificados, no me llega nunca a mostrar todos, ya que se bloquea incluso el movimiento de los motores.
Aquí está el código PI:

import cv2
import serial
import time

# Inicializar la comunicación serial con Arduino
arduino = serial.Serial('/dev/ttyACM0', 9600)  # Asegúrate de ajustar el puerto y la velocidad correctos

# Inicializar la cámara
camera = cv2.VideoCapture(0)
camera.set(3, 640)  # Ancho de la imagen
camera.set(4, 480)  # Alto de la imagen

# Leer una imagen desde la cámara
ret, frame = camera.read()
object_list = []  # Lista para almacenar los objetos detectados y sus coordenadas
# Leer una imagen desde la cámara
ret, frame = camera.read()
if not ret:
    raise ValueError("No se pudo obtener una imagen de la cámara")

# Convertir la imagen a escala de grises
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# Aplicar un umbral adaptativo para obtener una imagen binaria
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# Realizar una operación de apertura para eliminar ruido
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
opened = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=2)

# Encontrar contornos en la imagen
contours, _ = cv2.findContours(opened, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
    # Resto del código para el procesamiento de contornos y detección de objetos
# Calcular el área y perímetro del contorno
    area = cv2.contourArea(contour)
    perimeter = cv2.arcLength(contour, True)

    # Calcular la circularidad del contorno
    circularity = 4 * 3.1415 * (area / (perimeter * perimeter))

    # Determinar si el objeto es un tornillo o una arandela basado en la circularidad y longitud
    if circularity > 0.7:
        object_type = "Arandela"
    else:
        object_type = "Tornillo"

    # Obtener el rectángulo delimitador y coordenadas del centro del contorno
    x, y, w, h = cv2.boundingRect(contour)
    center_x = x + w // 2
    center_y = y + h // 2

    # Dibujar un rectángulo alrededor del objeto detectado y etiqueta
    cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
    cv2.putText(frame, object_type, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)
    
   
    
    # Enviar los datos a Arduino a través de comunicación serial
    data = f"{object_type},{center_x},{center_y}\n"
    arduino.write(data.encode())
    time.sleep(1)
    
    
    # Agregar los datos del objeto a la lista object_list
    object_list.append((object_type, center_x, center_y))

# Mostrar los datos por pantalla en la Raspberry Pi
for i, obj in enumerate(object_list):
    object_type, center_x, center_y = obj
    print(f"Objeto {i+1}: Tipo={object_type}, Coordenadas=({center_x} mm, {center_y} mm)")

    # Mostrar la imagen con los objetos detectados
cv2.imshow("Detección de objetos", frame)
cv2.waitKey(0)
# Liberar los recursos
camera.release()
cv2.destroyAllWindows()
arduino.close()

A continuación, he ejecutado el código y he obtenido las siguientes coordenadas:

[ WARN:0] global ../modules/videoio/src/cap_gstreamer.cpp (961) open OpenCV | GStreamer warning: Cannot query video position: status=0, value=-1, duration=-1
Objeto 1: Tipo=Tornillo, Coordenadas=(153 mm, 475 mm)
Objeto 2: Tipo=Tornillo, Coordenadas=(57 mm, 472 mm)
Objeto 3: Tipo=Arandela, Coordenadas=(316 mm, 410 mm)
Objeto 4: Tipo=Arandela, Coordenadas=(317 mm, 398 mm)
Objeto 5: Tipo=Tornillo, Coordenadas=(626 mm, 433 mm)
Objeto 6: Tipo=Arandela, Coordenadas=(292 mm, 330 mm)
Objeto 7: Tipo=Tornillo, Coordenadas=(322 mm, 343 mm)
Objeto 8: Tipo=Tornillo, Coordenadas=(565 mm, 95 mm)
Objeto 9: Tipo=Tornillo, Coordenadas=(372 mm, 61 mm)
Objeto 10: Tipo=Tornillo, Coordenadas=(167 mm, 240 mm)

A continuación, he usado su código para la Arduino y he obtenido lo siguiente por pantalla:

Tipo  :Tornillo
CoorX :153
CoorY :475
1 input restante : Tornillo,153,475 length 16
Objeto 1: Tipo=Tornillo, Coordenada X=153, Coordenada Y=475
¡Movimiento completado!
Tipo  :Tornillo
CoorX :57
CoorY :472
1 input restante : Tornillo,57,472 length 15
Objeto 1: Tipo=Tornillo, Coordenada X=57, Coordenada Y=472
¡Movimiento completado!
Tipo  :Tornillo
CoorX :565
CoorY :95
1 input restante : Tornillo,565,95 length 15
Objeto 1: Tipo=Tornillo, Coordenada X=565, Coordenada Y=95
¡Movimiento completado!
Tipo  :Tornillo
CoorX :372
CoorY :61
1 input restante : Tornillo,372,61 length 15
Objeto 1: Tipo=Tornillo, Coordenada X=372, Coordenada Y=61
¡Movimiento completado!
Tipo  :Tornillo
CoorX :167
CoorY :240
1 input restante : Tornillo,167,240 leng

Simplica las cosas, terminas enviando
Tornillo, 153, 475,Tornillo, 57, 472, Arandela, 316, 410,Arandela, 317, 398, Tornillo, 626, 433, Arandela, 292, 330, Tornillo, 322, 343, Tornillo, 565, 95, Tornillo, 372, 61, Tornillo, 167, 240

A ver como responde y te doy una devolución.

Bueno cambie el valor de mi variable

int longitud, longitudAnt = 200;

y ahora si

Iniciando.
Tipo  :Tornillo
CoorX :153
CoorY :475
1 input restante : Tornillo, 57, 472, Arandela, 316, 410,Arandela, 317, 398, Tornillo, 626, 433, Arandela, 292, 330, Tornillo, 322, 343, Tornillo, 565, 95, Tornillo, 372, 61, Tornillo, 167, 240 length 174
Tipo  :Tornillo
CoorX :57
CoorY :472
2 input restante :  Arandela, 316, 410,Arandela, 317, 398, Tornillo, 626, 433, Arandela, 292, 330, Tornillo, 322, 343, Tornillo, 565, 95, Tornillo, 372, 61, Tornillo, 167, 240 length 156
Tipo  : Arandela
CoorX :316
CoorY :410
3 input restante : Arandela, 317, 398, Tornillo, 626, 433, Arandela, 292, 330, Tornillo, 322, 343, Tornillo, 565, 95, Tornillo, 372, 61, Tornillo, 167, 240 length 136
Tipo  :Arandela
CoorX :317
CoorY :398
4 input restante :  Tornillo, 626, 433, Arandela, 292, 330, Tornillo, 322, 343, Tornillo, 565, 95, Tornillo, 372, 61, Tornillo, 167, 240 length 117
Tipo  : Tornillo
CoorX :626
CoorY :433
5 input restante :  Arandela, 292, 330, Tornillo, 322, 343, Tornillo, 565, 95, Tornillo, 372, 61, Tornillo, 167, 240 length 97
Tipo  : Arandela
CoorX :292
CoorY :330
6 input restante :  Tornillo, 322, 343, Tornillo, 565, 95, Tornillo, 372, 61, Tornillo, 167, 240 length 77
Tipo  : Tornillo
CoorX :322
CoorY :343
7 input restante :  Tornillo, 565, 95, Tornillo, 372, 61, Tornillo, 167, 240 length 57
Tipo  : Tornillo
CoorX :565
CoorY :95
8 input restante :  Tornillo, 372, 61, Tornillo, 167, 240 length 38
Tipo  : Tornillo
CoorX :372
CoorY :61
9 input restante :  Tornillo, 167, 240 length 19
Tipo  : Tornillo
CoorX :167
CoorY :240
10 input restante :  Tornillo, 167, 240 length 19
Objeto 1: Tipo=Tornillo, Coordenada X=153, Coordenada Y=475
¡Movimiento completado!
Objeto 2: Tipo=Tornillo, Coordenada X=57, Coordenada Y=472
¡Movimiento completado!
Objeto 3: Tipo= Arandela, Coordenada X=316, Coordenada Y=410
¡Movimiento completado!
Objeto 4: Tipo=Arandela, Coordenada X=317, Coordenada Y=398
¡Movimiento completado!
Objeto 5: Tipo= Tornillo, Coordenada X=626, Coordenada Y=433
¡Movimiento completado!
Objeto 6: Tipo= Arandela, Coordenada X=292, Coordenada Y=330
¡Movimiento completado!
Objeto 7: Tipo= Tornillo, Coordenada X=322, Coordenada Y=343
¡Movimiento completado!
Objeto 8: Tipo= Tornillo, Coordenada X=565, Coordenada Y=95
¡Movimiento completado!
Objeto 9: Tipo= Tornillo, Coordenada X=372, Coordenada Y=61
¡Movimiento completado!
Objeto 10: Tipo= Tornillo, Coordenada X=167, Coordenada Y=240
¡Movimiento completado!

Yo hago de cuenta que el Raspi envia los 10 a la vez
Veo que no es el caso, los envia de a 1 debido al "\n" entonces procesa de a 1
El problema no esta en Arduino sino en como lo envias

data = f"{object_type},{center_x},{center_y}\n"
    arduino.write(data.encode())

quita el \n y agrega un ',' y cuando termines de enviar todos los comandos pones el '\n'

He estado probando de varias formas. La siguiente es la última versión que he obtenido y me he dado cuenta de lo siguiente: el comando 'moveTo()' es el que me hace perder los datos. Agrego el nuevo código:

#include <AccelStepper.h>

// Configuración de los pines para el CNC Shield
#define X_STEP_PIN 2
#define X_DIR_PIN 5
#define Y_STEP_PIN 3
#define Y_DIR_PIN 6
#define Z_STEP_PIN 4
#define Z_DIR_PIN 7

// Configuración de las dimensiones del sistema
const float stepsPerRevolution = 200;  // Número de pasos por revolución del motor
const float microstepping = 8;         // Factor de microstepping del controlador

// Crear objetos AccelStepper para los tres motores
AccelStepper motorX(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN);
AccelStepper motorY(AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN);
AccelStepper motorZ(AccelStepper::DRIVER, Z_STEP_PIN, Z_DIR_PIN);

float Z=100.0; 
int objetoContador = 1;

void setup() {
  // Inicializar los motores, habilitar el driver
  motorX.setEnablePin(8);
  motorY.setEnablePin(8);
  motorZ.setEnablePin(8);
  // cambiar sentido de X
  motorX.setPinsInverted(true, false, false);  // Invertir los pines si es necesario
  motorY.setPinsInverted(false, false, true);
  motorZ.setPinsInverted(false, false, true);

  // Establecer la configuración de aceleración y velocidad máxima de los motores
  motorX.setMaxSpeed(1000.0);
  motorX.setAcceleration(500.0);
  motorY.setMaxSpeed(1000.0);
  motorY.setAcceleration(500.0);
  motorZ.setMaxSpeed(1000.0);
  motorZ.setAcceleration(500.0);

  // Habilitar los motores
  motorX.enableOutputs();
  motorY.enableOutputs();
  motorZ.enableOutputs();
  Serial.begin(9600);
}



void moverMotores(float X, float Y, float Z) {
  float targetXSteps = 2 * X / (0.01 * microstepping);
  float targetYSteps = 2 * Y / (0.01 * microstepping);
  float targetZSteps = 2 * Z / (0.01 * microstepping);
  
  // Configura las coordenadas objetivo para cada motor
  // SI COMENTO ESTAS 3 LINEAS NO REALIZA TODOS LOS MOVIMIENTOS
  motorX.moveTo(X);
  motorY.moveTo(Y);
  motorZ.moveTo(Z);

  // Mientras algún motor no haya alcanzado su posición objetivo
  while (motorX.distanceToGo() != 0 || motorY.distanceToGo() != 0 || motorZ.distanceToGo() != 0) {
    // Realiza un paso en cada motor
    motorX.run();
    motorY.run();
    motorZ.run();
  }

  // Detiene los motores y los libera
  motorX.stop();
  motorY.stop();
  motorZ.stop();
  
  motorX.disableOutputs();
  motorY.disableOutputs();
  motorZ.disableOutputs();

  Serial.print("Movimiento acabado.");

}


void recibir(){
  if (Serial.available() > 0) {
    String data = Serial.readStringUntil('\n');
    int commaIndex1 = data.indexOf(',');
    int commaIndex2 = data.indexOf(',', commaIndex1 + 1);
    int commaIndex3 = data.indexOf(',', commaIndex2 + 1);
  
    String objectType = data.substring(0, commaIndex1);
    int X = data.substring(commaIndex1 + 1, commaIndex2).toInt();
    int Y = data.substring(commaIndex2 + 1, commaIndex3).toInt();
  
     // Mostrar los datos por el monitor serial
    Serial.print("Objeto ");
    Serial.print(objetoContador);
    Serial.print(": Tipo=");
    Serial.print(objectType);
    Serial.print(", Coordenadas=(");
    Serial.print(X);
    Serial.print(" mm, ");
    Serial.print(Y);
    Serial.println(" mm)");
    // Incrementar el contador de objetos
    objetoContador++;
    moverMotores(X,Y,Z);

    delay(1000);
  }
}

void loop() {
  recibir();
}

Comentando esas 3 líneas obtengo lo siguiente en la PI:

[ WARN:0] global ../modules/videoio/src/cap_gstreamer.cpp (961) open OpenCV | GStreamer warning: Cannot query video position: status=0, value=-1, duration=-1
Objeto 1: Tipo=Tornillo, Coordenadas=(215 mm, 477 mm)
Objeto 2: Tipo=Tornillo, Coordenadas=(376 mm, 471 mm)
Objeto 3: Tipo=Tornillo, Coordenadas=(431 mm, 466 mm)
Objeto 4: Tipo=Tornillo, Coordenadas=(386 mm, 436 mm)
Objeto 5: Tipo=Tornillo, Coordenadas=(87 mm, 431 mm)
Objeto 6: Tipo=Tornillo, Coordenadas=(103 mm, 352 mm)
Objeto 7: Tipo=Tornillo, Coordenadas=(386 mm, 368 mm)
Objeto 8: Tipo=Arandela, Coordenadas=(380 mm, 327 mm)
Objeto 9: Tipo=Arandela, Coordenadas=(110 mm, 320 mm)
Objeto 10: Tipo=Arandela, Coordenadas=(113 mm, 308 mm)
Objeto 11: Tipo=Tornillo, Coordenadas=(394 mm, 316 mm)
Objeto 12: Tipo=Tornillo, Coordenadas=(495 mm, 230 mm)
Objeto 13: Tipo=Tornillo, Coordenadas=(512 mm, 248 mm)
Objeto 14: Tipo=Tornillo, Coordenadas=(494 mm, 148 mm)
Objeto 15: Tipo=Arandela, Coordenadas=(563 mm, 97 mm)
Objeto 16: Tipo=Tornillo, Coordenadas=(604 mm, 61 mm)
Objeto 17: Tipo=Tornillo, Coordenadas=(341 mm, 240 mm)
Objeto 18: Tipo=Tornillo, Coordenadas=(82 mm, 68 mm)

Y en la Arduino lo siguiente:

Objeto 1: Tipo=Tornillo, Coordenadas=(215 mm, 477 mm)
Movimiento acabado.Objeto 2: Tipo=Tornillo, Coordenadas=(376 mm, 471 mm)
Movimiento acabado.Objeto 3: Tipo=Tornillo, Coordenadas=(431 mm, 466 mm)
Movimiento acabado.Objeto 4: Tipo=Tornillo, Coordenadas=(386 mm, 436 mm)
Movimiento acabado.Objeto 5: Tipo=Tornillo, Coordenadas=(87 mm, 431 mm)
Movimiento acabado.Objeto 6: Tipo=Tornillo, Coordenadas=(103 mm, 352 mm)
Movimiento acabado.Objeto 7: Tipo=Tornillo, Coordenadas=(386 mm, 368 mm)
Movimiento acabado.Objeto 8: Tipo=Arandela, Coordenadas=(380 mm, 327 mm)
Movimiento acabado.Objeto 9: Tipo=Arandela, Coordenadas=(110 mm, 320 mm)
Movimiento acabado.Objeto 10: Tipo=Arandela, Coordenadas=(113 mm, 308 mm)
Movimiento acabado.Objeto 11: Tipo=Tornillo, Coordenadas=(394 mm, 316 mm)
Movimiento acabado.Objeto 12: Tipo=Tornillo, Coordenadas=(495 mm, 230 mm)
Movimiento acabado.Objeto 13: Tipo=Tornillo, Coordenadas=(512 mm, 248 mm)
Movimiento acabado.Objeto 14: Tipo=Tornillo, Coordenadas=(494 mm, 148 mm)
Movimiento acabado.Objeto 15: Tipo=Arandela, Coordenadas=(563 mm, 97 mm)
Movimiento acabado.Objeto 16: Tipo=Tornillo, Coordenadas=(604 mm, 61 mm)
Movimiento acabado.Objeto 17: Tipo=Tornillo, Coordenadas=(341 mm, 240 mm)
Movimiento acabado.Objeto 18: Tipo=Tornillo, Coordenadas=(82 mm, 68 mm)
Movimiento acabado.

En cambio si descomento esas lineas obtengo lo siguiente en la PI:

Objeto 1: Tipo=Tornillo, Coordenadas=(215 mm, 477 mm)
Movimiento acabado.Objeto 2: Tipo=Tornillo, Coordenadas=(376 mm, 471 mm)
Movimiento acabado.Objeto 3: Tipo=Tornillo, Coordenadas=(431 mm, 466 mm)
Movimiento acabado.Objeto 4: Tipo=Tornillo, Coordenadas=(386 mm, 436 mm)
Movimiento acabado.Objeto 5: Tipo=Tornillo, Coordenadas=(87 mm, 431 mm)
Movimiento acabado.Objeto 6: Tipo=Tornillo, Coordenadas=(103 mm, 352 mm)
Movimiento acabado.Objeto 7: Tipo=Tornillo, Coordenadas=(386 mm, 368 mm)
Movimiento acabado.Objeto 8: Tipo=Arandela, Coordenadas=(380 mm, 327 mm)
Movimiento acabado.Objeto 9: Tipo=Arandela, Coordenadas=(110 mm, 320 mm)
Movimiento acabado.Objeto 10: Tipo=Arandela, Coordenadas=(113 mm, 308 mm)
Movimiento acabado.Objeto 11: Tipo=Tornillo, Coordenadas=(394 mm, 316 mm)
Movimiento acabado.Objeto 12: Tipo=Tornillo, Coordenadas=(495 mm, 230 mm)
Movimiento acabado.Objeto 13: Tipo=Tornillo, Coordenadas=(512 mm, 248 mm)
Movimiento acabado.Objeto 14: Tipo=Tornillo, Coordenadas=(494 mm, 148 mm)
Movimiento acabado.Objeto 15: Tipo=Arandela, Coordenadas=(563 mm, 97 mm)
Movimiento acabado.Objeto 16: Tipo=Tornillo, Coordenadas=(604 mm, 61 mm)
Movimiento acabado.Objeto 17: Tipo=Tornillo, Coordenadas=(341 mm, 240 mm)
Movimiento acabado.Objeto 18: Tipo=Tornillo, Coordenadas=(82 mm, 68 mm)
Movimiento acabado.
ChatGPT
Basado en la salida que proporcionaste, parece que el programa está funcionando correctamente. Después de recibir los datos de objeto y coordenadas a través del puerto serial, el programa mueve los motores a las coordenadas especificadas y luego imprime "Movimiento acabado" en el monitor serial.

Cada objeto se mueve individualmente a sus coordenadas respectivas y, una vez que se alcanza la posición objetivo, se imprime "Movimiento acabado". Esto se repite para cada objeto que se recibe.

Si estás experimentando algún problema o tienes alguna pregunta adicional, por favor avísame y estaré encantado de ayudarte.





User
[ WARN:0] global ../modules/videoio/src/cap_gstreamer.cpp (961) open OpenCV | GStreamer warning: Cannot query video position: status=0, value=-1, duration=-1
Objeto 1: Tipo=Arandela, Coordenadas=(3 mm, 475 mm)
Objeto 2: Tipo=Arandela, Coordenadas=(397 mm, 401 mm)
Objeto 3: Tipo=Tornillo, Coordenadas=(429 mm, 395 mm)
Objeto 4: Tipo=Tornillo, Coordenadas=(264 mm, 416 mm)
Objeto 5: Tipo=Tornillo, Coordenadas=(389 mm, 380 mm)
Objeto 6: Tipo=Tornillo, Coordenadas=(283 mm, 343 mm)
Objeto 7: Tipo=Arandela, Coordenadas=(108 mm, 271 mm)
Objeto 8: Tipo=Tornillo, Coordenadas=(389 mm, 294 mm)
Objeto 9: Tipo=Tornillo, Coordenadas=(398 mm, 242 mm)
Objeto 10: Tipo=Arandela, Coordenadas=(386 mm, 162 mm)
Objeto 11: Tipo=Arandela, Coordenadas=(502 mm, 151 mm)
Objeto 12: Tipo=Tornillo, Coordenadas=(482 mm, 125 mm)
Objeto 13: Tipo=Tornillo, Coordenadas=(564 mm, 55 mm)
Objeto 14: Tipo=Tornillo, Coordenadas=(495 mm, 66 mm)
Objeto 15: Tipo=Tornillo, Coordenadas=(518 mm, 148 mm)
Objeto 16: Tipo=Tornillo, Coordenadas=(495 mm, 14 mm)
Objeto 17: Tipo=Tornillo, Coordenadas=(401 mm, 74 mm)
Objeto 18: Tipo=Tornillo, Coordenadas=(355 mm, 9 mm)
Objeto 19: Tipo=Tornillo, Coordenadas=(149 mm, 240 mm)
Objeto 20: Tipo=Tornillo, Coordenadas=(74 mm, 69 mm)

Y en la Arduino lo siguiente:

Objeto 1: Tipo=Arandela, Coordenadas=(3 mm, 475 mm)
Movimiento acabado.Objeto 2: Tipo=Arandela, Coordenadas=(397 mm, 401 mm)
Movimiento acabado.Objeto 3: Tipo=Tornillo, Coordenadas=(429 mm, 395 mm)
Movimiento acabado.Objeto 4: Tipo=Tornillo, Coordenadas=(264 mm, 416 mm)
Movimiento acabado.Objeto 5: Tipo=Tornillo, Coordenadas=(389 mm, 380 mm)
Movimiento acabado.Objeto 6: Tipo=Tornillo, Coordenadas=(283 mm, 108 mm)
Movimiento acabado.Objeto 7: Tipo=Tornillo, Coordenadas=(389 mm, 294 mm)
Movimiento acabado.Objeto 8: Tipo=Arandela, Coordenadas=(386 mm, 162 mm)
Movimiento acabado.Objeto 9: Tipo=Tornillo, Coordenadas=(482 mm, 125 mm)
Movimiento acabado.Objeto 10: Tipo=Tornillo, Coordenadas=(564 mm, 518 mm)
Movimiento acabado.Objeto 11: Tipo=Tornillo, Coordenadas=(401 mm, 74 mm)
Movimiento acabado.Objeto 12: Tipo=Tornillo, Coordenadas=(149 mm, 240 mm)
Movimiento acabado.

En la Arduino tan solo llega hasta 12 en vez de hasta 20. Necesito saber si hay alguna otra forma de hacerlo.

No he entendido muy bien donde tengo que colocar el "\n". La lectura del Arduino cambiaría entonces. Osea, la recepción de los datos es correcta porque lo he probado hasta con 30 datos. ¿Puede ser que la forma en la que leo los datos, pero limite el movimiento?

Y es lógico, los motores tardan más en moverse de lo que demoran en llegar los datos y el programa no hace nada más que esperar que dejen de moverse

  // Mientras algún motor no haya alcanzado su posición objetivo
  while (motorX.distanceToGo() != 0 || motorY.distanceToGo() != 0 || motorZ.distanceToGo() != 0) {
    // Realiza un paso en cada motor
    motorX.run();
    motorY.run();
    motorZ.run();
  }

obviamente en algún momento se llena el buffer serie y se pierden datos.

En este caso, a 9600 bps, si llegan datos continuamente y no se leen porque se está esperando a que termine el movimiento de los motores, en 66 mseg. llegaron 64 caracteres y se llenó el buffer, a partir de ese instante la UART se queda "sorda" y se pierden datos.

Ya le dije en mi primer respuesta que subiera los bps.

Hombre cambias los criterios a cada paso
Eran 25 y ahora 30
Haz las cuentas de cuantos bytes son los que envias y coloca a la variable que te hice cambiar hace un momento con un valor como 1000 asi estas bien.
pero segun que arduino uses no se si tendras tanta RAM para hacerlo

int longitud, longitudAnt = 1000;

Para ue envias Arandela Tornillo si con 1 o 2 es suficiente? Ahorras muchos bytes inútiles
10 por Arandela (8 bytes) son 80 bytes contra 8 bytes de poner 1 indicando eso por Arandela
10 por Tornillo (8 bytes) lo mismo 80 bytes menos
tal vez no cambie mucho pero el Arduiino UNO, NANO tiene 2k y todo suma.

Y sería peor porque perdería más datos todavía.

Por poner un ej., a 19200 bps el buffer se llenaría en 34 mseg. mientras el micro sigue esperando pacientemente que terminen de moverse los motores...

Hace falta algún protocolo para no enviar datos hasta que el arduino pueda recibirlos y manejar mejor el tema de los motores. Incluso bajar los bps puede ser de ayuda (como las viejas impresoras de matríz de puntos, que eran una carreta pero no perdían caracteres porque trabajaban a 2400 bps y menos también).

Yo le envié 20 combinaciones a Wokwi y las hizo sin problemas.
Una cosa es la recepción de comandos y otra la ejecución de los mismos.

Si, el problema es que ambas tareas trabajen juntas y más cuando una depende de la otra.
Y es más problemático aún si además de esperar a que terminen de moverse los motores, alguien "le clava" un segundo de delay

    moverMotores(X,Y,Z);

    delay(1000);

Entonces, ¿existe alguna forma de rehacer el código de forma que no se llene el buffer? Mis conocimientos son limitados en este ámbito. Se trata de un trabajo de fin de grado y no sé si tengo que replantear de 0 todo el código o podría utilizar lo que ya tengo.

Tiene lógica la verdad, porque en el caso de tener 6 datos me llegan esos 6 datos con sus 6 movimientos. ¿Me debería replantear buscar una placa más potente?, la mía es una Arduino UNO. Aunque si existiera alguna forma de solucionarlo en la Arduino UNO sería mucho mejor.

¿Y si mando los datos cada más tiempi en la PI? Osea, hago que tarden más en llegar los datos, para liberar un poco el buffer.

@MaximoEsfuerzo olvidate del delay(1000)
En el código que le modifiqué no hay delay() y toma bien todos los comandos, al menos a mi.
Evidentemente a el no.
Yo puedo leer mas de 10 comandos y tu no?