Datalogger con memoria EEPROM

  • 6 Respuestas
  • 3382 Vistas

PabloS

  • Novato
  • *
  • Mensajes: 18
Datalogger con memoria EEPROM
« : octubre 21, 2013, 14:26:37 pm »
Hola Boris,

Siendo que mi duda puede ser de utilidad para muchos usuarios, te amplio un poco lo que te consultaba por mail. Cada X segundos tomo una muestra de VIN1 y un timestamp para crear un datalogger. El mismo tiene que funcionar como un sistema FIFO (Primero en entrar, Primero en Salir)

Lo primero que debo tener en cuenta, es reservar los primeros 4 bytes, para poder grabar un número entero con la última posición o address disponible. Estando la memoria vacía, se supone que la primera posición libre es la 4. Con lo cual, por única vez, puedo ejecutar un programa para grabar este valor, y evitar errores futuros.

Esto es un resumen de mi programa Ladder, aunque lo copio en Pawn para que sea mas facil de visualizar:
Código: [Seleccionar]
//En el evento Al inicio del programa puedo leer la última posición libre:
EepromReadCells(0, 4, gai_ValorRead)

//Y acá es donde tengo dudas de como armar el entero gi_UltimaDisponbile, en base al array gai_ValorRead. ¿Con desplazamiento de bits?
gi_UltimaDisponible =  

//Luego armo los valores que quiero grabar, y los escribo
gai_ValorWrite[0] = RtcGetTimestamp()
gai_ValorWrite[1] = Vin1Read()
EepromWriteCells(gi_UltimaDisponible, 2, gai_ValorWrite)

// Como cada entero ocupa 4 bytes, incremento la última posición disponible y la guardo,
// Siempre y cuando no me exceda de la capacidad de mi memoria. Si me excedo, arranco en la primera
// Posición para ir descartando los registros mas antiguos
// Después no hace falta volver a leerla porque la voy guardando en gi_UltimaDisponible

gi_UltimaDisponible = gi_UltimaDisponible + 8
if(gi_UltimaDisponible > EepromSize())
{
    gi_UltimaDisponible = 4
}
//Escribo la última disponible en la address 0
[b]EepromWriteCells[/b](0, 1, gi_UltimaDisponible)

Ahora, y a modo de ejemplo, ¿Cómo hago para recuperar los datos guardados, ya sea para mostrar en display o enviar por UDP, mail, etc?
Me encuentro con el mismo problema, que al leer los datos, del array tengo que armar un entero. Supongo que lo mejor es trabajar con datos empaquetados, pero no estoy familiarizado con los comandos.

Agradecería si me podes mostrar un ejemplo para realizar un datalogger.

Gracias,
Pablo.

« Última Modificación: octubre 21, 2013, 14:31:06 pm por PabloS »

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2087
  • Soporte Técnico
Re: Datalogger con memoria EEPROM
« Respuesta #1 : octubre 21, 2013, 19:57:03 pm »
Lo mejor para ese caso es implementar un buffer circular (ring buffer), que es un sistema FIFO. El principio de funcionamiento lo podes ver en el siguiente link:

http://es.wikipedia.org/wiki/Buffer_circular

http://www.embedded.com/electronics-blogs/embedded-round-table/4419407/The-ring-buffer

Hay bastante codigo en la red.

La idea es previamente implementar una serie de funciones que te permiten escribir en el buffer o leer en el mismo. No lo haces directamente.

Las muestras se van escribiendo en el buffer circular en las posiciones libres  (no te preocupas en que direccion) y luego cuando las necesitas, las lees.

Por cada lectura, vas liberando posiciones del buffer circular.

Entonces, cuando debes enviarlas via UDP, lees el buffer circular y lo almacenas en un array intermedio para enviar.

Las funciones que implementes, si deben comprobar internamente que almacenas en una posicion correcta de EEPROM, pero luego te olvidas.

En Pawn no hay punteros, por ello los ejemplos que veas en la red utilizan direcciones de memoria.
Debes reemplazarlas por una variable en Pawn que almacene la proxima direccion libre.

Fijate de leer un poco del tema de los buffer circulares e intentar realizar las funciones basicas para manipularlo.

Si vas teniendo dudas, consultanos.
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2087
  • Soporte Técnico
Re: Datalogger con memoria EEPROM
« Respuesta #2 : octubre 21, 2013, 20:18:48 pm »
Aca hay un ejemplo sencillo en C, deberias adaptarlo a Pawn, pero es para que veas la idea.
Deberias definir la direccion de escritura en EEPROM internamente en las funciones.

Código: [Seleccionar]
#define BUFSIZE 128
char buf[BUFSIZE];
char *pIn, *pOut, *pEnd;
char full;

// init
void buf_init()
{
    pIn = pOut = buf;       // init to any slot in buffer
    pEnd = &buf[BUFSIZE];   // past last valid slot in buffer
    full = 0;               // buffer is empty
}

// add char 'c' to buffer
int buf_put(char c)
{
    if (pIn == pOut  &&  full)
        return 0;           // buffer overrun

    *pIn++ = c;             // insert c into buffer
    if (pIn >= pEnd)        // end of circular buffer?
        pIn = buf;          // wrap around

    if (pIn == pOut)        // did we run into the output ptr?
        full = 1;           // can't add any more data into buffer
    return 1;               // all OK
}

// get a char from circular buffer
int buf_get(char *pc)
{
    if (pIn == pOut  &&  !full)
        return 0;           // buffer empty  FAIL

    *pc = *pOut++;              // pick up next char to be returned
    if (pOut >= pEnd)       // end of circular buffer?
        pOut = buf;         // wrap around

    full = 0;               // there is at least 1 slot
    return 1;               // *pc has the data to be returned
}
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

PabloS

  • Novato
  • *
  • Mensajes: 18
Re: Datalogger con memoria EEPROM
« Respuesta #3 : octubre 24, 2013, 18:19:57 pm »
Hola Boris,

Entendí perfectamente lo del anillo, pero hice algunas modificaciones en base al ejemplo.

Dejo un ejemplo de cómo quedó conformado mi ejemplo de Datalogger. Funciona bien sólo, excepto que todavía no lo incorporé al programa principal.

A modo de ejemplo, estan las funciones, que cada uno despues tendrá que adaptar, cuales son los eventos que producirán la grabación y la desgrabación de datos.

En mi caso al iniciar el PLC leo la posición 0x00 donde tengo almacenada la ultima posicion disponible. De esta manera, ante una interrupción de energía, puede continuar grabando desde donde se había quedado. Otra cosa que hice, si se llena el espacio, comienza a borrar los datos mas viejos.

Una contra, al momento de leer la memoria para el recupero de datos, por ahora no hay nada que indique si esta llena o no. Con lo cual es necesario leer todas las posiciones. En la "primera vuelta" se puede leer de 0x00 a la última address, pero si ya estamos sobreescribiendo datos viejos, entonces hay que leer toda la memoria.
De todas maneras no es algo que demore mucho tiempo.

« Última Modificación: octubre 25, 2013, 12:10:07 pm por PabloS »

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2087
  • Soporte Técnico
Re: Datalogger con memoria EEPROM
« Respuesta #4 : octubre 25, 2013, 11:57:47 am »
Perfecto Pablo buena implementacion.

Adicionalmente, recorda que en Pawn podes crear funciones para estructurar mejor el código.

Por ejemplo, en StxLadder agrega al proyecto un script que se llame datalog.p (por ejemplo) y adentro
de ese archivo podes escribir funciones Pawn para fácil manejo del buffer, por ejemplo:

EepromBufferAdd(item)
{
   // Agregar item a buffer
}

EepromBufferRead()
{
   // Leer ultimo item agregado al buffer.

   // Retornar 1 si se retorno un item o 0 si el buffer esta vacío.
}

EepromBufferIsFull()
{
   // Comprobar si el buffer esta lleno (retornar 1 o 0).
}

EepromBufferFlush()
{
   // Vaciar buffer
}

EepromBufferReadArray(Array[], Count)
{
   // Leer "Count" items del buffer y almacenar en "Array"

   // Aqui podrias llamas a la funcion EepromBufferRead() para leer los items del buffer.
}


Luego desde Ladder u otro script Pawn haces uso de estas funciones llamándolas y manteniendo el código ordenado.

Ademas te permite abstraerte de las particularidades del hardware y/o implementacion en caso que necesites modificar a futuro.

Quedo a disposición.
« Última Modificación: octubre 25, 2013, 12:06:45 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

PabloS

  • Novato
  • *
  • Mensajes: 18
Re: Datalogger con memoria EEPROM
« Respuesta #5 : octubre 25, 2013, 12:26:20 pm »
Por ejemplo, ¿Algo asi?

Código: [Seleccionar]
EepromBufferAdd(ArrayEscritura,Count)
{
   if(EepromWriteCells(UltimaAdress(), Count, ArrayEscritura) == 0)
{
return 0;
}
else //Error al procesar el comando
{
return 1;
}
}

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2087
  • Soporte Técnico
Re: Datalogger con memoria EEPROM
« Respuesta #6 : octubre 25, 2013, 19:55:00 pm »
Si, aunque como ArrayEscritura es un array, en la definicion de la funcion debes escribirlo como ArrayEscritura[] :

Código: [Seleccionar]
EepromBufferAdd(ArrayEscritura[],Count)
{
   if(EepromWriteCells(UltimaAdress(), Count, ArrayEscritura) == 0)
{
return 0;
}
else //Error al procesar el comando
{
return 1;
}
}

Pero tambien recorda que en esta funcion debes comprobar antes si tenes espacio en EEPROM, la direccion libre a donde escribir, etc.
La funcion debe ser lo mas transparente posible, asi no te preocupas cuando la llames desde otro script o diagrama.

Quedo a disposicion.
« Última Modificación: octubre 25, 2013, 20:04:40 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com