[SOLUCIONADO].... Utilizacion de MILLIS con motores p.a.p

.

Hola maestros todos

En el código siguiente realizo una intermitencia en dos LEDS independientemente uno del otro (funciona).
Ademas quisiera utilizar millis para separar el tiempo entre pasos del motor p.a.p..
Como comprobareis, el motor no funciona.
Seguro es una incorrección de código, me podeis dar un empujón ???.

Un saludo !!! :cocktail: :cocktail:

[code]
/*
  
  Utiliza el motor UNIPOLAR NMB-PM35L-048. Con el controlador LN2003A.
  Se detiene X  segundos y luego continua nuevamente. 
  Secuencia de PASO DOBLE   conectando dos bobinas por paso. 

  Segun la cifra "< X" en FOR dara mas o menos pasos:
  Alimentar ULN2003 con fuente de alimentacion externa de 12 - 24 V.
  Dos LEDS con intermitencia independiente por "millis".
*/
// PASO COMPLETO SIMPLE

int INTERPASO = 3;      // INTERPASO: Tiempo entre pasos, no debe ser menor a 10 ms.
int INTERPASOX = 2000;  // INTERPASOX: Tiempo de DESCANSO.
//********************************************
boolean estadoLED7 = true;
boolean estadoLED12 = true;

unsigned long LED7Tiempo;
unsigned long LED12Tiempo;
unsigned long TiempoPaso1;
unsigned long TiempoPaso2;
unsigned long TiempoPaso3;
unsigned long TiempoPaso4;
unsigned long TiempoPaso5;

 int INTERVALO_LED_7 = 513 ;  //tiempo de INTERVALO 7 
 int INTERVALO_LED_12 = 200 ; //tiempo de INTERVALO 12  

//***********************************************

void setup() 
{
  Serial.begin(9600);
  Serial.println(" ===============  M_MOTOR_PAP_UNIPOLAR_MILLIS  =========  ");
  Serial.println(""); 
   
  pinMode(7, OUTPUT);  // pin digital 7 de Arduino a intermitente
  pinMode(8, OUTPUT);  // pin digital 8 de Arduino a IN1 de modulo controlador    
  pinMode(9, OUTPUT);  // pin digital 9 de Arduino a IN2 de modulo controlador    
  pinMode(10, OUTPUT); // pin digital 10 de Arduino a IN3 de modulo controlador
  pinMode(11, OUTPUT); // pin digital 11 de Arduino a IN4 de modulo controlador
  pinMode(12, OUTPUT); // pin digital 12 de Arduino a intermitente
}
                           
void loop() 
{
  if ((millis()- LED7Tiempo) >= INTERVALO_LED_7)// Tiempo 513 
  {
    estadoLED7 = !estadoLED7;
    digitalWrite (7, estadoLED7);
    Serial.print("======== LED 7 = ");
    Serial.println(estadoLED7);
    LED7Tiempo = millis();
  }

  if ((millis() - LED12Tiempo) >= INTERVALO_LED_12)// Tiempo 200
  {
    estadoLED12 = !estadoLED12;
    digitalWrite (12, estadoLED12);
    Serial.print("======== LED 12 = ");
    Serial.println(estadoLED12);   
    
    LED12Tiempo = millis();    
  } 
     // ************************************* MOTOR PAP  *********************************
  
  for (int i = 0; i < 145; i++) // Segun la cifra "< X" dara mas o menos pasos. 
 {
  if  
 ((millis()- TiempoPaso1) >= INTERPASO)
  {  
    digitalWrite( 8, HIGH);  // paso 1 
    digitalWrite( 9, HIGH);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
    unsigned long TiempoPaso1 = millis();
  }
if 
 ((millis()- TiempoPaso2) >= INTERPASO)
  {  
    digitalWrite( 8, LOW); // paso 2
    digitalWrite( 9, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(11, LOW);
    unsigned long TiempoPaso2 = millis();
  }
   if  
 ((millis()- TiempoPaso3) >= INTERPASO)
  {  
    digitalWrite( 8, LOW); // paso 3
    digitalWrite( 9, LOW);
    digitalWrite(10, HIGH);
    digitalWrite(11, HIGH);
    unsigned long TiempoPaso3 = millis();
  }
    if 
 ((millis()- TiempoPaso4) >= INTERPASO)
  {  
    digitalWrite( 8, HIGH); // paso 4
    digitalWrite( 9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, HIGH);
    unsigned long TiempoPaso4 = millis();
  }
    if  
 ((millis()- TiempoPaso5) >= INTERPASOX)
 {  digitalWrite( 8, LOW); 
    digitalWrite( 9, LOW);
    digitalWrite(10, LOW);   //  BLOQUE DE DESCANSO
    digitalWrite(11, LOW);
    unsigned long TiempoPaso5 = millis();
 }
  } 
   }  

// ===============================  FIN  ==============================

[/code]type or paste code here

.

Falta que muestres como esta todo cableado. Esquema electrónico.

1 Like

.

Hola Surbyte

Me es difícil presentar un esquema de cableado.

Pero ese no es el problema, ya que en otros códigos similares, el mismo cableado, pero sin millis y pero con delay el motor funciona perfectamente.

No se, si este código, en la parte de los millis del motor es correcto.

Si funciona la primera parte encendiendo dos leds intermitentes con secuencia diferenciada uno del otro.

Un saludo Surbyte !!!!

.

Hola a todos:

Han pasado 20 días desde mi ultima comunicación pero aun no he recibido ninguna idea (a parte de la sugerencia de Surbyte).

Por eso, lo vuelvo a intentar a ver si tengo suerte ahora.

Un saludo !!! .... :cocktail:

El código está mal planteado.
Tienes que quitar el lazo for().
Creo que lo conveniente es una máquina de estados.

1 Like

.

Hola MaximoEsfuerzo

Gracias por la rápida respuesta !!!.

En un código anterior, resolví con for y delay y funcionaba.
Ahora intentaba hacerlo con millis.
Podrías enviarme algún código de ejemplo con maquina de estados para motores pap (aunque no fuera exactamente la solución al mio) ???

Un saludo !!!... :cocktail:

.

Ve a documentación ahi tienes ejemplos de máquinas de estado y tutoriales de millis().

1 Like

Hola Surbyte

Me parece que en el código que subí en este hilo, la redacción de millis esta bien, es la que utilizo en otros códigos.
Donde crees que esta el fallo ????.
A tu colega MaximoEsfuerzo le he pedido un ejemplo cualquiera de maquina de estados aplicada a motores pap, podrías también facilitarme alguno ???

Muchas Gracias !!!

Segun esto tu código funciona bien

asi que debo suponer que algo no hace contacto en tu driver ULN2003 o motor.

1 Like

.

Hola surbyte

Veo que has simulado el código y y a ti si te funciona.
Cosas de la informática, a mi no !!!.
Como ya te comenté: Si cambio de código, sin mover absolutamente nada de la instalación eléctrica, funciona el motor.
Vuelvo a cambiar a este código y nada!!!. :joy:

Tu debes estar en invierno, pero por aquí hace unos calores de
infierno !!!! . Debe estar recalentado !!!.
Lo dejare que repose unos días y ya volveré a atacar.

Gracias como siempre, por tu colaboración. :cocktail: :cocktail:
y un karma !!!

.

O sea.. funciona con un código como cual? postealo.
Algo que no me gusta en tu códgio que acabo de observar es esto

((millis()- TiempoPaso4) >= INTERPASO)
  {  
    digitalWrite( 8, HIGH); // paso 4
    digitalWrite( 9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, HIGH);
    unsigned long TiempoPaso4 = millis();   // <=== No me gusta   
}

Eso de definir la variable en cada ciclo no me gusta.
Hazlas variables globales. a todas.

1 Like

Con todo respeto, reitero, ese código no hace lo que se supone que debería.
Al inicio da 20000 pasos en 2 segundos, luego 1000 pasos cada 22 segundos.
Y nunca hace el descanso de 2 segundos.

Como dije antes, está mal planteado pero además tiene errores que podrían decirse graves.
El mayor error: declaras las variables globales

unsigned long TiempoPaso1;
unsigned long TiempoPaso2;
unsigned long TiempoPaso3;
unsigned long TiempoPaso4;
unsigned long TiempoPaso5;

lo cual está bien, pero luego en cada condicional declaras, por ej.,

unsigned long TiempoPaso1 = millis();

que es una variable local, nada tiene que ver con TiempoPaso1 (global) y además se destruye al salir del if(). Lo mismo ocurre con las otras variables de las que creas homónimos locales.
Como resultado las variables globales siempre contienen 0 (porque nunca se actualizan) y los condicionales se cumplen siempre a partir de los primeros 3 mseg de la puesta en marcha.

¿Funciona? Si.
¿Funciona bien? Ni por casualidad.

1 Like

Yo le sugerí poner las variables como globales pero OBVIAMENTE sacar las definición local.
Evidentemente no entendió.
Si se usa una cosa no se usa la otra.
La segunda invalida la primera.

1 Like

No puede usar variables locales que solo existen en el ámbito de cada if().

El post #12 es sobre el código de #1, lo empecé más temprano pero demoré en subirlo (creo que sabés que trabajo los domingos), recién entonces vi tu respuesta y bueh, ya estaba hecho.

1 Like

.

Hola amables Surbyte y MaximoEsfuerzo

Veo que mi pregunta ha suscitado un cúmulo de soluciones.
Sois muy rápidos !!!
Voy a estudiar y rectificar mi código primitivo y ya os comentare: (soy mas lento y novato que vosotros)

Gracias a ambos !!!.... :cocktail: ....:cocktail:

.

Hola aquí estoy otra vez

He retocado el código original , suprimo unsigned long de las locales y mantengo en las globales.
Con el código anterior, el motor estaba"mudo"; ahora "vibra", pero NO gira.

Que os sugiere ????

/*

     M_MOTOR_PAP_UNIPOLAR_MILLIS_foro.2 
  
  Realiza giroS completoS del motor NMB-PM35L-048. Con el controlador ULN2003A,
  Se detiene X  segundos y luego comienza nuevamente. 
  La secuencia de PASO DOBLE  UNIPOLAR conectando dos bobinas por paso. 

  Segun la cifra "< X" en FOR dara mas o menos pasos:
  Alimentar ULN2003 con fuente de alimentacion externa de 12 - 24 V.
  Dos LEDS con intermitencia independiente por "millis".
*/
// PASO COMPLETO SIMPLE

int INTERPASO = 3;      // INTERPASO: Tiempo entre pasos, no debe ser mayor a 10 ms.
int INTERPASOX = 2000;  // INTERPASOX: Tiempo de DESCANSO.
//********************************************
boolean estadoLED7 = true;
boolean estadoLED12 = true;

unsigned long LED7Tiempo;
unsigned long LED12Tiempo;
unsigned long TiempoPaso1;
unsigned long TiempoPaso2;
unsigned long TiempoPaso3;
unsigned long TiempoPaso4;
unsigned long TiempoPaso5;

 int INTERVALO_LED_7 = 513 ;  //tiempo de INTERVALO 7 
 int INTERVALO_LED_12 = 200 ; //tiempo de INTERVALO 12  

//***********************************************

void setup() 
{
  Serial.begin(9600);
  Serial.println(" ===============  M_MOTOR_PAP_UNIPOLAR_MILLIS_foro.2  =========  ");
  Serial.println(""); 
   
  pinMode(7, OUTPUT);  // pin digital 7 de Arduino a intermitente
  pinMode(8, OUTPUT);  // pin digital 8 de Arduino a IN1 de modulo controlador    
  pinMode(9, OUTPUT);  // pin digital 9 de Arduino a IN2 de modulo controlador    
  pinMode(10, OUTPUT); // pin digital 10 de Arduino a IN3 de modulo controlador
  pinMode(11, OUTPUT); // pin digital 11 de Arduino a IN4 de modulo controlador
  pinMode(12, OUTPUT); // pin digital 12 de Arduino a intermitente
}
                           
void loop() 
{
  if ((millis()- LED7Tiempo) >= INTERVALO_LED_7)// Tiempo 513 
  {
    estadoLED7 = !estadoLED7;
    digitalWrite (7, estadoLED7);
  //  Serial.print("======== LED 7 = ");
  //  Serial.println(estadoLED7);
    LED7Tiempo = millis();
  }

  if ((millis() - LED12Tiempo) >= INTERVALO_LED_12)// Tiempo 200
  {
    estadoLED12 = !estadoLED12;
    digitalWrite (12, estadoLED12);
   // Serial.print("======================= LED 12 = ");
  //  Serial.println(estadoLED12);   
    
    LED12Tiempo = millis();    
  } 
     // ************************************* MOTOR PAP  *********************************
  
  for (int i = 0; i < 145; i++) // Segun la cifra "< X" dara mas o menos pasos. 
 {
  if  
 ((millis()- TiempoPaso1) >= INTERPASO)
  {  
    digitalWrite( 8, HIGH);  // paso 1 
    digitalWrite( 9, HIGH);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
    TiempoPaso1 = millis();
  }
if 
 ((millis()- TiempoPaso2) >= INTERPASO)
  {  
    digitalWrite( 8, LOW); // paso 2
    digitalWrite( 9, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(11, LOW);
    TiempoPaso2 = millis();
  }
   if  
 ((millis()- TiempoPaso3) >= INTERPASO)
  {  
    digitalWrite( 8, LOW); // paso 3
    digitalWrite( 9, LOW);
    digitalWrite(10, HIGH);
    digitalWrite(11, HIGH);
    TiempoPaso3 = millis();
  }
    if 
 ((millis()- TiempoPaso4) >= INTERPASO)
  {  
    digitalWrite( 8, HIGH); // paso 4
    digitalWrite( 9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, HIGH);
    TiempoPaso4 = millis();
  }
    if  
 ((millis()- TiempoPaso5) >= INTERPASOX)
 {  digitalWrite( 8, LOW); 
    digitalWrite( 9, LOW);
    digitalWrite(10, LOW);   //  BLOQUE DE DESCANSO
    digitalWrite(11, LOW);
    TiempoPaso5 = millis();
 }
  } 
   }  

// ===============================  FIN  ==============================

Creo que no entiendes que con millis() tienes que cambiar la forma de ver el problema y su solución.

A ver, hacer parpadear 1 LED con delay() es fácil, hacer parpadear un segundo LED a distinto ritmo ya es prácticamente imposible.
¿Por qué? Porque durante el delay() el micro solo hace tiempo sin hacer nada más que esperar que termine el delay para poder ejecutar la siguiente sentencia del programa.
Piensa que delay() es casi lo mismo que

unsigned long intervalo = 1000;
unsigned long oldmillis = millis();

while (millis() - oldmillis < intervalo);

que no hace nada más que esperar que se cumpla el intervalo.
Entonces, nada puede hacerse mientras dura el delay.

Tu código con delays, según nos comentas, funciona porque entre paso y paso el micro no hace nada, solo espera que "pase" el delay para poder dar el siguiente paso.
Entonces ejecuta un paso, espera, ejecuta el siguiente, espera, ejecuta... y espera.
¿Y con los LED qué pasa?
Porque dentro del lazo for(), solo de delays, hay 1740 mseg. Difícil que los LED parapadeen según lo esperado. Y no tengo en cuenta los 2 segundos de "descanso" que no me queda claro si ocurren dentro o fuera del for().

Ahora, con millis() la cosa cambia.
Debes ver que ocurre con los LED (¿es tiempo de cambiar alguno de estado?), y debes ver que ocurre con el motor (¿es tiempo de cambiar el estado de alguna bobina?), todo en cada pasada de loop() y sin ninguna demora.
Miras si hay algo que hacer y sino sigues de largo a ejecutar lo que siga.

Suponte un ejemplo que leí por ahí y me gustó.
Tienes que preparar un desayuno, huevos revueltos que tardan 3 minutos en cocinarse, tostadas que demoran unos 5 minutos y café otros 5.
No es lo mismo preparar los huevos y no hacer nada 3 minutos, luego las tostadas y esperar 5 minutos y finalmente esperar otros 5 minutos a que esté el café y comer los huevos fríos y las tostadas tibias 13 minutos después (en total), que empezar a poner a tostar el pan y comenzar a preparar el café, pasados 2 minutos empezar a preparar los huevos, ir controlando cada cosa y finalmente, apenas 5 minutos después de empezar, que todo llegue caliente a la mesa. ¿No?

Fijate que en el segundo caso hay como mínimo 2 estados, en el estado 1 están el pan y el café, en el estado 2 se agregan los huevos. Cuando termina el estado 2... "Ñam ñam!" decía mi hijo cuando era pequeñin. :smile:

O más simple, tienes un compromiso a determinada hora.
¿Dejas de hacer todo hasta que llegue la hora de tu compromiso o haces tus cosas hasta que sea hora de atender ese compromiso?

Fijate que tu "maquina" tiene varios estados, que se repiten 145 veces. Por decir, estado1 hace el primer movimiento y queda en ese estado hasta que se cumple el tiempo y recién entonces pasa al estado2. El estado2 hace el siguiente movimiento y queda en ese estado hasta que otra vez se cumpla su tiempo para pasar a estado3, lo mismo para el estado3 y estado4, pero en estado4, cuando se cumpla el tiempo, incrementas además un contador (equivale al del for()) antes de pasar a estado1, pero cuando llega a 145 lo reinicias a 0 y en lugar de volver a estado1 pasas a estado5 que hará la parada de descanso de 2 segundos, una vez cumplidos vuelves a estado1 y todo vuelve a empezar.

En otras palabras, juegas con los LED, te fijas qué ocurre con estadoX, o sea el estado actual en que se encuentra tu máquina, ¿hay que cambiar algo?. Si nada cambia vuelves a empezar a jugar con los LED y tal. Lo resuelves con un contador (para los 145 pasos) y un switch() para ver cual paso corresponde ejecutar. Así de simple y así de complicado. :laughing:

¿Se entendió?

Agrego:

Ahora veamos rápidamente tu código.
Inicia, teóricamente, con millis() = 0.
En microsegundos resuelve lo de los LED y entra al lazo for() (del que no saldrá hasta cumplir las 145 pasadas).
Durante 3 mseg no va a hacer nada (se va a cumplir más de un lazo porque cada pasada dura unos 12 useg), así que supongamos que loop() ya "pegó una vuelta" con for() incluido, y justo luego de "jugar" con los LED se cumplen los 3 mseg, millis() = 3 y todas tus variables a 0.
Se cumple el primer condicional y se ejecuta.
Se cumple también el siguiente condicional porque TiempoPaso2 también es 0 entonces se cumple el intervalo.
Se cumple el tercer condicional también.
Y el cuarto!
¿Y por qué se cumplen los 4?
Porque en 1 milisegundo se ejecutan cientos de instrucciones.
Haz la prueba con la simulación de @Surbyte , pon

Serial.begin(1000000);

(si 1 millón) e imprime el valor de millis() dentro de cada paso, te vas a sorprender.
¿Se mueve un motor real a tremenda velocidad?
No tengo experiencia aún con p.a.p. pero imagino que no llega a reaccionar y solo vibrará.

Sigamos. A los 6 mseg, otra vez se cumplen todos los condicionales de 1 a 4, y así hasta los 2000 mseg en que se cumpla el 5to. El supuesto descanso que no es tal porque al siguiente mseg ya deja de cumplirse el condicional, además se van a cumplir los otros (2001 es multiplo de 3 :wink: ) y fin del "descanso".
Resultado: el motor vibra y nada más.

Saludos

1 Like

.

Hola maestro MaximoEsfuerzo:

Gracias por tu tiempo empleado para la explicación; voy a estudiar con calma tus deducciones.
Ya te informare !!!

Gracias y un karma !!!!.... :cocktail:

Aquí estoy otra vez !!!

He conseguido escribir un código nuevo, que mediante millis enciendo intermitentes dos leds, independientes entre si y ademas hago funcionar un motor pap, todo al mismo tiempo y sin interferirse entre si.
Vuelvo a la pregunta del principio:
Como conseguir que el motor corra 145 pasos y se detenga un tiempo determinado de descanso y vuelva a empezar ...?????
Me comentasteis que no podía utilizar for...!!!

A ver, si al fin lo conseguimos !! ..... :cocktail:... :cocktail:



/* 
 *  
 *  M_MOTOR_PAP_UNIPO_EXPER_2_copia_FORO
 *  
 *     
*/

//  ==================================  ENGRAL JUL 2023  =================================

    const int LimiteSaltos = 4;  
    int Saltos; 
                             
    unsigned long Intervalo[LimiteSaltos] = { 3, 3, 3, 3 }; 
    unsigned long TiempoInicial; 
// *****************************************
   boolean estadoLED7 = true;
   boolean estadoLED12 = true;
   
   int INTERVALO_LED_7 = 513 ;  //tiempo de INTERVALO LED 7 
   int INTERVALO_LED_12 = 200 ; //tiempo de INTERVALO LED 12 
   
   unsigned long TiempoLED7;
   unsigned long TiempoLED12; 

//  ===================================  FUNCIONES " Pasos" DEL MOTOR PAP  ===================================

void Paso0()           // Función del paso "0".
 {
  digitalWrite(11, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(9, LOW);
  digitalWrite(8, LOW);  
 }
void Paso1()            // Función del paso "1".
 {
  digitalWrite(11, LOW);
  digitalWrite(10, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(8, LOW);
 }
void Paso2()             // Función del paso "2".
 { 
  digitalWrite(11, LOW);
  digitalWrite(10, LOW);
  digitalWrite(9, HIGH);
  digitalWrite(8, HIGH); 
 }
void Paso3()             // Función del paso "3".
 {
  digitalWrite(11, HIGH);
  digitalWrite(10, LOW);
  digitalWrite(9, LOW);
  digitalWrite(8, HIGH); 
 }

void setup()
{
  Serial.begin(9600);
  Serial.println(" ======== TITULO: M_MOTOR_PAP_UNIPO_EXPER_2_copia_FORO =============");
  Serial.println("");
   
  pinMode(7, OUTPUT);  // pin digital 7 de Arduino a intermitente
  pinMode(8, OUTPUT);  // pin digital 8 de Arduino a IN1 de modulo controlador    
  pinMode(9, OUTPUT);  // pin digital 9 de Arduino a IN2 de modulo controlador    
  pinMode(10, OUTPUT); // pin digital 10 de Arduino a IN3 de modulo controlador
  pinMode(11, OUTPUT); // pin digital 11 de Arduino a IN4 de modulo controlador
  pinMode(12, OUTPUT); // pin digital 12 de Arduino a intermitente

  Saltos = 0; 
 }

void loop()
 {
  
// *****************************  SECCION: LEDS INTERMITENTES   *****************************
  
  if ((millis()- TiempoLED7) >= INTERVALO_LED_7)// Tiempo 513 
  {
    estadoLED7 = !estadoLED7;
    digitalWrite (7, estadoLED7);
    
    TiempoLED7 = millis();
  }

  if ((millis() - TiempoLED12) >= INTERVALO_LED_12)// Tiempo 200
  {
    estadoLED12 = !estadoLED12;
    digitalWrite (12, estadoLED12);
    
    TiempoLED12 = millis();    
  } 

// *******************************   SECCION: MOTOR PAP   ***********************
  
  if ( millis() - TiempoInicial > Intervalo[Saltos] )
  {  
   
    TiempoInicial = millis(); // ============== "TiempoInicial" toma el valor actual de "millis"
    
    Saltos++;       // ============ Incrementa en "1" el "case" / "Saltos" en SWITCH .
    
    if ( Saltos == LimiteSaltos ) Saltos = 0; // Si "Saltos" llega al valor "LimiteSaltos"=4: cambia al primer "Saltos":"case 0".
                                                     
    switch ( Saltos )
  {
      case 0:
        Paso0(); //============= realiza la funcion "Paso "0"
        break; 
                             
      case 1:
        Paso1();// ============= realiza la funcion "Paso 1"
        break;

      case 2:
        Paso2(); // ============ realiza la funcion "Paso 2"
        break;

      case 3:
        Paso3(); // ============ realiza la funcion "Paso 3"
        break;      
    } 
  } 
}

// =============================================       FIN          ===============================

Ya vi tu post y vas bien encaminado.
En casa hay un corte de energía asi que estoy sin compu, internet y demás y mi móvil está bajo de batería, en cuanto se normalice veo como ajustar el código.

1 Like