Mostrando entradas con la etiqueta EEPROM. Mostrar todas las entradas
Mostrando entradas con la etiqueta EEPROM. Mostrar todas las entradas

Almacenamiento de información (parte 3)


GENERANDO NÚMERO ALEATORIOS

Antes de continuar con el método de almacenamiento de información, necesitaremos tener un código que genere números aleatorios y los almacene en memoria temporal. Puedes modificar estos programas para almacenarlo en la memoria EEPROM interna.







Generaremos números aleatorios con la función random de PICAXE, pero la cual nos da una secuencia de valores aleatorios, así que si quieres que te salga valores más variados debes cambiar el valor de la variable antes de la función random para cambiar dicho valor. El comando sertxd sirve para enviar datos del PICAXE al PC y que se puedan desplegar en la ventana de PICAXE presionando F8.

main:
            random b0
            sertxd("valor aleatorio: ",#b0,13,10)
            pause 150       
goto main

Con memoria EEPROM interna:

for b0 = 0 to 10
            random b1
            write b0,b1
next b0

pause 2500

for b0=0 to 10
            read b0,b2
            sertxd("dato: ",#b2,13,10)
next b0







Se generarán 20 números aleatorios usando la función rand(), la cual es dividida por 1767 para colocar número inferiores de 20 en el arreglo. La función rand() al igual que la de PICAXE, genera números aleatorios en secuencia, así que si se quiere variar más los números se debe utilizar el comando srand().

int aleatorio[21],i;
char info[8], inf2[8];

void main(){
     Lcd_Init(&PORTB);
     Lcd_Cmd(Lcd_CLEAR);
     Lcd_Cmd(Lcd_CURSOR_OFF);

     for (i=0; i<=20;i++){
          aleatorio[i] = (rand()/1767);  //1767 es un valor para reducir el número aleatorio
          Lcd_out (1,1, "posicion: ");
          IntToStr(i,info); //convierte valor entero a char
          Lcd_out (1,11, info);
          IntToStr(aleatorio[i],inf2);
          Lcd_out (2,4,inf2);
          delay_ms(1000);
          Lcd_Cmd(Lcd_CLEAR);
     }
}











Utilizamos la función que proporciona el lenguaje para generar un número aleatorio y almacenarlo en un arreglo de 10 posiciones. Cabe destacar que la funcion Random siempre tiene la misma secuencia, así que si quieres que en tu programa genere varias veces números al azar y que no sean los mismos, debes usar randomSeed(valordereferencia) para hacer que se ajuste la aleatorización.

int datos[10],val;

void setup() {
  Serial.begin(9600);
  for (int j=0;j<11;j++){
    randomSeed(j+val);
    datos[j] = random(0, 50);
    val++;
    }
  for (int i=0;i<11;i++){ 
    Serial.println(datos[i]);
  }
  Serial.println("-----------");
}

void loop() {
 
}

BUSQUEDA DE INFORMACIÓN

Cuando almacenamos de una forma desordenada los datos en el microcontrolador, no tenemos un orden o un carácter de criterio para almacenar. A este tipo de arreglo de datos se les llama “Arreglos desordenados”.

Imaginemos el siguiente ejemplo: hemos creado un arreglo y queremos que a través de un ID tag busquemos el valor censado en el arreglo y si lo encuentra enciende un LED verde. Sino un LED rojo.

Así que tenemos que implementar una búsqueda, en un arreglo desordenado. La búsqueda se utiliza generalmente para recuperar datos que se habían almacenado antes. Los métodos de búsqueda pueden ser internos y externos.

La búsqueda interna trabaja con los elementos almacenados en la memoria del microcontrolador.

La búsqueda externa trabaja con los elementos almacenados en una memoria externa.

El único método que podemos utilizar (y el que pensamos utilizar casi intuitivamente) en un arreglo desordenado es una búsqueda secuencial desordenada. La cual consiste en revisar elemento tras elemento hasta encontrar el dato.

BUSQUEDA SECUENCIAL DESORDENADA – MEMORIA EEPROM INTERNA

El siguiente algoritmo muestra una búsqueda secuencial desordenada, en la cual lo que se busca comprobar es la posición del dato en el arreglo.

I: variable tipo entero.
X: elemento de un arreglo desordenado
V: arreglo
N: datos

Hacer I = 0
Mientras ((I<=N)y(v[I]<>X)) repetir
            Hacer I = I +1
{fin del ciclo}
Si (I>N)
            Entonces
                        Escribir: “no se encuentra la información”
            Si no
                        Escribir: “la información se encuentra en la posición: “, I
{fin de condición}

Ahora traducimos el algoritmo a cada uno de los microcontroladores que utilizamos:








Utilizaremos la función generadora de valores aleatorios y almacenaremos 11 datos al azar, buscaremos un número específico (11) y comprobaremos la funcionalidad del algoritmo. Debido a que PICAXE no tiene para arreglos, el programa se probará en la memoria EEPROM interna y además el algoritmo sufre un leve cambio ya que no se pueden implementar arreglos en este lenguaje.

#no_data 'no sobrescribe la EEPROM al momento de grabar este programa

pause 2500

b3 = 0
b5 = 0
do
            read b5,b4
            b3 = b3+1
            b5 = b5+1
loop while b3<=10 and b4<>11

if b3 > 10 then
            sertxd ("dato no encontrado")
else
            sertxd ("dato encontrado en posición: ", #b3,13,10)
endif







Utilizamos el código para generar números aleatorios, y comprobaremos la funcionalidad del algoritmo, buscando el número 7. El proceso lo realizaremos en memoria RAM, se hace esto para reducir el uso en la memoria EEPROM del microcontrolador.

int aleatorio[21],i,j;
char info[8],inf2[8];

void main(){
     TRISA.F0 = 0;
     Lcd_Init(&PORTB);
     Lcd_Cmd(Lcd_CLEAR);
     Lcd_Cmd(Lcd_CURSOR_OFF);
     PORTA.F0=0;

     for (j=0; j<=20;j++){
          aleatorio[j] = (rand()/1767);  //1767 es un valor para reducir el número aleatorio
     }

     /*for (i=0; i<=20;i++){  //se puede usar este ciclo para desplegar el arreglo y comprobar en que posición esta el número 7
          aleatorio[i] = (rand()/1767);
          Lcd_out (1,1, "posicion: ");
          IntToStr(i,info);
          Lcd_out (1,11, info);
          IntToStr(aleatorio[i],inf2);
          Lcd_out (2,4,inf2);
          delay_ms(1000);
          Lcd_Cmd(Lcd_CLEAR);
     } */

    
     delay_ms(750);
    
     i = 0;
     while ((i<=20) && (aleatorio[i]!=7)) {
           i++;
     }
     if (i>20){
        Lcd_Out(1,1,"no encontrado");
        }
     else{
        PORTA.F0=1;
        Lcd_Out(1,1,"posicion:");
        IntToStr(i, info);
        Lcd_Out(1,10,info);
     }
}












Utilizaremos la función generadora de valores aleatorios y almacenaremos 60 datos al azar, buscaremos un número específico (30) y comprobaremos la funcionalidad del algoritmo. El proceso lo realizaremos en memoria RAM.

int datos[60],val;

void setup() {
  Serial.begin(9600);
  for (int j=0;j<61;j++){ //generación de número aleatorios
    randomSeed(j+val);
    datos[j] = random(0, 80);
    val++;
    }
  for (int i=0;i<61;i++){   //despliega el arreglo
    Serial.print(i);
    Serial.print(": ");
    Serial.println(datos[i]);
  }
  Serial.println("-----------");
  int I = 1;  //algoritmo de búsqueda
  while (I<61 && datos[I]!=30)
  {
    I++;
  }
  if (I > 60)  {
    Serial.println("dato no encontrado");
    }
  else{
    Serial.print("la informacion se encuentra en la posicion: ");
    Serial.println(I);
  }   
}

void loop() {
 
}

El algoritmo anterior esta diseñado para buscar el primer valor y desplegarlo o si no se encontró, el siguiente algoritmo posee recursividad, lo cual significa que aunque encontró un valor, buscará los demás que son iguales.

I: variable tipo entero que inicia en 0.
X: elemento de un arreglo desordenado
V: arreglo
N: datos

Si (I>N)
            Entonces
                        Escribir: “información no encontrada”
            Si no
                        Si (V[I]=X)
                                   Entonces
                                               Escribir: “la información se encuentra en la posición”, I
                        {fin de la condición}
                        I = I +1
                        Regresar al paso 1 del algoritmo
{fin de la condición}







Generaremos 60 valores aleatorios y se realizará una búsqueda para encontrar el número 11 y que despliegue en pantalla en donde se encontró. Se ha agregado un ciclo para desplegar los valores y así comprobar la efectividad del ciclo de búsqueda.

for b0 = 0 to 60 'almacena valores
            random b1
            write b0,b1
next b0

'pause 1000   'ciclo para mostrar los valores almacenados (opcional)
'sertxd("datos",13,10)

'for b0=0 to 60
'           read b0,b2
'           sertxd("dato: ",#b2,13,10)
'next b0

pause 2500
sertxd ("buscando...",13,10)

b2= 0 'ciclo de busqueda
ciclo: if b2 > 60 then
                        sertxd("busqueda finalizada")
             else
                        read b2,b3
                        if b3 = 11 then
                                   sertxd("información encontrada en ",#b2,13,10)
                        endif
                        b2 = b2 +1
                        goto ciclo
             endif
stop







Se generan 20 números aleatorios, de los cuales se buscarán todos los números 7. Se esta utilizando un arreglo, así que si quieres hacer pruebas con la EEPROM del microcontrolador, debes modificar un poco el código. NOTA: el algorimo se modifico un poco, específicamente en la parte del salto para volver al primer paso del algoritmo. Se utilizo una sentencia while y un if.

int aleatorio[21],i,j;
char info[8],inf2[8];

void main(){
     TRISA.F0 = 0;
     Lcd_Init(&PORTB);
     Lcd_Cmd(Lcd_CLEAR);
     Lcd_Cmd(Lcd_CURSOR_OFF);
     PORTA.F0=0;

     for (j=0; j<=20;j++){
          aleatorio[j] = (rand()/1767);  //1767 es un valor para reducir el número aleatorio
     }

     /*for (i=0; i<=20;i++){  //se puede usar este ciclo para desplegar el arreglo y comprobar en que posición esta el número 7
          aleatorio[i] = (rand()/1767);
          Lcd_out (1,1, "posicion: ");
          IntToStr(i,info);
          Lcd_out (1,11, info);
          IntToStr(aleatorio[i],inf2);
          Lcd_out (2,4,inf2);
          delay_ms(1000);
          Lcd_Cmd(Lcd_CLEAR);
     }*/

     delay_ms(750);

     i = 0;          // ciclo de búsqueda
     while (i <= 20){
           if (aleatorio[i] == 7 ){
                    Lcd_Cmd(Lcd_CLEAR);
                    Lcd_Out(1,1,"posicion:");
                    IntToStr(i, info);
                    Lcd_Out(1,10,info);
                    delay_ms(700);
           }
           i++;
     }
     if (i > 20){
        Lcd_Cmd(Lcd_CLEAR);
        Lcd_Out(1,1,"busqueda fin.");
     }
}











Grabaremos 60 números aleatorios, de los cuales desplegaremos todos los números 4 que se encuentren  y se desplieguen en el monitor serial de Arduino. NOTA: el código para esta búsqueda tiene el mismo cambio que el que se hizo para PIC.

int datos[60],val;

void setup() {
  Serial.begin(9600);
  for (int j=0;j<61;j++){ //generación de número aleatorios
    randomSeed(j+val);
    datos[j] = random(0, 80);
    val++;
    }
  for (int i=0;i<61;i++){   //despliega el arreglo
    Serial.print(i);
    Serial.print(": ");
    Serial.println(datos[i]);
  }
  Serial.println("-----------");
 
  int I = 0; //algoritmo de búsqueda
  while (I <= 60){
    if (datos[I] == 4){
      Serial.print("posicion: ");
      Serial.println(I);
    }
    I++;
  }
  if (I > 60){
    Serial.println("busqueda finalizada");
   }
}

void loop() {
 
}

BUSQUEDA SECUENCIAL DESORDENADA – MEMORIA EEPROM EXTERNA

Para realizar una búsqueda externa se requiere de más tiempos de proceso por lo que la búsqueda es más lenta, si queremos optimizar y reducir el tiempo de lectura y escritura, debemos ordenar la memoria (tema que discutiremos en otra entrada).

El algoritmo para una búsqueda externa es el mismo para ambos casos, salvo que en este tipo de búsqueda se necesita identificar qué dispositivo externo es por lo tanto debemos utilizar correctamente el CS (bus SPI) o la dirección del dispositivo por I2C.







Utilizaremos el algoritmo de generación de números aleatorios y de búsqueda secuencial desordenada, almacenará 35 datos en la memoria EEPROM 24LC256 y buscará el número 11.



hi2csetup i2cmaster, %10100000, i2cslow, i2cword
pause 1500

main:
            for b1 = 0 to 35 'ciclo de almacenamiento aleatorio
                        random b0
                        sertxd("valor aleatorio ",#b1,": ",#b0,13,10)
                        hi2cout b1,(b0)
                        pause 10
            next b1

            b3 = 0 'ciclo de búsqueda
            b5 = 0
            sertxd(“buscando…”,13,10)
            do
                        hi2cin b5,(b4)
                        if b4 <> 11 then
                                   b3 = b3+1
                                   b5 = b5+1
                        endif
            loop while b3<=35 and b4<>11

            if b3 > 35 then
                        sertxd ("dato no encontrado")
            else
                        sertxd ("dato encontrado en posición: ", #b3,13,10)
            endif

El siguiente código es para la búsqueda secuencial desordenada con recursividad, con la misma configuración de datos de búsqueda del algoritmo pasado.

hi2csetup i2cmaster, %10100000, i2cslow, i2cword
pause 1500

main:
            for b1 = 0 to 35 'ciclo de almacenamiento aleatorio
                        random b0
                        sertxd("valor aleatorio ",#b1,": ",#b0,13,10)
                        hi2cout b1,(b0)
                        pause 10
            next b1

            sertxd ("buscando...",13,10)

            b2= 0 'ciclo de busqueda
            ciclo: if b2 > 35 then
                                   sertxd("busqueda finalizada")
                         else
                                    hi2cin b2,(b3)
                                   if b3 = 11 then
                                               sertxd("información encontrada en ",#b2,13,10)
                                   endif
                        b2 = b2 +1
                        goto ciclo
             endif
stop











El siguiente programa almacena 10 datos aleatorios en la memoria EEPROM 25LC256 y realiza una búsqueda secuencial desordenada. Pon atención en como esta trabajando el código y sus cambios que sufre al convertirse de un arreglo a un dispositivo externo SPI. Observa que hay un cambio en el algoritmo para incrementar I.



#include <SPI.h>
int datos,val,resultado=0;

void setup() {
  Serial.begin(9600);
  pinMode(10,OUTPUT);
  pinMode(2,OUTPUT);
  digitalWrite(10, HIGH);
  digitalWrite(2, HIGH);
  SPI.begin(); 
  SPI.setDataMode(SPI_MODE3);  //configura protocolo SPI
  SPI.setClockDivider(SPI_CLOCK_DIV2); // 10 Mhz max para 25LC256
  SPI.setBitOrder(MSBFIRST);
 
  digitalWrite(10, LOW);
  SPI.transfer(6);  // escritura habilitada 6
  digitalWrite(10, HIGH);
 
  digitalWrite(10, LOW);
  SPI.transfer(1); // remueve protección de bloque 1,0
  SPI.transfer(0);
  digitalWrite(10, HIGH);
  delay(5);
 
  for (int j=0;j<11;j++){ //generación de número aleatorios
    randomSeed(j+val);
    datos = random(0, 80);
   
    digitalWrite(10, LOW);
    SPI.transfer(6); // escritura habilitada 6
    digitalWrite(10, HIGH);
     
    digitalWrite(10, LOW);
    SPI.transfer(2); // write 2,0
    SPI.transfer(0);
    SPI.transfer(j); // registro
    SPI.transfer(datos); // dato a almacenar
    digitalWrite(10, HIGH);
    delay(5);
     
    digitalWrite(10, LOW);
    SPI.transfer(6); // escritura habilitada 6
    digitalWrite(10, HIGH);
   
    val++;
    Serial.print(j); //despliega el arreglo
    Serial.print(": ");
    Serial.println(datos);
    }
  digitalWrite(10, LOW);
  SPI.transfer(4); // escritura deshabilitada 4
  digitalWrite(10,HIGH);
  Serial.println("--------");
 
  int I = 0;  //algoritmo de búsqueda secuencial   
  while (I<11 && resultado!=56) //se busca el número 56
  {
    digitalWrite(10, LOW);
    SPI.transfer(3); // lee 3,0
    SPI.transfer(0);
    SPI.transfer(I);
    resultado = SPI.transfer(0x00);
    digitalWrite(10, HIGH);
   
    if (resultado != 56){ //si se cambia el número de búsqueda, cambiarlo también aquí
      I++;
    }
  }
  if (I > 10)  {
    Serial.println("dato no encontrado");
    }
  else{
    Serial.print("la informacion se encuentra en la posicion: ");
    Serial.println(I);
  }
}

void loop() {
}

Espera la próxima entrada y la última de almacenamiento de información, donde hablaremos sobre los arreglos ordenados.

Almacenamiento de información (parte 1)

Almacenamiento de información

En esta entrada quiero centrarmeen las distintas formas de almacenamiento de datos en los microcontroladores.Observa los ejemplos de cómo se utilizan los comandos para almacenar y leer, además te recomiendo que analizes y repitas los códigos que se te proporcionan.

Variables

Es la primera forma de la quevamos a hablar. Definimos que una variable es un lugar en donde podemosalmacenar información temporalmente (ejemplo: memoria RAM), desarrollaremos ahoralas variables según el tipo de microcontrolador:

  • PICAXE: podemos utilizar únicamente dos tipos de variables tipo byte (b0, b1, b2, etc.) y Word (w0, w1, w2). Donde una variable Word es un conjunto de dos variables tipo byte, así que w0=b0+b1.Si son línea educativa se tiene hasta 28 variables tipo byte y 14 word, si es de la línea avanzada tiene 56 variables tipo byte y 28 word.

b0 = readadc(c.3)
b1 = 15
pinsc = b1

  • Arduino: acá tenemos más libertad de declaración de variables (int, long, char, etc.) y podemos nombrarlas como queramos.
 int cuenta = 0;
cuenta = cuenta +1;

  • PIC: según el lenguaje de programación, en mi caso que utilizo MikroC nos da la misma versatilidad que con Arduino para declarar variables.
 char letra = a;
unsigned int control= 240;

Memoria EEPROMinterna

Esta es la segunda forma quepodemos enlistar y es una memoria en la cual podemos almacenar un valor, éstequeda guardado incluso cuando se retira la alimentación del microcontrolador.Así que recurrimos a la EEPROMcuando queremos guardar valores y que éstos permanezcan intactos inclusodespués de quitar el voltaje.

NOTA: el tiempo de vida de la EEPROM generalmente es de100,000 ciclos de lectura/escritura, así que asegúrate de utilizar únicamente la EEPROM cuando la necesites.


  • PICAXE: estos microcontroladores generalmente tienen un espacio de 256 bytes de memoria EEPROM, pero algunos como el 8M2 la tienen compartida con la memoria del programa.
 Comando para trabajar con lamemoria EEPROM interna:

EEPROM: no es una instrucción,sino es un método de pre-almacenamiento de información a la EEPROM, este comando noocupa espacio en la longitud del programa.

EEPROM localización,(dato, dato, dato,…)

Ejemplo:
EEPROM 0,(“CORTO CIRCUITO”) ‘almacena en la memoria EEPROMeste valor al momento de programar el microcontrolador.
Read: lee los datos tipo byte de la memoria EEPROM.

read localización,variable, variable
Ejemplo:
EEPROM 0,(“CORTO CIRCUITO”)

for b0 = 0 to 13
            read b0, b1
            sertxd (b1)
next b0
 Write: lee los datos tipo byte de la memoria EEPROM

 write localización,dato, dato
Ejemplo:
for b0 = 0 to 4
            b1=b0+1
            write b0,b1
next b0

  • Arduino: Según el MCU que este en tu placa Arduino, así es su capacidad de almacenamiento en la EEPROM por ejemplo: ATmega328 1024 bytes, ATmega168 512 bytes, ATmega2560 4 Kbytes (4096 bytes). Arduino especifica que la memoria EEPROM del ATmega se tarda en escribir 3.3 ms.

Comando para trabajar con lamemoria EEPROM interna:

Write(): escribe un byte en la EEPROM

EEPROM.write(dirección,valor)

Donde valor puede tener un valor binario entre 0 hasta 255.


Ejemplo: nota que el ciclo se puso en el void setup para quese ejecutara solo una vez.
#include<EEPROM.h>

void setup()
{
            for (int i = 0; i < 512; i++)
            {
          EEPROM.write(i, i);
          delay(3);
            }
}

void loop()
{
}


Read (): lee un byte en la EEPROM, si los espacios no han sido escritos,éstos tienen un valor de 255.


EEPROM.read(dirección)

Ejemplo:
#include<EEPROM.h>
int valor, a= 0;

void setup()
{
}

void loop()
{
            valor = EEPROM.read(a);
            a = a + 1;
            if (a == 1024)
            {
                        a = 0;
            }
            delay (500);
}

  • PIC: según el microcontrolador que escojas así será su capacidad de almacenamiento en la EEPROM, ejemplo: 16F84A 64bytes, 16F688 256 bytes, 18F2550 256 bytes. Los comandos que se muestran son para MikroC. El retardo mínimo recomendado por MikroC es de 20 milisegundos.
Comando para trabajar con lamemoria EEPROM interna:

EEPROM_Write: escribe informaciónen una dirección de la memoria EEPROM


EEPROM_Write(unsigned int dirección, unsignedshort dato);

Ejemplo:

unsigned short i = 0, j = 0;

void main() {
  j = 4;
  for (i= 0; i < 20; i++)
   EEprom_Write(i, j++);
   delay_ms(20);
}


EEPROM_Read: lee la informaciónde una dirección en la memoria EEPROM.


EEPROM_Read(unsigned int dirección);

Ejemplo:
unsignedshort i = 0, j = 0;

void main(){
  PORTB = 0;
  TRISB = 0;

  for (i = 0; i < 20; i++) {
    PORTB = Eeprom_Read(i);
    Delay_ms(500);
  }
}


Memoria EEPROMexterna

Esta es el tercer método quepodemos utilizar, las EEPROM externas se pueden comunicar en paralelo, I2C oSPI. La ventaja de las memorias externas es que podemos almacenar másinformación ya que son mayores que las EEPROM internas de losmicrocontroladores y su ciclo de lectura/escritura se aumenta a un promedio de1,000,000. Ejemplo: 24LC256 es una EEPROM por I2C de 256 Kbytes, M28C16 es unaEEPROM paralela de 16 Kbytes y 25LC256 es una EEPROM por SPI de 256 Kbytes.

Espera la entrada de la próximasemana donde veremos algunos de estos tipos de memoria EEPROM.