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

Вот поэтому я и посетовал на отсутствие входных данных для расчета. Тем более, что:

И Вас это не настораживает?
Или самое главное “идеальный синусоид”?

Ну на то он и фильтр, чтобы отсекать в том числе и постоянную составляющую.
Но бесплатно ничего не бывает. Тем более, что расчеты Вы ведете в float, а не в double. А на осциллографе ни смещения частоты на несколько процентов , ни гармоник не замечаете…

Гм…
А Вы уверены, что это именно 38-я строка?

Объединить дело не хитрое, если устраивает “в режиме показометра”)))
Если нужно более-менее точно, надо весь код с нуля переписывать, да и то , на AVR не очень -то разгонишься(выше об этом сказали)

Вы наверное имели ввиду плоттер , т.к. в упор не вижу, куда здесь можно приложить щуп осциллографа))


Да, всё что сказал выше andriano в силе, я ничего не менял, лишь немного дописал., т.к. кто знает, что у вас за делитель

Спойлер
#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];
unsigned long timer; //UNSIGNED !!!


void setup()
{
  Serial.begin(115200);
  delay(300);
  pinMode(2, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.println("eff_voltage, voltage");

}

void loop()
{
  static unsigned int tik = 0; // счётчик циклов
  static float Vcalc = 0.0;    // для промежут. вычислений
  static float Veff = 0.0;    // эфф. значение напряжения

  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(Veff);
    Serial.print(" ");
    Serial.println(y, 1);

    if (y >= 0.0) {
      Vcalc = Vcalc + y;
    }
    if (y < 0.0) {
      Vcalc = Vcalc - y;
    }                      //сумма
    tik++;
    if (tik >= 400) {      // каждые 800мс

      Vcalc /= (float) tik; // среднее
      Veff = Vcalc * 1.11;  // действующее

      tik = 0;
    }
  }
}

по осциллографу, при включении сигнала и выключении сигнала амплитуды стали значительно зашкаливать и с изменением частоты. Измерение с довольно сильным запаздыванием. Спасибо большое за попытку, и подскажите STM32F4 сможет решить проблему с измерением среднеквадратического сигнала? Переключился на Raspberry Pi Pico, надо будет сходить за STM :laughing: К стати использую виртуальный осциллограф, название на картинке в левом верхнем углу. Позволяет выводить график с COM порта

1,2% гармоник (по ИНИ) я по осцилопупу вижу (видел), ну а 5-10% - легко

Слово “осциллограф” здесь надо брать в кавычки))

Ну так, если ваш изначальный “скетч” запустить, тоже самое, напр.
запуск при 100гц на входе (плоттер Arduino IDE)


Я же ничего не менял, лишь добавил немного…)))

Можно уменьшить, стр72, но будет заметно плавать
Я же говорю, показометр.
А по STM выше уже сказали

А в чём проблема? Что то не понятно что нужно сделать. Судя по первому посту нужно из оцифрованного сигнала (кстати сколько точек на период?) выделить гармонику 50 Гц и найти её величину. Или всё же среднеквадратическое полного сигнала? STM32F411 делает умножение за 1 такт, корень извлекает и делит за 14 тактов. Для расчёта среднеквадратичного надо точки возвести в квадрат, просуммировать, поделить на количество и взять корень. Если точек на период 64 то такой расчёт займёт около 2 мкс.

элеектроотехннику когда-нибудь изучали? иззвините ээто не димычуу вопрос а тс

Спасибо, nik182, за совет! Действительно, STM32 оказалась мощной штукой! Подключил к CUBE IDE библиотеку DSP, реализовал методом тыка и искусственного интеллекта YaGPT функцию RMS правда без буферизации и подтверждаю, что скорость какие то мкс. Так же есть и функции фильтрации, но информации по ним очень мало, знаю только что используется эта же таблица с коэффициентами фильтра, также помогает YaGPT. Может кто поможет разобраться с функцией arm_fir_sparse_f32 из библиотеки DSP в среде разработки CUBE IDE? можно и этот имеющийся код прикрутить, но там milis не работает, пытался вставить _clock_init(); выдает ошибку

Повторю вопрос. Что нужно сделать? Измерение “среднеквадратического” значения переменного сигнала или RMS гармоники 50 Гц переменного сигнала? Вычислять среднеквадратическое значение гармоники 50 Гц переменного сигнала через каждую оцифрованную точку не имеет ни какого смысла, т.к. сигнал гармоники синусоидальный и имеет стандартное преобразование через умножение максимального значения на коэффициент 0.707106781, что собственно и было запрограммировано в первом сообщении.

1 лайк

тогда нахрена фильтр?

задача состоит в следующем: требуется временное измерение входящих импульсов сигнала частотой 50Гц, проблема в том, что в в принимаемом сигнале различные частоты 100Гц
, 150Гц и 250 бывает. Поэтому и требуется фильтр, а также стабилизировать сигнал и измерение производить относительно определенного порога, но время импульса который входит на частоте 50Гц должен соответствовать времени выхода, поэтому в задаче допустимо временное смещение или фазовый сдвиг, но изменение времени входящего сигнала к выходящему недопустимо, а способ измерения порога отфильтрованного сигнала подойдет любая функция, главное не превышать истинные размеры входного сигнала с допуском не более 10мс. И функции закладываемые в STM32 из библиотеки DSP прекрасно решают эти задачи за мкс. Был бы рад если бы помогли с этими функциями библиотеки DSP

А ничего, что фильтр вносит и то, и другое. (несколько раз перечитал, но так и не понял, что допустимо, а что - нет)

Расшифруйте понятие “временное”. Импульс 50 Гц всегда имеет длительность 20 мс. Если импульс состоит из нескольких периодов, то длительность импульса будет кратна 20 мс. Если импульс начинается или заканчивается не на нулевом значении амплитуды, то при наличии в сигнале других частот, длительность импульса 50 Гц восстановить невозможно. Можно ещё раз сформулировать задачу? В том виде как она описана сейчас понять что требуется сделать сложно.

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

НИЧЁНЕПОНЯЛ но было интересно

Поддерживаю. Мне кажется, мы имеем дело с типичным случаем XY-проблемы.

1 лайк

Память ограничена, поэтому всегда есть края. Чем ближе амплитуда сигнала к нулю на краю, тем меньше гармоник. Можно накрыть сигнал оконной функцией и принудительно обнулить края, но если надо найти время отключения то это не поможет.
Цифровой фильтр никогда не рассчитывается на конкретную частоту. Частота среза фильтр всегда зависит от частоты оцифровки и составляет обычно 0-50% от частоты оцифровки. Поэтому нужно их нужно согласовывать.

Я тоже несколько раз перечитывал.
Но, вроде, если не считать “краев”, то все верно.

“Обычно” следует читать как “по теореме Котельникова”?

1 лайк

Или Найквиста.