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.

2 comentarios:

  1. Hola,
    Me parece muy instructivo tu blog, sólo que en el programa del Arduino (que haya visto), el bucle crea 11 valores u 61 valores, por lo que no funcionará. Dará un fallo de memoria ya que reservas sólo para 10 ó 60 valores.
    Un saludo.

    ResponderEliminar
    Respuestas
    1. Gracias por tu comentario (me confirma que voy por buen camino), tu corrección es un aspecto que en algún momento esperaba que se colocara. Ya que todos los programas que he creado han sido modificados en algunos aspectos y justo eso es lo que hablas.

      El número 61 y 11 esta puesto en la condición como "número<61" osea que solo llega a 60, porque la condición pone límite "menor que #número".

      for (int j=0;j<61;j++){ //generación de número aleatorios
      for (int j=0;j<11;j++){ //generación de número aleatorios

      Este ciclo indica que j inicia desde 0 y llega hasta 60 o 10 (no 61 o 11 porque dice "menor que 61" o "menor que 11) para ver ejemplos de esta sentencia mira http://arduino.cc/en/Tutorial/ForLoop

      Eliminar