POWER MONITOR на Arduino

Подключение исполнительных устройств, датчиков, контроллеров.

Модератор: immortal

Alex
Сообщения: 2357
Зарегистрирован: Пт апр 20, 2012 12:53 pm
Благодарил (а): 42 раза
Поблагодарили: 262 раза

Re: POWER MONITOR на Arduino

Сообщение Alex » Пт апр 26, 2013 4:35 pm

Спасибо, интересные ссылки. Если хорошенько разобраться, то можно профессором ТОЭ стать. :)
Могу ошибаться, но как я понял: Количество семплов подбирается так, что бы уместить как можно больше точек измерения за один период синусоиды, чем их больше, тем меньше погрешность измерения реально потребляемой мощности. Необходимо это для измерения угла сдвига фаз реактивной нагрузки. У OEM (open energy monitor) количество семплов равно 1480 и количество точек на период у них 50.
Теоретически это понятно. Хотелось бы чтобы кто-нибудь пояснил сколько нужно в нашем случае. Дело в том, что на практике показания с 3000 и 400 отсчётами практически совпадают, но 3000 по времени не лезут ни в какие ворота, а с 400 всё ок по времени. В чём подвох?
Кстати у вас цикл как построен? Возможно стоит измерять мощность каждого датчика с математикой по очереди. Сначала первый, потом - второй и т.д.
А в чём смысл? Почему по очереди? У меня берутся все значения максимально быстро и практически в одной временной точке, а потом вычисляется один отсчёт, затем идёт второй отсчёт — берутся все 14 значений и вычисляются и т.д.

Можно 13 раз запустить одиночный расчёт. Но чем это будет лучше? Чем хуже я могу сказать. Если значения взяты в одной временной точке, то их сумма должна отражать суммарную мгновенную мощность, а если значения взяты в разных временных точках, то их сумма уже не будет отражать суммарную (общую) мгновенную мощность.

У меня тут возникли сомнения вот какого рода. Я беру напряжение в одной физической точке (на шине в электрощите) и множу его на токи в других разных физических точках (на линиях). Раньше мне это казалось правильным. Или для корректного вычисления мощности я должен брать и напряжение и ток в одной физической точке? И при этом вычислять мощность отдельной линии в отдельном цикле? Но это несерьёзно по затратам. Например, сейчас я обхожусь одним трансформатором для напряжения, а в этом случае мне нужно будет 13 трансформаторов, 13 схем, 13 лишних ног на контроллере... Это не серьёзно! (с)

В защиту моей теперешней схемы могу сказать, что все значения верные и ведут себя предсказуемо. Единственный косяк — несовпадение суммы мощностей на линиях и мощности на общем вводе на ±0..15%.
Alex
Сообщения: 2357
Зарегистрирован: Пт апр 20, 2012 12:53 pm
Благодарил (а): 42 раза
Поблагодарили: 262 раза

Re: POWER MONITOR на Arduino

Сообщение Alex » Пт апр 26, 2013 4:53 pm

Количество семплов подбирается так, что бы уместить как можно больше точек измерения за один период синусоиды, чем их больше, тем меньше погрешность измерения реально потребляемой мощности
До меня дошёл смысл фразы. Если это так, то действительно лучше вычислять линии по отдельности. Но это точно так?

И, если это так, то почему у меня значения верные (± 1 % по тестовому амперметру в диапазоне 0..10А) при вычислении всех линий скопом?
P43YM
Сообщения: 13
Зарегистрирован: Вт мар 05, 2013 7:50 am
Благодарил (а): 0
Поблагодарили: 2 раза

Re: POWER MONITOR на Arduino

Сообщение P43YM » Пт апр 26, 2013 5:04 pm

Alex писал(а):Но это точно так?
Да.
Хотя я, честно сказать, уже сам немного запутался, слишком много информации на сегодня. Но советую вам просмотреть форумы и сайт OEM . И кстати еще одна версия есть в нелинейности показаний датчика тока, которые достигают у SCT-013-000 3%, и следовательно замеряя тринадцатью датчиками малые токи мы получаем некоторую погрешность в N% на каждом из них и в итоге , при подсчете общей мощности эти погрешности суммируются.
Alex
Сообщения: 2357
Зарегистрирован: Пт апр 20, 2012 12:53 pm
Благодарил (а): 42 раза
Поблагодарили: 262 раза

Re: POWER MONITOR на Arduino

Сообщение Alex » Пт апр 26, 2013 6:46 pm

И кстати еще одна версия есть в нелинейности показаний датчика тока, которые достигают у SCT-013-000 3%, и следовательно замеряя тринадцатью датчиками малые токи мы получаем некоторую погрешность в N% на каждом из них и в итоге , при подсчете общей мощности эти погрешности суммируются.
Тоже об этом думал.

В общем, итог такой. Несмотря на свои недостатки, для практических целей система применима. Позволяет отслеживать какие приборы в доме включены, какие выключены, позволяет оценивать энергопотребление приборов и дома в целом. На цикле 400 измерение 13 линий занимает 1 секунду, что более чем приемлемо. Небольшая погрешность не критична для наших целей.

А вот комментарий человека хорошо разбирающегося в предмете хотелось бы получить (для удаления тонких мест и доведения системы до ума).

Вопросы.

1. Сколько раз должен крутиться цикл? И как правильно рассчитать это значение?
2. Корректно ли измерять напряжение на шине и токи на линиях или нужно на этих же линиях измерять и отдельные напряжения?
3. Обязательно ли для каждой мощности крутить отдельный цикл или можно вычислять все мощности в одном цикле?
P43YM
Сообщения: 13
Зарегистрирован: Вт мар 05, 2013 7:50 am
Благодарил (а): 0
Поблагодарили: 2 раза

Re: POWER MONITOR на Arduino

Сообщение P43YM » Пт апр 26, 2013 7:36 pm

Alex писал(а):
для удаления тонких мест и доведения системы до ума
Необходим источник опорного напряжения и цап с большей разрядностью, ну и датчик ,наверно, поточнее.
Хотя здесь было бы проще реализовать все специализированной микросхемой, коих в избытке, например - ad7755 или ADE7757.
http://c2.at.ua/load/avr/izmeritel_akti ... /17-1-0-65

upd.http://www.analog.com/ru/analog-to-digi ... index.html А вот у AD целое семейство микросхем (есть,конечно, не только у них) в том числе и с spi и uart интерфейсом и замером тока, напряжения и мощности(например AD7763) , а не только потребленной мощности как у приведенных выше.

Upd2.http://www.aliexpress.com/item/AD7757-A ... 86444.html А вот и ADE7757 от китайцев за пять долларов, и не надо никаких spi и uart, есть импульсный выход для калибровки, который выдает значение мгновенной потребляемой мощности, и основной ,дающий значение кВт/ч.
Последний раз редактировалось P43YM Вс апр 28, 2013 3:41 pm, всего редактировалось 1 раз.
Alex
Сообщения: 2357
Зарегистрирован: Пт апр 20, 2012 12:53 pm
Благодарил (а): 42 раза
Поблагодарили: 262 раза

Re: POWER MONITOR на Arduino

Сообщение Alex » Пт апр 26, 2013 9:56 pm

Для общего развития полезная информация, спасибо. Но паять ещё одно устройство нет ни сил ни особого желания потому, что меня устраивает то, что уже есть. Хотелось бы только несколько окультурить и, так сказать, снять заусенцы напильником.
clark2
Сообщения: 10
Зарегистрирован: Пт янв 11, 2013 1:12 pm
Благодарил (а): 0
Поблагодарили: 1 раз

Re: POWER MONITOR на Arduino

Сообщение clark2 » Вс июл 14, 2013 11:13 pm

Alex писал(а): В общем, итог такой. Несмотря на свои недостатки, для практических целей система применима. Позволяет отслеживать какие приборы в доме включены, какие выключены, позволяет оценивать энергопотребление приборов и дома в целом. На цикле 400 измерение 13 линий занимает 1 секунду, что более чем приемлемо. Небольшая погрешность не критична для наших целей.
Здравствуйте.
Скетчем на 13 линий не поделитесь?
Alex
Сообщения: 2357
Зарегистрирован: Пт апр 20, 2012 12:53 pm
Благодарил (а): 42 раза
Поблагодарили: 262 раза

Re: POWER MONITOR на Arduino

Сообщение Alex » Пн июл 15, 2013 8:48 am

Будьте любезны. :)

Этот алгоритм берёт 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()

Последний раз редактировалось Alex Вт фев 25, 2014 2:26 pm, всего редактировалось 1 раз.
clark2
Сообщения: 10
Зарегистрирован: Пт янв 11, 2013 1:12 pm
Благодарил (а): 0
Поблагодарили: 1 раз

Re: POWER MONITOR на Arduino

Сообщение clark2 » Вт июл 16, 2013 1:19 am

Спасибо, буду пробовать.
BATONS
Сообщения: 107
Зарегистрирован: Сб июн 30, 2012 7:54 am
Благодарил (а): 0
Поблагодарили: 14 раз

Re: POWER MONITOR на Arduino

Сообщение BATONS » Пн июл 22, 2013 12:41 pm

dmw
Очень понравился ваш пост, на счет подключения в проект счетчика Меркурий.
хочу по аналогии с Вашей идеей (я про доработанный скрипт php) купить 3-х фазный меркурий и тем самым замерять
ток по 3 линиям. (у меня в щитке одна линия - на розетки, далее свет, и на плиту). хочу замерять ток по каждой из этих линий.

Еще вопрос, как будет выглядеть ваш скрипт php, чтобы он полученные данные писал в лог-файл? Вы сможете мне помочь "допилить" ваш php?
На данный момент у меня стоит mySQL и она с лог-файлов пишет все параметры в базу....вот и хочу прикрутить так же к ней и меркурий?
Ответить