//Inclusão de bibliotecas
#include
#include
#include
// Definições de rede
byte mac[] = { 0xDE, 0xEE, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 11);
IPAddress server(192, 168, 1, 68);
//Variaveis
int samples = 1500; //número de amostras
int inU = A0;//Portas de entrada tensão e corrente
int inI0 = A4;
double UCAL = 0.9;
double ICAL = 0.29;
double calibFase = 0.1;
int lastU,lastI,sampleU,sampleI;
double lastFilterU, lastFilterI, filterU, filterI = 0;
double filterTemp;
double calibU;
double sqrtI,sqrtU,instP,sumI,sumV,sumP;
double activPower,apparentPower,powerFactor,Vrms,Irms;
unsigned long postingInterval = 6000; //Intervalo de envios
unsigned long lastRequest = 0;
long now = 0;
int restart = 0;
unsigned long endTime, startTime, timeLastMeasure;
unsigned long startUpTime;
double energyTotal =0.0;
unsigned long LastZero;
unsigned long periodU;
unsigned long periodUSum;
unsigned long periodUCount;
float freq;
unsigned long sinPeriod = 20000;
unsigned long filterWidth = 2000;
//recebe as mensagens vindas do topico mqtt subscrito
//atualiza as constantes de calibração, tempo e estado
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
char msgBuffer[100];
for (int i=0;i
msgBuffer[i] = payload[i];
Serial.print((char)payload[i]);
}
String msg = String(msgBuffer);
Serial.println();
if(msg.startsWith("sendTime")){
postingInterval = msg.substring(8).toFloat();
Serial.println(postingInterval);
}else if(msg.startsWith("VConstant")){
UCAL = msg.substring(9).toFloat();
}else if(msg.startsWith("IConstant")){
ICAL = msg.substring(9).toFloat();
}else if(msg.startsWith("setToday")){
energyTotal = msg.substring(8).toFloat();
}else if(msg.equals("newDay")){
energyTotal = 0;
}else if(msg.startsWith("device")){
digitalWrite(msg.substring(6,7).toInt()+5,msg.substring(7,8).toInt());
}
}
EthernetClient ethClient;
PubSubClient client(ethClient);
//reinicia o programa
void software_Reset()
{
asm volatile (" jmp 0");
}
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("arduinoClient")) {
Serial.println("connected");
client.subscribe("sisge/control");
String getSettings = "getSettings";
char getSettingsArray[getSettings.length()];
getSettings.toCharArray(getSettingsArray, getSettings.length()+1);
client.publish("sisge/settings", getSettingsArray);
restart = 0;
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
restart++;
if(restart>=12){
software_Reset();
}
delay(1000);
}
}
}
int Energy()
{
for (int n=0; n
{
//guarda ultimas amostras
lastU=sampleU;
lastI=sampleI;
//Recolhe amostras
sampleU = analogRead(inU);
sampleI = analogRead(inI0);
//guarda ultimos valores filtrados
lastFilterU = filterU;
lastFilterI = filterI;
//Aplicação do filtro digital.
filterU = 0.996 * (lastFilterU+sampleU-lastU);
filterI = 0.996 * (lastFilterI+sampleI-lastI);
//Calibração de fase
calibU = lastFilterU + calibFase * (filterU - lastFilterU);
//Tensão RMS
sqrtU= calibU * calibU;
sumV += sqrtU;
//Corrente RMS
sqrtI = filterI * filterI;
sumI += sqrtI;
//Potência instantanea
instP = abs(calibU * filterI);
sumP += instP;
//Frequência
if (n==0) LastZero = micros();
//Verifica se está a passar por zero
if (lastFilterU < 0 && filterU >= 0 && n>1)
{
//Periodo da onda da tensão
periodU = micros() - LastZero;
//Filtra leituras erradas
if (periodU > (sinPeriod-filterWidth) && periodU<(sinPeriod+filterWidth))
{
periodUSum += periodU;
periodUCount++;
}
LastZero = micros();
}
}
//Cálculo dos valores aproximados
Vrms = UCAL*sqrt(sumV / samples);
Irms = ICAL*sqrt(sumI / samples);
//Potência
activPower = UCAL*ICAL*sumP / samples;
apparentPower = Vrms * Irms;
if(apparentPower>activPower){
powerFactor = activPower / apparentPower;
}else{
powerFactor=1;
}
//Frequência
freq = (1000000.0 * periodUCount) / periodUSum;
periodUSum=0;
periodUCount=0;
//Calcula o tempo desde a ultima medição
endTime = startTime;
startTime = millis();
timeLastMeasure = startTime - endTime;
//Calcula a energia consumida no intervalo e adiciona à soma dos kWh
energyTotal = energyTotal + ((activPower/1000.0) * 1.0/3600.0 * (timeLastMeasure/1000.0));
Serial.print("RP=");
Serial.print(activPower);
Serial.print(" AP=");
Serial.print(apparentPower);
Serial.print(" PF=");
Serial.print(powerFactor);
Serial.print(" V=");
Serial.print(Vrms);
Serial.print(" I=");
Serial.print(Irms);
Serial.print(" KW=");
Serial.print(energyTotal );
Serial.print(" F=");
Serial.println(freq);
//envia mensagem
if (now - lastRequest >= postingInterval) {
if(freq){freq=50;}
String energyStr = "Ard001;Monitor1;"+String(Vrms)+";"+(String)Irms+";"+(String)activPower+";"+(String)apparentPower+";"+(String)powerFactor+";"+(String)energyTotal +";"+(String)freq;
int energyStrLength = energyStr.length();
char energyArray[energyStrLength];
energyStr.toCharArray(energyArray, energyStrLength);
client.publish("sisge/energy", energyArray);
Serial.println("Message sent");
lastRequest = now;
}
sumV = 0;
sumI = 0;
sumP = 0;
}
void setup()
{
//inicia os resgitos relativos à porta Serie de debug,
//cliente mqtt, ethernet, e define quais os pinos de saída para os atuadores
Serial.begin(9600);
//Define a referência do ADC para 2,56V
analogReference(INTERNAL2V56);
client.setServer(server, 1883);
client.setCallback(callback);
Ethernet.begin(mac, ip);
startTime = millis();
startUpTime=startTime;
lastRequest = millis();
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
digitalWrite(6,0);
digitalWrite(7,0);
digitalWrite(8,0);
digitalWrite(9,0);
}
void loop()
{
now = millis();
if (!client.connected()) {
reconnect();
}
client.loop();
Energy();
delay(100);
}
}}
|