Pages: [1]   Go Down
Author Topic: Duda menús y guardado en eeprom [SOLUCIONADO]  (Read 967 times)
0 Members and 1 Guest are viewing this topic.
España
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
Hola gente.
Soy nuevo en el tema de Arduino, pero ya me hecho alguna aplicación para controlar aparatos que fabrico, como lásers y otras.

Ahora estaba haciendo un pequeño menú, aunque he visto que ya hay ejemplos de navegación por menús, pero no los acabo de entender, además que con un simple menú de una sola fila con valores me basta.
Ya tengo hecho el código para moverme por el menú, entrar en el valor, modificar, guardar o salir sin modificar, pero el problema ha venido cuando guardo los valores en la eeprom del micro.
En principio la eeprom guarda los valores en formato "byte" y a la hora de mostrarlo por el LCD ->  
Code:
lcd.print(EEPROM.read(valor[indice],DEC);
Lo paso a Decimal para mostrar el valor, encuentro la limitación de hasta 255 valores, pero bueno, que le vamos a hacer, podría usar dos valores para obtener así 65536 valores, aunque tengo que ver como juntar dos valores en byte para luego interpretarlo como decimal.

Os enseño el código y el problema concreto:
Code:
// incluimos la librería de pantalla de cristal liquido:
#include <LiquidCrystal.h>
#include <string.h>
#include <EEPROM.h>


// Inicializa la librería con los pines correspondientes a la pantalla por defecto
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// Definimos las variables y constantes necesarias:


                                       // Creamos las matrices
int textomenu = -1;

boolean edita = false;
int seleccionar = 6;            // Botones
int arriba = 7;
int abajo = 8;
int enter = 9;


const int totalopciones = 4;
int dato[totalopciones];

void setup() {
  // Setea el numero de columnas y filas de la pantalla:
  lcd.begin(16, 2);
  pinMode(seleccionar, INPUT);
  pinMode(arriba, INPUT);
  pinMode(abajo, INPUT);
  pinMode(enter, INPUT);
                                             //           lcd.print("hello, world!");
}

void loop() {

// Muestra en pantalla los menús
if(textomenu >= 0){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Menu");
lcd.setCursor(0,1);
lcd.print("Opcion ");
lcd.print(textomenu + 1);
        lcd.print(" =");
        dato[textomenu]= EEPROM.read(textomenu);
lcd.print(dato[textomenu], DEC);
        if(edita == true){  // Si está en modo editar, muestra el cursor, sino no.
          lcd.cursor();
        }else{
          lcd.noCursor();
        }
delay(100);
}

// ------------------------------------------------  Movimiento por menú simple.

if(digitalRead(seleccionar)==HIGH && textomenu < 0){   // Caso de apretar "select" sin estar dentro del menú, pone "valor" a ++, o sea 0, sin menú está a -1
  textomenu++;
  delay(50);
}
if(textomenu >= 0 && edita == false){                  // Dentro del menú diferentes opciones: ------------------
  if(digitalRead(seleccionar)==HIGH){   // Caso de apretar select sale del menú sin guardar.
    textomenu = -1;
    edita = false;
    delay(100);
    lcd.clear();
    // No guarda en eeprom, pero sí en variable RAM
  }else if(digitalRead(arriba)==HIGH){    // Si sube, tira atrás, por tanto valor--
    if(textomenu>0){ textomenu--; }
    delay(100);
  }else if(digitalRead(abajo)==HIGH){   // Si baja, tira alante por menú, por tanto valor++;
    if(textomenu < totalopciones - 1){ textomenu++; }
    delay(100);
  }else if(digitalRead(enter)==HIGH){    // Si da enter, setea el bit de editar
    edita = true;
    delay(100);
  }
}

if(edita == true){             // Si está editando, incrementa o decrementa el dato[] que corresponde.
  
  if(digitalRead(arriba)==HIGH){
    dato[textomenu]--;
    if(dato[textomenu] < 0 ) dato[textomenu]=0;    //Limite a 0  ----------------->>>> FALLA POR ALGUN MOTIVO, nunca se cumple
    delay(100);
  }else if(digitalRead(abajo)==HIGH){
    dato[textomenu]++;
    if(dato[textomenu] > 255 ) dato[textomenu]=255;    // Limite a 255  ----->>> FALLA POR ALGUN MOTIVO , nunca se cumple
    delay(100);
  }else if(digitalRead(enter)==HIGH){   // Si toca enter o select sale del modo edición, guardando el valor en memoria volátil.
    if( dato[textomenu] != EEPROM.read(textomenu)){
      EEPROM.write(textomenu, dato[textomenu]);       // Guarda en memoria el valor.
      lcd.setCursor(0, 0);
      lcd.print("Guardado EEPROM   ");
    }
    edita = false;
    delay(500);
    lcd.clear();
  
  }else if(digitalRead(seleccionar)==HIGH){          // Si no das a seleccionar sin dar a enter, sale de modo editar y volverá a leer la EEPROM del principio.
    edita = false;
    delay(100);
    lcd.clear();
  }
}


}

El problema es cuando tengo seteada el bit "edita", y entonces si subo o bajo, debería subir o bajar valor, pero como el valor es en "byte" pues creo que no lo hace, y además creo que no compara bien el valor "dato[textomenu]" que está como
Code:
int
.
En la pantalla solo se ve que la opción EDITAR está presente por que sale el cursor, y en principio mostraba el valor "255" que debe ser lo que tenía en EEPROM el micro, pero de ahí no puedo modificar el valor, ni subir ni bajar.
Luego puse el ejemplo para escribir EEPROM todo a valores 0, y ahora me salen con 0 pero sin poder modificarlo.

Lo que no acabo de entender, por que si le doy a escribir la eeprom y le pongo valores entero, me los convierte a byte automáticamente , debe hacerlo automático por que está la opción en la librería EEPROM, no ?

Sabeis a que se debe el problema que tengo, es un error de tipos de variables ?

Gracias por vuestra ayuda.

Saludos

PD: La opción de los botones, para evitar rebote, he puesto un simple delay, para no complicarme mientras aprendo el tema de menús y eeprom, es que si ponía los botones con antirebote luego se hace un código demasiado grande para ir aprendiendo.
« Last Edit: September 24, 2011, 05:06:19 pm by Alfon » Logged

El saber no ocupa lugar, pero sí tiempo

España
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola gente.
Ya solucioné el problema, al final no era tan complicado, solo un pequeño fallo con la parte donde muestra el valor de la variable guardada en EEPROM, al principio solo la debe mostrar, pero cuando la estaba editando no debía mostrarla ya que no podría editarla.

Para solucionar el problema tuve que poner unos cuantos Serial.print en diferentes puntos hasta encontrar el fallo.

He mejorado el código poniendo antirebote y un teclado analógico con 4 teclas con resistencias.
El código al leer la entrada analógica puede ser algo lento, pero para aprovechar entradas en un arduino nano, pues es perfecto.

Code:
/*
 Estructura menú con pantalla LCD con 4 bits, por Alfonso V1.4
 Opción de escritura en Eeprom, con una resolución de 8 bits (255 carácteres, incluido el 0), además de una memoria eeprom de 512Bytes, o sea un total de esas opciones.
 Opción de teclado analógico con Divisor tensión:
 + 5V --> Resistencia valor XX --> Entrada analógica --> Resistencia 1K --> 0v
 para Resistencia de 10k --> 92   --> Select
 para Resistencia de 5k6 --> 155   --> arriba
 para Resistencia de 2k4 --> 301   --> abajo
 para Resistencia de 1k --> 512   --> enter
 
 Tolerancia de +/- 20 puntos.
 
 
  La pantalla conectada a los pines:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)
 
 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 
 Menús:
 Estructura básica guardada en matrices, una que contiene los datos en texto, y otra matriz que contiene los valores.
 Ejemplo básico con los siguientes menús:
   Menu 1:
     - Opcion1 = valor 1
     - Opcion2 = valor 2
     - Opcion3 = valor 3
     - Opcion4 = valor 4
 
 */

// incluimos la librería de pantalla de cristal liquido:
#include <LiquidCrystal.h>   // Libreria LCD
#include <string.h>    // Libreria común para operaciones con carácteres
#include <EEPROM.h>  // Libreria EEPROM


// Inicializa la librería con los pines correspondientes a la pantalla por defecto
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


int textomenu = -1;
boolean edita = false;
int seleccionar = 6;            // Botones
int arriba = 7;
int abajo = 8;
int enter = 9;
boolean boton = false;
boolean botonpresionado = false;
int tiempoanterior = 0;
int tiempoactual = 0;
int an0 = 0;    // Entrada botonera analógica
int valorboton = 0;
const int totalopciones = 4;     // Total opciones menú
int dato[totalopciones];         // Array de opciones

void setup() {
  // Setea el numero de columnas y filas de la pantalla:
  lcd.begin(16, 2);
  //  Serial.begin(115200);
 }



void loop() {

// -------------------------------------- Entrada botones, antirebote y guarda valor del botón ------------------------------------------
valorboton = analogRead(an0);
if(valorboton > 20 && boton == false){
  boton = true;
  tiempoanterior = millis();
 
  // Serial.println(valorboton);
}
tiempoactual = millis() - tiempoanterior;
if(tiempoactual > 50 && boton == true && valorboton > 20){
  botonpresionado = true;
 //  Serial.println(valorboton);
 //  Serial.println(" boton presionado = true");
}


// --------------------------------------------- Muestra en pantalla los menús ------------------------------------------------------------
if(textomenu >= 0){
delay(100);
        lcd.clear();
lcd.setCursor(0,0);
lcd.print("Menu");
lcd.setCursor(0,1);
menu_(textomenu);
        if(edita == false){                            // Si no está editando, lee de la EEPROM
          dato[textomenu]= EEPROM.read(textomenu);
  lcd.print(dato[textomenu]);
          lcd.noCursor();
        }else{                           // Si está editando no lee de EEPROM por que todavía no hemos guardado el valor, por tanto muestra la variable
          lcd.print(dato[textomenu]);
          lcd.cursor();
        }
       
}

// ------------------------------------------------  Movimiento por menú simple -----------------------------------------------------------

if(botonpresionado == true && textomenu < 0 && valorboton > 75 && valorboton < 100 ){   // Caso de apretar "select" sin estar dentro del menú, pone "valor" a ++
  textomenu++;
  finteclado();
  delay(500);
  // Serial.println("Boton presionado, cuando no está el menu, y detecta valor entre 85<x<96");
}

// ------------------------------------------------- Dentro del menú, diferentes opciones -------------------------------------------------
if(textomenu >= 0 && edita == false && botonpresionado == true){                 
  if(valorboton > 75 && valorboton < 96){   // Caso de apretar select sale del menú sin guardar.
    textomenu = -1;
    edita = false;
    finteclado();
    lcd.clear();
  }else if(valorboton > 130 && valorboton < 165 ){    // Si sube, tira atrás, por tanto valor--
    if(textomenu > 0){
      textomenu--;
    }
    finteclado();
  }else if(valorboton > 260 && valorboton < 310){   // Si baja, tira alante por menú, por tanto valor++;
    if(textomenu < totalopciones - 1){
      textomenu++;
    }
    finteclado();
  }else if(valorboton > 450 && valorboton < 530){    // Si da enter, setea el bit de editar
    edita = true;
    finteclado();
  }
}

// ------------------------------------------------- Dentro del menú, si está editando los parámetros ----------------------------------------
if(edita == true && botonpresionado == true ){             
  if(valorboton > 130 && valorboton < 165){       // Botón subir
    dato[textomenu]--;
    // Serial.print("Opcion edita, apretado tecla arriba, descuenta: (dato[textomenu] de eeprom)"); Serial.println(dato[textomenu]);  // DEBUG
    if(dato[textomenu] < 0 ){
      dato[textomenu]=0;    //Limite a 0
      // Serial.print("Valor más pequeño de 0, pone a 0 el dato[textomenu] =");Serial.println(dato[textomenu]);  // DEBUG
    }
    finteclado();
  }else if(valorboton > 260 && valorboton < 310){     // Botón bajar
    dato[textomenu]++;
    // Serial.print("Opcion edita, apretado tecla abajo, incrementa: (dato[textomenu] de eeprom)"); Serial.println(dato[textomenu]);  //DEBUG
    if(dato[textomenu] > 255 ){
      dato[textomenu]=255;    // Limite a 255
      // Serial.print("Valor más grande de 255, pone a 255 el dato[textomenu] =");Serial.println(dato[textomenu]);   // DEBUG
    }
    finteclado();
  }else if(valorboton > 450 && valorboton < 530){   // Si toca enter o select sale del modo edición, guardando el valor en memoria volátil.
    if( dato[textomenu] != EEPROM.read(textomenu)){
      EEPROM.write(textomenu, dato[textomenu]);       // Guarda en memoria el valor.
      lcd.setCursor(0, 0);
      lcd.print("Guardado EEPROM   ");
      delay(1000);
    }
    edita = false;
    lcd.clear();
    finteclado();
  }else if(valorboton > 75 && valorboton < 96){          // Si no das a seleccionar sin dar a enter, sale de modo editar y volverá a leer la EEPROM del principio.
    edita = false;
    lcd.clear();
    finteclado();
  }
}
}      // Fin void loop()
// --------------------- Función fin botón presionado, resetea bits de control ------------------------------------------------
void finteclado(){
   
    boton = false;
    botonpresionado = false;
}

// --------------------------- Texto opciones ---------------------------------------------------------------------------------
void menu_(int opcion){
  switch(opcion){
    case 0:
    lcd.print("Opcion 1 =");
    break;
    case 1:
    lcd.print("Opcion 2 =");
    break;
    case 2:
    lcd.print("Opcion 3 =");
    break;
    case 3:
    lcd.print("Opcion 4 =");
    break;
  }
}

Iré mejorando el código, pero de momento ya me sirve para hacer algunos aparatos sencillos con ajustes en parámetros digitalmente.

Saludos
Logged

El saber no ocupa lugar, pero sí tiempo

Pages: [1]   Go Up
Jump to: