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.
Espera la próxima entrada y la última de almacenamiento de información, donde hablaremos sobre los arreglos ordenados.
Hola,
ResponderEliminarMe 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.
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.
EliminarEl 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