Система контроля напряжения 220v

Lachin
Offline
Зарегистрирован: 02.10.2016

Привет ребята,есть такая схемка,пытаюсь сделать вольт контроль,но есть проблема сенсором, есть код,нужно добиться минимального гистерезис между напряжением включения и напряжением отключения,как можно правильно реализовать это в коде подскажите пожалуйста как добиться этих параметров возможно нужна другая схема,возможно нужны исправления в коде,может кто что скажет,спасибо

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Научиться бы читать чужие мысли, чтобы понять, что чел хочет ... а так, ну совершенно не понятно ... вижу параметрический стабилизатор на 4.7 В и все ... на входе моста 12 В - это переменки или что-то другое? И что вы хотите контролировать?

Lachin
Offline
Зарегистрирован: 02.10.2016

ulis пишет:

Научиться бы читать чужие мысли, чтобы понять, что чел хочет ... а так, ну совершенно не понятно ... вижу параметрический стабилизатор на 4.7 В и все ... на входе моста 12 В - это переменки или что-то другое? И что вы хотите контролировать?

\

Хочу контролировать верхние и нижние пороги  напряжения,если в сети 250в отключаем реле,если же стало 230в то включаем реле,если в сети 180в отключаем реле.если в сети стало 200в то включаем реле,вот и нужен сенсор который будет нормально работать,и нужен гистерезис между включениями.

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Вариантов масса, даже в вашей схеме  .... стабилитрон не нужен, вам нужен амплитудный выпрямитель, в простейшем виде - просто расчитать постоянную времени (С*R), чтобы время разряда емкости было больше нескольких периодов сети, далее привести с помощью делителя полученное напряжение к диапазону дуни ну и далее - делайте с ним, что хотите   ... а еще как вариант посмотреть в сторону гальваноразвязки на IL300, но там, конечно, сложнее, но зато - красиво. Можно вообще, использовать 4 компаратора вместо дуни   

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Lachin, тогда уж так:

входом МК собирать квадратные корни, и считать rms :)

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

dimax пишет:

входом МК собирать квадратные корни, и считать rms :)

ну корни-то зачем, ему ж только амплитудные значения нужны ... хотя, чтоб дуня не простаивала :)

Lachin
Offline
Зарегистрирован: 02.10.2016

Уважаемые dimax и  ulis, я ценю ваш опыт без сомнения,но если можно для начинающего чуть по проще  объяснить,конкретно что нужно и какую схемку вы рекомендуете начать делать ,я же со своей стороны буду делать и выкладывать сюда все продельное о работе и будет хороши проект,возможно прошу много но все таки помогите добить проект.

Конечно хотелось бы красиво и как нужно,вот и хотел спросить вашего совета уважаемые ГУРУ.

Вот сам код,вот и нужно под этот код нужный сенсор,то что у меня по схеме не особо подходит просветите как сделать правильно,и программно и аппаратно.Вся проблема сейчас заключается в аппаратном решении и самом гистерезисе.
 
int sensorPin = A0; // аналоговый вход
int RelePin = 12;  // управление реле на 12 пине
int SysPin = 11;  // это пин соединить с 12, цифровой вход, защита от ногодрыга
unsigned int sensorValue = 0; // переменная напряжения сенсора
static unsigned long G;       // Переменная для накопления показаний датчика сенсора

int b = 8;  //объявляем переменную с номером пина, на который подключен biper
int Pin_Vmin_led = 7;
int Pin_Vmax_led = 6;
int Pin_V_ok_led = 5;
int V_min = 410;      // коэффициент для минимального напряжения
int V_max = 530;      // коэффициент для максимального напряжения
int V_gist = 15;      // гистерезис, без цифровой обработки значения входящего напряжения не может быть менее 7
                      // если будем использовать цифровой фильтр, то можно уменьшить, предположительно до значения 3

byte Vin_OK = 0;  //эта переменная служит для проверки входного напряжение, входит ли оно в наши установки, если входит, то 1, нет 0
byte Flag_T1 = 0;  //этот флаг информирует,что было зафиксировано правильное входное напряжение и запущен счетчик выдержки паузы на включение реле
unsigned int T1 = 10000;  // время задержки реле включения
unsigned long previousMillis = 0;

/* следующая ниже конструкция по идее должна бы высвободить 2 байта памяти занятые под переменные
 * и будет более правильной, так как использует команды препроцессора и по сути является макросом
 * заменяя в нужных местах слова на цифровые значения
 * при использовании реле с прямой логикой просто заменить 0 на 1, а 1 на ноль
 */
#define ReleON  0  // реле включено
#define ReleOFF 1  // реле выключено

void setup() {
  Serial.begin(9600); // скорость порта
  pinMode(RelePin, OUTPUT);
  pinMode(SysPin, INPUT);
  pinMode(Pin_Vmin_led, OUTPUT); // заниженное напряжение
  pinMode(Pin_Vmax_led, OUTPUT); // завышенное напряжение
  pinMode(Pin_V_ok_led, OUTPUT); // напряжение в норме
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers() {
  tone (b, 3000); //включаем тон 3000 Гц
  delay(200); //ждем 200 Мс
  noTone(b ); // отключаем
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers2() {
  tone (b, 7000); //включаем тон 7000 Гц
  delay(73); //ждем 73 Мс
  noTone(b ); // отключаем
}

void read_sensor(){
  for (int j=1; j <= 8; j++) {
   sensorValue = analogRead(sensorPin);
   G+=sensorValue-(G>>8);
   sensorValue=G>>8;                      // показания сенсора после цифрового фильтра
}
  }
  
void loop() {
  sensorValue = analogRead(sensorPin);  // раскомментировать, если не используем цифровой фильтр
  //read_sensor();                          // закомментировать, если не используем цифровой фильтр

  if (sensorValue <= V_min || sensorValue >= V_max) {  //тут делаем сравнение двух значении если в сети 170в  или 250в  то сбрасываем флаг
    Vin_OK = 0;
    Flag_T1 = 0;
   
      if (sensorValue <= V_min){
      digitalWrite(Pin_Vmin_led, HIGH);
      bipers(); // Если напряжение не в норме то сработал biper
      digitalWrite(Pin_Vmin_led, LOW);
     }
     if (sensorValue >= V_max){
      digitalWrite(Pin_Vmax_led, HIGH);
      bipers2(); // Если напряжение не в норме то сработал biper 
      digitalWrite(Pin_Vmax_led, LOW);
     }

  }

  else if (sensorValue > (V_min + V_gist) && sensorValue < (V_max - V_gist)) {  // тут делаем период включения между 180в и 230в
    Vin_OK = 1;
    if (Flag_T1 == 0) {
      previousMillis = millis();  //реле задержки включения
      Flag_T1 = 1;
    }
  }

// командами digitalRead(SysPin)==ReleOFF и digitalRead(SysPin)==ReleON избавляемся от повторной установки (НОГОДРЫГ)
// состояния реле, если уже установлено, надо ли это делать можно посмотреть осциллографом
// или триггером ловушкой оценить состояние пина в установившемся состоянии реле

  if (digitalRead(SysPin) == ReleOFF && Vin_OK == 1 && Flag_T1 == 1 && (millis() - previousMillis) >= T1) digitalWrite(RelePin, ReleON);
  else if (digitalRead(SysPin) == ReleON && Vin_OK == 0) digitalWrite(RelePin, ReleOFF);   //else digitalWrite(RelePin, ReleOFF);

  if(digitalRead(SysPin) == ReleON){digitalWrite(Pin_V_ok_led, HIGH);}
  else {digitalWrite(Pin_V_ok_led, LOW);}

  Serial.println(sensorValue); // выводим информацию в сериал порт

  delay(100);
}

 

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Начинать нужно с простого, двигаясь к сложному ... соберите, для начала схему, которую предложил dimax

Lachin
Offline
Зарегистрирован: 02.10.2016

ulis пишет:

Начинать нужно с простого, двигаясь к сложному ... соберите, для начала схему, которую предложил dimax

А какую из них выбрать,или без разницы какую собрать?

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

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

Lachin
Offline
Зарегистрирован: 02.10.2016

 Соберу по последней  схему,то есть не выше чем 1.1в? Только вот где же взять сейчас такой конденсатор С1 8200мкф 16в

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Совсем не обязательно 8200 на 16, вполне сойдет и 4700 и даже 2200 мкф. Если работать с опорным дуни по умолчанию - то оно равно 5 вольт, так что делитель R1, R2 при максимальном входном должен давать 5 вольт (пиковое, вольтметр должен показывать 5/1.42) или чуток меньше. Для калибровки, вам понадобится ЛАТР

Lachin
Offline
Зарегистрирован: 02.10.2016

ЛАТР есть,с конденсатором понятно тоже есть,начну сборку схемы,по схеме есть еще конденсатор С2 это 10мкф ?  диод VD2 можно поставить 4007 ? ну 7805 понятно стабилизатор тоже не проблема.  

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

dimax пишет:

Lachin, тогда уж так:

входом МК собирать квадратные корни, и считать rms :)

Дмитрий, а пример кода не приведёте?

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

C2 - да, 10 - 100 мкФ по питанию, диод любой, лишь бы по току прошел. 7805 - пойдет, но можно использовать вот это http://www.ebay.com/itm/401173017821?_trksid=p2057872.m2749.l2649&var=670732343007&ssPageName=STRK%3AMEBIDX%3AIT

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

ua6em пишет:

Дмитрий, а пример кода не приведёте?

Ну формула то известна - https://ru.wikipedia.org/wiki/%D0%A1%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B5_%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5 , другое дело, ее нужно будет прилепить к результатам ацп дуни

Lachin
Offline
Зарегистрирован: 02.10.2016

ulis пишет:

C2 - да, 10 - 100 мкФ по питанию, диод любой, лишь бы по току прошел. 7805 - пойдет, но можно использовать вот это http://www.ebay.com/itm/401173017821?_trksid=p2057872.m2749.l2649&var=670732343007&ssPageName=STRK%3AMEBIDX%3AIT

Ну так по ссылке это обычный DC-DC? если так то есть на LM2596.

toc
Offline
Зарегистрирован: 09.02.2013

Только для сравнения, аналогичное сертифицированное решение с гарантией.
Умеренно рекомендую. Опыт использования полгода, три штуки стоят, работают без проблем.
2140 руб.
УЗМ-51М УХЛ4 устройство защиты от скачков напряжения, нагрузка 63А

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Что мне подсказывает, что и цифровой фильтр и через подсчет RMS результат будет одинаковый, код ниже, через цифровой фильтр

int sensorPin = A0; // аналоговый вход
int RelePin = 12;  // управление реле на 12 пине
int SysPin = 11;  // это пин соединить с 12, цифровой вход, защита от ногодрыга
unsigned int sensorValue = 0; // переменная напряжения сенсора
static unsigned long G;       // Переменная для накопления показаний датчика сенсора

int b = 8;  //объявляем переменную с номером пина, на который подключен biper
int Pin_Vmin_led = 7;
int Pin_Vmax_led = 6;
int Pin_V_ok_led = 5;
int V_min = 410;      // коэффициент для минимального напряжения
int V_max = 530;      // коэффициент для максимального напряжения
int V_gist = 15;      // гистерезис, без цифровой обработки значения входящего напряжения не может быть менее 7
                      // если будем использовать цифровой фильтр, то можно уменьшить, предположительно до значения 3

byte Vin_OK = 0;  //эта переменная служит для проверки входного напряжение, входит ли оно в наши установки, если входит, то 1, нет 0
byte Flag_T1 = 0;  //этот флаг информирует,что было зафиксировано правильное входное напряжение и запущен счетчик выдержки паузы на включение реле
unsigned int T1 = 10000;  // время задержки реле включения
unsigned long previousMillis = 0;

/* следующая ниже конструкция по идее должна бы высвободить 2 байта памяти занятые под переменные
 * и будет более правильной, так как использует команды препроцессора и по сути является макросом
 * заменяя в нужных местах слова на цифровые значения
 * при использовании реле с прямой логикой просто заменить 0 на 1, а 1 на ноль
 */
#define ReleON  0  // реле включено
#define ReleOFF 1  // реле выключено

void setup() {
  Serial.begin(9600); // скорость порта
  pinMode(RelePin, OUTPUT);
  pinMode(SysPin, INPUT);
  pinMode(Pin_Vmin_led, OUTPUT); // заниженное напряжение
  pinMode(Pin_Vmax_led, OUTPUT); // завышенное напряжение
  pinMode(Pin_V_ok_led, OUTPUT); // напряжение в норме
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers() {
  tone (b, 3000); //включаем тон 3000 Гц
  delay(200); //ждем 200 Мс
  noTone(b ); // отключаем
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers2() {
  tone (b, 7000); //включаем тон 7000 Гц
  delay(73); //ждем 73 Мс
  noTone(b ); // отключаем
}

void read_sensor(){
  for (int j=1; j <= 200; j++) {
   sensorValue = analogRead(sensorPin);
   G+=sensorValue-(G>>8);
   sensorValue=G>>8;                      // показания сенсора после цифрового фильтра
}
  }
  
void loop() {
 // sensorValue = analogRead(sensorPin);  // раскомментировать, если не используем цифровой фильтр
  read_sensor();                          // закомментировать, если не используем цифровой фильтр

  if (sensorValue <= V_min || sensorValue >= V_max) {  //тут делаем сравнение двух значении если в сети 170в  или 250в  то сбрасываем флаг
    Vin_OK = 0;
    Flag_T1 = 0;
   
      if (sensorValue <= V_min){
      digitalWrite(Pin_Vmin_led, HIGH);
      bipers(); // Если напряжение не в норме то сработал biper
      digitalWrite(Pin_Vmin_led, LOW);
     }
     if (sensorValue >= V_max){
      digitalWrite(Pin_Vmax_led, HIGH);
      bipers2(); // Если напряжение не в норме то сработал biper 
      digitalWrite(Pin_Vmax_led, LOW);
     }

  }

  else if (sensorValue > (V_min + V_gist) && sensorValue < (V_max - V_gist)) {  // тут делаем период включения между 180в и 230в
    Vin_OK = 1;
    if (Flag_T1 == 0) {
      previousMillis = millis();  //реле задержки включения
      Flag_T1 = 1;
    }
  }

// командами digitalRead(SysPin)==ReleOFF и digitalRead(SysPin)==ReleON избавляемся от повторной установки (НОГОДРЫГ)
// состояния реле, если уже установлено, надо ли это делать можно посмотреть осциллографом
// или триггером ловушкой оценить состояние пина в установившемся состоянии реле

  if (digitalRead(SysPin) == ReleOFF && Vin_OK == 1 && Flag_T1 == 1 && (millis() - previousMillis) >= T1) digitalWrite(RelePin, ReleON);
  else if (digitalRead(SysPin) == ReleON && Vin_OK == 0) digitalWrite(RelePin, ReleOFF);   //else digitalWrite(RelePin, ReleOFF);

  if(digitalRead(SysPin) == ReleON){digitalWrite(Pin_V_ok_led, HIGH);}
  else {digitalWrite(Pin_V_ok_led, LOW);}

  Serial.println(sensorValue); // выводим информацию в сериал порт

  delay(100);
}

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

ua6em, у меня примеров нет, но на форуме точно есть.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

А этот код попробуйте:

поправил 3 раза, ПРОБУЙ
 

int sensorPin = A0; // аналоговый вход
int RelePin = 12;  // управление реле на 12 пине
int SysPin = 11;  // это пин соединить с 12, цифровой вход, защита от ногодрыга
unsigned int sensorValue = 0; // переменная напряжения сенсора
static unsigned long G;       // Переменная для накопления показаний датчика сенсора

int b = 8;  //объявляем переменную с номером пина, на который подключен biper
int Pin_Vmin_led = 7;
int Pin_Vmax_led = 6;
int Pin_V_ok_led = 5;
int V_min = 352;      // коэффициент для минимального напряжения равного 170 вольт
int V_max = 525;      // коэффициент для максимального напряжения равного 250 вольт
int V_gist = 5;      // гистерезис, без цифровой обработки значения входящего напряжения не может быть менее 7
                      // если будем использовать цифровой фильтр, то можно уменьшить, предположительно до значения 3

byte Vin_OK = 0;  //эта переменная служит для проверки входного напряжение, входит ли оно в наши установки, если входит, то 1, нет 0
byte Flag_T1 = 0;  //этот флаг информирует,что было зафиксировано правильное входное напряжение и запущен счетчик выдержки паузы на включение реле
unsigned int T1 = 10000;  // время задержки реле включения
unsigned long previousMillis = 0;

/* следующая ниже конструкция по идее должна бы высвободить 2 байта памяти занятые под переменные
 * и будет более правильной, так как использует команды препроцессора и по сути является макросом
 * заменяя в нужных местах слова на цифровые значения
 * при использовании реле с прямой логикой просто заменить 0 на 1, а 1 на ноль
 */
#define ReleON  0  // реле включено
#define ReleOFF 1  // реле выключено


/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers() {
  tone (b, 3000); //включаем тон 3000 Гц
  delay(200); //ждем 200 Мс
  noTone(b ); // отключаем
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers2() {
  tone (b, 7000); //включаем тон 7000 Гц
  delay(73); //ждем 73 Мс
  noTone(b ); // отключаем
}

void read_sensor(){
  for (int j=1; j <= 96; j++) {
   sensorValue = analogRead(sensorPin);
   G+=sensorValue-(G>>8);
   sensorValue=G>>8;                      // показания сенсора после цифрового фильтра
}
  }

  
void setup() {
  Serial.begin(9600); // скорость порта
  pinMode(RelePin, OUTPUT);
  pinMode(SysPin, INPUT);
  pinMode(Pin_Vmin_led, OUTPUT); // заниженное напряжение
  pinMode(Pin_Vmax_led, OUTPUT); // завышенное напряжение
  pinMode(Pin_V_ok_led, OUTPUT); // напряжение в норме
   
    for (int s=1; s <= 16; s++) {
    read_sensor();
    } 
}



  
void loop() {
 // sensorValue = analogRead(sensorPin);  // раскомментировать, если не используем цифровой фильтр
  read_sensor();                          // закомментировать, если не используем цифровой фильтр

  if (sensorValue <= (V_min+V_gist) || sensorValue >= (V_max-V_gist)) {  //тут делаем сравнение двух значении если в сети 170в  или 250в  то сбрасываем флаг
    Vin_OK = 0;
    Flag_T1 = 0;
   
      if (sensorValue <= (V_min+V_gist)){
      digitalWrite(Pin_Vmin_led, HIGH);
      bipers(); // Если напряжение не в норме то сработал biper
      digitalWrite(Pin_Vmin_led, LOW);
     }
     if (sensorValue >= (V_max-V_gist)){
      digitalWrite(Pin_Vmax_led, HIGH);
      bipers2(); // Если напряжение не в норме то сработал biper 
      digitalWrite(Pin_Vmax_led, LOW);
     }

  }

  else if (sensorValue > (V_min + V_gist) && sensorValue < (V_max - V_gist)) {  // тут делаем период включения между 180в и 230в
    Vin_OK = 1;
    if (Flag_T1 == 0) {
      previousMillis = millis();  //реле задержки включения
      Flag_T1 = 1;
    }
  }

// командами digitalRead(SysPin)==ReleOFF и digitalRead(SysPin)==ReleON избавляемся от повторной установки (НОГОДРЫГ)
// состояния реле, если уже установлено, надо ли это делать можно посмотреть осциллографом
// или триггером ловушкой оценить состояние пина в установившемся состоянии реле

  if (digitalRead(SysPin) == ReleOFF && Vin_OK == 1 && Flag_T1 == 1 && (millis() - previousMillis) >= T1) digitalWrite(RelePin, ReleON);
  else if (digitalRead(SysPin) == ReleON && Vin_OK == 0) digitalWrite(RelePin, ReleOFF);   //else digitalWrite(RelePin, ReleOFF);

  if(digitalRead(SysPin) == ReleON){digitalWrite(Pin_V_ok_led, HIGH);}
  else {digitalWrite(Pin_V_ok_led, LOW);}

  Serial.println(sensorValue); // выводим информацию в сериал порт

  delay(100);
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

dimax пишет:

ua6em, у меня примеров нет, но на форуме точно есть.

Дмитрий, хочу сравнить ЦШ и RMS ))) прямо в одном скетче всё собрать

Lachin
Offline
Зарегистрирован: 02.10.2016

 Ребята код как бы работает нормально но есть одно НО,получается проблема,при низком напряжении как бы все устраивает,то есть снижаю до 170в отключается реле сработал светодиод который говорит что напряжения занижено и пищит бузер,потом поднимаю до 200в как и планировал включается реле бузер не пищит и светодиод не моргает,потом загорается светодиод который говорит что в сети все ок, а вот при высоком напряжении все иначе  даже не то что надо,происходит следующие,повышаю до 250в но еще не дошел до 250 уже отключается реле примерно на 242в бузер при этом молчит и светодиод который показывает что напряжения завышено тоже молчит потом стоит приподнять примерно до 246в начинает срабатывать хаотично бузер и светодиод и следом дергает реле и светодиод который говорит что в сети все ОК,но стоит приподнять до 250-252 бузер пищит светодиод моргает тот что показывает что в сети высокое и реле не дергает,подскажите пожалуйста что может быть не так? возможно что то в коде упустили?

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Lachin пишет:

 Ребята код как бы работает нормально но есть одно НО

Если вы все понимаете, что происходит в коде, который запускаете, то тема имхо закрыта, лично я очень тупой и пока не пойму каждую строчку ... например, где вы видите в коде верхний и нижний контролируемый диапазон напряжений, там есть только "гистерезис" в 5 вольт?

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

ua6em пишет:

А этот код попробуйте: 

У меня к вам вопрос, что делает функция void read_sensor() ? Чтобы разобраться, накидал вот этот код:

static unsigned long G;  // Переменная для накопления входных значений
int sensorPin = A0;
unsigned int sensorValue = 0;

void read_sensor()
{
  sensorValue = 0;
  for(int j = 1; j <=96; j++)
  {    
    //sensorValue = random(0x00, 0xff);
    sensorValue = 0xfe;
    Serial.print(sensorValue,HEX);
    Serial.print(" ");
    G+=sensorValue-(G>>8);
    sensorValue=G>>8;
  }
  Serial.println();  
}

void setup()
{
  Serial.begin(9600);
  randomSeed(analogRead(sensorPin));
}

void loop()
{
  read_sensor();
  Serial.print("sensorValue after filter = ");
  Serial.println(sensorValue,HEX);
  delay(3000);  
}

 Значение sensorValue постепенно приближается к 0xfe и странно, никак не хочет "стартовать" с одного и того же значения, ведь перед циклом в функции стоит sensorValue = 0;
 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ulis пишет:

ua6em пишет:

А этот код попробуйте: 

У меня к вам вопрос, что делает функция void read_sensor() ? Чтобы разобраться, накидал вот этот код:

static unsigned long G;&nbsp; // Переменная для накопления входных значений
int sensorPin = A0;
unsigned int sensorValue = 0;

void read_sensor()
{
&nbsp; sensorValue = 0;
&nbsp; for(int j = 1; j <=96; j++)
&nbsp; {&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; //sensorValue = random(0x00, 0xff);
&nbsp;&nbsp;&nbsp; sensorValue = 0xfe;
&nbsp;&nbsp;&nbsp; Serial.print(sensorValue,HEX);
&nbsp;&nbsp;&nbsp; Serial.print(" ");
&nbsp;&nbsp;&nbsp; G+=sensorValue-(G>>8);
&nbsp;&nbsp;&nbsp; sensorValue=G>>8;
&nbsp; }
&nbsp; Serial.println();&nbsp; 
}

void setup()
{
&nbsp; Serial.begin(9600);
&nbsp; randomSeed(analogRead(sensorPin));
}

void loop()
{
&nbsp; read_sensor();
&nbsp; Serial.print("sensorValue after filter = ");
&nbsp; Serial.println(sensorValue,HEX);
&nbsp; delay(3000);&nbsp; 
}

 Значение sensorValue постепенно приближается к 0xfe и странно, никак не хочет "стартовать" с одного и того же значения, ведь перед циклом в функции стоит sensorValue = 0;
 

Это цифровой фильтр 1-го порядка

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ulis пишет:

Lachin пишет:

 Ребята код как бы работает нормально но есть одно НО

Если вы все понимаете, что происходит в коде, который запускаете, то тема имхо закрыта, лично я очень тупой и пока не пойму каждую строчку ... например, где вы видите в коде верхний и нижний контролируемый диапазон напряжений, там есть только "гистерезис" в 5 вольт?

Изначально код был таким:
 

int sensorPin = A0; // аналоговый вход
int RelePin = 12;  // управление реле на 12 пине
int SysPin = 11;  // это пин соединить с 12, цифровой вход, защита от ногодрыга
unsigned int sensorValue = 0; // переменная напряжения сенсора
static unsigned long G;       // Переменная для накопления показаний датчика сенсора

int b = 8;  //объявляем переменную с номером пина, на который подключен biper
int Pin_Vmin_led = 7;
int Pin_Vmax_led = 6;
int Pin_V_ok_led = 5;
int V_min = 352;      // коэффициент для минимального напряжения равного 170 вольт
int V_max = 525;      // коэффициент для максимального напряжения равного 250 вольт
int V_gist = 5;      // гистерезис, без цифровой обработки значения входящего напряжения не может быть менее 7
                      // если будем использовать цифровой фильтр, то можно уменьшить, предположительно до значения 3

byte Vin_OK = 0;  //эта переменная служит для проверки входного напряжение, входит ли оно в наши установки, если входит, то 1, нет 0
byte Flag_T1 = 0;  //этот флаг информирует,что было зафиксировано правильное входное напряжение и запущен счетчик выдержки паузы на включение реле
unsigned int T1 = 10000;  // время задержки реле включения
unsigned long previousMillis = 0;

/* следующая ниже конструкция по идее должна бы высвободить 2 байта памяти занятые под переменные
 * и будет более правильной, так как использует команды препроцессора и по сути является макросом
 * заменяя в нужных местах слова на цифровые значения
 * при использовании реле с прямой логикой просто заменить 0 на 1, а 1 на ноль
 */
#define ReleON  0  // реле включено
#define ReleOFF 1  // реле выключено


/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers() {
  tone (b, 3000); //включаем тон 3000 Гц
  delay(200); //ждем 200 Мс
  noTone(b ); // отключаем
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers2() {
  tone (b, 7000); //включаем тон 7000 Гц
  delay(73); //ждем 73 Мс
  noTone(b ); // отключаем
}

void read_sensor(){
  for (int j=1; j <= 96; j++) {
   sensorValue = analogRead(sensorPin);
   G+=sensorValue-(G>>8);
   sensorValue=G>>8;                      // показания сенсора после цифрового фильтра
}
  }

  
void setup() {
  Serial.begin(9600); // скорость порта
  pinMode(RelePin, OUTPUT);
  pinMode(SysPin, INPUT);
  pinMode(Pin_Vmin_led, OUTPUT); // заниженное напряжение
  pinMode(Pin_Vmax_led, OUTPUT); // завышенное напряжение
  pinMode(Pin_V_ok_led, OUTPUT); // напряжение в норме
   
    for (int s=1; s <= 16; s++) {
    read_sensor();
    } 
}



  
void loop() {
 // sensorValue = analogRead(sensorPin);  // раскомментировать, если не используем цифровой фильтр
  read_sensor();                          // закомментировать, если не используем цифровой фильтр

  if (sensorValue <= (V_min) || sensorValue >= (V_max)) {  //тут делаем сравнение двух значении если в сети 170в  или 250в  то сбрасываем флаг
    Vin_OK = 0;
    Flag_T1 = 0;
   
      if (sensorValue <= (V_min)){  // тут пищим бузером если напряжение ниже нормы
      digitalWrite(Pin_Vmin_led, HIGH);
      bipers(); // Если напряжение не в норме то сработал biper
      digitalWrite(Pin_Vmin_led, LOW);
     }
     if (sensorValue >= (V_max)){ // здесь пищим бузером если напряжение выше нормы
      digitalWrite(Pin_Vmax_led, HIGH);
      bipers2(); // Если напряжение не в норме то сработал biper 
      digitalWrite(Pin_Vmax_led, LOW);
     }

  }

  else if (sensorValue > (V_min + V_gist) && sensorValue < (V_max - V_gist)) {  // напряжение включения реле сдвигаем на величину гистерезиса
    Vin_OK = 1;
    if (Flag_T1 == 0) {
      previousMillis = millis();  //реле задержки включения
      Flag_T1 = 1;
    }
  }

// командами digitalRead(SysPin)==ReleOFF и digitalRead(SysPin)==ReleON избавляемся от повторной установки (НОГОДРЫГ)
// состояния реле, если уже установлено, надо ли это делать можно посмотреть осциллографом
// или триггером ловушкой оценить состояние пина в установившемся состоянии реле

  if (digitalRead(SysPin) == ReleOFF && Vin_OK == 1 && Flag_T1 == 1 && (millis() - previousMillis) >= T1) digitalWrite(RelePin, ReleON);
  else if (digitalRead(SysPin) == ReleON && Vin_OK == 0) digitalWrite(RelePin, ReleOFF);   //else digitalWrite(RelePin, ReleOFF);

  if(digitalRead(SysPin) == ReleON){digitalWrite(Pin_V_ok_led, HIGH);}
  else {digitalWrite(Pin_V_ok_led, LOW);}

  Serial.println(sensorValue); // выводим информацию в сериал порт

  delay(100);
}

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

ua6em пишет:

Изначально код был таким:

Да, я видел этот код

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

toc пишет:
Только для сравнения, аналогичное сертифицированное решение с гарантией. Умеренно рекомендую. Опыт использования полгода, три штуки стоят, работают без проблем. 2140 руб. УЗМ-51М УХЛ4 устройство защиты от скачков напряжения, нагрузка 63А

Если без "пионерии", то да, кстати прямо на динрейку монтируется, можно в щитке всё защитить

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ulis пишет:

ua6em пишет:

Изначально код был таким:

Да, я видел этот код

так я чуток откомментировал
видимо глаз замылился ну не вижу совсем, почему по верхам работает не так
по сути классическое реле напряжения в котором напряжение срабатывания одно, напряжение удержания другое, с нюансами )))

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

ua6em пишет:

по сути классическое реле напряжения в котором напряжение срабатывания одно, напряжение удержания другое, с нюансами )))

Но я все таки хочу спросить про функцию read_sensor. Вы говорите, что это цифровой фильтр .... нижних, верхних или полосовой? Можно как-то, гляда на код функции, сказать, что это первый порядок? И зачем там фильтр вообще? Я почему интересуюсь - потому-что хочу собрать что-то подобное, но не для отключения, а для мониторинга качества сети и записи на СД карту, чтобы потом можно было ткнуть носом энерго компанию за их качество электричества

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ulis пишет:

ua6em пишет:

по сути классическое реле напряжения в котором напряжение срабатывания одно, напряжение удержания другое, с нюансами )))

Но я все таки хочу спросить про функцию read_sensor. Вы говорите, что это цифровой фильтр .... нижних, верхних или полосовой? Можно как-то, гляда на код функции, сказать, что это первый порядок? И зачем там фильтр вообще? Я почему интересуюсь - потому-что хочу собрать что-то подобное, но не для отключения, а для мониторинга качества сети и записи на СД карту, чтобы потом можно было ткнуть носом энерго компанию за их качество электричества

Это к LOGIK, код он подсказал когда я потерялся как усреднять показания )))

Я вот простую функцию RMS осилить не могу, не пойму как вычислить квадратный корень из числа, не компилируется )))
 

double S;
float S1;
unsigned long G;

void read_RMS(){
   G=0;
   for (int k=1; k <= 100; k++) {
   sensorValue = analogRead(sensorPin);
   //G+=(sensorValue*2);
   G+=(sensorValue+sensorValue);
   //G+=sq(sensorValue);
   }
   //S1=G/100;
  
   //S=sqrt(S1);                
   }

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Если раскомментировать ваши строчки, то у меня без ошибок компилится

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ulis пишет:

Если раскомментировать ваши строчки, то у меня без ошибок компилится

А в какой версии IDE?

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

1.81 Снимок с экрана:

 

Lachin
Offline
Зарегистрирован: 02.10.2016

Посмотреть можно по вот этой ссылке как работает на данный момент залил код с 26 сообщения,когда горит зеленый светодиод это означает что в сети напряжения в норме,когда моргает оранжевый светодиод и пищит бузер это низкое напряжения в сети,когда моргает красный светодиод и пищит бузер это высокое напряжения,вот тут проблема по видео видно что реле отключилось бузер молчит и светодиод не моргает,если еще чуть на один вольт начинает пищать и моргать светодиод но не устойчиво и не синхронно и в этот момент начинает иногда реле срабатывать и зеленый светодиод чего и не должно быть,а вот если чуть добавить напряжения начинает работать в установках V_min стоит значения для 170в отключения и включения на 200в,а V_max значения стоит для 250в отключения а включения 230в.

https://www.youtube.com/watch?v=OgYkJuWFgsA&feature=youtu.be

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Какой отличный ЛАТР! Где вы такой надыбали???? :) Не забывайте, что калибровать нужно, если ЛАТР запитан от стабилизатора

Lachin
Offline
Зарегистрирован: 02.10.2016

ЛАТР взял у другу по работать,ЛАТР сразу запитан от сетй не от стабилизатора,бегал сегодня искал стабилизатор но не смог найти его.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

RMS без привязки к детектору перехода через 0 тоже не пойдёт, этот код похоже не укладывается в 10 миллисекунд а возможны и другие глюки
Умные люди для быстроты считывают данные в массив а уж потом его обрабатывают )))

void read_RMS(){
  G=0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  G+=sq(sensorValue);
  }
  float S1=(G/100);
  double S=sqrt(S1);
  sensorValue =  S;  
  }

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

думается схема должна быть такой:

1. однополупериодный выпрямитель с делителем
2. формируем из полупериода строб длительностью около 10 мсек
3 По переднему фронту запускам счетчик для длительности 4.9 мсек
4. По окончании импульса счетчика выполняем  sensorValue = analogRead(sensorPin);
5. Счётчик должен бытьл точным

 

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

ua6em пишет:

RMS без привязки к детектору перехода через 0 тоже не пойдёт, этот код похоже не укладывается в 10 миллисекунд а возможны и другие глюки

Так смотря rms чего вы хотите посчитать, если периодического сигнала, то один подход, если же, скажем, шумового сигнала, то там вообще через 0 перехода нет

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ulis пишет:

ua6em пишет:

RMS без привязки к детектору перехода через 0 тоже не пойдёт, этот код похоже не укладывается в 10 миллисекунд а возможны и другие глюки

Так смотря rms чего вы хотите посчитать, если периодического сигнала, то один подход, если же, скажем, шумового сигнала, то там вообще через 0 перехода нет

Чего, чего, что прилетает на порт A0 то и считаю )))

Есть еще один алгоритм, через поиск экстремума за период 10 миллисекунд, посмотреть что он даст,
Это если схему не менять

int sensorPin = A0; // аналоговый вход
int RelePin = 12;  // управление реле на 12 пине
int SysPin = 11;  // это пин соединить с 12, цифровой вход, защита от ногодрыга
unsigned int sensorValue = 0; // переменная напряжения сенсора
static unsigned long G;       // Переменная для накопления показаний датчика сенсора
//double S = 1.25;
//float S1=0;

int b = 8;  //объявляем переменную с номером пина, на который подключен biper
int Pin_Vmin_led = 7;
int Pin_Vmax_led = 6;
int Pin_V_ok_led = 5;
int V_min = 352;      // коэффициент для минимального напряжения равного 170 вольт
int V_max = 525;      // коэффициент для максимального напряжения равного 250 вольт
int V_gist = 5;      // гистерезис, без цифровой обработки значения входящего напряжения не может быть менее 7
                     // если будем использовать цифровой фильтр, то можно уменьшить, предположительно до значения 3

byte Vin_OK = 0;  //эта переменная служит для проверки входного напряжение, входит ли оно в наши установки, если входит, то 1, нет 0
byte Flag_T1 = 0;  //этот флаг информирует,что было зафиксировано правильное входное напряжение и запущен счетчик выдержки паузы на включение реле
unsigned int T1 = 10000;  // время задержки реле включения
unsigned long previousMillis = 0;

/* следующая ниже конструкция по идее должна бы высвободить 2 байта памяти занятые под переменные
* и будет более правильной, так как использует команды препроцессора и по сути является макросом
* заменяя в нужных местах слова на цифровые значения
* при использовании реле с прямой логикой просто заменить 0 на 1, а 1 на ноль
*/
#define ReleON  0  // реле включено
#define ReleOFF 1  // реле выключено


/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers() {
 tone (b, 3000); //включаем тон 3000 Гц
 delay(200); //ждем 200 Мс
 noTone(b ); // отключаем
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers2() {
 tone (b, 7000); //включаем тон 7000 Гц
 delay(73); //ждем 73 Мс
 noTone(b ); // отключаем
}

void read_sensor(){
  for (int j=1; j <= 96; j++) {
  sensorValue = analogRead(sensorPin);
  G+=sensorValue-(G>>8);
  sensorValue=G>>8;                      // показания сенсора после цифрового фильтра
}
 }

void read_RMS(){
  G=0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  G+=sq(sensorValue);
  }
  float S1=(G/100);
  double S=sqrt(S1);
  sensorValue =  S;  
  }

void read_VMAX(){
  int vmax =0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  if (sensorValue >vmax){vmax=sensorValue;}
  }
  sensorValue =  vmax; 
}
 
void setup() {
 Serial.begin(9600); // скорость порта
 pinMode(RelePin, OUTPUT);
 pinMode(SysPin, INPUT);
 pinMode(Pin_Vmin_led, OUTPUT); // заниженное напряжение
 pinMode(Pin_Vmax_led, OUTPUT); // завышенное напряжение
 pinMode(Pin_V_ok_led, OUTPUT); // напряжение в норме
 
/*   for (int s=1; s <= 16; s++) {
   read_sensor();
   } */
}

void loop() {
// sensorValue = analogRead(sensorPin);  // получение амплитуды входного напряжения прямым чтением порта ацп
// read_sensor();                        // получение амплитуды входного напряжения чтением через цифровой фильтр
// read_RMS();                           // получение амплитуды входного напряжения через рассчёт RMS
   read_VMAX();                          // получение амплитуды входного напряжения через поиск экстремума

 if (sensorValue <= (V_min) || sensorValue >= (V_max)) {  //тут делаем сравнение двух значении если в сети 170в  или 250в  то сбрасываем флаг
   Vin_OK = 0;
   Flag_T1 = 0;
 
     if (sensorValue <= (V_min)){  // тут пищим бузером если напряжение ниже нормы
     digitalWrite(Pin_Vmin_led, HIGH);
     bipers(); // Если напряжение не в норме то сработал biper
     digitalWrite(Pin_Vmin_led, LOW);
    }
    if (sensorValue >= (V_max)){ // здесь пищим бузером если напряжение выше нормы
     digitalWrite(Pin_Vmax_led, HIGH);
     bipers2(); // Если напряжение не в норме то сработал biper
     digitalWrite(Pin_Vmax_led, LOW);
    }

 }

 else if (sensorValue > (V_min + V_gist) && sensorValue < (V_max - V_gist)) {  // напряжение включения реле сдвигаем на величину гистерезиса
   Vin_OK = 1;
   if (Flag_T1 == 0) {
     previousMillis = millis();  //реле задержки включения
     Flag_T1 = 1;
   }
 }

// командами digitalRead(SysPin)==ReleOFF и digitalRead(SysPin)==ReleON избавляемся от повторной установки (НОГОДРЫГ)
// состояния реле, если уже установлено, надо ли это делать можно посмотреть осциллографом
// или триггером ловушкой оценить состояние пина в установившемся состоянии реле

 if (digitalRead(SysPin) == ReleOFF && Vin_OK == 1 && Flag_T1 == 1 && (millis() - previousMillis) >= T1) digitalWrite(RelePin, ReleON);
 else if (digitalRead(SysPin) == ReleON && Vin_OK == 0) digitalWrite(RelePin, ReleOFF);   //else digitalWrite(RelePin, ReleOFF);

 if(digitalRead(SysPin) == ReleON){digitalWrite(Pin_V_ok_led, HIGH);}
 else {digitalWrite(Pin_V_ok_led, LOW);}

 Serial.println(sensorValue); // выводим информацию в сериал порт

 delay(100);
}

А для полного счастья попробовать развязать гистерезисы сделав их раздельными для низкого и высокого напряжения, уж это точно рабочий вариант, при подборе гистерезисов для любого датчика )))
 

[code]
int sensorPin = A0; // аналоговый вход
int RelePin = 12;  // управление реле на 12 пине
int SysPin = 11;  // это пин соединить с 12, цифровой вход, защита от ногодрыга
unsigned int sensorValue = 0; // переменная напряжения сенсора
static unsigned long G;       // Переменная для накопления показаний датчика сенсора
//double S = 1.25;
//float S1=0;

int b = 8;  //объявляем переменную с номером пина, на который подключен biper
int Pin_Vmin_led = 7;
int Pin_Vmax_led = 6;
int Pin_V_ok_led = 5;
int V_min = 352;      // коэффициент для минимального напряжения равного 170 вольт
int V_max = 525;      // коэффициент для максимального напряжения равного 250 вольт
int V_gist = 10;      // гистерезис, без цифровой обработки значения входящего напряжения не может быть менее 7
                     // если будем использовать цифровой фильтр, то можно уменьшить, предположительно до значения 3
int V_gistv = 15;     // гистерезис для высокого напряжения                

byte Vin_OK = 0;  //эта переменная служит для проверки входного напряжение, входит ли оно в наши установки, если входит, то 1, нет 0
byte Flag_T1 = 0;  //этот флаг информирует,что было зафиксировано правильное входное напряжение и запущен счетчик выдержки паузы на включение реле
unsigned int T1 = 10000;  // время задержки реле включения
unsigned long previousMillis = 0;

/* следующая ниже конструкция по идее должна бы высвободить 2 байта памяти занятые под переменные
* и будет более правильной, так как использует команды препроцессора и по сути является макросом
* заменяя в нужных местах слова на цифровые значения
* при использовании реле с прямой логикой просто заменить 0 на 1, а 1 на ноль
*/
#define ReleON  0  // реле включено
#define ReleOFF 1  // реле выключено


/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers() {
 tone (b, 3000); //включаем тон 3000 Гц
 delay(200); //ждем 200 Мс
 noTone(b ); // отключаем
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers2() {
 tone (b, 7000); //включаем тон 7000 Гц
 delay(73); //ждем 73 Мс
 noTone(b ); // отключаем
}

void read_sensor(){
  for (int j=1; j <= 96; j++) {
  sensorValue = analogRead(sensorPin);
  G+=sensorValue-(G>>8);
  sensorValue=G>>8;                      // показания сенсора после цифрового фильтра
}
 }

void read_RMS(){
  G=0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  G+=sq(sensorValue);
  }
  float S1=(G/100);
  double S=sqrt(S1);
  sensorValue =  S;  
  }

void read_VMAX(){
  int vmax =0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  if (sensorValue >vmax){vmax=sensorValue;}
  }
  sensorValue =  vmax; 
}
 
void setup() {
 Serial.begin(9600); // скорость порта
 pinMode(RelePin, OUTPUT);
 pinMode(SysPin, INPUT);
 pinMode(Pin_Vmin_led, OUTPUT); // заниженное напряжение
 pinMode(Pin_Vmax_led, OUTPUT); // завышенное напряжение
 pinMode(Pin_V_ok_led, OUTPUT); // напряжение в норме
 
/*   for (int s=1; s <= 16; s++) {
   read_sensor();
   } */
}

void loop() {
// sensorValue = analogRead(sensorPin);  // получение амплитуды входного напряжения прямым чтением порта ацп
// read_sensor();                        // получение амплитуды входного напряжения чтением через цифровой фильтр
// read_RMS();                           // получение амплитуды входного напряжения через рассчёт RMS
   read_VMAX();                          // получение амплитуды входного напряжения через поиск экстремума

 if (sensorValue <= (V_min) || sensorValue >= (V_max)) {  //тут делаем сравнение двух значении если в сети 170в  или 250в  то сбрасываем флаг
   Vin_OK = 0;
   Flag_T1 = 0;
 
     if (sensorValue <= (V_min)){  // тут пищим бузером если напряжение ниже нормы
     digitalWrite(Pin_Vmin_led, HIGH);
     bipers(); // Если напряжение не в норме то сработал biper
     digitalWrite(Pin_Vmin_led, LOW);
    }
    if (sensorValue >= (V_max)){ // здесь пищим бузером если напряжение выше нормы
     digitalWrite(Pin_Vmax_led, HIGH);
     bipers2(); // Если напряжение не в норме то сработал biper
     digitalWrite(Pin_Vmax_led, LOW);
    }

 }

 else if (sensorValue > (V_min + V_gist) && sensorValue < (V_max - V_gistv)) {  // напряжение включения реле сдвигаем на величину гистерезиса
   Vin_OK = 1;
   if (Flag_T1 == 0) {
     previousMillis = millis();  //реле задержки включения
     Flag_T1 = 1;
   }
 }

// командами digitalRead(SysPin)==ReleOFF и digitalRead(SysPin)==ReleON избавляемся от повторной установки (НОГОДРЫГ)
// состояния реле, если уже установлено, надо ли это делать можно посмотреть осциллографом
// или триггером ловушкой оценить состояние пина в установившемся состоянии реле

 if (digitalRead(SysPin) == ReleOFF && Vin_OK == 1 && Flag_T1 == 1 && (millis() - previousMillis) >= T1) digitalWrite(RelePin, ReleON);
 else if (digitalRead(SysPin) == ReleON && Vin_OK == 0) digitalWrite(RelePin, ReleOFF);   //else digitalWrite(RelePin, ReleOFF);

 if(digitalRead(SysPin) == ReleON){digitalWrite(Pin_V_ok_led, HIGH);}
 else {digitalWrite(Pin_V_ok_led, LOW);}

 Serial.println(sensorValue); // выводим информацию в сериал порт

 delay(100);
}
[/code]

И крайний вариант, работа с бузерами и светодиодами вынесена в конец цикла, для удобства выключения этого блока и несколько изменён алгоритм для промежуточных фаз напряжений между крайними точками и точками гистерезиса )))
 

int sensorPin = A0; // аналоговый вход
int RelePin = 12;  // управление реле на 12 пине
int SysPin = 11;  // это пин соединить с 12, цифровой вход, защита от ногодрыга
unsigned int sensorValue = 0; // переменная напряжения сенсора
static unsigned long G;       // Переменная для накопления показаний датчика сенсора
//double S = 1.25;
//float S1=0;

int b = 8;  //объявляем переменную с номером пина, на который подключен biper
int Pin_Vmin_led = 7;
int Pin_Vmax_led = 6;
int Pin_V_ok_led = 5;
int V_min = 352;      // коэффициент для минимального напряжения равного 170 вольт
int V_max = 525;      // коэффициент для максимального напряжения равного 250 вольт
int V_gist = 10;      // гистерезис, без цифровой обработки значения входящего напряжения не может быть менее 7
                     // если будем использовать цифровой фильтр, то можно уменьшить, предположительно до значения 3
int V_gistv = 15;     // гистерезис для высокого напряжения                

byte Vin_OK = 0;  //эта переменная служит для проверки входного напряжение, входит ли оно в наши установки, если входит, то 1, нет 0
byte Flag_T1 = 0;  //этот флаг информирует,что было зафиксировано правильное входное напряжение и запущен счетчик выдержки паузы на включение реле
unsigned int T1 = 10000;  // время задержки реле включения
unsigned long previousMillis = 0;

/* следующая ниже конструкция по идее должна бы высвободить 2 байта памяти занятые под переменные
* и будет более правильной, так как использует команды препроцессора и по сути является макросом
* заменяя в нужных местах слова на цифровые значения
* при использовании реле с прямой логикой просто заменить 0 на 1, а 1 на ноль
*/
#define ReleON  0  // реле включено
#define ReleOFF 1  // реле выключено


/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers() {
 tone (b, 3000); //включаем тон 3000 Гц
 delay(200); //ждем 200 Мс
 noTone(b ); // отключаем
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers2() {
 tone (b, 7000); //включаем тон 7000 Гц
 delay(73); //ждем 73 Мс
 noTone(b ); // отключаем
}

void read_sensor(){
  for (int j=1; j <= 96; j++) {
  sensorValue = analogRead(sensorPin);
  G+=sensorValue-(G>>8);
  sensorValue=G>>8;                      // показания сенсора после цифрового фильтра
}
 }

void read_RMS(){
  G=0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  G+=sq(sensorValue);
  }
  float S1=(G/100);
  double S=sqrt(S1);
  sensorValue =  S;  
  }

void read_VMAX(){
   int vmax =0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  if (sensorValue >vmax){vmax=sensorValue;}
  }
  sensorValue =  vmax; 
}
 
void setup() {
 Serial.begin(9600); // скорость порта
 pinMode(RelePin, OUTPUT);
 pinMode(SysPin, INPUT);
 pinMode(Pin_Vmin_led, OUTPUT); // заниженное напряжение
 pinMode(Pin_Vmax_led, OUTPUT); // завышенное напряжение
 pinMode(Pin_V_ok_led, OUTPUT); // напряжение в норме
 
/*   for (int s=1; s <= 16; s++) {
   read_sensor();
   } */
}

void loop() {
// sensorValue = analogRead(sensorPin);  // получение амплитуды входного напряжения прямым чтением порта ацп
// read_sensor();                        // получение амплитуды входного напряжения чтением через цифровой фильтр
// read_RMS();                           // получение амплитуды входного напряжения через рассчёт RMS
   read_VMAX();                          // получение амплитуды входного напряжения через поиск экстремума

 if (sensorValue <= (V_min) || sensorValue >= (V_max)) {  //тут делаем сравнение двух значении если в сети 170в  или 250в  то сбрасываем флаг
   Vin_OK = 0;
   Flag_T1 = 0;
 
    }

 else if (sensorValue > (V_min + V_gist) && sensorValue < (V_max - V_gistv)) {  // напряжение включения реле сдвигаем на величину гистерезиса
   Vin_OK = 1;
   if (Flag_T1 == 0) {
     previousMillis = millis();  //реле задержки включения
     Flag_T1 = 1;
   }
 }

// командами digitalRead(SysPin)==ReleOFF и digitalRead(SysPin)==ReleON избавляемся от повторной установки (НОГОДРЫГ)
// состояния реле, если уже установлено, надо ли это делать можно посмотреть осциллографом
// или триггером ловушкой оценить состояние пина в установившемся состоянии реле

 if (digitalRead(SysPin) == ReleOFF && Vin_OK == 1 && Flag_T1 == 1 && (millis() - previousMillis) >= T1) digitalWrite(RelePin, ReleON);
 else if (digitalRead(SysPin) == ReleON && Vin_OK == 0) digitalWrite(RelePin, ReleOFF);   //else digitalWrite(RelePin, ReleOFF);

 if(digitalRead(SysPin) == ReleON){digitalWrite(Pin_V_ok_led, HIGH);}
 else {digitalWrite(Pin_V_ok_led, LOW);}

 Serial.println(sensorValue); // выводим информацию в сериал порт

/* попищим и помигаем светодиодами если с напряжением что-то не так */
     if (sensorValue <= (V_min+V_gist ) && digitalRead(SysPin) == ReleOFF){  // тут пищим бузером если напряжение ниже нормы
     digitalWrite(Pin_Vmin_led, HIGH);
     bipers(); // Если напряжение не в норме то сработал biper
     digitalWrite(Pin_Vmin_led, LOW);
    }
    if (sensorValue >= (V_max-V_gistv) && digitalRead(SysPin) == ReleOFF){ // здесь пищим бузером если напряжение выше нормы
     digitalWrite(Pin_Vmax_led, HIGH);
     bipers2(); // Если напряжение не в норме то сработал biper
     digitalWrite(Pin_Vmax_led, LOW);
    }
 delay(100);
}

Схему можно дополнить такой защёлкой и немного изменить код

int sensorPin = A0; // аналоговый вход
int RelePin = 12;  // управление реле на 12 пине
int SysPin = 11;  // это пин соединить с 12, цифровой вход, защита от ногодрыга
int RsPin = 10;  // этот пин для разряда конденсатора защёлки

unsigned int sensorValue = 0; // переменная напряжения сенсора
static unsigned long G;       // Переменная для накопления показаний датчика сенсора
//double S = 1.25;
//float S1=0;

int b = 8;  //объявляем переменную с номером пина, на который подключен biper
int Pin_Vmin_led = 7;
int Pin_Vmax_led = 6;
int Pin_V_ok_led = 5;
int V_min = 352;      // коэффициент для минимального напряжения равного 170 вольт
int V_max = 525;      // коэффициент для максимального напряжения равного 250 вольт
int V_gist = 10;      // гистерезис, без цифровой обработки значения входящего напряжения не может быть менее 7
                     // если будем использовать цифровой фильтр, то можно уменьшить, предположительно до значения 3
int V_gistv = 15;     // гистерезис для высокого напряжения                

byte Vin_OK = 0;  //эта переменная служит для проверки входного напряжение, входит ли оно в наши установки, если входит, то 1, нет 0
byte Flag_T1 = 0;  //этот флаг информирует,что было зафиксировано правильное входное напряжение и запущен счетчик выдержки паузы на включение реле
unsigned int T1 = 10000;  // время задержки реле включения
unsigned long previousMillis = 0;

/* следующая ниже конструкция по идее должна бы высвободить 2 байта памяти занятые под переменные
* и будет более правильной, так как использует команды препроцессора и по сути является макросом
* заменяя в нужных местах слова на цифровые значения
* при использовании реле с прямой логикой просто заменить 0 на 1, а 1 на ноль
*/
#define ReleON  0  // реле включено
#define ReleOFF 1  // реле выключено


/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers() {
 tone (b, 3000); //включаем тон 3000 Гц
 delay(200); //ждем 200 Мс
 noTone(b ); // отключаем
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers2() {
 tone (b, 7000); //включаем тон 7000 Гц
 delay(73); //ждем 73 Мс
 noTone(b ); // отключаем
}

void read_sensor(){
  for (int j=1; j <= 96; j++) {
  sensorValue = analogRead(sensorPin);
  G+=sensorValue-(G>>8);
  sensorValue=G>>8;                      // показания сенсора после цифрового фильтра
}
 }

void read_RMS(){
  G=0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  G+=sq(sensorValue);
  }
  float S1=(G/100);
  double S=sqrt(S1);
  sensorValue =  S;  
  }

void read_VMAX(){
  int vmax =0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  if (sensorValue >vmax){vmax=sensorValue;}
  }
  sensorValue =  vmax; 
}

void read_VMAX1(){
  digitalWrite(RsPin, ReleON); 
  delay(1);
  digitalWrite(RsPin, ReleOFF);         // Разрядили конденсатор защёлки 
  delay(10);                            // Заряжаем конденсатор до пикового напряжения
  sensorValue = analogRead(sensorPin);  // Измеряем 
 }
 
void setup() {
 Serial.begin(9600); // скорость порта
 pinMode(RelePin, OUTPUT);
 pinMode(SysPin, INPUT);
  pinMode(RsPin, OUTPUT);
 pinMode(Pin_Vmin_led, OUTPUT); // заниженное напряжение
 pinMode(Pin_Vmax_led, OUTPUT); // завышенное напряжение
 pinMode(Pin_V_ok_led, OUTPUT); // напряжение в норме
 
/*   for (int s=1; s <= 16; s++) {
   read_sensor();
   } */
}

void loop() {
// sensorValue = analogRead(sensorPin);  // получение амплитуды входного напряжения прямым чтением порта ацп
// read_sensor();                        // получение амплитуды входного напряжения чтением через цифровой фильтр
// read_RMS();                           // получение амплитуды входного напряжения через рассчёт RMS
// read_VMAX();                          // получение амплитуды входного напряжения через поиск экстремума
   read_VMAX1();                         // получение амплитуды входного напряжения через защёлку, по сути аналогичен предыдущему
                                         // но с применением аппартной защёлки 
                                         // отсюда - <a data-cke-saved-href="http://arduino.ru/forum/programmirovanie/izmerenie-amplitudy-impulsa#comment-184770" href="http://arduino.ru/forum/programmirovanie/izmerenie-amplitudy-impulsa#comment-184770" rel="nofollow">http://arduino.ru/forum/programmirovanie/izmerenie-amplitudy-impulsa#comment-184770</a>

 if (sensorValue <= (V_min) || sensorValue >= (V_max)) {  //тут делаем сравнение двух значении если в сети 170в  или 250в  то сбрасываем флаг
   Vin_OK = 0;
   Flag_T1 = 0;
 
    }

 else if (sensorValue > (V_min + V_gist) && sensorValue < (V_max - V_gistv)) {  // напряжение включения реле сдвигаем на величину гистерезиса
   Vin_OK = 1;
   if (Flag_T1 == 0) {
     previousMillis = millis();  //реле задержки включения
     Flag_T1 = 1;
   }
 }

// командами digitalRead(SysPin)==ReleOFF и digitalRead(SysPin)==ReleON избавляемся от повторной установки (НОГОДРЫГ)
// состояния реле, если уже установлено, надо ли это делать можно посмотреть осциллографом
// или триггером ловушкой оценить состояние пина в установившемся состоянии реле

 if (digitalRead(SysPin) == ReleOFF && Vin_OK == 1 && Flag_T1 == 1 && (millis() - previousMillis) >= T1) digitalWrite(RelePin, ReleON);
 else if (digitalRead(SysPin) == ReleON && Vin_OK == 0) digitalWrite(RelePin, ReleOFF);   //else digitalWrite(RelePin, ReleOFF);

 if(digitalRead(SysPin) == ReleON){digitalWrite(Pin_V_ok_led, HIGH);}
 else {digitalWrite(Pin_V_ok_led, LOW);}

 Serial.println(sensorValue); // выводим информацию в сериал порт

/* попищим и помигаем светодиодами если с напряжением что-то не так */
     if (sensorValue <= (V_min+V_gist ) && digitalRead(SysPin) == ReleOFF){  // тут пищим бузером если напряжение ниже нормы
     digitalWrite(Pin_Vmin_led, HIGH);
     bipers(); // Если напряжение не в норме то сработал biper
     digitalWrite(Pin_Vmin_led, LOW);
    }
    if (sensorValue >= (V_max-V_gistv) && digitalRead(SysPin) == ReleOFF){ // здесь пищим бузером если напряжение выше нормы
     digitalWrite(Pin_Vmax_led, HIGH);
     bipers2(); // Если напряжение не в норме то сработал biper
     digitalWrite(Pin_Vmax_led, LOW);
    }
 delay(100);
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Для функции read_VMAX1();

И для read_VMAX();

 

Logik
Offline
Зарегистрирован: 05.08.2014

ua6em пишет:

ulis пишет:

ua6em пишет:

по сути классическое реле напряжения в котором напряжение срабатывания одно, напряжение удержания другое, с нюансами )))

Но я все таки хочу спросить про функцию read_sensor. Вы говорите, что это цифровой фильтр .... нижних, верхних или полосовой? Можно как-то, гляда на код функции, сказать, что это первый порядок? И зачем там фильтр вообще? Я почему интересуюсь - потому-что хочу собрать что-то подобное, но не для отключения, а для мониторинга качества сети и записи на СД карту, чтобы потом можно было ткнуть носом энерго компанию за их качество электричества

Это к LOGIK, код он подсказал когда я потерялся как усреднять показания )))

Ну я. НЧ конечно. Первого, зуб даю что не третьего и не половинного. Только порядок у цифровых и аналоговых - немного сильно отличаются;) А чего сомнения у Вас? Зачем он там- ну он не помешает. Вобще если автор посчитал и всунул - знач нужно.

А энергокомпанию тыкать носом ненадо. Она вас в ответ как тыкнет - век без ликтричества будете. Так шо хавайте ток того качества, что дают или вобще не хавайте.  И вобще, ваша поделка сертификат имеет? метрологически поверена? В реестре средств измерения числится? Пломбы целы? срок поверки не истек? И що Вы своей марахайкой сможете показать после всего этого? 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

LOGIK! На сей момент самым качественным решением оказалось решение на основе ПУЗЫРЬКА, поиск экстремума )))
read_VMAX();

andriano
andriano аватар
Онлайн
Зарегистрирован: 20.06.2015

ua6em пишет:

LOGIK! На сей момент самым качественным решением оказалось решение на основе ПУЗЫРЬКА, поиск экстремума )))
read_VMAX();

А зачем для экстремума пузырек? Экстремуму достаточно O(N), тогда как пузырек O(N^2).

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

ua6em пишет:

LOGIK! На сей момент самым качественным решением оказалось решение на основе ПУЗЫРЬКА, поиск экстремума )))
read_VMAX();

А зачем для экстремума пузырек? Экстремуму достаточно O(N), тогда как пузырек O(N^2).

я же и написал на основе ПУЗЫРЁК, проход то всего один )))
 

Исправленный вариант скетча:

 


int sensorPin = A0; // аналоговый вход
int RelePin = 12;  // управление реле на 12 пине
int SysPin = 11;  // это пин соединить с 12, цифровой вход, защита от ногодрыга
int RsPin = 10;  // этот пин для разряда конденсатора защёлки

unsigned int sensorValue = 0; // переменная напряжения сенсора
static unsigned long G;       // Переменная для накопления показаний датчика сенсора
//double S = 1.25;
//float S1=0;

int b = 8;  //объявляем переменную с номером пина, на который подключен biper
int Pin_Vmin_led = 7;
int Pin_Vmax_led = 6;
int Pin_V_ok_led = 5;
int V_min = 352;      // коэффициент для минимального напряжения равного 170 вольт
int V_max = 525;      // коэффициент для максимального напряжения равного 250 вольт
int V_gist = 20;      // гистерезис, без цифровой обработки значения входящего напряжения не может быть менее 7
                      // если будем использовать цифровой фильтр, то можно уменьшить, предположительно до значения 3
int V_gistv = 20;     // гистерезис для высокого напряжения  
                      // коэффицент ориентировочный 2 единицы на вольт (рабоачая зона 180-240 вольт)              

byte Vin_OK = 0;  //эта переменная служит для проверки входного напряжение, входит ли оно в наши установки, если входит, то 1, нет 0
byte Flag_T1 = 0;  //этот флаг информирует,что было зафиксировано правильное входное напряжение и запущен счетчик выдержки паузы на включение реле
unsigned int T1 = 10000;  // время задержки реле включения
unsigned long previousMillis = 0;

/* следующая ниже конструкция по идее должна бы высвободить 2 байта памяти занятые под переменные
* и будет более правильной, так как использует команды препроцессора и по сути является макросом
* заменяя в нужных местах слова на цифровые значения
* при использовании реле с прямой логикой просто заменить 0 на 1, а 1 на ноль
*/
#define ReleON  0  // реле включено
#define ReleOFF 1  // реле выключено


/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers() {
 tone (b, 3000); //включаем тон 3000 Гц
 delay(200); //ждем 200 Мс
 noTone(b ); // отключаем
}

/* высокий тон высокачая частота мигания светодиода - напряжение завышено */
void bipers2() {
 tone (b, 7000); //включаем тон 7000 Гц
 delay(73); //ждем 73 Мс
 noTone(b ); // отключаем
}

void read_sensor(){
  for (int j=1; j <= 96; j++) {
  sensorValue = analogRead(sensorPin);
  G+=sensorValue-(G>>8);
  sensorValue=G>>8;                      // показания сенсора после цифрового фильтра
}
 }

void read_RMS(){
  G=0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  G+=sq(sensorValue);
  }
  float S1=(G/100);
  double S=sqrt(S1);
  sensorValue =  S;  
  }

void read_VMAX(){
  int vmax =0;
  for (int k=1; k <= 100; k++) {
  sensorValue = analogRead(sensorPin);
  if (sensorValue >vmax){vmax=sensorValue;}
  }
  sensorValue =  vmax; 
}

void read_VMAX1(){
  digitalWrite(RsPin, ReleON); 
  delay(1);
  digitalWrite(RsPin, ReleOFF);         // Разрядили конденсатор защёлки 
  delay(10);                            // Заряжаем конденсатор до пикового напряжения
  sensorValue = analogRead(sensorPin);  // Измеряем 
 }
 
void setup() {
 Serial.begin(9600); // скорость порта
 pinMode(RelePin, OUTPUT);
 pinMode(SysPin, INPUT);
 pinMode(RsPin, OUTPUT);
 pinMode(Pin_Vmin_led, OUTPUT); // заниженное напряжение
 pinMode(Pin_Vmax_led, OUTPUT); // завышенное напряжение
 pinMode(Pin_V_ok_led, OUTPUT); // напряжение в норме
 
/*   for (int s=1; s <= 16; s++) {
   read_sensor();
   } */
}

void loop() {
// sensorValue = analogRead(sensorPin);  // получение амплитуды входного напряжения прямым чтением порта ацп
// read_sensor();                        // получение амплитуды входного напряжения чтением через цифровой фильтр
// read_RMS();                           // получение амплитуды входного напряжения через рассчёт RMS
// read_VMAX();                          // получение амплитуды входного напряжения через поиск экстремума
   read_VMAX1();                         // получение амплитуды входного напряжения через защёлки, по сути аналогичен предыдущему
                                         // но с применением аппартной защёлки 
                                         // отсюда - <a data-cke-saved-href="http://arduino.ru/forum/programmirovanie/izmerenie-amplitudy-impulsa#comment-184770" href="http://arduino.ru/forum/programmirovanie/izmerenie-amplitudy-impulsa#comment-184770" rel="nofollow">http://arduino.ru/forum/programmirovanie/izmerenie-amplitudy-impulsa#comment-184770</a>

 if (sensorValue <= (V_min) || sensorValue >= (V_max)) {  //тут делаем сравнение двух значении если в сети 170в  или 250в  то сбрасываем флаг
   Vin_OK = 0;
   Flag_T1 = 0;
 
    }

 else if (sensorValue > (V_min + V_gist) && sensorValue < (V_max - V_gistv)) {  // напряжение включения реле сдвигаем на величину гистерезиса
   Vin_OK = 1;
   if (Flag_T1 == 0) {
     previousMillis = millis();  //реле задержки включения
     Flag_T1 = 1;
   }
 }

// командами digitalRead(SysPin)==ReleOFF и digitalRead(SysPin)==ReleON избавляемся от повторной установки (НОГОДРЫГ)
// состояния реле, если уже установлено, надо ли это делать можно посмотреть осциллографом
// или триггером ловушкой оценить состояние пина в установившемся состоянии реле

 if (digitalRead(SysPin) == ReleOFF && Vin_OK == 1 && Flag_T1 == 1 && (millis() - previousMillis) >= T1) digitalWrite(RelePin, ReleON);
 else if (digitalRead(SysPin) == ReleON && Vin_OK == 0) digitalWrite(RelePin, ReleOFF);   //else digitalWrite(RelePin, ReleOFF);

 if(digitalRead(SysPin) == ReleON){digitalWrite(Pin_V_ok_led, HIGH);}
 else {digitalWrite(Pin_V_ok_led, LOW);}

 Serial.println(sensorValue); // выводим информацию в сериал порт

/* попищим и помигаем светодиодами если с напряжением что-то не так */
     if (sensorValue <= (V_min+V_gist) && digitalRead(SysPin) == ReleOFF){  // тут пищим бузером если напряжение ниже нормы
     digitalWrite(Pin_Vmin_led, HIGH);
     bipers(); // Если напряжение не в норме то сработал biper
     digitalWrite(Pin_Vmin_led, LOW);
    }
    if (sensorValue >= (V_max-V_gistv) && digitalRead(SysPin) == ReleOFF){ // здесь пищим бузером если напряжение выше нормы
     digitalWrite(Pin_Vmax_led, HIGH);
     bipers2(); // Если напряжение не в норме то сработал biper
     digitalWrite(Pin_Vmax_led, LOW);
    }
 delay(100);
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Lachin! Когда соберёшь схему с аппаратной защёлкой, скинь сюда осциллограмку в точке A0!!!
Из просмотренных в справочнике диодов шоттки, о каких я лично имею  представление, думаю стоит попробовать тип BAT62, из советских ГД-507, но первый лучше, но для этого конкретного случая в принципе должны работать любые

Logik
Offline
Зарегистрирован: 05.08.2014

ua6em пишет:

andriano пишет:

ua6em пишет:

LOGIK! На сей момент самым качественным решением оказалось решение на основе ПУЗЫРЬКА, поиск экстремума )))
read_VMAX();

А зачем для экстремума пузырек? Экстремуму достаточно O(N), тогда как пузырек O(N^2).

я же и написал на основе ПУЗЫРЁК, проход то всего один )))

Говорил же, что ПУЗЫРЬКОМ не совсем то называют ))) Вот люди и путаются.

Там просто полный перебор для поиска экстремума, он конечно O(N). Но долго и уж слишком по рабочекрестянски. Градиентный спуск, к примеру, покрасивше бы был.

Ну для поиска еще ладно, годится, чтоб на локальный экстремум не нарватся,  но для поддержания уж совсем некошерно. Или у Вас поддержание не требуется, нашли раз при старте и все?

ПС. Для тех кто не понял - это был офтоп по теме про черный ящик.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Logik пишет:

ua6em пишет:

andriano пишет:

ua6em пишет:

LOGIK! На сей момент самым качественным решением оказалось решение на основе ПУЗЫРЬКА, поиск экстремума )))
read_VMAX();

А зачем для экстремума пузырек? Экстремуму достаточно O(N), тогда как пузырек O(N^2).

я же и написал на основе ПУЗЫРЁК, проход то всего один )))

Говорил же, что ПУЗЫРЬКОМ не совсем то называют ))) Вот люди и путаются.

Там просто полный перебор для поиска экстремума, он конечно O(N). Но долго и уж слишком по рабочекрестянски. Градиентный спуск, к примеру, покрасивше бы был.

Ну для поиска еще ладно, годится, чтоб на локальный экстремум не нарватся,  но для поддержания уж совсем некошерно. Или у Вас поддержание не требуется, нашли раз при старте и все?

ПС. Для тех кто не понял - это был офтоп по теме про черный ящик.

да нет жеж, меряется из лупа, так как синхронизации прохода через ноль нет, от слова совсем, меряю сплошным потоком 100 раз в цикле (не менее 10 мллисекунд), максимум из этого массива и считаем экстремумом, я понимаю, что есть затраты в тактах между измерениями, но раз оно по даташиту 100 микросекунд принимаем, что за период между измерениями грандиозных изменений нет )))
С аппаратной защёлкой вообще всё должно быть абсолютно точно в пределах погрешности ацп, но и по этому методу получилось уложиться в 2 единицы ацп )))

А вот по Градиентному спуску - заставишь меня посмотреть, что это такое ))) так как подумалось, может еще какой метод измерения напряжения впендюрить ))) а вот до твоего поста мыслей то и не было

ЗЫ чёрный ящик в деле, сижу лечу протрузии шейных

PPS
Посмотрел, смысла не увидел, так как 10 миллисекунд мы обязаны обрабатывать сигнал при любых типах измерений, хоть с защёлкой, хоть напрямую усредняя или пропуская через цифровой фильтр

Метод красивый конечно:

Про градиент брал отсюда

Logik
Offline
Зарегистрирован: 05.08.2014

Не совсем понимаю, но всеже рабочая точка немного раскачивается?

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