Terminamos esta serie de entradas dedicadas al control de consumo eléctrico con Arduino facilitando a nuestros lectores una pequeña utilidad software para visualizar los consumos almacenados en fichero LOG (formato csv). En la primera parte comentábamos cómo utilizar el sensor de consumo no invasivo SCT-013-030, mientras que en la segunda nos centrábamos en la captura del fichero de consumos. Si hemos llegado hasta aquí sabremos ya cómo obtener un fichero tipo csv cuyos datos podemos analizar fácilmente.
El programa utilizado [ PowerLOG v. 1.3 ] es, básicamente, el mismo comentado en entradas anteriores pero con unas pequeñas modificaciones a nuestro gusto, a saber:
- Nombre de fichero: consumo.csv
- Captura de consumo cada 10 segundos.
- Iteraciones = 40 (rutina smoothread).
- Añadida variable de nombre de ubicación.
- Estructura csv guardada ligeramente modificada
La estructura se genera en esta parte del programa
y el resultado – con datos grabados – será similar a este
El fichero obtenido puede ser abierto con cualquier procesador de textos para su edición, por un programa externo que se encargue de visualizar los datos obtenidos o con una hoja de cálculo que nos permitirá ver e, incluso, obtener gráficas del mismo mediante las herramientas gráficas que incorpora.
Nosotros hemos optado por añadir un fichero Excel (descargable al final del artículo) que, mediante programación VBA, nos abrirá automáticamente el fichero generado (consumo.csv) y nos mostrará la gráfica del consumo. Su aspecto al cargar los datos será algo así
NOTA: Al contener código VBA el programa Excel nos pedirá autorización para su ejecución (seguridad/macros).
El código VBA es fácilmente modificable para adaptarlo a nuestras necesidades por cualquier persona con unos pocos conocimientos de este entorno. Su utilización es muy intuitiva ya que tan solo hemos de utilizar los dos «botones» existentes en la pestaña CONTROL. Con cada carga de datos se nos creará una nueva pestaña con su correspondiente «TimeStamp». Podemos copiar los datos y gráficos obtenidos a cualquier otro formato. El botón de borrado se encarga de limpiar todas las hojas salvo, claro está, la hoja CONTROL.
Esta utilidad Excel VBA se incluye «as is» y simplemente a modo de ejemplo. Además podemos descargar un fichero con datos de varias horas para las primeras pruebas.
Algo importante a tener en cuenta es que existe una limitación de tamaño (nº de líneas) en Excel (si no me equivoco unas 64000 líneas en Excel 32 bits), por lo que deberemos modificar el programa para generar ficheros CSV diferenciados si tenemos el propósito de guardar mucha información en los mismos.
Ahora ya podemos registrar y guardar el consumo eléctrico a nuestro gusto. Recuerda que nuestro montaje no pretende ser un equipo de laboratorio sino un modo de DIVERTIRNOS con la tecnología.
PROGRAMA POWER_LOG v 1.3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
// ============================================================ // = Arduino PowerLOG - DIVERTEKA (Abril 2014) v. 1.3 = // = Develop by Txus [J.C. Garcia Preciado] = // ============================================================ // Parte de este codigo esta basado en: // RTC Control ==> <http://www.combustory.com> John Vaughters // SD Control ===> <http://code.google.com/p/sdfatlib> // ------------------------------------------------------------ const int chipSelect = 8; // <=== IMPORTANTE (Sparkfun cs pin) #include "Wire.h" #include <SdFat.h> #define DS1307_I2C_ADDRESS 0x68 // direccion I2C // ------------------------------------------------------------ byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; const int analogInPin = A0; // pin de entrada analogica int retardo = 10; // (tiempo (s.) entre lecturas) float lectura,ff, ff2, pW,iA,vV,vS,S_Ratio; int voltios,vatios,Hz; int Sensor_OK; SdFat sd; SdFile myFile; char Volts [10]; char Vats [10]; int StatusLED = 6; long item = 0; String nombre = "CASA"; // ------------------------------------------------------------ void setup() { pinMode(StatusLED, OUTPUT); Blink(10); int n = 1; Wire.begin(); Serial.begin(9600); S_Ratio = 36.5; // Sensor/ratio (mV/mA ) : 36.5 vV = 230; // valor de tension a computar Hz = 50; // variables ff y ff2 segun Hz -> (50Hz/60 Hz) if (Hz == 50){ ff = 5000; ff2 = 10000; } else { ff = 4166; ff2 = 16664; } while (!Serial) { } // solo necesario para A. Leonardo Serial.print("- Iniciando programa PowerLOG [v 1.3] " ); pinMode(10, OUTPUT); for (n;n<4;n++){ delay(500); Serial.print(n); Serial.print(" ");} Serial.println("."); Serial.println(" "); Serial.print("- Inicializando SD ..."); if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { Serial.println(" ERROR."); return; } Serial.println(" OK."); } // ------------------------------------------------------------ float smoothread(){ Sensor_OK = 0; double Houston = 0; int ni = 40; // n. iteraciones => smooth (10-50) float retorno = 0.0; Serial.print("Midiendo "); for (int x = 0; x< ni; x++) { do { Houston++; if (Houston > 50000) // { Sensor_OK = 0; return 0; } } while (analogRead(0) != 0); // espero paso por cero Sensor_OK = 1; delayMicroseconds (ff + ff2); //estabiliz. CAD + espera centro de ciclo retorno = retorno +(analogRead(0)); delay (10); // estabilizacion CAD } return retorno / ni; } // ------------------------------------------------------------ void Blink(int n) { int i; for (i=0;i<n;i++){ digitalWrite(StatusLED, HIGH); delay(50); digitalWrite(StatusLED, LOW); delay(50); } } // ------------------------------------------------------------ byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); } // ------------------------------------------------------------ byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); } // ------------------------------------------------------------ void LeeRTC(){ Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.write((byte)0x00); Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 7); second = bcdToDec(Wire.read() & 0x7f); minute = bcdToDec(Wire.read()); hour = bcdToDec(Wire.read() & 0x3f); dayOfWeek = bcdToDec(Wire.read()); dayOfMonth = bcdToDec(Wire.read()); month = bcdToDec(Wire.read()); year = bcdToDec(Wire.read()); } // ------------------------------------------------------------ String fprint (int dato) // formatea dato a dos digitos { String retorno = String(dato); if (retorno.length() < 2) retorno = "0" + retorno; return retorno; } // ------------------------------------------------------------ void EfectuaMedida() // calcula datos desde sensor SCT013 { Serial.println(); Serial.println("==================================="); Serial.println(" * PowerLOG - DIVERTEKA v. 1.3 * " ); Serial.println("===================================" ); lectura = smoothread () / 1.41; // lectura (rms) vS = (lectura * 0.0048); // valor de C.A.D. iA = (lectura * S_Ratio)/1000; // Intensidad (A.) pW = vV * iA; // Potencia (vat.) // Casting a int para escritura en fichero LOG voltios = (int)vV; vatios = (int)pW; Serial.print (voltios); Serial.print(" voltios, " ); Serial.print(vatios); Serial.println(" vatios" ); Serial.println("-----------------------------------" ); } // ------------------------------------------------------------ int CheckSD() // verifica tarjeta SD OK { return sd.begin(chipSelect, SPI_HALF_SPEED); } // ------------------------------------------------------------ void EscribeLog (String dato) // escribe datos en fichero LOG { if (!myFile.open("consumo.csv", O_RDWR | O_CREAT | O_AT_END)) { Serial.println(" ERROR en tarjeta SD !!"); Serial.println("-----------------------------------" ); return; } myFile.println(dato); myFile.close(); Serial.println(" OK."); } // ------------------------------------------------------------ int CheckRTC() // verifica modulo DS1307 OK { int retorno = 0; int valorA,valorB; long randNumber; randomSeed(analogRead(0)); randNumber = random(1,100); valorA = (int)randNumber; // escribo en RAM DS1307 Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.write((byte)0x09); Wire.write(decToBcd(valorA)); Wire.endTransmission(); // leo en RAM DS1307 Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.write((byte)0x09); Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 2); valorB = bcdToDec(Wire.read()) ; if (valorA == valorB) retorno = 1; return retorno; } // ------------------------------------------------------------ void loop() // Bucle principal del programa { LeeRTC(); EfectuaMedida(); // -- conformamos cadena a grabar en LOG a nuestro gusto -- item ++; if (item > 2000000000) item = 0; String DatoTS = String(item); DatoTS.concat (";"); DatoTS.concat (nombre); DatoTS.concat (";"); DatoTS.concat (fprint(dayOfMonth)); DatoTS.concat ("."); DatoTS.concat (fprint(month)); DatoTS.concat ("."); DatoTS.concat ("20"); DatoTS.concat (fprint(year)); DatoTS.concat (";"); DatoTS.concat (fprint(hour)); DatoTS.concat ("."); DatoTS.concat (fprint(minute)); DatoTS.concat ("."); DatoTS.concat (fprint(second)); DatoTS.concat (";"); DatoTS.concat (vatios); if (!CheckSD()) { digitalWrite(StatusLED, HIGH); Serial.println("Datos no guardados en fichero LOG !"); Serial.println("-----------------------------------" ); Serial.println(" ** ERROR de Tarjeta SD ** "); Serial.println("-----------------------------------" ); } if (!CheckRTC()) { digitalWrite(StatusLED, HIGH); Serial.println("Datos no guardados en fichero LOG !"); Serial.println("-----------------------------------" ); Serial.println(" ** ERROR de RTC [DS1307] **"); Serial.println("-----------------------------------" ); } if (!Sensor_OK) { digitalWrite(StatusLED, HIGH); Serial.println("Datos no guardados en fichero LOG !"); Serial.println("-----------------------------------" ); Serial.println(" ** ERROR de sensor SCT-013-030 ** "); Serial.println("-----------------------------------" ); } if ( (CheckSD()) && (CheckRTC()) && (Sensor_OK) ) { Blink(1); Serial.print ("TS+Datos: "); Serial.println(DatoTS); Serial.println("-----------------------------------" ); Serial.print("Escribiendo en fichero LOG ..."); EscribeLog (DatoTS); Serial.println("-----------------------------------" ); } Serial.println(); delay(retardo * 1000); } |
El fichero descargable contiene:
- Software Power_LOG (v 1.3) para Arduino.
- Utilidad Excel VBA Power_LOG.xls
- Fichero ejemplo con datos CONSUMO.CSV.