Будьте любезны.
Этот алгоритм берёт 13 значений, а потом вычисляет все параметры и так в цикле n-ное количество раз. Судя по всему, это не совсем правильно. Видимо, нужно брать 1 значение n-ное количество раз, вычислять параметры, а затем переходить ко второму значению (каналу).
Переписать этот алгоритм не так сложно. Как будет свободное время я его переделаю. Но и в данном виде он вполне приемлемо работает. Единственный момент — если работает реактивная нагрузка показания мощности могут убегать примерно до 40%.
А вообще тут нужна светлая голова, чтобы не гадать и экспериментировать, а просто взять и сделать как надо.
Код: Выделить всё
#include <SPI.h>
#include <Ethernet.h>
#include <DallasTemperature.h>
#include <OneWire.h>
//-----------------------------------------------------------------------------------------//
//---------------------------------- CONST's and VAR's ----------------------------------//
//-----------------------------------------------------------------------------------------//
//---------------------- Ethernet
byte mac[] = {0x00,0x2A,0xF5,0x12,0x67,0xDA}; // MAC-адрес (!)
byte ip[] = {192,168,1,15}; // ip-адрес Arduino (!)
byte rserver[] = {192,168,1,47}; // ip-адрес MajorDoMo
//---------------------- Server
#define MAX_COMMAND_LEN (10)
String url = String(25);
int maxLength=25;
char gCommandBuffer[MAX_COMMAND_LEN + 1];
//---------------------- Pin's
int keyPin = 3;//pin 5 [PWM]
#define ONE_WIRE_BUS 2
//---------------------- U, I & P
const int MAX_UI_SENSORS = 14;
const int START_I_SENSOR = 1;
const int UI_REFRESH_MIN = 1;
int samples = 400;
// 1 2 3 4 5 1 2 3 4 5 6 7 8
int pinsUI[] = {0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15};
// Коэффициенты для калибровки выводимых значений
double VCAL = 46.00;
// 1 2 3 4 5 1 2 3 4 5 6 7 8
double ICAL[] = {0, 1.35, 1.28, 0.73, 0.73, 1.28, 0.72 , 0.73, 0.73, 0.73, 0.73, 0.73, 0.73, 0.73};
double PHASECAL = 2.3; // для мощности
double UI_RATIO[MAX_UI_SENSORS];
// Образцы переменных
int sampleUI[MAX_UI_SENSORS];
int oldSampleUI[MAX_UI_SENSORS];
// Переменные для фильтров
double filteredUI[MAX_UI_SENSORS];
double oldFilteredUI[MAX_UI_SENSORS];
// Калибровочное значение фазы мгновенного напряжения
double shiftedU;
// Расчет переменной для мощности
double sqUI[MAX_UI_SENSORS];
double sumUI[MAX_UI_SENSORS];
double instP[MAX_UI_SENSORS];
double sumP[MAX_UI_SENSORS];
// Полезные значения переменных
double UIrms[MAX_UI_SENSORS];
double power[MAX_UI_SENSORS];
double sumPWR[MAX_UI_SENSORS];
int iPWR[MAX_UI_SENSORS];
double dPWR[MAX_UI_SENSORS];
double sumUIrms[MAX_UI_SENSORS];
int iUIrms[MAX_UI_SENSORS];
double dUIrms[MAX_UI_SENSORS];
int tmpUIrms[MAX_UI_SENSORS];
int tmpPwr[MAX_UI_SENSORS];
int stt0 = 1; int stp0 = 14;
int stt1 = 1; int stp1 = 6;
char buf[200];
String sss = "";
//---------------------- Timers 20, 30, 40 sec., 1, 3, 5 minutes
unsigned long timeSec; //time in seconds
unsigned long timeSec20s; boolean cycle20s = false; //cycle 20 sec.
unsigned long timeSec30s; boolean cycle30s = false; //cycle 30 sec.
unsigned long timeSec40s; boolean cycle40s = false; //cycle 40 sec.
unsigned long timeSec01m; boolean cycle01m = false; //cycle 1 minute
unsigned long timeSec03m; boolean cycle03m = false; //cycle 3 minutes
unsigned long timeSec05m; boolean cycle05m = false; //cycle 5 minutes
int startSendTime = 10;
//---------------------- Time (virtual RTC)
boolean timeIsSet = false;
unsigned long now = 0;
unsigned long base = 0;
unsigned long delta = 0;
unsigned long hour_base = 0;
unsigned long minute_base = 0;
unsigned long second_base = 0;
unsigned long hour = 0;
unsigned long minute = 0;
unsigned long second = 0;
unsigned long timeCorSec = 0;
unsigned long fromMidnight = 0;
//---------------------- Prof
unsigned long cycle_start = 0;
unsigned long cycle_end = 0;
unsigned long cycle_delta = 0;
//---------------------- Objects
EthernetClient rclient;
//---------------------- Server
EthernetServer server(80);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//++++++++++++++++++++++++++++++++++++++ FUNCTIONS ++++++++++++++++++++++++++++++++++++++//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//----------------------------------------------- Functions requests
//---------------------- Request MajorDomo
void sendHTTPRequest() {
if (rclient.connect(rserver, 80)) {
Serial.println(buf);
rclient.println(buf);
rclient.println("Host: 192.168.1.81");
rclient.println();
delay(100); // 500!!!
rclient.stop();
} else {
Serial.println("not connected");
}
} //end sendHTTPRequest
//----------------------------------------------- Other
//---------------------- comMess
void comMessAB(String s1, String s2) {
Serial.print(s1);
Serial.println(s2);
} //end comMess
//---------------------- Set Requests
void setReqSens01(char s[], int ne) {
sprintf(buf, "GET /objects/?object=%s&op=m&m=update&v=%d", s, ne);
sendHTTPRequest();
} //end setReqSens01
void setReqSens05(char s[], char s2[], int ne) {
sprintf(buf, "GET /objects/?object=%s&op=m&m=update&%s=%d", s, s2, ne);
sendHTTPRequest();
} //end setReqSens01
void setReqSensor(char s[], int n, int nn) {
sprintf(buf, "GET /objects/?object=%s&op=m&m=update&v=%0d.%d HTTP/1.0", s, n, nn);
sendHTTPRequest();
}
void setReqSensor_(char s[], char s2[], char s3[], int n, int nn) {
if(nn<10){
sprintf(buf, "GET /objects/?object=%s&op=m&m=update&v=%0d.%s%d HTTP/1.0", s, n, s2, nn);
}else{
sprintf(buf, "GET /objects/?object=%s&op=m&m=update&v=%0d.%s%d HTTP/1.0", s, n, s3, nn);
}
sendHTTPRequest();
}
void setReqSensorF(char s[], float n) {
sprintf(buf, "GET /objects/?object=%s&op=m&m=update&v=%F HTTP/1.0", s, n);
sendHTTPRequest();
}
void setReqSensor2(char s[], char ss[], int n, int nn) {
sprintf(buf, "GET /objects/?object=%s&op=m&m=update&v=%s%0d.%d HTTP/1.0", s, ss, n, nn);
sendHTTPRequest();
} //end setReqSensor2
//=========================================================================================//
//======================================== SETUP ========================================//
//=========================================================================================//
void setup() {
//---------------------- U, I, P
UI_RATIO[0] = 50.5 / 1024 * VCAL;
UI_RATIO[1] = (long double)15.15 * 5 / 1024 * ICAL[1];
UI_RATIO[2] = (long double)15.15 * 5 / 1024 * ICAL[2];
UI_RATIO[3] = (long double)15.15 * 5 / 1024 * ICAL[3];
UI_RATIO[4] = (long double)15.15 * 5 / 1024 * ICAL[4];
UI_RATIO[5] = (long double)15.15 * 5 / 1024 * ICAL[5];
UI_RATIO[6] = (long double)15.15 * 5 / 1024 * ICAL[6];
UI_RATIO[7] = (long double)15.15 * 5 / 1024 * ICAL[7];
UI_RATIO[8] = (long double)15.15 * 5 / 1024 * ICAL[8];
UI_RATIO[9] = (long double)15.15 * 5 / 1024 * ICAL[9];
UI_RATIO[10] = (long double)15.15 * 5 / 1024 * ICAL[10];
UI_RATIO[11] = (long double)15.15 * 5 / 1024 * ICAL[11];
UI_RATIO[12] = (long double)15.15 * 5 / 1024 * ICAL[12];
UI_RATIO[13] = (long double)15.15 * 5 / 1024 * ICAL[13];
//---------------------- Timers
timeSec = millis() / 1000;
timeSec20s = millis() / 1000;
timeSec30s = millis() / 1000;
timeSec40s = millis() / 1000;
timeSec01m = millis() / 1000;
timeSec03m = millis() / 1000;
timeSec05m = millis() / 1000;
now = millis() / 1000;
//---------------------- Others
Serial.begin(9600);
Ethernet.begin(mac, ip);
//---------------------- Server
server.begin();
//---------------------- Delay
delay(1000);
//---------------------- MajorDoMo
Serial.println("Connection to MajorDoMo...");
if (rclient.connect(rserver, 80)) {
Serial.println("Connected to MajorDoMo :)");
//rclient.println("GET /search?q=arduino HTTP/1.0");
rclient.println();
} else {
Serial.println("Connect to MajorDoMo failed");
//Serial.println(" ");
}
delay(1000);
rclient.stop();
} //end setup
//======================================== loop =========================================
void loop() {
//---------------------- Time (virtual RTC)
now = millis() / 1000;
cycle_start = now;
delta = now - base;
fromMidnight = timeCorSec + delta;
hour = fromMidnight / 3600;
minute = (fromMidnight - hour*3600) / 60;
second = fromMidnight % 60;
if (fromMidnight >= 86400) {
base = millis() / 1000;
hour_base = 0;
minute_base = 0;
second_base = 0;
timeCorSec = 0;
fromMidnight = 0;
}
Serial.print("-- ");
serialPrintTime();
//---------------------- Timers
timeSec = millis() / 1000;
if (timeSec - timeSec20s > 19) { //20 sec
timeSec20s = timeSec;
cycle20s = true;
}
if (timeSec - timeSec30s > 29) { //30 sec
timeSec30s = timeSec;
cycle30s = true;
}
if (timeSec - timeSec40s > 3) { //40 sec
timeSec40s = timeSec;
cycle40s = true;
}
if (timeSec - timeSec01m > 59) { //1 minute
timeSec01m = timeSec;
cycle01m = true;
}
if (timeSec - timeSec03m > 179) { //3 minutes
timeSec03m = timeSec;
cycle03m = true;
}
if (timeSec - timeSec05m > 299) { //5 minutes
timeSec05m = timeSec;
cycle05m = true;
}
//---------------------- Server
// if an incoming client connects, there will be bytes available to read
EthernetClient client = server.available();
if (client == true) {
Serial.println("");
boolean current_line_is_blank = true;
while (client.connected()) { // Пока клиент подключен
if (client.available()) { // Если от него пришел символ
char c = client.read(); // Читаем этот символ
if (url.length() < maxLength) {
url += (c);
}
Serial.print(c);
// Если получен перевод строки ('\n') и current_line_is_blank == true,
// значит мы получили пустую строку, т.е. запрос клиента окончен – можно слать ответ
if (c == '\n' && current_line_is_blank) {
if (url.indexOf("?") >= 0) {
String commandReceived;
String parametersReceived;
int PosB = url.indexOf("?") + 1;
int PosE = url.indexOf("HTTP");
if (url.indexOf("=") >= 0) { // Команда с параметром
int PosP = url.indexOf("=");
commandReceived = url.substring(PosB, PosP);
parametersReceived = url.substring(PosP + 1, PosE - 1);
} else { // Команда без параметров
commandReceived = url.substring(PosB, PosE - 1);
parametersReceived = "";
}
Serial.println("command: ");
Serial.println(commandReceived);
Serial.println("parameter: ");
Serial.println(parametersReceived);
//---------------------- Time correction
if (commandReceived.indexOf("hour") >= 0){
hour_base = parametersReceived.toInt();
base = millis() / 1000;
timeIsSet = true;
}
if (commandReceived.indexOf("minute") >= 0){
minute_base = parametersReceived.toInt();
base = millis() / 1000;
timeIsSet = true;
}
if (commandReceived.indexOf("second") >= 0){
second_base = parametersReceived.toInt();
base = millis() / 1000;
timeIsSet = true;
}
timeCorSec = hour_base*3600 + minute_base*60 + second_base;
//---------------------- /Time correction
url = "";
} else {
// Команды нет, показываем help
}
// Шлем стандартный HTTP заголовок
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println(); // Он тоже заканчивается пустой строкой!
// Выдаем поочередно значения 6 аналоговых входов
client.print("mega01 (Main)");
client.print(" - OK");
client.println("<br>");
client.println("<br>");
client.print("Time: ");
if (hour < 10) {client.print("0");}
client.print(hour);
client.print(":");
if (minute < 10) {client.print("0");}
client.print(minute);
client.print(":");
if (second < 10) {client.print("0");}
client.println(second);
client.println("<br>");
client.println("<br>");
client.print("goLight: ");
client.println("<br>");
client.print("MODE: ");
client.println("<br>");
/*
for (int i = 0; i < 15; i++) {
client.print("analog input ");
client.print(i);
client.print(" is ");
client.print(analogRead(i));
client.println("<br>");
}
*/
break; // Работа окончена – можно выходить из цикла while
} // end if (c == '\n' && current_line_is_blank)
if (c == '\n') { // Если получен перевод строки, значит началась новая строка
current_line_is_blank = true; // Выставим флаг current_line_is_blank = true
} else if (c != '\r') { // Если получен любой другой символ, отличный от возврата каретки ('\r'), значит получаемая строка непустая
current_line_is_blank = false;
}
} //end if (client.available())
} // end while (client.connected())
delay(1); //небольшая пауза, чтобы данные успели уйти
client.stop(); //разрываем соединение с клиентом
} //end if (client == true)
//***************************************************//
//******************** Electro ********************//
//***************************************************//
if (cycle20s || (timeSec < startSendTime)) {
getUIP("packPowerMega01", stt0, stp0, samples);
} // cycle20s
//***************************************************//
//**************** MajorDoMo tests *****************//
//***************************************************//
//---------------------- MajorDoMo
if (cycle01m) {
setReqSens01("ncMega01", 1);
}
//***************************************************//
//***************** End of cycle ******************//
//***************************************************//
//---------------------- End cycle
cycle20s = false;
cycle30s = false;
cycle40s = false;
cycle01m = false;
cycle03m = false;
cycle05m = false;
cycle_end = millis() / 1000;
cycle_delta = cycle_end - cycle_start;
if (cycle_delta > 0) {
Serial.print("-->");
Serial.print(cycle_delta);
Serial.println("s");
} else {
Serial.println("-->");
}
delay(500);
} //end loop
//---------------------- Function
void calcSumV() {
} // end of calcIrms()
//---------------------- time
void serialPrintTime() {
//Serial.print("Time: ");
if (hour < 10) {Serial.print("0");}
Serial.print(hour);
Serial.print(":");
if (minute < 10) {Serial.print("0");}
Serial.print(minute);
Serial.print(":");
if (second < 10) {Serial.print("0");}
Serial.println(second);
} // end of serialPrintTime()
//---------------------- send values to MajorDoMo
void getUIP(char obj[], int STT, int STP, int count) {
int prof1 = millis();
for (int i = 0; i < count; i++) {
oldSampleUI[0] = sampleUI[0];
for (int n = STT; n < STP; n++) {
oldSampleUI[n] = sampleUI[n];
}
sampleUI[0] = analogRead(pinsUI[0]);
for (int n = STT; n < STP; n++) {
sampleUI[n] = analogRead(pinsUI[n]);
}
oldFilteredUI[0] = filteredUI[0];
filteredUI[0] = 0.996 * (oldFilteredUI[0] + sampleUI[0] - oldSampleUI[0]);
for (int n = STT; n < STP; n++) {
oldFilteredUI[n] = filteredUI[n];
filteredUI[n] = 0.996 * (oldFilteredUI[n] + sampleUI[n] - oldSampleUI[n]); // Цифровой фильтр для удаления постоянного смещения 2,5В
}
shiftedU = oldFilteredUI[0] + PHASECAL * (filteredUI[0] - oldFilteredUI[0]); // Калибруем фазу
// Среднеквадратический метод расчета
sqUI[0] = filteredUI[0] * filteredUI[0]; // 1) square current values
sumUI[0] += sqUI[0]; // 2) Суммируем
for (int n = STT; n < STP; n++) {
sqUI[n] = filteredUI[n] * filteredUI[n]; // 1) square current values
sumUI[n] += sqUI[n]; // 2) Суммируем
}
for (int n = STT; n < STP; n++) {
instP[n] = shiftedU * filteredUI[n]; // Мгновенная мощность
sumP[n] += instP[n]; // Суммируем
}
} // end for (int i = 0; i < count; i++)
UIrms[0] = UI_RATIO[0] * sqrt(sumUI[0] / count);
for (int n = STT; n < STP; n++) {
UIrms[n] = UI_RATIO[n] * sqrt(sumUI[n] / count); // Расчет корня из среднего напряжения и тока (rms)
}
if (UIrms[0] < 0.1) { // Коррекция малых искажений
UIrms[0] = 0.0;
}
for (int n = STT; n < STP; n++) {
if (UIrms[n] < 0.1) { // Коррекция малых искажений
UIrms[n] = 0.0;
}
}
for (int n = STT; n < STP; n++) {
power[n] = UIrms[0] * UIrms[n]; // Расчет величины мощности
}
sumUI[0] = 0; // Сброс накопленных значений
sumP[0] = 0;
for (int n = STT; n < STP; n++) {
sumUI[n] = 0; // Сброс накопленных значений
sumP[n] = 0;
}
int prof2 = millis();
int prof00 = prof2 - prof1;
Serial.print(">>>");
Serial.println(prof00);
//---------------------- Выдача результатов
if (UIrms[0] < 400) {
iUIrms[0]++;
sumUIrms[0] = sumUIrms[0] + UIrms[0];
dUIrms[0] = sumUIrms[0] / iUIrms[0];
iPWR[0]++;
sumPWR[0] = sumPWR[0] + power[0];
dPWR[0] = sumPWR[0] / iPWR[0];
for (int n = STT; n < STP; n++) {
iUIrms[n]++;
sumUIrms[n] = sumUIrms[n] + UIrms[n];
dUIrms[n] = sumUIrms[n] / iUIrms[n];
iPWR[n]++;
sumPWR[n] = sumPWR[n] + power[n];
dPWR[n] = sumPWR[n] / iPWR[n];
}
if (iUIrms[0] == UI_REFRESH_MIN) {
tmpUIrms[0] = (dUIrms[0] - (int)dUIrms[0]) * 100;
tmpPwr[0] = (dPWR[0] - (int)dPWR[0]) * 100;
for (int n = STT; n < STP; n++) {
tmpUIrms[n] = (dUIrms[n] - (int)dUIrms[n]) * 100;
tmpPwr[n] = (dPWR[n] - (int)dPWR[n]) * 100;
}
/*
sprintf(buf, "GET /objects/?object=%s&op=m&m=update&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d HTTP/1.0",
"pack01", "u", (int)dUIrms[0], abs(tmpUIrms[0]),
"i1", (int)dUIrms[1], abs(tmpUIrms[1]), "i2", (int)dUIrms[2], abs(tmpUIrms[2]), "i3", (int)dUIrms[3], abs(tmpUIrms[3]),
"i4", (int)dUIrms[4], abs(tmpUIrms[4]), "i5", (int)dUIrms[5], abs(tmpUIrms[5]), "i6", (int)dUIrms[6], abs(tmpUIrms[6]),
"i7", (int)dUIrms[7], abs(tmpUIrms[7]), "i8", (int)dUIrms[8], abs(tmpUIrms[8]), "i9", (int)dUIrms[9], abs(tmpUIrms[9]),
"i10", (int)dUIrms[10], abs(tmpUIrms[10]), "i11", (int)dUIrms[11], abs(tmpUIrms[11]),
"i12", (int)dUIrms[12], abs(tmpUIrms[12]), "i13", (int)dUIrms[13], abs(tmpUIrms[13]));
sendHTTPRequest();
*/
if (STT == stt0 && STP == stp0) {
sprintf(buf, "GET /objects/?object=%s&op=m&m=update&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d HTTP/1.0",
obj, "u", (int)dUIrms[0], abs(tmpUIrms[0]),
"p1", (int)dPWR[1], abs(tmpPwr[1]), "p2", (int)dPWR[2], abs(tmpPwr[2]), "p3", (int)dPWR[3], abs(tmpPwr[3]),
"p4", (int)dPWR[4], abs(tmpPwr[4]), "p5", (int)dPWR[5], abs(tmpPwr[5]), "p6", (int)dPWR[6], abs(tmpPwr[6]),
"p7", (int)dPWR[7], abs(tmpPwr[7]), "p8", (int)dPWR[8], abs(tmpPwr[8]), "p9", (int)dPWR[9], abs(tmpPwr[9]),
"p10", (int)dPWR[10], abs(tmpPwr[10]), "p11", (int)dPWR[11], abs(tmpPwr[11]),
"p12", (int)dPWR[12], abs(tmpPwr[12]), "p13", (int)dPWR[13], abs(tmpPwr[13]));
sendHTTPRequest();
}
/*
if (STT == stt1 && STP == stp1) {
sprintf(buf, "GET /objects/?object=%s&op=m&m=update&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d&%s=%0d.%d HTTP/1.0",
obj, "u", (int)dUIrms[0], abs(tmpUIrms[0]),
"p1", (int)dPWR[1], abs(tmpPwr[1]), "p2", (int)dPWR[2], abs(tmpPwr[2]),
"p3", (int)dPWR[3], abs(tmpPwr[3]), "p4", (int)dPWR[4], abs(tmpPwr[4]),
"p5", (int)dPWR[5], abs(tmpPwr[5]));
sendHTTPRequest();
}
*/
iUIrms[0] = 0;
sumUIrms[0] = 0;
dUIrms[0] = 0;
iPWR[0] = 0;
sumPWR[0] = 0;
dPWR[0] = 0;
for (int n = STT; n < STP; n++) {
iUIrms[n] = 0;
sumUIrms[n] = 0;
dUIrms[n] = 0;
iPWR[n] = 0;
sumPWR[n] = 0;
dPWR[n] = 0;
}
} // end of (iUIrms[0] == UI_REFRESH_MIN)
} // end of (UIrms[0] < 400)
} // end of getUIP()