Medidor de Consumo Eléctrico CHINT + ESP8266 y Matrix Led MAX7912


En esta post  volveremos a un tema recurrente en este blog: la medición del consumo eléctrico de forma invasiva en un ambiente doméstico ,pero esta vez  usaremos  el  medidor CHINT DDS666,lo que técnicamente es un medidor residencial o residencial tradicional  pero con  una salida óptica  (también llamada   salida de pulsos)-

Precisamente por esa característica  de salida óptica, dado que en el mercado existe una amplia variedad de dispositivos con este tipo de salida   , esta propuesta que vamos a ver es perfectamente viable  también para  todo tipo de contadores con salida de pulso, como la mayoría de los contadores modernos  para uso personal  que se comercializan para fijar en carril DIN en el cuadro de distribución de c.a. cuya velocidad de flash de salida de prueba es de  500 impulsos por kWh ( es decir cada impulso corresponde a un 2W/H)

Lógicamente dado que la relación de pulsos/kwh  es diferente  según el contador , tendremos que ajustar el código de nuestro  programa para que el resultado sea exacto , pero insistimos: como esta relación es conocida  no es demasiado complejo ajustar   el código para el contador que elijamos

Advertencia: Se recomienda precaución ya que este tipos de proyectos implican riesgo eléctrico o electrocución ya que se utiliza un  equipo conectado de 220VCA -120 VCA por los que  se requieren conocimientos básicos  de electricidad , por favor esté documentado previamente en este sentido.

Conviene recordar que por seguridad cuando trabaje en cuadros de baja tensión siempre trabaje cortando la alimentación general y asegúrese después con un polímetro o un busca-polos que efectivamente no hay tensión c.a.

Obviamente si no se tiene experiencia en cableados de baja tensión o no esta seguro de la instalación , le  recomendamos encarecidamente  que este tipo de trabajos lo realice un instalador  o un electricista pues  manejar por error tensiones de ca puede ser peligroso  .

 

El circuito

 

El viejo modelo CHINT DSS66 permite la medición de energía activa o potencia activa en instalaciones domésticas. Es  un registrador ciclométrico, registrando medidas siempre positivas que evitan pérdidas fraudulentas de conexiones. Como se trata de un medidor invasivo que se requiere para abrir nuestro circuito eléctrico, se capturan los pulsos generados, Genera 3200 imp / kWh, que nos permitirá medir la potencia y el consumo de energía. El medidor tiene un optoacoplador para aislar la salida de pulso para realizar la medición. 

 Algunos medidores tienen una salida de pulso asociada con el consumo eléctrico, en el caso de este medidor específico, cada vez que se enciende el diodo led frontal, envía un pulso que activa un optoacoplador para la salida de pulsos terminales (11 +) (12 -) y el medidor integrado realiza la medición e integración de kilovatios / hora y enviando pulsos según el consumo siendo la relación de  este medidor  de 3200 imp “impulsos” / kwh,.

Este medidor tiene 2 características:

  • Es invasivo, es decir el circuito debe abrirse para colocar en serie el medidor entre la fuente y la carga
  • No tiene un protocolo de comunicación en serie, siendo la relación de salida de pulsos de 3200imp / kwh.

Gracias a la ayuda de un microcontrolador “Arduino, ESP8266 o ESP32”  podemos medir los watios consumidos. La elección precisamente de un  ESP8266 12E   o Arduino Nano Clone   , de hecho dependerá de si necesitamos enviar los datos  o no a un servidor en la nube  o simplemente queremos mostrar la información en un display 

Como contábamos al   principio de este post el modelo  DSS66 es algo anticuado por lo que es perfectamente viable usar   de contadores con salida de pulso de carril DIN , como la mayoría  que se comercializan para fijar en el cuadro de distribución de c.a. cuya velocidad de flash de salida de prueba es de  500 impulsos por kWh ( es decir cada impulso corresponde a un 2W/H)

 

 

Durante las primeras pruebas  se conectaron el GPIO directamente al medidor,dado que el medidor de mentón tiene su propio optoacoplador, pero por alguna razón cada vez que se genera un pulso, el módulo ESP8266 grababa 2 pulsos, algo que no sucedió con Arduino .

La solución para el problema es  aislar la salida del watímetro mediante la adición de un optoacoplador 4n25 y una fuente de alimentación de 5v :de esta manera sólo llegaría un pulso y ademas por seguridad se aislan los circuitos .

Para las primeras  pruebas   se propone usar un  ESP8266 y/o arduino y solo  haremos la medición de Active Power, por ejemplo  utilizando una  bombilla de 45W, para tener una carga fija que represente un “hogar”.

 

Lista de componentes

 

 

Código IDE de Arduino

 

El código para el módulo ESP8266 por ahora no tiene ninguna rutina de comunicación de envio  hacia  el Cloud, así que por el momento visualizaremos la potencia con un Matrix led x4 MAX7912 pero se puede usar un display de 7 segmentos  o  simplemente la salida serie

El medidor solo tiene una salida de pulso,por lo que  para realizar el cálculo del consumo eléctrico, capturamos a través de una interrupción en el GPIO 5 (D1), técnicamente utilizando el factor apropiado del medidor 3200imp / kWh = 3.2, se calcula la potencia activa instantánea.

Una diferencia horaria entre pulsos y basada en 1 hora = 3600 s. potencia = (3600000000.0 / (pulseTime – lastTime)) / 3.2

Este cálculo se realiza en la interrupción, solo cada vez que se registra un nuevo pulso.

Inicialmente, gracias a OpenEnegyMonitor, por la documentación, el cálculo se tomó de una de las versiones anteriores de su página

 

Este es el codigo usado para probar la funcionlidad 


#include <SPI.h>
#include <bitBangedSPI.h>
#include <MAX7219_Dot_Matrix.h>
const byte chips = 4;

unsigned long lastMoved = 0;
unsigned long MOVE_INTERVAL = 20; // mS
int messageOffset;
int counters=0;


// 12 chips (módulos de pantalla), SPI de hardware con carga en D10


MAX7219_Dot_Matrix display (chips, 2); // Chips / LOAD

char message [64] = “mensaje  a mostrar inicial ….“;
char myCharMessage[64];
String Message;

// Número de pulsos, utilizados para medir la energía.
long pulseCount = 0;


// Se usa para medir la potencia.
unsigned long pulseTime,lastTime,diffTime;
long timeout_reset=0;


//power and energy
double power elapsedkWh,watts;

// Número de pulsos por wh – encontrado o configurado en el medidor.

//1000 pulsos/kwh = 1 pulso por wh 3200 imp = 3.2

float ppwh = 3.2     ; 

int First_pulse = 0;
///***********************************************************************************


const byte interruptPin = 5; /// pin 5 D1


#include <Ticker.h>
Ticker flipper;


void flip() /// displayed
{

//bucle para almacenar en un array el mensaje de bienvenida

for (int i=0;i<64;i++)
{
message[i] = myCharMessage[i];
}
updateDisplay ();

}

 

 

Y este es el cuerpo del programa_

void setup ()
{
pinMode(interruptPin, INPUT_PULLUP);    //define el pin como entrada binaria
attachInterrupt(digitalPinToInterrupt(interruptPin), onPulse, FALLING);
Serial.begin(115200);
display.begin ();
} // end of setup


//
void onPulse()
{
if(First_pulse<2){ First_pulse++; }

else {
/// se usa para medir el tiempo entre pulsos.
lastTime = pulseTime;
pulseTime = micros();

//Contador de pulsos
pulseCount++;

//Calculo de la potencia
power_ = (3600000000.0 / (pulseTime – lastTime))/ppwh;

if (power_ < 1000) {
watts= power_;
Serial.print(“watts = “);
Serial.print(watts,4);
Serial.println(“W”);
}
}
}

 

 

void updateDisplay ()
{
display.sendSmooth (message, messageOffset);
// la próxima vez muestra un píxel en adelante

if (messageOffset++ >= (int) (strlen (message) * 8))
messageOffset = – chips * 8;
} // end of updateDisplay

void loop ()
{

// DEBUG SERIAL
 Serial.print(“watts = “);
 Serial.println(watts,4);

////las cadenas se deben cargar a la variable (Message) para que se visualicen en la matriz

//Message =”Power “+String(watts)+” W :)”;
Message =String(watts)+”W”;

//sacamos por consola la potencia
Serial.println(Message);

int L_Message = Message.length(); ///length String
String(Message).toCharArray(myCharMessage, L_Message+1);

/// String to char array  y scroll
flipper.attach(0.1, flip);

// restardo


delay(100);


} //fin del bucle

 

 

 

En el siguiente video  podemos ver el circuito en acción:

 

 

 

 

Mas informacion en  https://www.instructables.com/id/Electric-Consumption-Meter-CHINT-ESP8266-Matrix-Le/

Anuncios

Watimetro con Esp8266


Éste proyecto se aprovecha de que los contadores modernos  inteligentes  incluyen en el frontal un LED que parpadea cada 1kW consumido, de modo que conectando un par de  cables a dicho LED y montando una pequeño circuito   basada en el módulo Wifi ESP8266, podemos medir con bastante precisión el consumo producido.

Obviamente  no es  legal abrir el contador  inteligente de nuestra vivienda para soldar un para de  cables al LED del watimetro, básicamente porque el equipo no nos pertence  ya que las compañías suministradoras  lo suelen  ofrecer en modo alquiler , pero debe saber que  éste tipo de contadores  también lo podemos instalar en nustra vivienda  o local   en el cuadro de distribución de corriente alterna en un carril DIN, normalmente a a la salida del magneto-térmico general  que alimenta a todos los circuitos que haya instalados en  nuestra vivienda.

Por ejemplo el modulo  XCSOURCE® Medidor Energía KWH Kilovatio Hora LCD CA 50Hz Fase Simple Riel DIN 230V BI04   se puede comprar por unos 14€ en  Amazon siendo la instalación de riel DIN estándar de 35mm, y ademas cumpliendo con el estándar DIN EN 50023   y con el ancho del poste sencillo (módulo de 17.5mm), que cumple con el estándar DIN 43881.

El modulo en su configuración Estándar  tiene una ventana de visualización de 7+1 dígitos  (9999999.1kwh) mediante un LCD blanco y negro así, como también una salida con un led verde para el estado de suministro de energía y Rojo para la señal de impulso de energía  como el de los contadores “inteligentes”.

Además , no necesitamos desmontar el modulo para capturar la salida del led de consumo pues tiene una salida SO Estándar donde  podemos conectar el circuito qeu vamos   a ver (respetando la polaridad)

Realmente como vemos en el esquema de conexiones de watimetro este  se alimenta por los terminales  1 y 4 (terminales de arriba)   y su salida ira a lo terminales 3 y 6  que conectaremos a la carga ( es decir el resto de circuitos de nuestro vivienda o local) , y resaltar que precisamente en lo terminales 20 (+) y 21(-)  tenemos la salida standar  SO   de pulsos de 50ms por 1wh

 

El circuito final que el autor propone para mejorar la visualizacion de watimetro  , cuenta de los siguiente elementos:

  • De  un ESP8266-12E como corazón del diseño
  • Una  pantalla OLED
  • Una conexión para programación via conversion usb-serie
  • Una fuente de almentacion de 3.3V
  • Un  circuito de  entrada procedente de la señal SO del watimetro
  • Una entrada adicional opcional para medir consumos individuales de una carga sin watimetro exterior

 

El circuito propuesto es el siguiente:

 

.

 

Hardware

  • ESP8266-12E
  • ACS712 Current Sensor
  • 0.96″ OLED Display
  • BT136 Triac
  • MOC3021 Opto-triac
  • MCT2E
  • LM11173.3V LDO Regulator
  • 5V SMPS Module

 

Software

 

Y a continuación el código fuente  Arduino  que deberíamos grabar en el el ESP8266

 

Codigo Arduino

/***********************************************************************************/
/* This is an simple application to illustrate IoT Home Automation. /
/ This is an example for our Monochrome OLEDs based on SSD1306 drivers /
/ Pick one up today in the adafruit shop! /
/ ——> http://www.adafruit.com/category/63_98 /
/ This example is for a 128×64 size display using I2C to communicate /
/ 3 pins are required to interface (2 I2C and one reset) /
/ Adafruit invests time and resources providing this open source code, /
/ please support Adafruit and open-source hardware by purchasing /
/ products from Adafruit! /
/ Written by Limor Fried/Ladyada for Adafruit Industries. /
/ BSD license, check license.txt for more information /
/ All text above, and the splash screen must be included in any redistribution /
/************************************************************************************/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP8266WiFi.h>
#include / Local DNS Server used for redirecting all requests to the configuration portal /
#include / Local WebServer used to serve the configuration portal /
#include <WiFiManager.h> / https://github.com/tzapu/WiFiManager WiFi Configuration Magic */

#define VOLTAGE_DIVIDER 10.0f
#define REF_VOLT 0.9f
#define RESOLUTION 1024
#define WATTS_THRES 25.0
#define AC_VOLT 230.0
#define VPP_RMS 0.3535
#define BASE_PRICE 125
#define UNITS_UPL_FREQ 30 /* In 2Sec /
#define THEFT_THRESHOLD 15
#define VperAmp 0.1f / See AC712 Datasheet */
#define TRUE 1
#define FALSE 0
#define OLED_RESET 4
#define SSD1306_LCDHEIGHT 64
Adafruit_SSD1306 display(OLED_RESET);

const char* ssid = “IotEM”; /* Device SSID /
String apiKey = “GBH1K3293KFNO8WY”; / Replace with your thingspeak API key /
const char server = “api.thingspeak.com”;

/* Create an instance of the client */
WiFiClient client;
WiFiManager wifiManager;

/* Port Pin Definition */
int InVolPin = A0;
int LoadPin = 14;
int PulsePin = 12;
struct {
unsigned char LdCon: 1;
unsigned char Units:1;
} Flags;

double Voltage, VRMS, AmpsRMS, Watts;
volatile byte interruptCounter = 0;
int Pulses = 0;
int PrevUnits = 0;
int PrevMUnits = 0;
int Units, MeasUnits;

#if (SSD1306_LCDHEIGHT != 64)
#error(“Height incorrect, please fix Adafruit_SSD1306.h!”);
#endif

#define LoadOn() digitalWrite(LoadPin, 1)
#define LoadOff() digitalWrite(LoadPin, 0);

static void DispInfo (void);
static void DispStat (void);
static void SendUnits (void);
static void SendTheftInfo (void) ;
static void SendSMS (int8_t Type);
static void DisplayUnits(void);
static void TheftOccurred (void);

ADC_MODE(ADC_TOUT);

void setup(void) {
Wire.begin(0,2);
Serial.begin(9600);
pinMode(InVolPin, INPUT);
pinMode(LoadPin, OUTPUT);
pinMode(PulsePin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PulsePin), handleInterrupt, FALLING);
Flags.LdCon = FALSE;

display.display();
delay(500);
LoadOn();
ConnectAP();
DisplayUnits();
}

void loop() {
static unsigned long i = 0, j = 0, l = 0;
VRMS = getVPP() * VPP_RMS;
AmpsRMS = VRMS / VperAmp;
Watts = AmpsRMS * AC_VOLT;
if (Watts >= WATTS_THRES)
Flags.LdCon = TRUE;
else
Flags.LdCon = FALSE;
#ifdef DEBUG
Serial.print(Watts);
Serial.print(AmpsRMS);
Serial.println(” Amps RMS”);
#endif
if (Flags.LdCon) {
#ifdef DEBUG
Serial.println(MeasUnits);
Serial.println(Pulses);
Serial.println(l);
#endif
if (MeasUnits == Pulses)
if(++l > THEFT_THRESHOLD) TheftOccurred();
}
if (i++ >= UNITS_UPL_FREQ) { /* End of Day /
Units = Pulses – PrevUnits;
PrevUnits = Pulses;
SendUnits();
i = 0;
}
if (interruptCounter > 0) {
interruptCounter–;
Pulses++;
MeasUnits = Pulses;
l = 0;
#ifdef DEBUG
Serial.print(“Total Units: “);
Serial.println(Pulses);
#endif
DisplayUnits();
}
delay(1000);
}
void handleInterrupt() {
interruptCounter++;
}
static void TheftOccurred(void) {
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(3);
display.setTextColor(WHITE);
display.print(“!THEFT!”);
display.display();
SendTheftInfo();
delay(5000);
LoadOff();
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(2);
display.setTextColor(WHITE);
display.print(” Contact CESCOM”);
display.display();
delay(2000);
ESP.deepSleep(0, WAKE_RF_DEFAULT); / RIP /
for(;;);
}
void DisplayUnits(void) {
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(3);
display.setTextColor(WHITE);
display.print(Pulses);
display.setCursor(90,13);
display.setTextSize(2);
display.setTextColor(WHITE);
display.print(“Kwh”);
display.display();
}
void ConnectAP(void) {
#ifdef DEBUG
Serial.print(“Connecting Wifi: “);
Serial.println(ssid);
#endif
display.clearDisplay(); / For Display /
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println(“Connecting”);
display.display();
wifiManager.autoConnect(ssid);
#ifdef DEBUG
Serial.println(“”);
Serial.println(“WiFi connected”);
Serial.println(“IP address: “);
IPAddress ip = WiFi.localIP();
Serial.println(ip);
#endif
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println(“Connected”);
display.display();
delay(1000);
}
void SendTheftInfo(void) {
if (client.connect(server,80)) {
String postStr = apiKey;
postStr +=”&field2=”;
postStr += String(1);
postStr += “\r\n\r\n”;
client.print(“POST /update HTTP/1.1\n”);
client.print(“Host: api.thingspeak.com\n”);
client.print(“Connection: close\n”);
client.print(“X-THINGSPEAKAPIKEY: “+apiKey+”\n”);
client.print(“Content-Type: application/x-www-form-urlencoded\n”);
client.print(“Content-Length: “);
client.print(postStr.length());
client.print(“\n\n”);
client.print(postStr);
}
client.stop();
}
void SendUnits(void) {
if (client.connect(server,80)) {
String postStr = apiKey;
postStr +=”&field1=”;
postStr += String(Units);
postStr += “\r\n\r\n”;
client.print(“POST /update HTTP/1.1\n”);
client.print(“Host: api.thingspeak.com\n”);
client.print(“Connection: close\n”);
client.print(“X-THINGSPEAKAPIKEY: “+apiKey+”\n”);
client.print(“Content-Type: application/x-www-form-urlencoded\n”);
client.print(“Content-Length: “);
client.print(postStr.length());
client.print(“\n\n”);
client.print(postStr);
}
client.stop();
}
float getVPP() {
float result;
int readValue; //value read from the sensor
int maxValue = 0; // store max value here
int minValue = 1024; // store min value here
uint32_t start_time = millis();
while((millis()-start_time) < 1000) //sample for 1 Sec
{
readValue = analogRead(InVolPin);
// see if you have a new maxValue
if (readValue > maxValue)
{
/record the maximum sensor value/
maxValue = readValue;
}
if (readValue < minValue)
{
/record the minimum sensor value*/
minValue = readValue;
}
}
// Subtract min from max
result = (((maxValue – minValue) * REF_VOLT) / RESOLUTION) * VOLTAGE_DIVIDER ;
return result;
}

 

Y por cierto para los incredulos en el siguiente video podemos ver el circuito en funcionamiento