jueves, 20 de octubre de 2016

EEPROM: Como guardar y leer datos con PSoC5LP




Muchas veces en nuestros proyectos y aplicaciones, necesitamos algo que sea capaz de guardar algunos tipos de datos que nos proporcionan sensores, llámense posición, temperatura, humedad, Etc. O simplemente datos de inicialización necesarios para que un programa corra sin problemas. Es aquí en donde entra a jugar la memoria EEPROM, que como bien se sabe es una memoria de borrado electrónico que es capaz de retener datos para su almacenamiento durante los cortes de energía de la tarjeta y posterior lectura una vez se requiera.






Pero hablemos un poco de la memoria EEPROM de PSoC:





Datasheet EEPROM

Como bien lo dice la hoja de datos de la memoria EEPROM de PSoC5LP dice que tenemos
- 512B a 2KB de memoria 
- 1 Millón de ciclos de lectura escritura : Significa que vamos a poder leer y escribir un millón de veces, hace referencia más a la vida útil de estas memorias, para tener en cuenta ;).
- Lectura y y escritura de 1 byte por tiempo
- Capaz de programar 16Bytes A la vez

El uso de una memoria EEPROM tiene como base tratarla como una matriz, una vez se entienda este concepto se puede pensar en como programarla, lo explicaremos con el siguiente gráfico:


Tenemos que pensar en que hay direcciones de memoria que hacen referencia a el lugar en donde guardaremos los datos que para este proyecto seran solo 8 bits de datos.
En cada dirección de memoria esta presente un dato, entonces de esta manera y para el ejemplo de la imagen queda de la siguiente manera:

Dirección: 000 - Dato :0100
Dirección: 001 - Dato :0011
Dirección: 010 - Dato :1000

Etc...

Tener en cuenta que el manejo de las direcciones se muestran en binario pero pueden ser equivalentes a los hexadecimales o a enteros, cosa que no pasa con los datos, los datos son guardados de forma binaria en la memoria, como ya lo dije para este proyecto serán 8 bits , pero a la EEPROM del PSoC5LP guarda mas de 1 byte por dirección. Mi recomendación es que los datos se comparen con la tabla ASCII para ser guardados en 8 bits en la memoria EEPROM, se trata parte por parte y se guardan en diferentes direcciones de la EEPROM, así como haremos aquí.

El proyecto que construiremos se trata de un simple contador de 4 dígitos, lo construiremos a partir de un pulso generado por un PWM y a través de una interrupción incrementaremos dígito por dígito el contador, se hace de esa manera por que como se dice anteriormente vamos a comparar cada dígito con la tabla ASCII y guardar los caracteres en cada posición de la memoria EEPROM, por lo tanto usaremos 4 posiciones de memoria para guardar nuestro contador de 4 dígitos.
Una vez se le quite la energía a nuestro contador, el ultimo valor del contador quedará guardado en la memoria, para que cuando se vuela a energizar, reinicie el contador desde el valor donde iba, gracias a la lectura de este valor de la memoria.

El Objetivo General será aprender a Leer y guardar datos en la memoria EEPROM

Una vez tengamos claro cual es el manejo de lectura y escritura de los datos de la memoria, será fácil seguir a guardar cosas más grandes y en general cualquier tipo de dato, dándole un correcto tratamiento, repito que mi recomendación es tratar todo con la tabla ASCII.


Para comenzar a construir este proyecto tendremos que  empezar a construir el diagrama esquemático del programa

Lo primero que tengo que hablar es que el PWM tiene un reloj tan lento por que necesitamos que las cuentas sean pocas para lograr 1 Seg, el cual tiene a su salida un LED para indicarnos que efectivamente esta funcionando el PWM a 1seg, también tiene una interrupción ligada que será la que nos proporcione el incremento uno a uno de los dígitos. 

Necesitamos en donde mostrar los datos, para esto utilizo la librería de LCD custom, en donde podemos asignar los pines a donde queramos, esta librería se las dejare al final del articulo y tendrá que ser añadida manualmente por ustedes, a cada salida se le asigna un pin en strong drive y se asigna los nombres para no confundir nada.

Necesitamos el bloque de la memoria EEPROM también, no hay que configurar nada, el tratamiento de este bloque es solamente por software, bastará entonces con incluir el bloque al diagrama esquemático.

Por ultimo añadimos un botón de reset, este botón he decidido ponerlo externo solamente para mostrar que también funciona, el pin debe estar configurado como entrada en Pull up resistivo y conduce a una interrupción por flanco de subida. Este reset simplemente escribirá ceros en la memoria EEPROM y reiniciará el programa para que las cuentas empiecen de 0. 

Lo que hay que hacer antes de compilar este programa :

Para que funcione el sprintf tenemos que hacer algunas cosas en el compilador

1. 

2. Accederemos a las opciones del compilador y allí tenemos que añadir la opcion -u_printf_float como lo muestra la imagen:



3. Luego de esto vamos a nuestro archivo de configuración de pines y en el tenemos que cambiar el heap size de 0x80 a 0x200.


Una vez hecho esto tenemos que cablear la protoboard, lo cual es un proceso sencillo por que solamente estamos usando una LCD para mostrar todo el proceso, mi LCD la tengo cableada de la siguiente manera como ya es habitual: 


y lo unico que haría falta es el boton de reset externo con una resistencia de pull down, como lo muestra la siguiente imagen:




Lo único que cambio es que yo utilizo una resistencia de 10K en ves de la de 4.7K.


SOFTWARE


Como ya lo había explicado este es un proyecto que se basa más en software que en hardware, por tanto voy a dar la descripción completa del algoritmo del proyecto y dejaré el código comentado para que se pueda entender: 

lo primero que hice fue partir de la interrupcion generada por el PWM, en el método de interrupción, se hacen las reglas de incremento , separé los 4 dígitos del contador y los asigne a un vector entero de 4 posiciones. Cada vez que se generaba una interrupción se hacían las reglas de incremento de dígitos, para así completar el contador de 4 dígitos de 0 a 9999. Seguido a esto en el mismo método de interrupción se hace la conversión de el vector de enteros a vector de caracteres (ASCII), necesario para poder almacenar en la memoria EEPROM, seguido se hace la escritura en la memoria EEPROM mediante la siguiente instrucción:

writeStatus=EEPROM_WriteByte(numaimp[3],0);

La variable writeStatus hace referencia a si la lectura o escritura fue correcta, la función EEPROM_WriteByte() devuelve un 0 o 1 haciendo referencia a si la escritura fue correcta, de esta manera poder hacer un buen control del proceso.
Esta instrucción recibe dos parámetros, el primero es el dato a escribir, en este caso será un caracter de 8 bits que será almacenado. El segundo parámetro hace referencia a la dirección, como lo dije al principio esta era binaria pero se podía escribir su equivalencia en entero. Para este proyecto utilizaremos las direcciones 0, 1, 2 y 3 de la memoria. 
El código se encarga de almacenar los 4 dígitos de la memoria EEPROM.

Se han guardado los datos pero no se han leído

En el metodo de inicializacion se añaden las líneas que se ocupan para leer la memoria EEPROM las cuales son:

lectura[i]=EEPROM_ReadByte(i);

la instrucción es más sencilla que la de escribir, recibe la dirección la cual queremos leer y nos devuelve el dato en ella, para este caso lo que haremos será a través de un ciclo for, preguntar por las direcciones de la 0 a la 3 y guardar estas en un vector de caracteres que se llama lectura.

Pero este vector lectura no serviría para nada ya que no podemos hacer operaciones con el, por lo tanto cambiamos de caracter a entero.

por tanto este ultimo vector entero será el que podemos operar, y lo asignamos a el vector de numeros inicial para que pueda continuar los incrementos desde donde iba.

Por ultimo lo que queda por hacer es añadir la funcionalidad del reset. Simplemente hay que añadir el metodo de la interrupcion ligada al boton de reset, en este solamente a traves de la funcion de escribir datos en la memoria EEPROM, escribimos ceros en las posiciones de memoria que estamos utilizando y por ultimo para que el proceso se reanude, aplicamos un reset por software, el cual es:

CySoftwareReset();

Esto es a grandes rasgos el esquema del algoritmo utilizado para este proyecto, les dejaré el código completo y comentado aquí: 




Solamente queda asignar los pines a donde tienen su LCD su LED y el boton de RESET, y a hacer las pruebas de funcionamiento, las imagenes del proyecto final funcionando:




Por ultimo les comparto un vídeo tutorial de este proyecto, explicado todo al detalle:


No se olviden de compartir ;)

Archivos del proyecto : 

1 comentario: