1. Este sitio usa cookies. Para continuar usando este sitio, se debe aceptar nuestro uso de cookies. Más información
    Descartar aviso

El hilo de ARDUINO: Dudas, código, ejemplos, etc

Tema en 'Informática - Tecnología' iniciado por McClane, 26 May 2017.

  1. MiguelX5

    MiguelX5 En Practicas

    Registrado:
    8 Feb 2017
    Mensajes:
    118
    Me Gusta:
    75
    Si te interesa algo de lo que pongo te puedo pasar el enlace a los tutos, la mayoría con copia-pega los terminas en una tarde.

    Lo mejor es mezclar ambos entornos.

    Salu2!
     
    A katraska le gusta esto.
  2. MiguelX5

    MiguelX5 En Practicas

    Registrado:
    8 Feb 2017
    Mensajes:
    118
    Me Gusta:
    75
    Alguno controláis de Blynk y sus pins virtuales?

    Tengo un problema de código ya que al parecer dentro de los while no se pueden leer pines virtuales lo que implica que la condición nunca termina.

    Muchas gracias.

    Un saludo
     
  3. McClane

    McClane Moderador Informática Moderador Miembro del Club

    Registrado:
    20 Jul 2006
    Mensajes:
    34.266
    Me Gusta:
    9.230
    Ubicación:
    Getafe Madrid
    Modelo:
    2 E30, 1 E39
    Casi lo tengo!! Me falta un pequeño ajuste que logro dar con ello. :(

    Me he puesto a darme cabezazos delante del ordenador con el ARDUINO y he pensado en hacerme un semáforo con algunos LED que tengo por aquí, pero no un semáforo de solo coches con el rojo, verde y amarillo, sino también con el de peatones :LOL: Sin embargo, me ha sabido a poco porque no es más que una extensión del programa del LED integrado (digitalWrite y delay nada más), por lo que me he complicado metiendo... el botón de peatones. :LOL:

    El funcionamiento del botón de los semáforos es el siguiente. Cuando pulsas el botón, inmediatamente pasa a amarillo y luego a rojo. Sin embargo, si acaba de ponerse en verde, al pulsar el botón no cambiará a amarillo, ya que tiene que pasar un tiempo. Lo tengo casi todo. Cuando reseteo la placa y le pulso al botón, éste hace el funcionamiento correcto. Si soy un ansias, hasta que no pasan los diez segundos que le he puesto, no cambiará a amarillo. Si pasan cinco segundos y le pulso, hasta dentro de cinco segundos no pasa a amarillo. Una vez que pasa a amarillo, hace todo el programa correcto, volviendo al verde, pero es aquí donde viene el problema: la segunda vez ya no respeta los 10s de tiempo y cambia a amarillo inmediatamente. :(

    Creo tener el problema pero no tengo la solución. El comando millis() cuenta milisegundos desde que se inicia la placa, y no desde que se le llama, por lo que en el siguiente ciclo, pasa directamente a amarillo porque ya tiene el tiempo acumulado desde que arranca, pero no encuentro un comando para resetear el tiempo y las pruebas que he hecho no han funcionado. He probado a restar el tiempo a sí mismo, pero creo que luego vuelve a tomar su valor. He creado también una variable secundaria para guardar el tiempo y restarlo pero no hay manera: solo funciona bien la primera vez. :(

    A ver si damos con ello, y así habré sacado adelante el proyecto más ambicioso de ARDUINO: un put* semáforo. :descojon:

    CODE, HTML o PHP Insertado:
    int coche_verde(11);
    int coche_rojo(12);
    int coche_ambar(13);
    int peaton_verde(7);
    int peaton_rojo(6);
    int pulsador(2);
    unsigned int boton; //variable de número de pulsaciones
    unsigned int tiempo2; //variable secundaria de tiempo
    
    void setup()
    {
    pinMode(peaton_rojo, OUTPUT);
    pinMode(peaton_verde, OUTPUT);
    pinMode(coche_verde, OUTPUT);
    pinMode(coche_rojo, OUTPUT);
    pinMode(coche_ambar, OUTPUT);
    pinMode(pulsador, INPUT_PULLUP);
    Serial.begin(9600); //únicamente utilizado como diagnóstico, no sirve para nada
    
    }
    
    void loop()
    
    //Inicio, cuenta tiempo y prepara el semáforo para estar en verde
    
    {
     
      empezar:
      unsigned long tiempo=millis();
      digitalWrite(peaton_rojo, HIGH);
      digitalWrite(coche_rojo, LOW);
      digitalWrite(coche_verde, HIGH);
    
    //Botón
     
      tiempo-tiempo2;
      if (tiempo<10000) {
        goto empezar;
        
        }else{
          boton = digitalRead(pulsador);
        
          if (boton == HIGH){
          boton++;
        
          }else{
            goto empezar;
            }
        
            if (boton=0){
            goto empezar;
            } 
      }
    
    //Cambio a rojo
    
      continuar:
      Serial.println(boton); //únicamente utilizado como diagnóstico, no vale
      digitalWrite(coche_verde, LOW);
      digitalWrite(coche_ambar, HIGH);
      delay(2000);
      digitalWrite(coche_ambar, LOW);
      digitalWrite(coche_rojo, HIGH);
    
    //Peatones
    
      digitalWrite(peaton_rojo, LOW);
      digitalWrite(peaton_verde, HIGH);
      delay(6000);
      digitalWrite(peaton_verde, LOW);
      delay(500);
      digitalWrite(peaton_verde, HIGH);
      delay(500);
      digitalWrite(peaton_verde, LOW);
      delay(500);
      digitalWrite(peaton_verde, HIGH);
      delay(500);
      digitalWrite(peaton_verde, LOW);
      digitalWrite(peaton_rojo, HIGH);
      delay(2000);
      tiempo2=tiempo; //guarda el tiempo actual en la segunda variable
      boton=0; //almacena cero pulsaciones en el botón
     
    
    }
    Estoy seguro de que es una chorrada, pero solamente si se pudiese resetear el comando millis() sería lo único que me faltaría. ¿Me echáis una mano? ;)
     
    Última edición: 14 Jun 2017
    A jormi y Tizon les gusta esto.
  4. katraska

    katraska Coordinador Coordinador

    Registrado:
    24 Ene 2002
    Mensajes:
    9.238
    Me Gusta:
    1.340
    Ubicación:
    Sanse - Madrid
    Modelo:
    325i E92
    Cosas que veo @McClane

    etiquetas y goto's, en C están prohibidos. Se pueden evitar con while, for, if, etc. Complican mucho la lectura del código y puedes tener resultados poco predecibles

    El primer bucle lo resuelves con:

    while (tiempo-tiempo2 < 1000){
    <lo que sea>
    }

    Además, en ese bucle estás asignando el mismo valor a las salidas digitales miles de veces.... y declarando también miles de veces la variable tiempo.

    Usas la variable tiempo2 sin haberla inicializado. Es decir, al comenzar el programa no sabes qué valor tiene. Sólo has reservado un espacio en memoria, pero igual no está a cero (suele estarlo al reiniciar, pero nunca se sabe).

    Nada mas empezar haces: tiempo - tiempo2, que no entiendo como te deja el compilador, porque no hace nada. No se si quieres decir tiempo = tiempo - tiempo2 o qué.

    A continuación preguntas si tiempo<10000. como acabas de iniciar el arduino, el contador millis() empieza de cero, así que la primera vez se tira 10 segundos en ese bucle, hasta que millis pasa de 10000.

    luego, si no pulsas nada, se mete en ese código, donde hay un montón de delays encadenados. Entiendo que tras los primeros 10 segundos es lo que buscas (cambiar a rojo) .Por tanto el arduino está metido en un montón de delays y cada 12 segundos pasa fugazmente por el control del botón pulsado (ya es casualidad que lo pille en estado bajo, que entiendo es lo que te ofrece cuando pulsas). Es decir, durante todo este tiempo, aunque pulses, pasa de ti porque el arduino no está mirando la entrada del botón. Para solventar esto, como te contaba en un post previo, tienes que utilizar interrupciones.... y no utilizar delay: deberías hacerte una función equivalente, que te retarde la ejecución del código, usando el valor millis. Alternativamente, podrías no utilizar interrupciones, pero verificar la pulsación dentro de la función de los retardos... las alternativas son infinitas.

    El bloque que pone:

    if (boton=0){
    goto empezar;
    }

    creo que no se ejecuta nunca, pulses o no pulses. No alcanzo a ver para qué lo usas.

    Tampoco parece adecuado que a una variable tipo int le asignes un valor HIGH. No es que no se pueda porque HIGH es 1, pero lleva un poco al huerto cuando lees el código.

    Como primera medida, intenta eliminar todas las etiquetas y goto. Te obligará a pensar el código de modo más lógico y serás capaz de ver por dónde pasa. Inicializa el valor tiempo2.

    te recomiendo que antes de meterte a escribir código organices las ideas tratando de hacer un esquema (tipo diagrama de flujo) donde vayas escribiendo acciones atómicas sencillas y luego con flechas vas organizando dónde debe ir el código en caso de condiciones.

    Te diría dónde tocar, pero me temo que no es cosa de tocar una variable o una línea. Si quieres te hago algo, pero te lo tendría que dar la vuelta (lo siento ;))


    salu2
     
    Última edición: 15 Jun 2017
    A borja.lopez y Tizon les gusta esto.
  5. McClane

    McClane Moderador Informática Moderador Miembro del Club

    Registrado:
    20 Jul 2006
    Mensajes:
    34.266
    Me Gusta:
    9.230
    Ubicación:
    Getafe Madrid
    Modelo:
    2 E30, 1 E39
    Aupa!! :LOL: No te contesto no porque pase del tema, es que ahora no puedo sacar ni una hora para dedicarte. :(

    @katraska
     
  6. katraska

    katraska Coordinador Coordinador

    Registrado:
    24 Ene 2002
    Mensajes:
    9.238
    Me Gusta:
    1.340
    Ubicación:
    Sanse - Madrid
    Modelo:
    325i E92
    No hay problema, cuando lo retomes seguimos ;-)

    salu2
     
    A Tizon le gusta esto.
  7. McClane

    McClane Moderador Informática Moderador Miembro del Club

    Registrado:
    20 Jul 2006
    Mensajes:
    34.266
    Me Gusta:
    9.230
    Ubicación:
    Getafe Madrid
    Modelo:
    2 E30, 1 E39
    A ver si ahora. :D

    Cuando programo o intento programar :LOL: tengo detrás la página de ARDUINO ton todas las instrucciones disponibles, así voy viendo instrucciones que me pueden valer y así intentar echarlas a andar. La instrucción goto sí está contemplada y las etiquetas también, de ahí que las use, ya que no tengo ni puñetera idea ni de C, ni de C+ ni de C++. :(

    Todo lo que veas de tiempo y tiempo2 y demás, son intentos frustrados de intentar restar el tiempo antiguo al nuevo con la esperanza de que se resetee, pero como puedes comprobar, no resetea, así que ahora mismo no lo tengas muy en cuenta. :LOL:

    En cuanto al millis(), el tiempo de 10000ms y el botón, si funciona. Cuando meto tensión al ARDUINO, éste ejecuta el millis, se pone a contar y empieza con la luz verde para coches y la luz roja para peatones. Si pasan esos diez segundos, el semáforo sigue en verde siempre hasta que pulse el botón. Cuando pulso el botón, inmediatamente hace el ciclo del ámbar y rojo para volver a empezar. Si no llega a los diez segundos y yo ya he pulsado el botón, cuando el contador llegue a 10 segundos, el semáforo hace la función. Para ponerlo más claro. Al meter tensión al ARDUINO:

    -Si no pulso el botón, SIEMPRE se queda en verde
    -Si pulso el botón después de los 10s, cambia inmediatamente a ámbar
    -Si pulso el botón antes de los 10s, hasta que no llegue al tiempo estipulado, no cambia a ámbar

    Con esto comprobamos que el código en sí, funciona, y que el contador de pulsaciones también lo hace. Que la programación no sea la óptima, te lo compro, bastante que casi consigo hacer el put* semáforo. :LOL: Tendré que empezar a cagarla por algún lado. :descojon: En cuanto a los delays, pues no he encontrado otro código viable con mis conocimientos, que no llegan ni al 1%. De momento, con que me funcione perfecto aunque no esté perfectamente programado, me doy por satisfecho. :LOL: Iré poniéndome poco a poco retos de estos porque sí, ves que se pueden hacer mil cosas pero te pones a programar tu idea y de esas mil cosas, te salen mil dudas. :LOL: Lo siguiente que haga seguramente sea un control de temperatura de frío o calor, o ambos, que si baja de temperatura active una salida y si sube de una temperatura, active otra salida. Pero antes quiero que el semáforo funcione. ;)

    Si está casi entero, pero me falta que respete esos 10s siempre. :LOL:

    Muchas gracias por la ayuda. Volveré a leerme tu respuesta y cuando tenga un rato y no haga tanto calor :LOL: me pongo con ello. ;)
     
    A SPTR y Tizon les gusta esto.
  8. SPTR

    SPTR Forista Legendario Moderador Miembro del Club

    Registrado:
    18 Ago 2005
    Mensajes:
    9.025
    Me Gusta:
    739
    Ubicación:
    X
    Cómo te va el bacalao mclein!! :chulo:
     
  9. katraska

    katraska Coordinador Coordinador

    Registrado:
    24 Ene 2002
    Mensajes:
    9.238
    Me Gusta:
    1.340
    Ubicación:
    Sanse - Madrid
    Modelo:
    325i E92
    Mira @McClane, un ejemplo de gestión de dos teclas por interrupciones.

    Cuando se pulsa una de las teclas se ejecuta la rutina de interrupción (botón_up o botón_down), que lo único que hacen es poner a true una variable global.
    En el búcle loop se está mirando continuamente el valor de esas variables, y si de repente están a true es que ha saltado la rutina de interrupción. Haces lo que sea y luego vuelves a poner a false la variable global, para la próxima. Aprovecho a meter un timer para evitar que los rebotes de las teclas hagan que se detecte como varias pulsaciones.


    CODE, HTML o PHP Insertado:
    #define PIN_UP 3            // pin de entrada de tecla UP
    #define PIN_DOWN 2          // pin de entrada de tecla DOWN
    #define TIMER_SWITCH 150    // temporizador para evitar rebotes de teclas
    
    boolean up, down;
    
    //-------------------------------------------------------------------------
    void setup() {
      Serial.begin(115200);
      pinMode(PIN_UP, INPUT_PULLUP);
      pinMode(PIN_DOWN, INPUT_PULLUP);
      attachInterrupt(digitalPinToInterrupt(PIN_UP), boton_up , RISING);
      attachInterrupt(digitalPinToInterrupt(PIN_DOWN), boton_down, RISING);
      delay(300);       // -- para evitar que salten las interrupciones al comienzo
      up = false;
      down = false;
    }
    
    //--------------------------------------------------------------------------
    void loop() {
      if (up){
         Serial.println("UP");
         delay(TIMER_SWITCH);
         up = false;
        }
    
       if (down){
          Serial.println("DOWN");
          delay(TIMER_SWITCH);
          down = false; 
       }
    }
    
    // -----------------------------------------------------------------------
    //    manejo de interrupción de boton UP pulsado
    // -----------------------------------------------------------------------
    void boton_up(){
      up = true;
      }
    
    
    // -----------------------------------------------------------------------
    //    manejo de interrupción de boton DOWN pulsado
    // -----------------------------------------------------------------------
     void boton_down(){
      down = true;
      } 
     
    Última edición: 22 Jun 2017 a las 19:13
    A SPTR y Tizon les gusta esto.