leonel_flores
Published © GPL3+

PQduino

Add AC power monitoring to your Arduino projects in the safest way ever. Please support at www. kickstarter. com/projects/pqduino/pqduino

BeginnerWork in progress700
PQduino

Things used in this project

Hardware components

ESP8266 ESP-12E
Espressif ESP8266 ESP-12E
×1
HC-06 Bluetooth Module
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Custom parts and enclosures

PQduino Board

PQduino Classic

Schematics

Circuit diagram

Code

Main code

Arduino
#include <ESP8266WiFi.h>                         
#include <WebSocketsServer.h>                    
#include <ESP8266WebServer.h>                    
#include "ESP8266HTTPUpdateServer.h"
#include "ADE7753.h"
#include <SPI.h>
#include <Math.h>
#include "Main_Webpage.h"

#define SPI_Speed 1000000 //SPI Speed
#define CS_Pin D8         //GPIO15 SPI_Chip Select Pin
#define IRQPin D4         //IRQ Notify Pin on ESP8266

const char* ssid     = "XXXX";
const char* password = "XXXX";

ADE7753 myADE(CS_Pin);

const char* host = "my_powermeter";
const char* update_path = "/firmware";
const char* update_username = "admin";
const char* update_password = "admin";

signed long WAVE_VAL [128];
long voltaje_A=0;
long v_real=0;
String v_string="", v_comp="", v_int="", v_dec="";
long corriente_A=0;
long i_real=0;
String i_string="", i_comp="", i_int="", i_dec="";
byte temp_val=0;
long freq_val=0;
long freq_real=0;
String freq_string="", freq_comp="", freq_int="", freq_dec="";
String REG_DATA;
signed int activa=0, reactiva=0, aparente=0;
volatile byte wave_flag=false;
volatile int wave_counter=0;

unsigned long last;                             
int inputVal;                                    
float voltVal;                                   
float voltValPrev = 0 ;                           
String myString;                                 

String Voltage,Current,P_Power,S_Power,Q_Power,THDV,THDI,Temp,PF,WaveForm;


ESP8266WebServer server (80);
ESP8266HTTPUpdateServer httpUpdater;
WebSocketsServer webSocket = WebSocketsServer(81);

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {                                                                        
  switch(type) {                      
    case WStype_CONNECTED: {IPAddress ip = webSocket.remoteIP(num);webSocket.sendTXT(num,myString);}break;              
    case WStype_DISCONNECTED:break;                         
    case WStype_TEXT:break; 
    case WStype_ERROR:break; 
    }
}

void set_ScreenHead(){
  REG_DATA="";
  REG_DATA=REG_DATA+String(myADE.read16bits(MODE))+'-';
  REG_DATA=REG_DATA+String(myADE.read16bits(LINECYC))+'-';
  REG_DATA=REG_DATA+String(myADE.read8bits(GAIN))+'-';
  REG_DATA=REG_DATA+String(myADE.read16bits(IRQEN));
  Serial.println(REG_DATA);
}
void get_Voltage(){
  myADE.write16(MODE, 0x8C);                            //Cycle energy accumulation Mode
  set_ScreenHead();
  voltaje_A = myADE.getVRMS(10);
  v_real=voltaje_A*449/1000;
  v_comp= String(v_real);
  v_dec= v_comp.substring(v_comp.length()-3);
  v_int= v_comp;
  v_int.replace(v_dec,"");
  v_string=v_int + '.' + v_dec;
  delay(0);
}

void get_Current(){
  myADE.write16(MODE, 0x8C);                            //Cycle energy accumulation Mode 
  set_ScreenHead();
  corriente_A = myADE.getIRMS(10);
  i_real=corriente_A*449/1000;
  i_comp= String(i_real);
  i_dec= i_comp.substring(i_comp.length()-3);
  i_int= i_comp;
  i_int.replace(i_dec,"");
  i_string=i_int + '.' + i_dec;
  delay(0);
}

void get_Temp(){
  temp_val = myADE.read8bits(TEMP);
  temp_val=(temp_val-222)*3+25;                       //If Chip produce value of 222 at 25°C
  //------------------------------
  freq_val = myADE.read16bits(PERIOD);
  freq_real=freq_val;
  freq_comp= String(freq_real);
  freq_dec= freq_comp.substring(freq_comp.length()-3);
  freq_int= freq_comp;
  freq_int.replace(freq_dec,"");
  freq_string=freq_int + '.' + freq_dec + "Hz";
  delay(0);
}


void setup() {
  pinMode(IRQPin, INPUT_PULLUP);
  pinMode(CS_Pin, OUTPUT);
  myADE.Start(SPI_Speed,CS_Pin);
  digitalWrite (CS_Pin,LOW);
  delay(10);
  attachInterrupt(IRQPin,readWaveReg_I,FALLING);
  myADE.write16(MODE, 0x8C);      //Cycle energy accumulation Mode 
  myADE.write16(LINECYC, 0x78);   //120 half-cycles to power accumulation
  myADE.write8(GAIN, 0x00);       //0.5V max per chanel
  delay(10);
  
  Serial.begin(115200);
  Serial.println();

  WiFi.mode(WIFI_STA); //para que no inicie el SoftAP en el modo normal
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {delay(500); Serial.print(".");}
  delay(0);
  Serial.println("");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  
  webSocket.begin();
  webSocket.onEvent(webSocketEvent);
  server.on("/", []() {server.send_P(200, "text/html", main_webpage);});
  httpUpdater.setup(&server, update_path, update_username, update_password);
  server.begin();                                     
}

void loop() {
  webSocket.loop();
  server.handleClient();                             
  if ((millis()-last) > 500) {
    last = millis();                    
    get_Voltage();
    get_Current();
    if (wave_flag==false){
      WaveForm="";
      for(int a=0;a<128;a++){WaveForm=WaveForm+"$"+String(WAVE_VAL[a]*128/1950);}
      get_WAVE_V();
    }
    myString = String(v_string)+"#"+String(i_real)
               +"#"+String(activa)+"#"+String(reactiva)
               +"#"+String(aparente)+"#"+String(6*voltVal)
               +"#"+String(7*voltVal)+"#"+String(8*voltVal)
               +"#"+String(temp_val)+"#"+String(10*voltVal)
               +"#"+String(11*voltVal)+"#"+String(12*voltVal)
               +"#"+String(13*voltVal)+"#"+String(14*voltVal)
               +"#"+String(15*voltVal)+"#"+String(freq_real)+"#"+String(REG_DATA)+"#"+WaveForm;
    webSocket.broadcastTXT(myString);  
    Serial.println(myString);                                           
  }
}

ADE7753 Library

Arduino
#include "Arduino.h"
#include <SPI.h>
#include "ADE7753.h"
#include <math.h>
#define ISP_DELAY 4       //This time is needed between SPI sent bytes, at least 4μs

ADE7753::ADE7753(int _CS){
	CS = _CS;
}

void ADE7753::Start(uint32_t SPI_speed , uint8_t chipSelect_Pin){
  pinMode(CS,OUTPUT);
  digitalWrite (CS,HIGH);
  SPI.begin();
  SPI.beginTransaction(SPISettings(SPI_speed,MSBFIRST,SPI_MODE2));
  delay(10);
}
long ADE7753::getInterruptStatus(){
    return read16bits(STATUS);
}
long ADE7753::getResetInterruptStatus(){
    return read16bits(RSTSTATUS);
}
unsigned char ADE7753::read8bits(char reg){
	//enable();
    unsigned char b0;
	delayMicroseconds(ISP_DELAY);
	SPI.transfer(reg);
	delayMicroseconds(ISP_DELAY);
	b0=SPI.transfer(0x00);
	delayMicroseconds(ISP_DELAY);
    //disable();
	return b0;
}

unsigned int ADE7753::read16bits(char reg){
    //enable();
    unsigned char b1,b0;
    delayMicroseconds(ISP_DELAY);
    SPI.transfer(reg);
    delayMicroseconds(ISP_DELAY);
    b1=SPI.transfer(0x00);
    delayMicroseconds(ISP_DELAY);
    b0=SPI.transfer(0x00);
    delayMicroseconds(ISP_DELAY);
    //disable();
    return (unsigned int)b1<<8 | (unsigned int)b0;
}
unsigned long ADE7753::read24bits(char reg){
    //enable();
    unsigned char b2,b1,b0;
    delayMicroseconds(ISP_DELAY);
    SPI.transfer(reg);
    delayMicroseconds(ISP_DELAY);
    b2=SPI.transfer(0x00);
    delayMicroseconds(ISP_DELAY);
    b1=SPI.transfer(0x00);
    delayMicroseconds(ISP_DELAY);
    b0=SPI.transfer(0x00);
    delayMicroseconds(ISP_DELAY);
    return (unsigned long)b2<<16 | (unsigned long)b1<<8 | (unsigned long)b0;
}
long ADE7753::getVRMS(){
    unsigned long VRMS_VAL = 0;
    long lastupdate = 0;
        getResetInterruptStatus(); //clear interrupts
        lastupdate = millis();
        while(!(getInterruptStatus() & (ZX))){ 
            if((millis()-lastupdate)>100){
              return -1; //return on Timeout
            }
        }
        VRMS_VAL += read24bits(VRMS); 
}

ADE7753 Library

Arduino
#include "Arduino.h"
#ifndef ADE7753_h
#define ADE7753_h   

#define WRITE 0x80 //0x80 = b10000000 voor te schrijven moet BT7 1 zijn

#define MODE          0x09  //16B R/W U
#define LINECYC       0x1C  //16B R/W U
#define GAIN          0x0F  //08B R/W U
#define IRQEN         0x0A  //16B R/W U
#define STATUS        0x0B  //16B R   U
#define RSTSTATUS     0x0C  //16B R   U

#define WAVEFORM      0x01  //24B R   S
#define IRMS          0x16  //24B R   U
#define VRMS          0x17  //24B R   U
#define TEMP          0x26  //08B R   U
#define PERIOD        0x27  //16B R   U

#define LAENERGY      0x04  //24B R   U

//-----------CONSTANTS-----------------
#define ZX            0x10  //Indicates ZX event in STATUS REG
#define WSMP          0x08  //Indicates WAVEFORM event in STATUS REG


class ADE7753{
  public:
    ADE7753(int _CS);
    void Start(uint32_t SPI_speed , uint8_t chipSelect_Pin);
    long getVRMS();
    long getInterruptStatus();
    long getResetInterruptStatus();
    
    //Later in private te plaatsen
    unsigned char read8bits(char reg);
    unsigned int read16bits(char reg);
    unsigned long read24bits(char reg);
    
    //write methodes, later ook in private plaatsen
    void write8(char reg, unsigned char data);
    void write16(char reg, unsigned int data);
    void write24(char reg, unsigned long data);
	
  private:
    int CS;

    void enable();
    void disable();
    void calibrateOffset(char phase);
    
    
};
#endif

Credits

leonel_flores
1 project • 1 follower

Comments