This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

A cookie will be stored in your browser regardless of choice to prevent you being asked this question again. You will be able to change your cookie settings at any time using the link in the footer.

  • 1 voto(s) - 4 Media
  • 1
  • 2
  • 3
  • 4
  • 5
Estacion Meteorologica
#21
Ye he pedido por ahora los DHT22, el Arduino el LCD 20x4 y el RealTime, cuando llegen voy posteando los resultados....cuando controle los dos modulos a la perfeccion, pedire mas Gran sonrisa

Un saludo¡¡
  Responder
#22
Pide ya el sensor del aire!! xD

Puede que te interese un sample de aquí: http://www.serpac.com/default.aspx
  Responder
#23
Ummm, acabo de mandarles un formulario a los de las cajas aver que me dicen Gran sonrisa
  Responder
#24
Para estas cosas están muy bien las cajitas esas.
  Responder
#25
Revivo esto, para comentar que esta empezando el proyecto a moverse, al final los elementos que voy a emplear por ahora son los siguiente:

Cerebro
Arduino NANO
[Imagen: NanoFront.jpg]

Temperatura-Humedad
DHT22
Datasheet
[Imagen: dht22.jpg]

Real Time
DS1307RTC
Datasheet
[Imagen: images?q=tbn:ANd9GcQmPHfMNdAADqYBbsTmnau...pqkBo_oFAQ]

Luminosidad
BH1750FVI
Datasheet
[Imagen: BH1750FVI-Digital-Light-Sensor-with-IIC-..._10-32.jpg]

Presion
BMP180
Datasheet
[Imagen: bmp180-breakout-top-460x460.png]

Lluvias
Sensor Lluvia

Sensor CO2 o OZONO
Aun esta por determinar cual de los dos usare, ambos me pueden aportar ciertos datos sobre la calidad del aire

Sensor Sonoro
Para intentar medir los Db, aun lo tengo por determinar, cualquier sugerencia sera bienvenida

Comunicacion
Modulo 433Mhz
[Imagen: images?q=tbn:ANd9GcQWTct6mRak1ARYAkW_Fjd...0y0rspUq86]

Para mostrar los datos empleare una pantalla LCD de 20x4 y un encoder rotativo para desplazarme por los menus

Tengo muchos flancos a los que atacar, la estacion exterior esta mas o menos definida, a falta de escoger un sensor de "humos" y el de ruido. Quiero valorar si el consumo no es muy elevado, tanto del arduino como de los sensores, el uso de una bateria, y una placa solar para recargarla. El problema es que no tengo ni idea de tecnologia de baterias, quisiera una que el controlador no fuera muy complejo(El de carga vamos) y que fuera medianamente sencillo medir el nivel de carga de la misma, esto seguro que los expertos en RC podeis aconsejarme, creo que Litio descartado debido a que el sistema de carga y demas es bastante complejo...., pensaba usar un PANEL SOLAR de este estilo:

Panel

Para cargar una bateria de unos 6V, y con esta alimentar el arduino, creo que podria llegar a ser posible hacer autonoma la estacion externa, si el consumo del arduino no es muy elevado.


Ahora estoy metido con la estacion interior, organizando como hacer los menus, como desplazarme por ellos y aprendiendo a usar el encoder, del cual he cogido un codigo ya echo, debido a que me costaba solventar el tema de los rebotes, que al parecer se dan al principio de la primera señal que cambia, nose si me explico, debemos evitar leer esos rebotes y desplazarnos un solo "grado", estoy todabia mirando como funciona, aunque ya lo he conseguido hacer funcionar con este programa. En breves pondre las conclusiones que he sacado del encoder y demas y como funciona. En mi caso mecanico rotativo.

Para el DS1037RTC empleo esta libreria, de la cual creo que me voy a ver en la necesidad o bien de modificarla, o bien mirar otras, ya que no tengo las manera de recibir el dia de la semana en el que me encuentro, por tanto no puedo saber el dia de la semana en el que estamos. Mas adelante me metere con ello.

Estoy estudiandome tambien el BUS I2C, ya que me gustaria saber como funciona el mismo, cualquier informacion al respecto es bienvenida, sin mas demora, os dejo un video de los que tengo echo, que no es nada al fin y al cabo....



Esto es todo por ahora, luego mas informacion sobre I2C y el Encoder
  Responder
#26
Tiene muy buena pinta, a ver como sigue avanzando el tema. Has añadido unas cuantas cosas que la gente no suele poner.
-> Mi CNC de escritorio CNCDesktop 500 -> https://www.spainlabs.com/foros/tema-Fresadora-Desktop-CNC-500
-> Laboratorio de Fabricación Digital Maker www.lowpower.io 
--> Twitter: https://twitter.com/Grafisoft_ES  | IG: https://www.instagram.com/lowpowerio/
  Responder
#27
Hace poco que ando por aqui pero lo de la estacion externa sin duda sique me interesa jejeje no quitare ojo

Enviado desde mi GT-I9505 mediante Tapatalk
  Responder
#28
Al final te has liado a meter más y más chuches, así me gusta, xd.

Te mandaron la caja los de serpac¿?

Lo del rotatory encoder lo tengo que mirar también, y como programar una estructura de menús.
  Responder
#29
jukillo escribió:Al final te has liado a meter más y más chuches, así me gusta, xd.

Te mandaron la caja los de serpac¿?

Lo del rotatory encoder lo tengo que mirar también, y como programar una estructura de menús.

Me comentaron que de el modelo que solicite no mandaban Muestra Triste jajajaja

Respecto del encoder, he estado haciendo varias pruebas, intentando comprender el programa para evitar los rebotes sobre todo, y he llegado a alguna conclusion que mañana pondre por aqui, porque ahora mismo estoy tronzao jajajaja
  Responder
#30
ENCODER

Bueno, como voy a utilizar un encoder para desplazarme por los distintos menus, queria comprender al 100% su funcionamiento y los programas que pueda llegar a usar para controlarlo.

Para empezar yo compre un modulo ya preparado, pero las conexiones del mismo son muy sencillas, solo que tendriamos que añadir un par de resistencias PULLUP. En mi caso tenemos dos tres salidas, CLK, DT y SW, y la alimentacion GND y VCC(+)

[Imagen: 7daa7154-407e-4278-97f6-f7fcd81e513d_zps87fef659.jpg]

Es un encoder mecanico, existen tambien opticos, pero logicamente son mas caros y mas precisos. Como todo elemento mecanico tenemos rebotes que deberemos de solucionar.

El funcionamiento es simple, tenemos dos salidas, llamemoslas A y B, las cuales al girar el potenciometro para derecha o izquierda vienen desfasadas, ya sea la A respecto la B o viceversa segun el sentido de giro, para verlo con mas claridad os dejo esta foto:

[Imagen: rotary.png]

CW significa que gira en el sentido de las agujas del reloj, y CCW en el sentido contrario.

Sabiendo esto, ya podriamos realizar un programa que nos indique para que lado hemos girado el encoder, tomamos una señal como referencia en este caso la A, elegimos si queremos comprobar en el flanco de bajada o de subida, en nuestro caso flanco de bajada, pues bien, si en el flanco de bajada la señal B es 1 tendremos que hemos girado para la derecha, en el caso de ser 0 que hemos girado para la izquierda.

Ahora vamos a entrar en materia, lo primero que queria comprobar era el rebote, para ello recurri al analizador logico del pickit2, y aqui van los resultados:

[Imagen: IMG_20131123_231147_zpsd6ddf8ce.jpg]

[Imagen: ReboteDT_BIG_zps72fb4e49.jpg]

[Imagen: ReboteCLK1_zps7bf48eed.jpg]

Como vemos, en cuanto una de las señales tiene un flanco ya sea de bajada o de subida, tenemos un rebote, en algunos casos mayor, en otros menor, que nos puede dar problemas a la hora de la lectura del giro, ya que dada la alta velocidad de estos micros, encontraremos que ademas del verdadero flanco de bajada, nos lee tambien los flancos de los rebotes..., esto sucede siempre que la señal cambia 1-0, 0-1 ya que es un elemento mecanico.

Esto podemos solucionarlo introduciendo un pequeño Delay() para evitar estos rebotes, aunque tambien se puede solucionar por HD con resistencias y condensadores, pero me parece mas aparatoso.

Para usar este encoder, me he leido dos rutinas, una muy sencilla, en la que no emplearemos Interrupciones, quizas esto para un programa corto este bien, pero para un programa largo como sera el de la estacion, en el que tendremos una linea de codigo bastante extensa, nos puede dar problemas ya que podemos girar el encoder y que el arduino no este en ese momento haciendo la lectura del pin A y por tanto no se veria modificada la posicion. Sin contar que tendriamos que introducir una funcion de lectura del encoder en cada submenu.

Pero para empezar esta bien:

Código:
// Pines de lectura del encoder
int a = 9;
int b = 8;
// Valores de medida
int anterior = 1;
int contador;

void setup()
{
  // Inicializamos la lectura del encoder
  pinMode(a, INPUT);
  pinMode(b, INPUT);

  // Inicializamos las variables
  anterior = 1;
  contador = 0;
  escribir();
}

void loop()
{
  // Lectura de A, si es 0, volvemos a medir para asegurar el valor
  int actual = digitalRead(a);  //Si A tiene flanco de bajada cae a 0
  if(actual == 0) {        //Si A pasa a 0
    delay(10);               //Delay para evitar rebotes
    actual = digitalRead(a);  //Comprobamos que la actual siga siendo 0
  }

  // Actuamos únicamente en el flanco descendente
  if(anterior == 1 && actual == 0)    //Flanco descendente pasamos de 1 a 0
  {
    int valor_b = digitalRead(b);    //Leemos B
    if(valor_b == 1) contador++;  // Si B = 1, aumentamos el contador  //Si B es valor alto, hemos girado a la derecha, por tanto sumamos valor
    else contador--;  // Si B = 0, reducimos el contador                          //Si B es valor bajo, hemos girado a la izquierda, por tanto restamos valor
  }
  anterior = actual;  //Seteamos anterior a 0, ya que el ultimo valor leido es cero.

ORIGEN

Es un codigo que no se puede simplificar mas, me costo ver un poco la ultima linea la verdad, pero si no igualas la anterior a la actual, la anterior sigue siendo uno, cosa que no es cierta, por tanto en el periodo que la señal A esta a nivel BAJO, estarias adeptando la condicion de flanco de bajada, y por tanto leyendo la B, y restando valores. En cambio si corriges la posicion anterior que ahora seria 0, hasta que no vuelves a tener un valor positivo de A no volvemos a leer si tenemos un flanco de bajada. Es necesario tener en cuenta, que el Arduino, es capaz de leer muchisimo mas rapido de lo que las señales cambian. No hace falta nada mas que ver las graficas obtenidas con el pickit2.

Ahora vamos con las interrupciones, yo desconocia esta funcion en el arduino la verdad, nunca se para de aprender. Pues bien, lo primero para comprenderlas recomiendo leer este enlace

Una vez tenemos el concepto de interrupcion pillado, me gustaria decir que la asignacion de interrupcion a los pines en Arduino NANO es diferente a Arduino Leonardo, que tiene 2 mas, porque me he vuelto loco comprendiendo el codigo ejecutandolo con Leonardo, y resulta que tenia las interrupciones mal puestas.

Resumiendo una interrupcion es un comando que en cualquier momento que el valor de un pin se vea modificado, llama a una funcion, independientemente del lugar en el LOOP del programa que nos encontremos, deja de ejecutarse y vamos a la funcion citada en el attachInterrupt();, tras ser ejecutada la funcion, volvemos a la parte del codigo a la que nos encontrabamos.

El codigo con Interrupciones es el siguiente:

Código:
/* interrupt routine for Rotary Encoders


   The average rotary encoder has three pins, seen from front: A C B
   Clockwise rotation A(on)->B(on)->A(off)->B(off)
   CounterCW rotation B(on)->A(on)->B(off)->A(off)

   and may be a push switch with another two pins, pulled low at pin 8 in this case
  

*/

// usually the rotary encoders three pins have the ground pin in the middle
enum PinAssignments {
  encoderPinA = 2,   // right (labeled DT on our decoder, yellow wire)
  encoderPinB = 3,   // left (labeled CLK on our decoder, green wire)
  clearButton = 8    // switch (labeled SW on our decoder, orange wire)
// connect the +5v and gnd appropriately
};

volatile unsigned int encoderPos = 0;  // a counter for the dial
unsigned int lastReportedPos = 1;   // change management
static boolean rotating=false;      // debounce management

// interrupt service routine vars
boolean A_set = false;              
boolean B_set = false;


void setup() {

  pinMode(encoderPinA, INPUT_PULLUP); // new method of enabling pullups
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(clearButton, INPUT_PULLUP);
// turn on pullup resistors (old method)
  //digitalWrite(encoderPinA, HIGH);
// digitalWrite(encoderPinB, HIGH);
// digitalWrite(clearButton, HIGH);

// encoder pin on interrupt 0 (pin 2)
  attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
  attachInterrupt(1, doEncoderB, CHANGE);

  Serial.begin(9600);  // output
}

// main loop, work is done by interrupt service routines, this one only prints stuff
void loop() {
  rotating = true;  // reset the debouncer

  if (lastReportedPos != encoderPos) {
    Serial.print("Index:");
    Serial.println(encoderPos, DEC);
    lastReportedPos = encoderPos;
  }
  if (digitalRead(clearButton) == LOW )  {
    encoderPos = 0;
  }
}

// Interrupt on A changing state
void doEncoderA(){
  // debounce
  if ( rotating ) delay (1);  // wait a little until the bouncing is done

  // Test transition, did things really change?
  if( digitalRead(encoderPinA) != A_set ) {  // debounce once more
    A_set = !A_set;

    // adjust counter + if A leads B
    if ( A_set && !B_set )
      encoderPos += 1;

    rotating = false;  // no more debouncing until loop() hits again
  }
}

// Interrupt on B changing state, same as A above
void doEncoderB(){
  if ( rotating ) delay (1);
  if( digitalRead(encoderPinB) != B_set ) {
    B_set = !B_set;
    //  adjust counter - 1 if B leads A
    if( B_set && !A_set )
      encoderPos -= 1;

    rotating = false;
  }
}

ORIGEN

Bueno este codigo tiene algo mas de chicha, debemos de tener en cuenta que al usar interrupciones, estas van a saltar en los rebotes que tenemos a la hora de accionar el encoder, y es un tema que debemos de solucionar.

Para empezar al comienzo del codigo tenemos la asigancion de pines, que en este caso se ha empleado una enumeracion (enum), que es una forma de declarar varios elementos es arduino. Tras esto asignamos la variable de posicion y la de ultima posicion. Por ultimo asignamos una variable para el rebote.

Tenemos una variables de tipo Boole, que seteamos en false, debido a que empezamos sin existir ningun cambio en las señales.

Asignamos los pines y las interrupciones en el setup, como vemos las interrupciones son sencillas de asignar, en nuestro caso saltaran ante cualquier cambio del pin de la interrupcion.

Y empezamos el programa, como no ha sucedido nada aun activamos el debouncer(rebote), escribimos Index:0 ya que la posicion ultima es diferente a la del encoder, y las igualamos, ya estamos en la posicion 0 establecidos.

Si giramos hacia la derecha, la primera interrupcion en saltar es la A, llamamos a la funcion y realizamos un retardo para evitar posibles rebotes ya que rotating es true.

En este caso vamos a funcionar con el flanco de subida, en el primer flanco se activa la interrupcion, pero el valor leido en A es cero, por tanto no entramos en el bucle para cambiar A_set.

Tras esta interrupcion, la siguiente en llegar sera una dada por B, debido a la manera de funcionar del encoder. Entramos en la interrupcion de B, pero nos encontramos con el caso anterior que con A, y es que el valor del pin ahora es cero, por tanto no es un flanco de subida.

La siguiente interrupcion en llegar es el flanco de subida en A, en este caso, y tras realizar el delay, leemos un valor alto en A, por tanto entramos en el IF, cambiando el valor de A_set, que lo ponemos el TRUE, es como si hubieramos ya detectado el flanco de subida, vemos que tambien se cumple el IF de sumar posicion, debido a que el valor de B_set no ha cambiado, es 0 valor que leemos en el flanco de subida y que nos indica que giramos a la derecha.

Tras esta interrupcion y tener A_set, tenemos el rotating en false, por tanto no realizariamos el delay hasta mostrar la posicion Index. Pero y si tenemos un rebote?, la funcion EncoderA volveria a saltar, pero sabiendo que el ciclo de A ya se acabo, por tanto vamos a leer un valor alto en el PIN, y que A_set es alto, vemos que no ha cambiado nada, solo ha sido un rebote, por tanto pasamos.

Aun no hemos acabado, aun le queda por llegar al flanco de subida de la señal B, en este caso, entraremos en el condicional, porque el pin B el valor es alto, y B_set es bajo, por tanto seteamos B_set en TRUE, pero no sumamos, ya que no cumplimos el condicional de que B_set sea TRUE y el conjugado de A_set sea TRUE, ya que venimos de tener A_set en TRUE por tanto el conjugado es FALSE.

Y ya hemos acabado el ciclo, seteamos rotating=TRUE y mostramos la posicion a la espera de otro giro.

Vamos a ver que pasa si iniciamos otro giro, tenemos A_set=TRUE y B_set=TRUE, si giramos otra vez hacia la derecha, el flanco de bajada de A, nos seteara de nuevo A_set=FALSE, y volveremos a tener solo en cuenta el flanco de subida, y B_set se vuelve a setear a FALSE en el flanco de bajada de B que vendra despues del de A como antes mencionamos.

Si simplificamos el sentido es parecido al de la rutina anterior, pero teniendo en cuenta que con las interrupciones tendremos que evitar los flancos de bajada y tener en cuenta los de subida, ademas de evitar posibles rebotes.


Me he planteado simplificar el codigo de esta segunda, pero me parece que esta muy bien la verdad, asique es posible que use este mismo, porque no veo manera de simplificarlo, en un principio pense en las interrupciones solo saltar cuando tengas un flanco (RISING, FALLING), pero los rebotes son muy incomodos, quizas funcionaria con algo asi, y teniendo en cuenta que no he visto rebotes que sucedan despues del milisegundo se podria implementar creo una rutina con una sola interrupcion, pero no estoy seguro, voy a ponerme con ello y os cuento.

Y esto es todo por ahora, seguiremos informando, proximamente informacion sobre el modulo REALTIME DS1307

:yeah: :yeah:
  Responder
#31
Bueno, creo que he conseguido algo, aqui os dejo el asunto:

Código:
//Autor::Triggerr
enum PinAssignments {
  encoderPinA = 2,   // right (labeled DT on our decoder, yellow wire)[Interrupt 1]
  encoderPinB = 4,   // left (labeled CLK on our decoder, green wire)
// connect the +5v and gnd appropriately
};

volatile unsigned int encoderPos = 0;      // a counter for the dial
unsigned int lastReportedPos = 1;       // change management
static boolean rotating=false;          // debounce management
boolean A_set = false;                     //Seting A variable

void setup() {
    pinMode(encoderPinA, INPUT_PULLUP); // new method of enabling pullups
    pinMode(encoderPinB, INPUT_PULLUP);
    pinMode(clearButton, INPUT_PULLUP);
    // encoder pin on interrupt 1 (pin 2) [If use arduino NANO/UNO, change 1 to 0]
    attachInterrupt(1, doEncoderA, FALLING);    //Falling Edge
      Serial.begin(9600);  // output
}

void loop() {
    rotating = true;  // reset the debouncer
    if (lastReportedPos != encoderPos) {    //If last record its diferent that new record print new position
        Serial.print("Index:");
        Serial.println(encoderPos, DEC);
        lastReportedPos = encoderPos;        //Seting new position
    }
    if(digitalRead(encoderPinA)==1 && digitalRead(encoderPinB)==1)     //When rotating finish twice signals are 1
    A_set = false;                                                    //Reset A_seting
}
// Interrupt on A falling edge
void doEncoderA(){
  // debounce
  if ( rotating ) delay (10);    
  //Check that pinA its 0, after the falling edge, and A_set isnt set yet
  if (!A_set && digitalRead(encoderPinA) == 0){    
    if(digitalRead(encoderPinB) == 1) {         //If PinB 1, turn encoder right
        A_set=!A_set;                            //A signal set TRUE, dont repeat until nex turn
        encoderPos++;
    }
    else{                                        //If PinB 0, turn encoder left
        A_set=!A_set;                            //A signal set TRUE, dont repeat until nex turn
        encoderPos--;
    }  
    rotating = false;                            //Stop Debouncer
  }
}

En principio funciona correctamente a falta de testearlo durante mas tiempo, empleo una sola interrupcion por lo que tenemos una libre, testeando una unica señal en ved de las dos, el ahorro de memoria es inapreciable la verdad.

Mañana sigo dandole vueltas al encoder aver si le afecta el rebote, pero me parece que es efectivo.
  Responder
#32
Tendras que testearlo(todo el conjunto) dejandolo funcionar durante un tiempo largo, y con largo me refiero a varias horas o incluso superando el dia. Seguire tus avances con detenimiento ^^
-> Mi CNC de escritorio CNCDesktop 500 -> https://www.spainlabs.com/foros/tema-Fresadora-Desktop-CNC-500
-> Laboratorio de Fabricación Digital Maker www.lowpower.io 
--> Twitter: https://twitter.com/Grafisoft_ES  | IG: https://www.instagram.com/lowpowerio/
  Responder
#33
grafisoft escribió:Tendras que testearlo dejandolo funcionar durante un tiempo largo, y con largo me refiero a varias horas o incluso superando el dia. Seguire tus avances con detenimiento ^^

El problema es que si quiero testearlo en activo la unica manera es a mano, quiero decir tengo que girar yo el encoder para ir viendo si se salta algun numero si va de dos en dos alguna vez...no es un programa de ejecucion automatica requiere de la intervencion humana jajajaja probe dando vueltas uno a uno asta 80 rotaciones....ahi me pare que llevo todo el dia cacharreando y ya estoy out. Hay veces que el tema de los rebotes es bastante aleatorio quiero decir, la longitud de los rebotes no es fija, no es algo que puedas programar, solo tienes que asegurarte de que los evitas

Enviado desde mi Nexus 4 mediante Tapatalk
  Responder
#34
Comprobando el codigo del encoder, tengo que con un delay(10) del encoder, tengo rebotes y sumas de 2 en dos, ocasionalmente, no siempre, la unica forma de solucionarlo en principio al 100% ha sido recurrir a un delay de 200ms, no me gusta llegar a un delay tan largo la verdad, y quizas en programas con muchas lineas de codigo, de problemas, no estoy del todo seguro. El problema que me encuentro es que en el primer flanco de bajada o segundo realizamos la suma, pero luego vienen rebotes consecutivos que me ponen A_set en FALSE, por lo tanto me reinician el ciclo, pudiendose sumar otro index de mas...., me esta dando batalla.
  Responder
#35
Bueno, aunque parezca que esto esta parado no lo esta¡¡, ya tengo la mayoria de sensores.

Me he estado peleando aun con el encoder rotativo, y sinceramente, creo que voy a pasar de usarlo, empleare botones, me esta dando muchos problemas, se salta pasos, a veces pasa de dos en dos...., sin contar el uso de codigo que necesita. He empleado un codigo de interrupciones ya que al ser el codigo largo es la mejor opcion, pero nada, no es nada eficiente, puede que se deba a la escasa calidad del mismo...., pero no me voy a romper la cabeza, lo que si dejo el codigo por si alguien quiere echarlo un ojo:

Código:
//Libreriaswgw
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <Bounce.h>


LiquidCrystal_I2C lcd(0x20,20,4);  // set the LCD address to 0x20 for a 20 chars and 4 line display

//Caracteres
byte flecha_dech[8] = { 0x0,0x8,0xc,0xe,0xc,0x8,0x0,0x0 };
//ENCODER+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// usually the rotary encoders three pins have the ground pin in the middle
enum PinAssignments {
  encoderPinA = 2,   // right (labeled DT on our decoder, yellow wire)
  encoderPinB = 3,   // left (labeled CLK on our decoder, green wire)
// connect the +5v and gnd appropriately
};

const int encoderSW = 8;

volatile int menu = 1;  // a counter for the dial
int lastmenu = 0;
static boolean rotating=false;      // debounce management

boolean salir = false;

// interrupt service routine vars
boolean A_set = false;              
boolean B_set = false;
//Asignamos el pin
Bounce encoderSW_bounce = Bounce(8,100);
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void setup() {
    lcd.init();
      lcd.backlight();                     //Iniciamos la retroiluminacion
      lcd.setCursor(6,0);                //Situamos el cursor al inicio
      lcd.print("Estacion");        //Imprimimos mensaje inicial
      lcd.setCursor(3,1);
      lcd.print("Meteorologica");
      lcd.setCursor(7,3);                //        
      lcd.print("L1llo5");                //
      delay(2000);                        //Esperamos 2 segundos con el mensaje
      lcd.clear();                        //Limpiamos la pantalla
    //SETUP ENCODER+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    pinMode(encoderPinA, INPUT_PULLUP); // new method of enabling pullups
      pinMode(encoderPinB, INPUT_PULLUP);
    pinMode(encoderSW, INPUT_PULLUP);
    //Antirebote
      // encoder pin on interrupt 0 (pin 2)
      attachInterrupt(0, doEncoderA, CHANGE);
    // encoder pin on interrupt 1 (pin 3)
      attachInterrupt(1, doEncoderB, CHANGE);
      //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  //Caracteres, creacion
  lcd.createChar(1,flecha_dech);
}

void loop() {
    rotating = true;  // reset the debouncer
    if(menu != lastmenu){
        lcd.clear();
        lastmenu=menu;
    }

      if (menu>4) {
          menu=1;
          lcd.clear();
          }
      if (menu<1) {
          menu=4;
          lcd.clear();
          }
    switch (menu) {
        case 1:
        lcd.setCursor(6,0);
        lcd.print("Reloj");
    printhour();
        break;
        case 2:
        lcd.setCursor(6,0);
        lcd.print("Tiempo");
        break;
        case 3:
        lcd.setCursor(6,0);
        lcd.print("Opciones");
    lcd.setCursor(1,1);
    lcd.print("Ajustar Hora");
    lcd.setCursor(1,2);
    lcd.print("Ajustar Fecha");
    encoderSW_bounce.update();
    if (encoderSW_bounce.risingEdge()){
      salir = false ;
      menu= 1 ;
      lastmenu = 0;
      while ( salir == false ){
        rotating = true;  // reset the debouncer
        if(menu != lastmenu){
          lastmenu=menu;
          delete_cursor();
        }
        if (menu > 4){
          lcd.clear();
          lcd.setCursor(1,0);
          lcd.print("Ajuste Alarmas");
          lcd.setCursor(1,1);
          lcd.print("Salir");
        }
        else if (menu >5){
          menu = 1;
          lcd.clear();
          lcd.setCursor(1,1);
          lcd.print("Ajustar Hora");
          lcd.setCursor(1,2);
          lcd.print("Ajustar Fecha");
        }
        else if (menu < 1){
          menu = 5;
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("Ajuste Alarmas");
          lcd.setCursor(0,1);
          lcd.print("Salir");
        }
      switch (menu) {
        case 1:
        lcd.setCursor(0,1);
        lcd.write(1);
        break;
        case 2:
        lcd.setCursor(0,2);
        lcd.write(1);
        break;
        case 3:
        lcd.setCursor(0,3);
        lcd.write(1);
        break;
        case 4:
        lcd.setCursor(0,0);
        lcd.write(1);
        break;
        case 5:
        lcd.setCursor(0,1);
        lcd.write(1);
      }
      }
    }
        break;
        case 4:
        lcd.setCursor(6,0);
        lcd.print("Alarmas");
        break;
    }
}


//FUNCIONES++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Interrupt on A changing state
void doEncoderA(){
  // debounce
  if ( rotating ) delay (1);  // wait a little until the bouncing is done
  // Test transition, did things really change
    if( digitalRead(encoderPinA) != A_set ) {  // debounce once more
    A_set = !A_set;
    // adjust counter + if A leads B
    if ( A_set && !B_set )
      menu ++;
    rotating = false;  // no more debouncing until loop() hits again
  }
}

// Interrupt on B changing state, same as A above
void doEncoderB(){
  if ( rotating ) delay (1);
  if( digitalRead(encoderPinB) != B_set ) {
    B_set = !B_set;
    //  adjust counter - 1 if B leads A
    if( B_set && !A_set )
      menu --;
    rotating = false;
  }
}
//Printing the time on LCD
void printhour(){
    tmElements_t tm;
  if (RTC.read(tm)) {
    lcd.setCursor(0,1);
    if(tm.Hour >= 0 && tm.Hour < 10){
      lcd.print('0');
    }
    lcd.print(tm.Hour);
    lcd.print(':');
    if(tm.Minute >= 0 && tm.Minute < 10){
      lcd.print('0');
    }
    lcd.print(tm.Minute);
    lcd.print(':');
    if(tm.Second >= 0 && tm.Second < 10){
      lcd.print('0');
    }
    lcd.print(tm.Second);
    lcd.setCursor(0,2);
    lcd.print(tmYearToCalendar(tm.Year));
  }
}
//Borrar cursores
void delete_cursor(){
  lcd.setCursor(0,0);
  lcd.print(" ");
  lcd.setCursor(0,1);
  lcd.print(" ");
  lcd.setCursor(0,2);
  lcd.print(" ");
  lcd.setCursor(0,3);
  lcd.print(" ");
}

Mañana preparare una botonera y me pondre al lio, el codigo cambiara bastante, ya os mostrare los avances, por ahora me estoy centrando en la distribucion de los menus y submenus, y el acceso a los mismo
  Responder
#36
Pues me estuve planteando usar un encoder para mi proyecto, estaba esperando leer tus opiniones, porque lo que yo había visto era bastante pesado para usarlo. Es más tengo el cajetín hecho y solo me quedaba hacer los agujeros para los botones o el encoder.
  Responder
#37
jukillo escribió:Pues me estuve planteando usar un encoder para mi proyecto, estaba esperando leer tus opiniones, porque lo que yo había visto era bastante pesado para usarlo. Es más tengo el cajetín hecho y solo me quedaba hacer los agujeros para los botones o el encoder.

He estado esta tarde probando la libreria encoder.h, ya como ultima escapatoria, y nada, funcionando solo la rutina del encoder va bien, ahora en cuanto lo metes en un codigo largo...., pierde pasos, a veces salta de dos en dos...., debe de ser que las interrupciones a codigos largos no le sientan nada bien....., sin contar que al menos mi encoder es bastante malillo..., todo eran problemas.

Voy a probar con botones aver como funciona, si logras algo con el encoder comentamelo¡¡

Un Saludo¡
  Responder
#38
ufff, eso es una explicación de funcionamiento y lo demás son tonterías Mola

La verdad es que si que se ve bastante pesado de usar, aunque la interface final sea buena. Demasiado código solo para un método de entrada, y con interrupciones, delay etc...

muy bueno el proyecto, pillo sitio para ver los resultados, ya que tengo el 95% de los componentes por aqui desperdigados :elrisas:


salu2!
  Responder
#39
biketrial981 escribió:ufff, eso es una explicación de funcionamiento y lo demás son tonterías Mola

La verdad es que si que se ve bastante pesado de usar, aunque la interface final sea buena. Demasiado código solo para un método de entrada, y con interrupciones, delay etc...

muy bueno el proyecto, pillo sitio para ver los resultados, ya que tengo el 95% de los componentes por aqui desperdigados :elrisas:


salu2!

Ire explicando en la medida de lo posible a todo lo que me vaya enfrentado jajaja

Pues si, como comentabamos me parece a mi que se hace muy pesado para un codigo en el cual realmente la prioridad no es la posicion del encoder...., he preguntado en el foro de Arduino oficial, si me dicen algo lo comento por aqui¡
  Responder
#40
Respecto a los encoders: http://webdelcire.com/wordpress/archives/1545
  Responder


Posibles temas similares…
Tema Autor Respuestas Vistas Último mensaje
  Estación meteorológica v2 - giltesa giltesa 69 18,880 25-01-2024, 08:31 PM
Último mensaje: sermosderendert