Среднеквадратичное измерение переменного сигнала после полосового фильтра

Добрый день, форумчане! Прошу помощи в объединении двух кодов. Первый это полосовой фильтр сигнала настроенный на 50Гц, второй измерение среднеквадратического измерения переменного сигнала.
Полосовой фильтр:

#define N    5
float NUM[N+1] = { 
  0.01532520608050539800,
        0.00000000000000000000,
        -0.03065041216101079700,
        0.00000000000000000000,
        0.01532520608050539800
  };
float DEN[N+1] = { 
   1.00000000000000000000,
        -3.01655375560368010000,
        3.99960268004005300000,
        -2.62535482894370190000,
        0.76013222899613697000
  };

float mas1[N];
float mas2[N];
long timer;


void setup() 
{
  Serial.begin(115200);
  pinMode(2, OUTPUT);
 
  pinMode(LED_BUILTIN, OUTPUT);

}

void loop() 
{

   
  if (micros()-timer>=2000)
    {
      int adc= analogRead(A0);
      timer= micros();
     // первый контур
      for(int i=N-1; i>0; i--) mas1[i]=mas1[i-1];
      mas1[0]= adc;
      float sum1=0;
      for(int i=0; i<N; i++)
        {
          sum1= sum1+ mas1[i]*NUM[i];
        }
     // второй контур
      for(int i=N-1; i>0; i--) mas2[i]=mas2[i-1];
      float sum2=0;
      for(int i=1; i<N; i++)
        {
          sum2= sum2+ mas2[i]*DEN[i];
        }
        
     // сумма
      float y= sum1-sum2;
      mas2[0]= y; 
      Serial.print(analogRead(A0));
      Serial.print(" ");
      Serial.println(y,1);
      
   
  }
    }

Измерение среднеквадратического переменного сигнала:

const int sensorIn = A0;

double Voltage = 0;

double VRMS = 0;

int i;


void setup(){

 Serial.begin(115200);

 

}

void loop(){

  VRMS = voltage_READ();

  Serial.print(analogRead(A0));
   
  Serial.print("V = ");

  Serial.print(VRMS);

  Serial.println("V");

  delay(1000);

}

 float voltage_READ(void)

{

 float max;

 
 unsigned int temp=0;

 float maxpoint = 0;

 for(i=0;i<500;i++)

   {

      if(temp =analogRead(sensorIn),temp>maxpoint)

      {

         maxpoint = temp;

      }

   }

maxpoint = maxpoint *(10.0/1023.0);

maxpoint = (maxpoint -5.0);

maxpoint = maxpoint *110.1909091;

 max=maxpoint *.707106781;

 return max;

 }

Прошу строго не судить, недавно познакомился с ардуино. Библиотеку подключал по измерению среднеквадратического сигнала, но она медленнодействующая, что критично

а что за датчик?

Это не среднеквадратичное напряжение. Если скорость критична то надо брать процессор с аппаратным умножением. Плата блюпил на stm32f1 считает среднеквадратичное напряжение за период по 256 точкам за 800 мкс. Блакпил наstm32f4 почти в 3 раза быстрее. А к ардуине это всё имеет очень опосредованное отношение. Это вопросы цифровой обработки сигналов.

трансформатор

А какой процессор (плата)?

Даже в double не влезет…

1 лайк

в ардуине более 6 цифр после запятой - бессмысленны.

1 лайк

Ардуино НАНО

да фильтр то работает отлично, проблема стабилизировать цифры на выходе

@Medder , в исходнике фильтра у Вас несколько ошибок, а второй исходник вообще не имеет ничего общего с вычислением среднеквадратичного значения.

1 лайк

имеет только когда сигнал идеальной синосуидальной формы

Ну да. Сферический конь в вакууме… К тому же цифровой фильтр со столь малой свёрткой сильно не почистит исходный сигнал. Одна надежда на узкополосный трансформатор.

1 лайк

если не трудно, подскажите эти ошибки первого кода. Второй код - не вычисление среднеквадратического значения я знаю, просто пытался встроить из него функцию voltage_READ() в первый код на выход фильтра, но у меня что то коряво это получается. В принципе для меня этого было бы достаточно. Есть хорошая библиотека #include <TrueRMS.h>, но у него замедление аж за 300мс уходит

по осциллографу на выходе идеальный синусоид

полосой фильтр 2 порядка Чебышева не плохо работает, скетч любезно предоставил Дмитрий

По хорошему, там надо подробно разбираться в коде, т.к. реализация фильтра написана человеком, который в программировании не очень разбирается, а потому мог наделать ошибок, которые при поверхностном взгляде не видны. (А то, что Вы не привели исходные данные для расчета фильтра, только делает эту работу более трудоемкой)
Из того, что очевидно:
строка №37: а кто будет вычитать постоянную составляющую?
строки №35 и 38: как Вы думаете, каков период оцифровки? Так вот, он минимум на 6% отличается от того, на который Вы рассчитываете. Самый простой способ исправить, записать строку №38 в виде: timer += 2000;
объясните, что Вы вообще хотели сказать строкой №58? Если бы было Serial.print(adc);, я бы еще понял, а так…
Остальное надо подробно анализировать на наличие неочевидных ошибок и описок.

Вы всерьез надеетесь суметь отличить по осциллографу “идеальный синусоид” от сигнала с 5-10% гармоник?

должен быть unsigned long

для расчета фильтра берутся коэффициенты с матлаба и вставляются в код с 1 по 14 строки. В матлабе выбираешь характеристики фильтра и он вытаскивает коэффициенты. К стати при закладке в этот код почему то приходится расчеты в матлаб закладывать частоты в двое выше, не знаю чем это вызвано. Ноль исходного сигнала лежит в пределах 430 из-за использования мной делителя напряжения, а после фильтра постоянная составляющая исчезает и ноль находится на нуле. Попробовал исправить строку №38 с if (micros() - timer >= 2000) на if (timer += 2000) - теряется свойство полосового фильтра. №58 исправил на Serial.print(adc)

не работает с unsigned long

значить и с long не работает

Звучит занимательно.
“Будем наблюдать” (c)