Qué tal comunidad. He estado trabajando en el desarrollo de un proyecto para monitorear la temperatura de las cámaras de los camiones que transportan alimentos que deben estar a una temperatura inferior a los 0°C. El objetivo es utilizar 2 sesnsores lm355 y un arduino nano. Colocar el embebido en las cámaras y estar muestreando 64 veces cada 3 minutos y guardar el promedio de esa muestra en la EEPROM del arduino. He estado haciendo pruebas y funciona bien para medir la temperatura y monitorearla mediante el puerto serial. El problema es a la hora de querer recuperar los datos guardados en la EEPROM. El objetivo es que cuando la carga llegue a su destino poder conectar el arduino a un ordenador y abriendo un interruptor al puerto 2 del arduino y mediante el programa TeraTerm poder ver los valores de la memoria. Pero no logro hacerlo. Alguna idea?
Mi código es el siguiente:
#include <EEPROM.h>
int numeroMuestras=64;
int i=0,j=0;
float promedio=0.0;
float temperatura[64];
int memFull = 12;
int addr = 0;
int address = 0;
byte value;
void setup(){
Serial.begin (9600); //inicia comunicacion serial
pinMode(2, INPUT);
}
void loop(){
//Calcula la temperatura usando como referencia 5v
for(i=0;i<=numeroMuestras;i++)
{
temperatura[i] = (5.0 * analogRead(0)*100.0)/1023.0;
delay ((180/64)*1000);
}
for(j=0;j<=numeroMuestras;j++)
{
promedio=promedio+temperatura[j];
}
promedio=promedio/numeroMuestras;
//Empezar a guardar los datos en la EEPROM
EEPROM.write(addr, promedio);
addr = addr + 1;
if (addr == 512)
{
addr = 0;
digitalWrite(memFull, HIGH);
}
//Para leero los datos de la EEPROM
if(digitalRead(2)==HIGH)
{
value = EEPROM.read(address);
Serial.print(address);
Serial.print("\t");
Serial.print(value, DEC);
Serial.println();
address = address + 1;
if (address == 512)
{
address = 0;
}
delay(500);
}
}
El switch está conectado de la siguiente manera.Una pata va a 5Vcc, la otra a una resistencia de 10K que va a Gnd y de ese mismo nodo sale un alambre al D2 del arduino.
He pensado en utilizar una estructura "Switch/Case" para comenzar a leer la EEPROM.
De tal forma que sea...
siwtch(digitalRead(2))
{
case LOW:
//Hacer todo el muestreo
break;
case HIGH:
//Hacer rutina para leer los datos de la EEPROM
break;
}
Antes, recordarte que debes leer las Normas del Foro y luego edita tu post insertando los tags para códigos. Se ve horrible tu código simplemente pasteado como lo has hecho.
Vamos a tu problema:
La EEPROM de un NANO/UNO solo puede escribirse 100.000 veces. Recuerdalo por si cambias esa tasa de muetreo.
Luego si haces una cuenta no pierdas tiempo haciendola todo el tiempo.
La calculas y las pegas 180/641000=2812
Simplemente pones delay(2812) y deberías compensar lo que te pierdes en 64 iteracciones 640.5= 32 factor de conversión.
for(i=0;i<=numeroMuestras;i++)
{
temperatura = (5.0 * analogRead(0)*100.0)/1023.0;
delay ((180/64)*1000);
}
Esto debiera ser temperatura Luego escribes * *EEPROM.write(addr, promedio);* * donde addr esta bien y promedio es un valor float. Pero que dice el Playground al respecto EEPROM.Write Description Write a byte to the EEPROM. Syntax EEPROM.write(address, value) Parameters address: the location to write to, starting from 0 (int) value: the value to write, from 0 to 255 (byte) Entonces para guardar un float necesitas modificiaciones a tu códgo. La mejor opcion es usar esto que recomienda el Playground de Arduinio. ``` template int EEPROM_writeAnything(int ee, const T& value)
{
const byte p = (const byte*)(const void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++)
EEPROM.write(ee++, *p++);
return i;
}
template int EEPROM_readAnything(int ee, T& value)
{
byte* p = (byte*)(void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++) p++ = EEPROM.read(ee++);
return i;
} * *Entonces la usas asi* * EEPROM_writeAnything(addr, promedio); * *y la lees * * EEPROM_readAnything(addr, promedio); ```
Gracias por responder. Lo siento, no vuelve a pasar lo de los tags para el código.
He hecho las modificaciones al programa, pero me manda mensajes de error a la hora de compilar; es la primera vez que lo utilizo y no se si lo estoy haciendo bien. Las modificaciones que hice son las siguientes:
switch(digitalRead(2))
{
case LOW:
//Calcula la temperatura usando como referencia 5v
for(i=0;i<=numeroMuestras;i++)
{
temperatura[i] = (5.0 * analogRead(0)*100.0)/1023.0;
delay ((180/64)*1000);
}
for(j=0;j<=numeroMuestras;j++)
{
promedio=promedio+temperatura[j];
}
promedio=promedio/numeroMuestras;
//Empezar a guardar los datos en la EEPROM
template <class T> int EEPROM_writeAnything(addr, promedio)
{
const byte* p = (const byte*)(const void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++)
EEPROM.write(ee++, *p++);
return i;
}
break;
Y para leer datos de la EEPROM, tengo lo siguiente:
case HIGH:
//Para leero los datos de la EEPROM
template <class T> int EEPROM_readAnything(addr, promedio)
{
byte* p = (byte*)(void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++)
*p++ = EEPROM.read(ee++);
return i;
}
break;
Y me aparece el siguiente mensaje de error:
Arduino:1.6.3 (Windows 7), Placa:"Arduino Nano, ATmega328"
Opciones de compilación cambiadas, reconstruyendo todo
TermometroGuardaDatos2.ino: In function 'void loop()':
TermometroGuardaDatos2.ino:40:1: error: a template declaration cannot appear at block scope
TermometroGuardaDatos2.ino:48:3: error: expected ';' before 'break'
TermometroGuardaDatos2.ino:52:5: error: a template declaration cannot appear at block scope
TermometroGuardaDatos2.ino:60:4: error: expected ';' before 'break'
Error de compilación
This report would have more information with
"Show verbose output during compilation"
activala desde Archivo > Preferencias
GO_zalo, hice lo que me dijiste, guardé el siguiente código con el nombre EEPROMAnything.h en la misma carpeta que está el programa del termómetro. Pero al código al momento de compilarlo sigue marcando erroes. El código es:
#include <EEPROM.h>
#include <Arduino.h> // for type definitions
void setup() {
// put your setup code here, to run once:
}
void loop() {
template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
const byte* p = (const byte*)(const void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++)
EEPROM.write(ee++, *p++);
return i;
}
template <class T> int EEPROM_readAnything(int ee, T& value)
{
byte* p = (byte*)(void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++)
*p++ = EEPROM.read(ee++);
return i;
}
}
EEPROM.writeAnything(addr, promedio);
addr = addr + 1;
if (addr == 512)
{
addr = 0;
digitalWrite(memFull, HIGH);
}
break;
case HIGH:
//Para leero los datos de la EEPROM
value = EEPROM.read(address);
Serial.print(address);
Serial.print("\t");
Serial.print(value, DEC);
Serial.println();
address = address + 4;
if (address == 512)
{
address = 0;
}
delay(500);
Pero me manda este mensaje:
Arduino:1.6.3 (Windows 7), Placa:"Arduino Nano, ATmega328"
Opciones de compilación cambiadas, reconstruyendo todo
TermometroGuardaDatos2.ino:1:1: error: stray '\' in program
TermometroGuardaDatos2.ino:1:7: error: stray '#' in program
TermometroGuardaDatos2.ino:1:1: error: stray '\' in program
TermometroGuardaDatos2.ino:1:1: error: stray '\' in program
TermometroGuardaDatos2.ino:2:28: fatal error: EEPROMAnything.h: No such file or directory
compilation terminated.
Error de compilación
This report would have more information with
"Show verbose output during compilation"
activala desde Archivo > Preferencias
Preferiblemente se suele usar tarjetas Micro-SD para hacer ese tipos de tareas. Las EEPROM, sobre tod interna, está bien para guardar y recuperer datos de configuraciones. Por ejemplo, los canales de la TV, el volumen, contraste, todo eso en la EEPROM tipo 24LCxx. Eso si, otros TV le dan por guardarla dentro de la EEPROM principal del firmware, cosa rara pero cada vez se ven más. Normalemente van fuera.
Preferiblemente se suele usar tarjetas Micro-SD para hacer ese tipos de tareas. Las EEPROM, sobre tod interna, está bien para guardar y recuperer datos de configuraciones. Por ejemplo, los canales de la TV, el volumen, contraste, todo eso en la EEPROM tipo 24LCxx. Eso si, otros TV le dan por guardarla dentro de la EEPROM principal del firmware, cosa rara pero cada vez se ven más. Normalemente van fuera.
La ventaja que tiene, puedes guardar los datos con extensiones conocidas como text o el de excell, después lo pasas al PC y lo entiende, la EEPROM interna no. ejjejej.
surbyte:
Aca la solución.
MIra los archivos que adjunto.
Solo una pregunta mas. Cómo puedo hacer para que al momento de pasar los datos a la pc, sólo me muestre las temperaturas que ha guardado y no todo lo que tiene la memoria? Hice un programa que guarda 0s en la memoria, entonces las temperaturas las sobre escribe. Pero al momento de pasar los datos, si solo ha guardado 2 temperaturas, me muestra todos los ceros que tiene la memoria. Intente hacerlo con un ciclo. Pero no resultó.
case HIGH:
//Para leer los datos de la EEPROM
for(k=0;k<=cont;k++)
{
value = EEPROM_readAnything(address, promedio);
Serial.print(promedio, 2);
Serial.print("\t");
Serial.println();
address = address + 4;
if (address == 512) {
address = 0;
}
delay(250);
}
break;
Y bueno descarta todo lo que es 0
Pregunta si distinto de 0, y si lo es lo envías.
for(k=0;k<=cont;k++)
{
value = EEPROM_readAnything(address, promedio);
if (value > 0.0) {
Serial.print(promedio, 2);
Serial.print("\t");
Serial.println();
}
address = address + 4;
if (address == 512) {
address = 0;
}
porque escaneas de este modo y no asi
for(address=0;k<=512;address=address+4) {
value = EEPROM_readAnything(address, promedio); // lees el valor
if (value > 0.0) { // si es mayor que 0 lo presentas
Serial.print(promedio, 2);
Serial.print("\t");
Serial.println();
}
// else break; // usa esta linea si quieres interrumpir la lectura cuando lees un 0.
}
ahora en cuanto lees un 0 no deberías interrumpir el for? para que seguir si no se ha llenado?
Si guardaste dos datos leerás address 0 y 4 y luego cuando intentes leer 8 dará un 0, entonces sales del for.
Sigue sin parar. Lo he dejado que muestree solamente una temperatura. Pero al momento de pasar los datos al ordenador, me escribe la misma temperatura 512 veces. No sé que tengo mal en los ciclos, o qué pueda estar mal al momento de leer la memoria Esta fue la modificación al código. Lo intente tanto con (;address<=512;) y (;k<=512;)
//Para leer los datos de la EEPROM
for(address=0;address<=512;address=address+4)
{
value = EEPROM_readAnything(address, promedio);
if(value!=0.0)
{
Serial.print(promedio, 2);
Serial.print("\t");
Serial.println();
}
}
Tiene razón noter, valor no devuelve mas que la dirección de la EEPROM, el valor es transferido a la variable promedio y por ende se debe comparar con el.
Buena observación, GO_zalo. Supongo que sean funciones (más bien sospecho macros) de las últimas versiones del IDE, o sencillamente se me escaparon cuando ojeé la referencia de EEPROM. Tomo nota de las tres que aparecen.