Problema con Serial y AccelSteper [solcuionado]

Muy buenas a todos.
Llevo tiempo peleandome con motores paso a paso. He tratado de implementar un regulador de velocidad mediante una resistencia y la librería <Stepper.h>. Después de varios problemas y darme cuenta de las limitaciones de esta librería, probé suerte con la librería <AccelStepper.h>

Una vez la he implementado en un sketch, me ha surgido un problema del cual no doy encontrado explicación. Si implemento un Serial.begin(); y envío Serial.prrint() para leer un potenciometro conectado en la entrada A0, cuando el arduino envía los datos por Serial, el motor se mueve mucho más lento y no alcanza la velocidad máxima…
Alguien sabe cual es la razón técnica de este inconveniente.

En resumen, lo que trato de explicar, es que si implemento comunicación serial desde arduino hacia el ordenador (monitor serial) el motor va muchísimo más lento.

El código empleado es el siguiente.

#include <AccelStepper.h>

#define FULLSTEP 4
#define HALFSTEP 8

                        
#define motorPin1  8     
#define motorPin2  9     
#define motorPin3  10    
#define motorPin4  11    
                        
AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);  
//Los pines estan cambiados de orden porque el driver de mi paso a paso viene invertido el 2 y el 3 

void setup() 
{
  stepper1.setMaxSpeed(1250);
  stepper1.setAcceleration(100);
  stepper1.setSpeed(100);
  stepper1.moveTo(-2036);  // 1 revolution 
  
  Serial.begin(9600);

}


void loop() 
{
  //Change direction at the limits
  if (stepper1.distanceToGo() == 0) 
    stepper1.moveTo(-stepper1.currentPosition());
    stepper1.run();
  
  Serial.print("valor");
  Serial.println(stepper1.currentPosition());
  

}

Si alguien tiene una explicación, lo agradecería,

Un saludo.

es el tiempo que tarda en ejecutar el loop a mas imprimas mas tarda en dar el siguiente paso. Para empezar sube la velocidad del serial a 115200 y lo notaras por que tardara 12 veces menos la transmisión

(tampoco hay que ser tan experto)

Afinando un poco más la explicación, llegas enseguida a llenar el buffer Serial tx, con lo que el loop se detiene para poder aceptar más caracteres en dicho buffer. Yo probaría a imprimir por serial sólo una vez de cada x (habría que buscar un valor adecuado para esa x) o mejor aún, imprimir sólo cuando dispongamos de espacio suficiente en el buffer. Estuve mirando un poco la librería hardwareserial, porque suponía que tenía que haber algo así. No lo he probado, pero intenta poner tu serial print así (no hace falta que cambies la velocidad serial):

if (Serial.availableForWrite() > 30) { // si quedan más de 30 caracteres libres en buffer de salida (supongo)
  Serial.print("valor");
  Serial.println(stepper1.currentPosition());
}

Y comparte tus resultados.

Muchas gracias por las respuestas. GO_zalo, subir la velocidad del serial a 115200 ya lo había probado y si, funcionaba, pero durante la prueba el PC empezó a sobrecargarse y se quedó bloqueado temporalmente hasta que corté la comunicación serie.

Es cierto que el hecho de que el tiempo que dedica el Arduino para enviar datos por serial, es el que provoca ese ralentizamiento del motor, pero trataba de buscar una explicación más detallada. Soy nuevo en Arduino y estoy aprendiendo en la academia del prueba y error, y a los temarios de dicha academia se les escapan muchos detalles importantes :-D

noter, algo así estaba buscando. Hasta el lunes no podré probar lo que me recomiendas, pero siendo el serial el que limita el sketch, es seguro que funcionará. Lo probaré y te confirmaré si es la solución apropiada.

Muchas gracias por el aporte a los dos. Un saludo.

Bueno. Tampoco habría hecho falta abrir las tripas de la librería hardwareserial. Me acabo de dar cuenta de que el sublime text también te muestra en el autocompletado el availableForWrite :blush: :blush: :blush: . Puedo confirmar que funciona, aunque no lo he probado en el mismo contexto (con accelstepper), pero con este sencillo programa:

int contador;
void setup() {
  // put your setup code here, to run once:
  pinMode(13, OUTPUT);
  Serial.begin(9600);
}

void loop() {
 if (++contador == 0) {
 digitalWrite(13, !digitalRead(13));
 }
 if(Serial.availableForWrite()>60){
 Serial.print(F("Contador: "));
 Serial.println(contador);
 }
}

Que enciende/apaga cada vez que desborda el contador (osea cada 65536 loops) vemos que parpadea el led unas dos veces por segundo, a la par que por el monitor serial estamos recibiendo datos constantemente. Si quitamos el if (serial.availableForWrite), incluso cambiando el tipo de contador a byte para que desborde cada 256 loops vemos que tardan bastante más tiempo en realizarse esos 256 loops que los 65536 anteriores. El contador en el monitor va a repasar todos los números, eso sí, pero la velocidad de datos mostrados en pantalla es la misma, lo que significa que sencillamente cuando el buffer de escritura está lleno y enviamos algo a serial, el programa se detiene hasta que hay nuevamente espacio.

GO_zalo, subir la velocidad del serial a 115200 ya lo había probado y si, funcionaba, pero durante la prueba el PC empezó a sobrecargarse y se quedó bloqueado temporalmente hasta que corté la comunicación serie.

Que el PC se sobrecargue? Houston tenemos un problema. De ningún modo una PC se puede sobrecargar con 115kbps y que pasa con USB3.0 o las transferenicas de disco. Algo anda mal ahi.

Efectivamente, surbyte; no tiene porqué sobrecargarse por la transmisión a 115200, aunque sí cabe la posibilidad de que estemos sobrecargando al monitor serial. Con el monitor del sublime, por ejemplo, se ve que va a trompicones, pero tiene más que ver con el refresco de pantalla (cuando alcanza la parte baja y debe hacer scroll) y posiblemente el almacenaje temporal en memoria/disco de los datos que van llegando (estamos creando un largo archivo de texto plano) que con que se sature la recepción.

Efectivamente noter, al incluir en el código if(Serial.availableForWrite()>60) el motor no reduce su velocidad y los datos se envían por puerto serie con fluidez. Indicar (repito que soy nuevo en esto) que he estado probando, y al subir if(Serial.availableForWrite()>*) *por encima de 63, deja de enviar ningún dato por el puerto serie.

Muchas gracias por las respuestas. Un saludo

Tengo que seguir investigando al respecto, pues al usar una pantalla de crlistal líquido también me sucede lo mismo de ralentizarse el motor. :frowning:

#include <AccelStepper.h>

#define FULLSTEP 4
#define HALFSTEP 8

                        
#define motorPin1  8     
#define motorPin2  9     
#define motorPin3  10    
#define motorPin4  11    
                        
AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);  
//Los pines estan cambiados de orden porque el driver de mi paso a paso viene invertido el 2 y el 3 


#include <Wire.h>    
#include <LiquidCrystal_I2C.h>                      
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  //direccion pantalla china y pineado


void setup() 
{
  stepper1.setMaxSpeed(1250);
  stepper1.setAcceleration(100);
  stepper1.setSpeed(100);
  stepper1.moveTo(2036);  // 1 revolution 

  lcd.begin(16,2);
  
}


void loop() 
{
  //Change direction at the limits
  if (stepper1.distanceToGo() == 0) 
    stepper1.moveTo(-stepper1.currentPosition());
    stepper1.run();
 
  
  lcd.setCursor(0,0);
  lcd.print("Angulo:");
  lcd.setCursor(8,0);
  lcd.print(map(stepper1.currentPosition(), -2036,2036,0,360));
 
}

No me creo que a nadie que estuviese empezando le hubiese pasado antes y no lo comentase en los foros. Aplicaciones con motores paso a paso y pantallas lcd hay a cientos…

Efectivamente, por encima de 63 no se va a cumplir nunca la condición, pues por defecto el buffer de transmisión serial es de 64 bytes. Puse precisamente un if(Serial.availableForWrite()>60) porque indica que el buffer está prácticamente vacío (bueno, que hay como mucho 3 de los 64 bytes disponibles) y que tienes "hueco" para meter hasta 60 bytes en el buffer; más que suficiente para poner en él la cadena "contador: xxxxx". A partir de ahí, hardwareserial se ocupa de ir transmitiendo en segundo plano lo que hay en el buffer, y cuando vuelven a quedar 3 bytes para estar vacío se vuelve a cumplir el if.