MAQUETA ZOLTAR (BIG), problema con stepper continuo durante secuencia de Leds.

Buenas tardes!
Llevo un tiempo trasteando con Arduino por la necesidad de automatizar y darle algo de vidilla a mi pasión princial: el modelismo. Estoy acostumbrado a investigar y solucionar mi cuenta los múltiples problemas y dudas que me van surgiendo, en cuanto a Arduino y todo. Me cuesta un poco la programación porque soy muuuy de letras (de otro tipo de letras!) pero voy tirando porque, además, Arduino tiene algo de droga.

Es la primera vez decido pedir algo de ayuda, porque llevo casi una semana intentando programar una maqueta que he hecho del popular ZOLTAR de la peli de BIG (aquí video con el funcionamiento), y ya no salgo de mi propio void loop XD Algo desesperadillo estoy ya. He investigado millis, whiles..., todo, pero llega un punto en que no entiendo nada o no sé si voy por el lugar correcto. Si lo llevo a saber utilizo un motor DC y ea, pero como ya he comprado e instalado el stepper, he de apechugar jaja

Mi problema es, creo, sencillo: Necesito que el stepper 28byj-48 que mueve la cabeza de Zoltar funcione SIEMPRE mientras tiene lugar una secuencia muy sencilla de leds que animan los paneles de info. Es decir, dos Void loops simultaneos.

He leído que en este caso es imposible utilizar el DELAY para la secuencia de Leds, que es mejor usar millis, pero lo he intentado y se escapa a mi comprensión. De verdad que agradecería enormemente algo de luz al respecto, la que sea.

Estoy usando Arduino NANO. Este es el código que he hecho:

// Include the Arduino Stepper.h library:
#include <Stepper.h>

int PANEL1 = 3;  //OPCION 1 PANEL
int PANEL2 = 4;  //OPCION 2 PANEl
int TEXTFRONT = 5;  //TEXTO FRONTAL
int OJOS = 7;  //OJOS

// Define number of steps per rotation:
const int stepsPerRevolution = 600;


// Create stepper object called 'myStepper', note the pin order:
Stepper myStepper = Stepper(stepsPerRevolution, 9, 11, 10, 12);

void setup() {
  myStepper.setSpeed(45);
    // Begin Serial communication at a baud rate of 9600:
  Serial.begin(9600);
  pinMode(PANEL1 , OUTPUT);
  pinMode(PANEL2 , OUTPUT);
  pinMode(TEXTFRONT , OUTPUT);
  pinMode(OJOS , OUTPUT);
}

void loop() {
  // Step one revolution in one direction:
  digitalWrite(OJOS , HIGH);   
  Serial.println("clockwise");
  myStepper.step(stepsPerRevolution);         
  digitalWrite (PANEL1 , HIGH);   
  delay(1500);                  
  digitalWrite(PANEL2 , HIGH);   
  delay(1500);                   
  digitalWrite(TEXTFRONT , HIGH);   
  delay(100);
  digitalWrite(TEXTFRONT, LOW);
  delay(100);
  digitalWrite(TEXTFRONT , HIGH);
  delay(100);
  digitalWrite(TEXTFRONT, LOW);
  delay(100);
  digitalWrite(TEXTFRONT , HIGH);
  delay(1000);
  digitalWrite(OJOS , LOW);
  delay(150);
  digitalWrite(OJOS , HIGH);
  delay(100);   
  digitalWrite(OJOS , LOW);
  delay(150);
  digitalWrite(OJOS , HIGH);
  delay(100);
  digitalWrite(OJOS , LOW);
  delay(150);
  digitalWrite(OJOS , HIGH);     
  digitalWrite(TEXTFRONT, LOW);
  digitalWrite(PANEL1 , LOW);
  digitalWrite(PANEL2 , LOW);
  delay(100);
}

He hecho parcialmente tu trabajo por es muy tedioso.

Mira hasta esta situación es que he modificado como debe ser.
Luego de la definición del stepper y antes de setup comienza esto

// Create stepper object called 'myStepper', note the pin order:
Stepper myStepper = Stepper(stepsPerRevolution, 9, 11, 10,  // puse para que lo referencies
byte estado = 0;
unsigned long start;


void setup() {
  myStepper.setSpeed(45);
    // Begin Serial communication at a baud rate of 9600:
  Serial.begin(9600);
  pinMode(PANEL1 , OUTPUT);
  pinMode(PANEL2 , OUTPUT);
  pinMode(TEXTFRONT , OUTPUT);
  pinMode(OJOS , OUTPUT);
}

void loop() {
  
  switch(estado) 
    case 0: digitalWrite(OJOS , HIGH);   
            Serial.println("clockwise");
            myStepper.step(stepsPerRevolution);         
            digitalWrite (PANEL1 , HIGH);   
            start = millis();
            estado = 1;
            break;
    case 1: if (millis()-start > 1500UL) {
                digitalWrite(PANEL2 , HIGH);   
                start = millis();
                estado = 2;
            }
            break;
    case 2: if (millis()-start > 1500UL) {
                digitalWrite(TEXTFRONT , HIGH);   
                start = millis();
                estado = 3;
            }
            break;
    case 3: if (millis()-start > 100UL) {
                digitalWrite(TEXTFRONT, LOW);
                start = millis();
                estado = 4;
            }
            break;
    case... sigue
  
  }

y reemplaza esta parte o sección del loop

void loop() {
  // Step one revolution in one direction:
  digitalWrite(OJOS , HIGH);   
  Serial.println("clockwise");
  myStepper.step(stepsPerRevolution);         
  digitalWrite (PANEL1 , HIGH);   
  delay(1500);                 
  digitalWrite(PANEL2 , HIGH);   
  delay(1500);                   
  digitalWrite(TEXTFRONT , HIGH);   
  delay(100);
  digitalWrite(TEXTFRONT, LOW);

Buenos dias Surbyte!!
Antes de nada, MIL GRACIAS por tu ayuda, de verdad. He estado trasteando con el código que has elaborado (añadiendo los eventos que se suceden de los paneles y buscado info sobre switch, break, etc) y me ocurren dos cosas:
1-El stepper solo gira medio segundo y ya da paso a la secuencia de paneles.
2-Cuando sucede el último "case", cuando ya he puesto todos elementos en LOW, ya no vuelve a empezar, no hace loop, y se queda todo parado.

Entonces, mi pregunta es la siguiente: el uso del Switch Case permite la simultaneidad? (es decir, que el stepper gire absolutamente siempre mientras tienen lugar los eventos PANEL1,PANEL2 etc). En caso de que lo permtia, ¿cómo se podría hacer? Igual es sólo diciendole al stepper que haga X revoluciones (que entiendo que sería su manera de ponerlo en HIGH), pero no estoy seguro.

Muchísimas gracias y un saludo!!!

¿Pusiste

estado = 0;

en el último case?

Saludos

Luego respondo lo de switch case.

1-El stepper solo gira medio segundo y ya da paso a la secuencia de paneles.

Esta mal lo que hice. Ya lo corrijo.

con poner el manejo del servo en el loop y no dentro de la máquina de estado, queda resuelto.

// Create stepper object called 'myStepper', note the pin order:
Stepper myStepper = Stepper(stepsPerRevolution, 9, 11, 10,  // puse para que lo referencies
byte estado = 0;
unsigned long start;


void setup() {
  myStepper.setSpeed(45);
    // Begin Serial communication at a baud rate of 9600:
  Serial.begin(9600);
  pinMode(PANEL1 , OUTPUT);
  pinMode(PANEL2 , OUTPUT);
  pinMode(TEXTFRONT , OUTPUT);
  pinMode(OJOS , OUTPUT);
}

void loop() {
  Serial.println("clockwise");
  myStepper.step(stepsPerRevolution);         
  switch(estado)
    case 0: digitalWrite(OJOS , HIGH);   
            digitalWrite (PANEL1 , HIGH);   
            start = millis();
            estado = 1;
            break;
    case 1: if (millis()-start > 1500UL) {
                digitalWrite(PANEL2 , HIGH);   
                start = millis();
                estado = 2;
            }
            break;
    case 2: if (millis()-start > 1500UL) {
                digitalWrite(TEXTFRONT , HIGH);   
                start = millis();
                estado = 3;
            }
            break;
    case 3: if (millis()-start > 100UL) {
                digitalWrite(TEXTFRONT, LOW);
                start = millis();
                estado = 4;
            }
            break;
    case 4: if (millis()-start > 100UL) {
                digitalWrite(TEXTFRONT , HIGH);   
                start = millis();
                estado = 5;
            }
            break;
    case 5: if (millis()-start > 100UL) {
                digitalWrite(TEXTFRONT, LOW);
                start = millis();
                estado = 6;
            }
            break;
    case 6: if (millis()-start > 1000UL) {
                digitalWrite(TEXTFRONT , HIGH);   
                start = millis();
                estado = 7;
            }
            break;
    case 7: if (millis()-start > 150UL) {
                digitalWrite(OJOS , LOW);
                start = millis();
                estado = 8;
            }
            break;
    case 8: if (millis()-start > 150UL) {
                digitalWrite(OJOS , HIGH);
                start = millis();
                estado = 9;
            }
            break;
    case 9: if (millis()-start > 100UL) {
                digitalWrite(OJOS , LOW);
                start = millis();
                estado = 10;
            }
            break;
    case 10: if (millis()-start > 150UL) {
                digitalWrite(OJOS , HIGH);
                start = millis();
                estado = 11;
            }
            break;            
    case 11: if (millis()-start > 100UL) {
                digitalWrite(OJOS , LOW);
                start = millis();
                estado = 12;
            }
            break;
    case 12: if (millis()-start > 150UL) {
                digitalWrite(OJOS , HIGH);
                digitalWrite(TEXTFRONT, LOW);
                digitalWrite(PANEL1 , LOW);
                digitalWrite(PANEL2 , LOW);
                start = millis();
                estado = 13;
            }
            break;                        
    case 13: if (millis()-start > 100UL) {
                 estado = 0;                  // vuelve al primer paso o sea el 0
             }
             break;
  } 
}

¡¡¡FUNCIONA!!!!
Surbyte, gatul, muchísimas gracias por vuestra ayuda, sois unos cracks. Ahora además entiendo un poco mejor el tema de la máquina de estados, porque ya lo puedo relacionar con un funcionamiento práctico. Y es algo que voy a tener que aplicar a cualquier maqueta/diorama que vaya a hacer a partir de ahora, porque las posibilidades son enormes, así que genial, ahora leo info al respecto y sé de que demonios hablan jajaja

Lo último que me gustaría conseguir es que el último panel haga blink rápido. Llevo un rato intentando modificar el código para conseguirlo, pero sin éxito. Naturalmente he probado con cambiar el valor de unsigned long (UL), pero más bajo que 1000UL ya no se nota el cambio de velocidad. También he intentado hacerlo cambiandolo por INTERVAL, pero tampoco. Imagino que la solución debe ser una tontería, pero no doy con ella

Lo mejor que puedes hacer es crear otra máquina de estados y que algun flag le diga cuando activarse y cuando no.

Piensa que la máquina de estados devuelve el funcionamiento al Arduino, ahora pareciera que no hace nada... solo atiende el stepper y de tanto en cuanto cuando corresponde activa o no una salida.
Bueno de igual modo creas otra M.E. (máquina de estado) y le dices en el caso 0 prendo, paso a otro estado, espero tantos mseg y desactivo, cambio de estado, vuelvo al inico.

Como veras es fácil pero requiere un ejercicio en nuestras cabezas diferentes. Ahora debes pensar en ESTADOS reales y no como antes en secuencias.
Delay es fácil pero no cuando se deben atacar eventos como aquí.

Olvidate del delay() y serás feliz!!

Pues si, voy a probar a hacer otra m.e. y hacer el blink. Y si, aunque pensar en delays es más fácil, es super limitado, ya me di cuenta jajajaja

Muchas gracias surbyte!!! Si no te importa, me gustaría mencionarte en en el blog donde voy a colgar estas maquetas, agradeciendo tu colaboración.

Tu dime si el hilo esta solucionado o seguiras haciendo consultas.

Solucionadísimo, gracias!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.