Hackster is hosting Hackster Holidays, Ep. 7: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 7 on Friday!
Mitch K
Published © CC BY-NC-SA

AC Current Monitor

This is a project for measuring the AC current of a device plugged into the outlet and data feedback using Blynk with OTA.

IntermediateShowcase (no instructions)3 hours5,531
AC Current Monitor

Things used in this project

Hardware components

WeMos D1 Mini Pro
×1
Evaluation Board, ADS1015 12-Bit ADC
Evaluation Board, ADS1015 12-Bit ADC
×1
Generic 5.0 Volt 1A Power Supply
×1
Resistor 270 ohm
×1
Resistor 120 ohm
×1
Generic 2 port AC Outlet
×1
Generic 3-wire AC grounded power cord
×1

Software apps and online services

Blynk
Blynk
Arduino IDE
Arduino IDE

Story

Read more

Schematics

AC Current Schematic

Code

AC Current code

Arduino
#include <Wire.h>
#include <BlynkSimpleEsp8266.h>

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <EEPROM.h>


uint16_t config3 = 0x0003  |      //  Disable comparator
	0x0000  |                        // non-latching Comparator
	0x0000  |                        // Alert/Rdy active low   (default)
	0x0000  |                        // Traditional comparator (default)
	0x00A0  |                        // 2400 samples per second
	0x0000  |                        // cont mode
	0x0400  |                        // +/-2.048V
	0x4000  |                        // Single-ended AIN0
	0x8000;                         // Set 'start single-conversion' bit


uint16_t offsetConfig = 0x0003  | // Disable comparator
	0x0000  |                      // non-latching Comparator
	0x0000  |                       // Alert/Rdy active low   (default)
	0x0000  |                       // Traditional comparator (default)
	0x00A0  |                       // 2400 samples per second
	0x0000  |                      // cont mode
	0x0400  |                      // +/-2.048V
	0x7000  |                      // Single-ended AIN3
	0x8000;                        // Set 'start single-conversion' bit


char auth[] = "auth token";
char ssid[] = "wifi network";
char pass[] = "wifi password";


int i2caddress = 0x48;

int converDelay = 250;  // microseconds


///////////////////


byte appConnected;

int reading0;
int maxValue1 = 0;
int adjusted = 0;
int userVoltage = 120;
int kwhCount = 0;

float volt1;
float current1;
float offset;
float watts;
float currentKwh;
float hourKwhAccrue = 0.0;
float kwhHourTotal = 0.0;
float runKwhTotal = 0.0;

unsigned long timer1 = 0;
unsigned long timer2 = 0;
unsigned long timer3 = 0;
unsigned long timer4 = 0;
unsigned long timer5 = 0;
unsigned long timer6 = 0;



void setup()
{
	EEPROM.begin(512);

	Wire.begin(D4, D5);
	Wire.setClock(400000);

	Blynk.begin(auth, ssid, pass);

	wifi_station_set_hostname("ESP-AC Mon");
	ArduinoOTA.setHostname("AC Monitor");
	ArduinoOTA.begin();

	getOffset();

	EEPROM.get(0, runKwhTotal);
	Blynk.virtualWrite(V6, runKwhTotal);

	write_register_ADC(i2caddress, config3);
} // setup



void loop()
{
	Blynk.run();
	ArduinoOTA.handle();


	if (millis() - timer2 > 500 && appConnected)
	{
		pullCurrent();
		getKwh();
	}

	else if (millis() - timer2 > 10000)
	{
		pullCurrent();
		getKwh();
	}


	if (millis() - timer4 > 15000)
	{
		maint();
		timer4 = millis();
	}

	if (millis() - timer6 > 86400000)
	{
		EEPROM.put(0, runKwhTotal);
		EEPROM.commit();
		timer6 = millis();
	}
} // loop

///////////////////////////////////////

void pullCurrent()
{
	maxValue1 = 0;
	timer1 = millis();

	while (millis() - timer1 < 500)
	{
		reading0 = ( read_ADC(i2caddress, 0x00) >> 4 );
		delayMicroseconds(converDelay);

		if (reading0 > maxValue1)
		{
			maxValue1 = reading0;
		}
	}

	adjusted = maxValue1 - offset;

	volt1 = ((float)adjusted / 2048) * 2.048;

	current1 = volt1 * 30;
	// current2 = volt2 * 30;

	Blynk.virtualWrite(V0, current1);
	Blynk.virtualWrite(V30, maxValue1);
	Blynk.virtualWrite(V32, adjusted);


	timer2 = millis();
} // pullCurrent


/////////////////////////////////////////


void getOffset()
{
	write_register_ADC(i2caddress, offsetConfig);
	delay(10);

	offset = ( read_ADC(i2caddress, 0x00) >> 4 );

	Blynk.virtualWrite(V31, offset);
}


/////////////////////////////////////////



void getKwh()
{
	watts = current1 * userVoltage;
	currentKwh = watts / 1000;

	kwhCount++;
	hourKwhAccrue += currentKwh;
	kwhHourTotal = hourKwhAccrue / kwhCount;

	if (millis() - timer5 > 3600000)
	{
		runKwhTotal += kwhHourTotal;

		kwhCount = 0;
		kwhHourTotal = 0;
		hourKwhAccrue = 0;
		timer5 = millis();
		Blynk.virtualWrite(V6, runKwhTotal);
	}

	Blynk.virtualWrite(V5, kwhHourTotal);
} // getKwh

/////////////////////////////////////////


void maint()
{
	int myRssi = wifi_station_get_rssi();

	Blynk.virtualWrite(V10, myRssi);
}


/////////////////////////////////////////

void write_register_ADC(uint8_t address, uint16_t regis)
{
	Wire.beginTransmission(address);
	Wire.write(0x01);
	Wire.write((uint8_t)( regis >> 8 ));
	Wire.write((uint8_t)( regis & 0xFF ));
	Wire.endTransmission();
}

/////////////////////////////////////////


uint16_t read_ADC(uint8_t address, uint8_t reg1)
{
	Wire.beginTransmission(address);
	Wire.write(reg1);
	Wire.endTransmission();
	Wire.requestFrom(address, (uint8_t)2);
	return ( ( Wire.read() << 8 ) | Wire.read() );
}



/////////////////////////////////////////


BLYNK_CONNECTED()
{
  Blynk.syncAll();
}



BLYNK_APP_CONNECTED()
{
	appConnected = 1;
}

BLYNK_APP_DISCONNECTED()
{
	appConnected = 0;
}



BLYNK_WRITE(V20)
{
	byte restartChip = param.asInt();

	if (restartChip == 1)
	{
		ESP.restart();
	}
}


BLYNK_WRITE(V21)
{
	byte resetCounter = param.asInt();

	if (resetCounter)
	{
		runKwhTotal = 0.0;
		EEPROM.put(0, runKwhTotal);
		EEPROM.commit();
	}
}


BLYNK_WRITE(V22)
{
	byte resetOffset = param.asInt();

	if (resetOffset == 1)
	{
		getOffset();
	}
}


BLYNK_WRITE(V23)
{
	userVoltage = param.asInt();
}

Credits

Mitch K
10 projects • 34 followers
Maker, designer, & all around fun to be around!

Comments