Плавающая СКО в Python - PullRequest
       0

Плавающая СКО в Python

0 голосов
/ 21 января 2020

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

Однако моя плавающая RMS не возвращает правильные значения, не связанные с размером моей выборки.

Код:

import matplotlib.pyplot as plot
import numpy as np
import math


if __name__ == '__main__':
    # sine generation
    time_array = []
    value_array = []
    start = 0
    end = 6*math.pi
    steps = 100000
    amplitude = 10

    #rms calc
    acc_load_current = 0
    sample_size = 1000

    for time in np.linspace(0, end, steps):
        time_array.append(time)
        actual_value = amplitude * math.sin(time)
        value_array.append(actual_value)

        # rms calc
        acc_load_current -= (acc_load_current/sample_size)
        # square here
        sq_value = actual_value * actual_value
        acc_load_current += sq_value
    # mean and then root here

    floating_rms = np.sqrt(acc_load_current/sample_size)
    fixed_rms = np.sqrt(np.mean(np.array(value_array)**2))
    math_rms = 1/math.sqrt(2) * amplitude

    print(floating_rms)
    print(fixed_rms)
    print(math_rms)

    plot.plot(time_array, value_array)
    plot.show()

Результат:

2.492669969708522
7.071032456438027
7.071067811865475

enter image description here

1 Ответ

0 голосов
/ 21 января 2020

Я решил проблему с помощью рекурсивного среднего с обнаружением пересечения нуля:

import matplotlib.pyplot as plot
import numpy as np
import math


def getAvg(prev_avg, x, n):
    return (prev_avg * n + x) / (n+1)

if __name__ == '__main__':
    # sine generation
    time_array = []
    value_array = []
    used_value_array = []
    start = 0
    end = 6*math.pi + 0.5
    steps = 10000
    amplitude = 325

    #rms calc
    rms_stream = 0
    stream_counter = 0
    #zero crossing
    in_crossing = 0
    crossing_counter = 0
    crossing_limits = [-5,5]
    left_crossing = 0

    for time in np.linspace(0, end, steps):
        time_array.append(time)
        actual_value = amplitude * math.sin(time) + 4 * np.random.rand()
        value_array.append(actual_value)

        # detect zero crossing, by checking the first time we reach the limits
        # and then not counting until we left it again
        is_crossing = crossing_limits[0] < actual_value < crossing_limits[1]
        # when we are at amp/2 we can be sure the noise is not causing zero crossing
        left_crossing = abs(actual_value) > amplitude/2
        if is_crossing and not in_crossing:
            in_crossing = 1
            crossing_counter += 1
        elif not is_crossing and in_crossing and left_crossing:
            in_crossing = 0

        # rms calc
        # square here
        if 2 <= crossing_counter <= 3:
            sq_value = actual_value * actual_value
            rms_stream = getAvg(rms_stream, sq_value, stream_counter)
            stream_counter += 1
            # debugging by recording the used values
            used_value_array.append(actual_value)
        else:
            used_value_array.append(0)

    # mean and then root here
    stream_rms_sqrt = np.sqrt(rms_stream)

    fixed_rms_sqrt = np.sqrt(np.mean(np.array(value_array)**2))
    math_rms_sqrt = 1/math.sqrt(2) * amplitude

    print(stream_rms_sqrt)
    print(fixed_rms_sqrt)
    print(math_rms_sqrt)

    plot.plot(time_array, value_array, time_array, used_value_array)
    plot.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...