как усреднить 100 значений датчика за секунду

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

Добрый день.

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

подскажите как в коде задать измерять 100 значений и усреднить их за секунду, чтобы отображалось постоянное текущее значение мощности?
например ампер (220v переменное)

 

#include <ACS712.h>                  
ACS712 sensor(ACS712_30A, A1);       

void setup() {
sensor.calibrate();
              }

  void loop(){
float I = sensor.getCurrentAC();   //Амперы
             }

 

-NMi-
Offline
Зарегистрирован: 20.08.2018

Это как, симистором по ШИМ???

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

-NMi- пишет:

Это как, симистором по ШИМ???

суть не в этом. как подсчитать и усреднить амперы (код выше)?

b707
Offline
Зарегистрирован: 26.05.2017

denis160374@gmail.com пишет:

суть не в этом. как подсчитать и усреднить амперы (код выше)?

это вопрос из детского сада?

Усреднить - сложить N измерений и потом разделить на N... в классе примерно пятом изучают.

anatoli_nik
Offline
Зарегистрирован: 17.01.2019

Скользящее среднее будет лучше. ИМХО.

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

b707 пишет:

denis160374@gmail.com пишет:

суть не в этом. как подсчитать и усреднить амперы (код выше)?

это вопрос из детского сада?

Усреднить - сложить N измерений и потом разделить на N... в классе примерно пятом изучают.

да. возможно из детского. вариантов много. но они размыты по длинному коду. и я новичек чтобы читать такие коды "с листа". поэтому обратился за помощью.  нужен просто кусок кода.

b707
Offline
Зарегистрирован: 26.05.2017

denis160374@gmail.com пишет:

нужен просто кусок кода.

#include <ACS712.h>                  
ACS712 sensor(ACS712_30A, A1);    
#define   K  100   // число измерений

void setup() {
sensor.calibrate();
              }

  void loop(){
  static int N =0;
  static float summ =0;
  float I = sensor.getCurrentAC();   //Амперы
  N++;
  summ += I;
  if (N == K)  { 
     float average = summ/ K;  // среднее 
      N =0;
      summ =0;
     } 
    }

 

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

b707 пишет:

denis160374@gmail.com пишет:

нужен просто кусок кода.

#include <ACS712.h>                  
ACS712 sensor(ACS712_30A, A1);    
#define   K  100   // число измерений

void setup() {
sensor.calibrate();
              }

  void loop(){
  static int N =0;
  static float summ =0;
  float I = sensor.getCurrentAC();   //Амперы
  N++;
  summ += I;
  if (N == K)  { 
     float average = summ/ K;  // среднее 
      N =0;
      summ =0;
     } 
    }

 

 

странно, но значения амперметра всё-равно скачут. не скачут при 0 и больше 250. пробовал не 100 а 1000 подсчетов делать - безрезультатно...

b707
Offline
Зарегистрирован: 26.05.2017

denis160374@gmail.com пишет:

странно, но значения амперметра всё-равно скачут. не скачут при 0 и больше 250. пробовал не 100 а 1000 подсчетов делать - безрезультатно...

и что, размах "скачков" тот же? - не верю

Покажите свой реальный код - как вы читаете данные с амперметра и как выводите данные на экран. в монитор или еще куда

rkit
Offline
Зарегистрирован: 23.11.2016

Библиотека уже считает RMS-ток как надо. Ошибка где-то еще. Скорее всего, в непонимании математики такого измерения.

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

b707 пишет:

denis160374@gmail.com пишет:

и что, размах "скачков" тот же? - не верю

Покажите свой реальный код - как вы читаете данные с амперметра и как выводите данные на экран. в монитор или еще куда

#include <ACS712.h>                  //для амперметра
ACS712 sensor(ACS712_30A, A1);       //для амперметра 30Ампер (5A, 20A, 30A)
#define   K  100                    //для амперметра - кол-во измерений
#include <LiquidCrystal.h>           //для экрана 16х2
LiquidCrystal lcd(8, 7, 6, 5, 4, 3); //для экрана 16х2


//----------------------ENCODER-----------------------------------------
int wattencoder = 120;       // мощность, начинаем с половины
int stepW = 5;        // шаг изменения мощности
unsigned long currentTime;
unsigned long loopTime;
const int pin_A = 9;       // pin 9
const int pin_B = 10;       // pin 10
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;
//-----------------------------VOLTMEMTR--------------------------------
const int analogInPin = A0;  
int Volt = 0;
float popravkaV = 0.3455;  //коэффициент под текущий блок питания



void setup() {
Serial.begin  (9600);
lcd.begin(16, 2);  
//------------------------------ENCODER---------------------------------
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  currentTime = millis();
  loopTime = currentTime; 
//----------------------СИМИСТОР---------------------------------
pinMode(11, OUTPUT);         // устанавливаем pin 11 как выход на симистор (ШИМ D3,5,6,9,10,11)

//-----------------------------AMPERMETR--------------------------------
sensor.calibrate();   
 }


  void loop(){

//----------------------ENCODER-----------------------------------------
  currentTime = millis();
  if(currentTime >= (loopTime + 5)){ // проверяем каждые 5мс (200 Гц)
    encoder_A = digitalRead(pin_A);     // считываем состояние выхода А энкодера 
    encoder_B = digitalRead(pin_B);     // считываем состояние выхода B энкодера    
    if((!encoder_A) && (encoder_A_prev)){    // если состояние изменилось с положительного к нулю
      if(encoder_B) {
        // выход В в полож. сост., значит вращение по часовой стрелке
        // увеличиваем яркость, не более чем до 1000
        if(wattencoder - stepW >= 0) {wattencoder -= stepW;}               
      }   
      else {
        // выход В в 0 сост., значит вращение против часовой стрелки     
        // уменьшаем яркость, но не ниже 0
        if(wattencoder + stepW <= 255) {wattencoder += stepW;}              
      }   
 
    }   
    encoder_A_prev = encoder_A;     // сохраняем значение А для следующего цикла   
    loopTime = currentTime;
  }                       
//-----------------------------VOLTMEMTR-----------------------------------
  Volt = analogRead(analogInPin);   //Вольты 

//-----------------------------AMPERMETR-----------------------------------
  static int N =0;
  static float summ =0;
  float I = sensor.getCurrentAC();   //Амперы
  N++;
  summ += I;
  if (N == K)  { 
     float average = summ/ K;  // среднее 
      N =0;
      summ =0;
     } 
    
  float W = Volt*popravkaV * I;                // Ватты

    
  analogWrite(11, wattencoder); 

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(wattencoder, 1);   //установленная мощность
  lcd.setCursor(0, 2); 
  lcd.print(W, 0);             //реальная мощность
  lcd.setCursor(6, 2); 
  lcd.print(Volt*popravkaV,0); // V   
  lcd.setCursor(12, 2); 
  lcd.print(I, 2);             // A
  }
  
  
  

 

sadman41
Offline
Зарегистрирован: 19.10.2016

ACS712 не для слабаков. К нему хорошее психическое здоровье нужно и башка с мозгами.

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

sadman41 пишет:

ACS712 не для слабаков. К нему хорошее психическое здоровье нужно и башка с мозгами.

интересно то, что с покупным  тиристорным диммером работает идеально (), а вот после тиристор+ШИМардуино - скачет "аки конь"

b707
Offline
Зарегистрирован: 26.05.2017

denis160374@gmail.com пишет:

интересно то, что с покупным  тиристорным диммером работает идеально (), а вот после тиристор+ШИМардуино - скачет "аки конь"

вас в самом начале спрашивали уже - вы что тиристором с помощью ШИМа управляете? - где вы такое вычитали?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

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

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

управление киловатной электроплитой. контроль нагрева спирали симисором - не противозаконно. ТЭНами ещё управляют.

b707
Offline
Зарегистрирован: 26.05.2017

denis160374@gmail.com пишет:

управление киловатной электроплитой. контроль нагрева спирали симисором - не противозаконно. ТЭНами ещё управляют.

я вас не об этом спрашивал, я спрашивал кто вас надоумил управлять симистором с помощью ШИМ?

Вы в курсе, как работает симистор? а как ШИМ?  и главное, чем они отличаются?

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

BOOM пишет:

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

схема:

конденсатор (RC цепочку) вот по этой схеме добавил:

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

b707 пишет:

denis160374@gmail.com пишет:

управление киловатной электроплитой. контроль нагрева спирали симисором - не противозаконно. ТЭНами ещё управляют.

я вас не об этом спрашивал, я спрашивал кто вас надоумил управлять симистором с помощью ШИМ?

Вы в курсе, как работает симистор? а как ШИМ?  и главное, чем они отличаются?

намекаете что он может работать только как реле?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Намекает на обратное - шим это быстро включавшееся и выключающееся реле, а тиристору нужно аналоговое напряжение управления. 

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

BOOM пишет:

Намекает на обратное - шим это быстро включавшееся и выключающееся реле, а тиристору нужно аналоговое напряжение управления. 

вот обратное мнение. и скетч рабочий. так что аналоговое управление возможно и правильнее, но и по цифре ТЭНами тоже получается управлять. вопрос как заставить не скакать показания амперметра.....

"""""""

Итак, имелась плата  Arduino ProMini, к ней все и подключим. Код получается мелкий и простой, надеюсь, что сообщество извинит, что я его выкладываю прямо тут:

 

byte pers;  // Переменная для получения данных порта

int x;  // Переменная координат алгоритма Брезенхема

int y;  // Переменная координат алгоритма Брезенхема

int onoff ;  // Переменная сигнала на плату симистора

void setup() {

pinMode(12, OUTPUT); // Назначаем пин на выход (плата симистора)

}

void loop() {

pers = analogRead(pinPot); // Положение потенциометра

pers = map(pers, 0, 1013, 0, 100); // Переводим показания потенциометра в проценты

if (pot > 100) {pot = 100; }  // Ограничиваем значение

y = 0;

for (int i = 1; i <= 100; i++){  // Алгоритм Брезенхема

x = i * pers / 100 ; 

if (x == y) {onoff = 0;}

else {onoff = 1;}

digitalWrite(12, onoff);

delay(10);

y = x;

}

}

 

Ну вот, отлично работает эта схема. Крутим потециометр и смотрим на мигание лампочки на электрическом чайнике. Красота. Получился прекрасный диммер - регулятор мощности переменного тока, нагрузкой, если верить даташиту симистора, до 40A и напряжением до 600В при наличии хорошего радиатора.

"""""""

 

b707
Offline
Зарегистрирован: 26.05.2017

denis160374@gm , после просмотра вашего кода я уже ни на что не намекаю.

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

Знаете. у нас на форуме есть правило - готовый код новичкам не давать. С вами я отступил от правил - вы показались мне разумным человеком. я вижу. что я ошибся, вы еще не готовы писать собственные программы.

Идите светодиодиком помигайте

 

b707
Offline
Зарегистрирован: 26.05.2017

denis160374@gmail.com пишет:

 Код получается мелкий и простой, надеюсь, что сообщество извинит, что я его выкладываю прямо тут:

не извинит. Во-первых, вставлен неверно, во-вторых - он даже не компилируется.

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

b707 пишет:

denis160374@gmail.com пишет:

 Код получается мелкий и простой, надеюсь, что сообщество извинит, что я его выкладываю прямо тут:

не извинит. Во-первых, вставлен неверно, во-вторых - он даже не компилируется.

 

это не мой текст. а человека который его написал. и он не целый - поэтому не компилируется. вставлен для примера, что симистор и шим дружат.

b707
Offline
Зарегистрирован: 26.05.2017

denis160374@gmail.com пишет:

 он не целый - поэтому не компилируется.

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

Цитата:
вставлен для примера, что симистор и шим дружат.

я уж не знаю, тут смеятся или плакать. Во-первых, этот код имеет принципиальное отличие от ардуиновского ШИМ. Так что хотя в нем ошибка - его можно поравить... а ваш нет.

Ну а главное, что для вас все эти строчки - как иероглифы. Вы в них ничего не смыслите. Купите готовый диммер и не мучайтесь

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

b707 пишет:

denis160374@gmail.com пишет:

 он не целый - поэтому не компилируется.

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

вставлен для примера, что симистор и шим дружат.

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

Ну а главное, что для вас все эти строчки - как иероглифы. Вы в них ничего не смыслите. Купите готовый диммер и не мучайтесь

так я и пишу в "песочницу" а не в "программирование". т.к. не программист.  что я изолентой то прикрутил? кто тут спец я или тот кто отвечает? и я не прошу весь код "на блюдечке". это разные просьбы.

С электричеством дружу и все сделал - только прыгают показания амперметра.   ...и причем тут моргать диодиками...

b707
Offline
Зарегистрирован: 26.05.2017

denis160374@gmail.com пишет:

я не прошу весь код "на блюдечке". это разные просьбы.

А что вы просите, интересно? как вам помочь, если вы элементарных вещей не понимаете? вы получили готовый код усреднения и даже не смогли его вставить в свой скетч.

Я повторяю вопрос - где вы в своем коде используете усредненное значение, чтобы утверждать, что "усреднение не помогло"? - Вы как читали с датчика единичное значение тока - так и читаете, никакого усреднения 100 значений у вас и в помине нет.

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

 

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

понятно, что вместо I нужно указывать average 

static int N =0;
  static float summ =0;
  float I = sensor.getCurrentAC();   //Амперы
  N++;
  summ += I;
  if (N == Ka)  {
     float average = summ/ Ka;  // среднее
      N =0;
      summ =0;
     }
    
  float W = Volt*popravkaV * average;         

но тогда выходит ошибка: 'average' was not declared in this scope

-NMi-
Offline
Зарегистрирован: 20.08.2018

Шо_опять?  :)))

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

-NMi- пишет:

Шо_опять?  :)))

ДА! думаю вдруг тебе грустно так решил повеселить на ночь

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

denis160374@g

Попробуй вот так

#include <ACS712.h>                  //для амперметра
ACS712 sensor(ACS712_30A, A1);       //для амперметра 30Ампер (5A, 20A, 30A)
#define   K  100                    //для амперметра - кол-во измерений
#include <LiquidCrystal.h>           //для экрана 16х2
LiquidCrystal lcd(8, 7, 6, 5, 4, 3); //для экрана 16х2


//----------------------ENCODER-----------------------------------------
int wattencoder = 120;       // мощность, начинаем с половины
int stepW = 5;        // шаг изменения мощности
unsigned long currentTime;
unsigned long loopTime;
const int pin_A = 9;       // pin 9
const int pin_B = 10;       // pin 10
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;
//-----------------------------VOLTMEMTR--------------------------------
const int analogInPin = A0;  
int Volt = 0;
float popravkaV = 0.3455;  //коэффициент под текущий блок питания



void setup() {
Serial.begin  (9600);
lcd.begin(16, 2);  
//------------------------------ENCODER---------------------------------
  pinMode(pin_A, INPUT);
  pinMode(pin_B, INPUT);
  currentTime = millis();
  loopTime = currentTime; 
//----------------------СИМИСТОР---------------------------------
pinMode(11, OUTPUT);         // устанавливаем pin 11 как выход на симистор (ШИМ D3,5,6,9,10,11)

//-----------------------------AMPERMETR--------------------------------
sensor.calibrate();   
 }


  void loop(){

//----------------------ENCODER-----------------------------------------
  currentTime = millis();
  if(currentTime >= (loopTime + 5)){ // проверяем каждые 5мс (200 Гц)
    encoder_A = digitalRead(pin_A);     // считываем состояние выхода А энкодера 
    encoder_B = digitalRead(pin_B);     // считываем состояние выхода B энкодера    
    if((!encoder_A) && (encoder_A_prev)){    // если состояние изменилось с положительного к нулю
      if(encoder_B) {
        // выход В в полож. сост., значит вращение по часовой стрелке
        // увеличиваем яркость, не более чем до 1000
        if(wattencoder - stepW >= 0) {wattencoder -= stepW;}               
      }   
      else {
        // выход В в 0 сост., значит вращение против часовой стрелки     
        // уменьшаем яркость, но не ниже 0
        if(wattencoder + stepW <= 255) {wattencoder += stepW;}              
      }   
 
    }   
    encoder_A_prev = encoder_A;     // сохраняем значение А для следующего цикла   
    loopTime = currentTime;
  }                       
//-----------------------------VOLTMEMTR-----------------------------------
  Volt = analogRead(analogInPin);   //Вольты 

//-----------------------------AMPERMETR-----------------------------------
  analogWrite(11, wattencoder);
  static int N =0;
  static float summ =0;
  float W =0;
  float I = sensor.getCurrentAC();   //Амперы
  N++;
  summ += I;
  if (N == K)  { 
     float average = summ/ K;  // среднее 
      N =0;
      summ =0;
   float W = Volt*popravkaV * average;                // Ватты
  }
    
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(wattencoder, 1);   //установленная мощность
  lcd.setCursor(0, 2); 
  lcd.print(W, 0);             //реальная мощность
  lcd.setCursor(6, 2); 
  lcd.print(Volt*popravkaV,0); // V   
  lcd.setCursor(12, 2); 
  lcd.print(I, 2);             // A
  }

 

denis160374@gma...
Offline
Зарегистрирован: 25.02.2020

b707 пишет:

denis160374@gmail.com пишет:

нужен просто кусок кода.

#include <ACS712.h>                  
ACS712 sensor(ACS712_30A, A1);    
#define   K  100   // число измерений

void setup() {
sensor.calibrate();
              }

  void loop(){
  static int N =0;
  static float summ =0;
  float I = sensor.getCurrentAC();   //Амперы
  N++;
  summ += I;
  if (N == K)  { 
     float average = summ/ K;  // среднее 
      N =0;
      summ =0;
     } 
    }

 

всё заработало. больше не прыгает. нужно было вверху строчку дописать:

#include <ACS712.h>                  
ACS712 sensor(ACS712_30A, A1);    
float average=0;  ===ВОТ ЭТУ===
#define   K  100   // число измерений

остановился на 64 опросах. дальше тормозит. 64 делает за 5,5сек

b707
Offline
Зарегистрирован: 26.05.2017

denis160374@gmail.com пишет:

остановился на 64 опросах. дальше тормозит.

опять значит код "изолентой примотали"