En la imagen del BMV-700 podrás ver que se suministra con un shunt para intercalar en el cableado de las baterías, medirá la intensidad en dirección a las baterías como la intensidad que suministren éstas.
Materiales empleados:
- Arduino-UNO + Fuente de alimentación
- Ethernet shield
- Termistor NTC-MF52-103
- Pinza amperimétrica SCT-013-000 (100A)
- Un módulo relé, viene optoacoplado y con dos leds, uno rojo de alimentación y otro verde de estado.
- Un Modulo Bidireccional I2c CII Convertidor Nivel Logico 5v-3.3v
- Una pequeña caja estanca para meterlo todo.
En éste caso, el programa subirá 24 relativos al buffer del dispositivo BMV, muchos de ellos actualmente no los estoy usando, pero quizás mañana si.
El programa también está programado para el uso de dos equipos híbridos tipo Voltronic o PIP, normalmente el equipo esclavo se encontrará apagado, y sólo se encenderá cuando alcance o supere el nivel establecido en la variable WtEsclavo, para ello soldaremos unos pequeños hilos que irán desde el relé hasta las patillas del interruptor del híbrido, el interruptor lo colocaremos en la posición apagado para que sea el relé quien abra o cierre el contacto. Se utilizará el pin 7.
El BMV se conectará mediante el cable Tx al Rx de Arduino y compartirán también GND.
Por seguridad he instalado entre el BMV y el arduino un Modulo Bidireccional I2c CII Convertidor Nivel Logico 5v-3.3 para separar las tensión de ambos, aunque en este caso no es necesario por no compartir el pin power, nunca esta de más un poco de protección.
He utilizado un Arduino-Uno al que he añadido una shield ethetnet
En el parámetro "emon1.current(0, 56.606);// Pinza amperimetrica:( input pin, calibration)" deberás cambiar los valores para la calibración de la pinza.
El relé utilizado es igual que el de la imagen, ya viene provisto de optoacloplador y un par de led, alimentación rojo y estado en verde.
Una vez tengas instalado el sistema, deberás registrarte en emoncms.org. cuando entres en tu perfil podrás visualizar la api key que tendrás que cambiarla por la que está escrita en el programa, lo datos comenzarán a subirse al sitio web, podrás visualizar los inputs que llegan al portal y decidir cuales vas a convertir en feed, para finalmente configurar la interfaz grafica haciendo uso de los feeds. Encontrarás más información en la documentación API https://emoncms.org/site/api
En el próximo brico y a partir de este sistema realizaré un sistema de derivación de excedentes, el proyecto consistirá en montar en una cajita estanca un WeMos que recoja información del sistema y realice derivación a cargas resistivas mientras no se produzca consumo en las baterías.
Aquí tienes disponible el código para Arduino.
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 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 | /***************************************************************************** * *************************************************************************** * Fecha: 05/07/2016 Autor: AntonioBG * Material: Arduino + ethernet shield + thermistor NTC-MF52-103 + * relé + pinza amperimetrica SCT-013-000 * * Objetivo: * -Primero.- Monitorización online del monitor de baterías, subiendo * los datos a emoncms.org * -Segundo.- Mantener apagado el híbrido esclavo tipo Voltronic, * cuando la pinza amperimetrica detecte menos de lo establecido * en el parámetro "WtEsclavo" y enciende el híbrido si detecta más carga de * la indicada. * * Conexión: * -Pin digital 7, conexión al relé actuador del híbrido. * -Pin analógico A1, conexión del thermistor. * -Pin analógico A0, pinza amperimétrica no invasiva, he empleado el modelo * 100A aunque recomiendo el de 30A que ofrece mejor resolución. * -El monitor BMV de Victron es de 3,3v y Arduino de 5v, la conexión será * del monitor pin Tx a Rx de Arduino, y GND de ambos, por seguridad y aunque no * sea necesario, he instalado un módulo "I2c CII Convertidor Nivel Logico 5v-3.3v * Modulo Bidireccional". * * LICENCIA DE USO GNU GPL, si mejoras el programa o añades funcionalidades, * por favor, compártelo! */ #include <SoftwareSerial.h> #include <SPI.h> #include <Ethernet.h> #include "EmonLib.h" #include <math.h> byte mac[] = {0x50, 0xA1, 0xDA, 0x00, 0x39, 0xE5}; IPAddress ip(192, 168, 1, 201); //IP estática IPAddress subnet(255, 255, 255, 0); IPAddress DNS(8, 8, 8, 8); IPAddress gw(192, 168, 1, 1); // Puerta de enlace EthernetClient clientEmon; EnergyMonitor emon1; SoftwareSerial Victron(0,1); // (RX, TX) RX se ecuentra establecido en el 0 #define P(str) (strcpy_P(p_buffer, PSTR(str)), p_buffer) char c; String V_buffer; // Buffer para datos del monitor Victron String E_buffer; // Buffer para datos de ethernet shield float I; // I Intensidad instantanea float V; // V Vo
ltaje instananeo float TTG;// TTG time to go float CE;// Consumo Amp/h int H1;//Profundidad descarga máxima int H2;//Profundidad ultima descarga int H3;//Profundidad de la descarga media int H4;//Numero de ciclos de carga int H5;//Numero de descargas completas float H6;//Horas acumuladas amperaje float H7;//Minimo voltaje bateria float H8;//Maximo voltage bateria float H9;//Tiempo desde ultima descarga int H10;//Numero de sincronizaciones automaticas int H11;//Numero de alarmas voltaje bajo int H12;//Numero de alarmas voltaje alto int H17;//Cantidad energia descargada float H18;//Cantidad de energia cargada int Alarm_high_voltage; int Alarm_low_voltage; int Alarm_low_soc; String Alarm; String Relay; double Irms; //Calculo pinza amp int WtEsclavo = 9; // W Establece los amperios a los que se activa el hibrido esclavo int ReleHibrido = 7; // Pin para arrancar el hibrido paralelo char serverEmon[] = "emoncms.org"; String apikey = "XXXXa0XXXXX1dXXXX96e8XXXXX4b2XXX"; //api key, regístrate en emoncms.org e introduce tu api key int node = 0; //if 0, not used, puede tener más nodos unsigned long lastConnectionTime = 0; // ultima vez que conectó en milisegundos boolean lastConnected = false; // estado de la conexión última vez a través delloop const unsigned long postingInterval = 10*1000; // establece en milisegundos el delay en actualizaciones void setup() { Serial.begin(19200); Victron.begin(19200); Serial.println("Emoncms client starting..."); Ethernet.begin(mac, ip, DNS, gw, subnet); emon1.current(0, 56.606);// Pinza amperimetrica:( input pin, calibration)// pinMode(ReleHibrido, OUTPUT); } // <-- Inicio loop void loop() { // <-- Victron if (Victron.available()) { c = Victron.read(); if (V_buffer.length() <80) { V_buffer += c; } if (c == '\n') { // New line. if (V_buffer.startsWith("I")) {//Corriente bateria String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); double temp_int = temp_string.toInt(); I = (float) temp_int/1000;} if (V_buffer.startsWith("P")) {//Potencia instantanea String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); int temp_int = temp_string.toInt(); P = (int) temp_int;} if (V_buffer.startsWith("CE")) {//Consumido kwh String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); double temp_int = temp_string.toInt(); CE = (float) temp_int/1000;} if (V_buffer.startsWith("TTG")) {//Time to go String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); double temp_int = temp_string.toInt(); TTG = (float) temp_int/60;} if (V_buffer.startsWith("H1")) {//Profundidad descarga máxima String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); int temp_int = temp_string.toInt(); H1 = (int) temp_int/10;} if (V_buffer.startsWith("H2")) {//Profundidad ultima descarga String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); int temp_int = temp_string.toInt(); H2 = (int) temp_int/10;} if (V_buffer.startsWith("H3")) {//Profundidad de la descarga media String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); int temp_int = temp_string.toInt(); H3 = (int) temp_int;} if (V_buffer.startsWith("H4")) {//Numero de ciclos de carga String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); int temp_int = temp_string.toInt(); H4 = (int) temp_int;} if (V_buffer.startsWith("H5")) {//Numero de descargas completas String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); int temp_int = temp_string.toInt(); H5 = (int) temp_int;} if (V_buffer.startsWith("H6")) {//Horas acumuladas amperaje String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); double temp_int = temp_string.toInt(); H6 = (float) temp_int/1000;} if (V_buffer.startsWith("H7")) {//Minimo voltaje bateria String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); double temp_int = temp_string.toInt(); H7 = (float) temp_int/1000;} if (V_buffer.startsWith("H8")) {//Maximo voltage bateria String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); double temp_int = temp_string.toInt(); H8 = (float) temp_int/1000;} if (V_buffer.startsWith("H9")) {//Tiempo desde ultima descarga String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); double temp_int = temp_string.toInt(); H9 = (float) temp_int/86400;} if (V_buffer.startsWith("H10")) {//Numero de sincronizaciones automaticas String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); int temp_int = temp_string.toInt(); H10 = (int) temp_int;} if (V_buffer.startsWith("H11")) {//Numero de alarmas voltaje bajo String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); int temp_int = temp_string.toInt(); H11 = (int) temp_int;} if (V_buffer.startsWith("H12")) {//Numero de alarmas voltaje alto String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); int temp_int = temp_string.toInt(); H12 = (int) temp_int;} if (V_buffer.startsWith("H17")) {//Cantidad energia descargada String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); double temp_int = temp_string.toInt(); H17 = (float) temp_int/1000;} if (V_buffer.startsWith("H18")) {//Cantidad de energia cargada String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); double temp_int = temp_string.toInt(); H18 = (float) temp_int/1000;} if (V_buffer.startsWith("Alarm")) { Alarm = V_buffer.substring(V_buffer.indexOf("\t")+1); Alarm.trim();} if (V_buffer.startsWith("Relay")) { Relay = V_buffer.substring(V_buffer.indexOf("\t")+1); Relay.trim();} if (V_buffer.startsWith("AR")) { String temp_string = V_buffer.substring(V_buffer.indexOf("\t")+1); int temp_int = temp_string.toInt(); if (bitRead(temp_int,0)) { Alarm_low_voltage = 1;} else {Alarm_low_voltage = 0;} if (bitRead(temp_int,1)) { Alarm_high_voltage = 1;} else {Alarm_high_voltage = 0;} if (bitRead(temp_int,2)) {Alarm_low_soc = 1;} else {Alarm_low_soc = 0;} } V_buffer=""; } } // Victron --> if (!clientEmon.connected() && lastConnected) { Serial.println(); Serial.println("Desconectando..."); clientEmon.stop(); } if(!clientEmon.connected() && (millis() - lastConnectionTime > postingInterval)) { // <-- Pinza amperimetrica Irms = emon1.calcIrms(1480); // Calculate Irms only // <-- Activa esclavo if (Irms >= WtEsclavo){ digitalWrite(ReleHibrido,LOW);// Activa el hibrido esclavo } else { digitalWrite(ReleHibrido,HIGH); } // Activa esclavo --> sendData(); } lastConnected = clientEmon.connected(); } // Fin Loop --> // <-- Devuelve grados celsius double Thermister(int RawADC) { double Temp; Temp = log(((10240000/RawADC) - 10000)); Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp ); Temp = Temp - 273.15;// Converierte de Kelvin a Celsius //Para convertir Celsius a Farenheith esriba en esta linea: Temp = (Temp * 9.0)/ 5.0 + 32.0; return Temp; } // Devuelve grados celsius --> // <-- Envía datos a emoncms void sendData() { if (clientEmon.connect(serverEmon, 80)) { Serial.println("Connecting..."); clientEmon.print("GET /api/post?apikey="); clientEmon.print(apikey); if (node > 0) { clientEmon.print("&node="); clientEmon.print(node); } clientEmon.print("&json={"); clientEmon.print(",Potencia:"); clientEmon.print(P); clientEmon.print(",SOC:"); clientEmon.print(SOC); clientEmon.print(",TTG:"); clientEmon.print(TTG); clientEmon.print(",CE:"); clientEmon.print(CE); clientEmon.print(",H1:"); clientEmon.print(H1); clientEmon.print(",H2:"); clientEmon.print(H2); clientEmon.print(",H3:"); clientEmon.print(H3); clientEmon.print(",H4:"); clientEmon.print(H4); clientEmon.print(",H5:"); clientEmon.print(H5); clientEmon.print(",H6:"); clientEmon.print(H6); clientEmon.print(",H7:"); clientEmon.print(H7); clientEmon.print(",H8:"); clientEmon.print(H8); clientEmon.print(",H9:"); clientEmon.print(H9); clientEmon.print(",H10:"); clientEmon.print(H10); clientEmon.print(",H11:"); clientEmon.print(H11); clientEmon.print(",H12:"); clientEmon.print(H12); clientEmon.print(",H17:"); clientEmon.print(H17); clientEmon.print(",H18:"); clientEmon.print(H18); clientEmon.print(",Alarm_high_voltage:"); clientEmon.print(Alarm_high_voltage); clientEmon.print(",Alarm_low_voltage:"); clientEmon.print(Alarm_low_voltage); clientEmon.print(",Alarm_low_soc:"); clientEmon.print(Alarm_low_soc); clientEmon.print(",Alarm:"); clientEmon.print(Alarm); clientEmon.print(",Relay:"); clientEmon.print(Relay); // <-- Thermister int val=analogRead(A1);//Lee el valor del pin analogo 0 y lo mantiene como val double temp=Thermister(val);//Realiza la conversión del valor analogo a grados Celsius clientEmon.print(",Temp:"); clientEmon.print(temp); Serial.println("temp: ");//Escribe la temperatura en el monitor serial debug Serial.println(temp);//Escribe la temperatura en el monitor serial debug // Thermister --> // <-- Pinza amp clientEmon.print(",Consumo_W_Hibrid:"); clientEmon.print(Irms*230); // Potencia W aparente clientEmon.print(",Consumo_I:"); clientEmon.print(Irms); // Irms // Pinza amp --> clientEmon.println("} HTTP/1.1"); clientEmon.println("Host:emoncms.org"); clientEmon.println("User-Agent: Arduino-ethernet"); clientEmon.println("Connection: close"); clientEmon.println(); lastConnectionTime = millis(); } else { // Si no puede establecer conexión: Serial.println("Conexion fallida"); Serial.println("Desconectando..."); clientEmon.stop(); } } // Envía datos a emoncms --> |
No hay comentarios:
Publicar un comentario