Anuncios

Watimetro con Arduino


Realmente construir un watimetro no es demasiado  complejo cuando hablamos de corriente continua , por ejemplo pensando en una instalación fotovoltaica , pues basta  simplemente en recordar  la formula física de la  Potencia(P)   , la cual es el producto de la tensión instantánea(voltios) por la intensidad  (Amp ) , es decir  P = V x I ,  expresándose la unidad de potencia en  Watt o KW
Pero la potencia  en watios,  no expresa  ensimismo  potencia energética, por lo  que se recurre  al  producto de la potencia (vatios)  por el tiempo (en horas) , es  decir  E = P x t , expresándose  la unidad de energía que  todo conocemos como  vatios hora(Wh) o kilovatios hora (kWh).

Si unimos ambas formulas sustituyendo el valor de P obtenemos E =Px t= (V xI) x t , es decir  el producto de la tensión  e intensidad por el el tiempo

Precisamente pues de la ultima fórmula anterior queda claro que para medir la energía que necesitamos tres parámetros:

  1.  Tensión
  2.  Intensidad
  3.  Tiempo

Veamos pues como  obtener estas valores con un Arduino  para obtener en tiempo real en un display lcd  la potencia en kwh de un sistema en cc

En el siguiente  video podemos ver el proyecto funcionando, incluso enviando datos al IoT  con  Xively (esta opción ya no esta disponible para aficionados)

Medida de tensión

El voltaje se puede medir con la ayuda de un circuito divisor de tensión  formado  por dos resistencias iguales  . Como el  voltaje de entrada en cualquier pin analógico de ARDUINO esta limitado a 5V por se logica TTL , el  divisor de voltaje servirá para  que el voltaje de la salida de ella sea menor que 5V y no queme la electronica interior.

Por ejemplo para una batería  que se utilice para almacenar la energía de un  panel solar de  6v  y   5.5Ah  de capacidad , tendríamos que bajar la  tensión desde 6.5v a una tensión menor que 5V para no estropear el Arduino.

Si usamos R1 = 10k y R2 = 10K  nos da una corriente pequeña 6.5v/(10k+10K)=0,325mA .

Es cierto que se podrían  tomar valores de R1 y R2    inferiores, pero el problema es que cuando la resistencia es menor  mayor corriente  pasas  a través de ella generando como resultado gran cantidad de energía  disipada en forma de calor(recuerde  que P = I ^ 2R) . por tanto el valor de las resistencias  puede ser elegido diferente pero debe tenerse cuidado para reducir al mínimo la pérdida de energía a través de las resistencias.

El resultado de la tensión entre una de las resistencias y masa seria igual a R xI =10k  x 0.325mA=3.25v que es inferior a 5v y, tensión soportada sin problemas  para el pin analógico de  ARDUINO

Calibración de voltaje:

Cuando la batería está completamente cargada (6.5v) obtenemos una Vout = 3.25v y ese seria el valor  que iría al  convertidor analógico digital  de un puerto analógico  de  Arduino

Si tenemos que medir los 3.25v desde el divisor de tensión   obtendremos un valor aproximado de 696 en el monitor serial (  sample1 es el valor de ADC corresponde a 3.25v)  .

Precisamente con ese valor o tendremos que extrapolar  que 3.25v  es equivalente a 696,  1 es equivalente a 3.25/696=4.669mv    por lo que podemos usar  estas dos reglas:

Vout = (4.669 * sample1 ) / 1000 voltios
voltaje de la batería real = (2 * Vout) voltios

Con el siguiente código de Arduino  podemos obtener el valor de tensión:

/ / tomar 150 muestras de divisor de tensión con un intervalo de 2 segundos y medio samples data collected for(int i=0;i<150;i++)
{
sample1=sample1+analogRead(A2); //leer  el voltaje del circuito divisor
delay (2);
}
sample1=sample1/150;
voltage=4.669*2*sample1/1000;

Medición de intensidad

Para mediciones de intensidad  es típico usar una resistencia en serie  de poco  valor con la carga  y medir la diferencia de potencial entre los extremos   de esta  y luego calcular   la intensidad gracias a la la ley de ohm (I=V/R  ) donde como vemos   dividiríamos este valor por el valor en ohmios de la resistencia

El efecto Hall se basa en  la producción de una diferencia de potencial(el voltaje de Hall) a través de un conductor eléctrico, transversal a una corriente eléctrica en el conductor y un campo magnético perpendicular a la corriente.

Afortunadamente actualmente existen CI especializados  como   son  los   sensores de corriente basados en efecto Hall ACS 712

Existen comercialmente  sensores de la gama ACS712  para  diferentes  rangos de corrientes máximas , así que se debe escoger este  según su requisito,como por ejemplo para una corriente máxima de 20 A.

ACS712.png

En el  esquema vemos un LED como una carga ( aunque  la carga real sera diferente) .

Tambien vemos el  ACS 712 (soporta  20Amps DC)  ofreciendo una una salida analógica 100mV/A

Tambien es destacar la alimentación del Arduino  cuya salida alimenta a través de la placa de prototipos a la ACS712

La calibración  es muy sencilla :
La lectura analógica  produce un valor de 0-1023, equiparando a 0v a 5v analógico .Leer 1 = (5/1024) V = 4.89mv
Valor = (4,89 * valor analógico leído) / 1000 V,  pero según hojas de datos offset 2.5V (cero corriente obtendrá 2.5V del sensor de salida)
valor Actual = (valor 2.5) V
corriente en amp = valor real * 10

Código de ARDUINO:

/ / tomando 150 ejemplos de sensores con un intervalo de 2 segundos y luego media de los datos de las muestras recogidos
for (int i = 0; i < 150; i ++)
{
+= sample2 analogRead(A3);  //  leer la corriente de sensor
delay(2);
}
sample2 = sample2/150;
=(5.0*sample2)/1024.0; 
actualval = val-2.5;  //tensión de offset es 2.5v
amperios = actualval * 10;

 Medición del tiempo

Para la medida del tiempo no se necesita ningún hardware externo, pues ARDUINO en sí mismo tiene contador de tiempo incorporado.

La función millis() devuelve el número de milisegundos desde que la placa Arduino comenzó a ejecutar el programa actual.

Código de ARDUINO:

long milisec = millis();  // calcular el tiempo en milisegundos
long time=milisec/1000; // convertir de milisegundos a segundos

 Calculo de la potencia y energía

Estas son las formulas basicas empleadas por el fw  en Arduino:
  • totamps = totamps + amperios;  //calcular amperios total
  • avgamps = totamps/tiempo;  // promedio de amps
  • amphr =(avgamps*time)/3600;  // Ah
  • Watts = voltaje * amperios;  //Potencia = Voltaje * corriente
  • energía =(watt*time)/3600;  // Vatios-seg vuelve a convertir en Watt-hora dividiendo 1hr(3600sec)
  •  energy=(watt*time)/(1000*3600); //para la lectura en kWh

completo.jpg

Todos los resultados se pueden visualizar en el monitor serial o mediante una pantalla LCD   de 16 x 2 caracteres para mostrar todos los resultados obtenidos en los pasos anteriores.

El conexionado del LCD sigue la conexión estandar de 4 pines para la linea de  datos mas las señales de control RS,RW  y Enable

Asimismo también es necesario un trimer de 10k  para el contraste de la pantalla

Resumidamente estas son pues las conexiones para el lcd

LCD -> Arduino
1. VSS -> GND de Arduino
2. VDD -> Arduino + 5v
3. VO -> Arduino GND pin + resistencia o potenciómetro
4. RS -> Arduino pin 8
5. RW -> Arduino pin 7
6. E -> pin Arduino 6
7. D0 -> Arduino – no conectado
8. D1 -> Arduino – no conectado
9. D2 -> Arduino – no conectado
10. D3 -> Arduino – no conectado
11. D4 -> Arduino pin 5
12. D5 -> Arduino pin 4
13. D6 -> Arduino pin 3
14. D7 -> pin Arduino 2
15. A -> Pin 13 de Arduino + resistencia (potencia de luz de fondo)
16. K -> Arduino GND (tierra de luz de fondo)

A continuación este es el  código de ejemplo para sacar por el monitor serie  los valores calculados

Serial.Print (“tensión:”);
Serial.print(voltage);
Serial.println(“Volt”);
Serial.print (“actual:”);
Serial.print(amps);
Serial.println(“Amps”);
Serial.print (“potencia:”);
Serial.print(watt);
Serial.println(“Watt”);
Serial.print (“energía consumida:”);
Serial.print(energy);
Serial.println(“Watt-Hour”);
Serial.println(“”);  //imprimir los siguiente conjuntos de parámetro después de una línea e
delay(2000);
Para manejar el  LCD tiene que primero importar la biblioteca de “LiquidCrystal” en el código.
A continuación este es el  código de ejemplo para sacar por el display  lcd  los valores calculados:
#include
lcd (8, 7, 6, 5, 4, 3, 2);
luz int = 9;
void setup()
{
pinMode (luz de fondo, salida); //set pin 9 como salida
analogWrite (contraluz, 150); //controls la intensidad de luz 0-254
lcd.begin(16,2); / / columnas, filas. tamaño de pantalla
LCD.Clear(); claro la pantalla
}
void loop()
{
lcd.setCursor(16,1); / / establecer el cursor fuera de la cuenta de pantalla
lcd.print(“”); imprimir carácter vacío
delay(600);
impresión de potencia y energía que un LCD / / /
lcd.setCursor(1,0); coloca el cursor en la columna 1 y fila 1

LCD.Print(Watt);
lcd.print (“W”);
lcd.print(voltage);
lcd.print(“V”);
lcd.setCursor(1,1); coloca el cursor en la fila 1 columna y 2 º
lcd.print(energy);
lcd.print (“WH”);
lcd.print(amps);
lcd.print(“A”);
}

 

Componentes

A continuación por ultimo algunos de los componentes necesarios para llevar a cabo este circuito:

 

1. ARDUINO UNO  (unos 9€ en Amazon)


3. Display LCD de 16 x 2 caracteres LCD (en Amazon con I2C  menos de 5€ )

4. ACS 712 SENSOR de corriente .Rango de corriente: 30A; Tamano: 31 x 13mm / 1.2 “x 0.5” (L * W) ( en Amazon unos 2€ )


Varios : resistencias de 10k v2,resistencia de 330ohm, POTENCIÓMETRO de 10K ,cables puente , placa de prototipos,etc

 

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

 

Descargas por Mega

descarga las mejores series y anime desde mega facil y senzillo

WordPress.com en Español

Blog de Noticias de la Comunidad WordPress.com

A %d blogueros les gusta esto: