Линия задержки данных

Здравствуйте.
Я в С++ ни бум-бум, только немного в С# могу.

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

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

У меня есть определённая сигнатура события, я должен прогонять эти данные через обработку, получать среднее скользящее, но не просто среднее скользящее, а условно говоря, сразу три средних скользящих, для трёх соседних последовательностей значений, ну вы поняли, которые расположены на шкале времени рядом. Например в первом отрезке 1-20 отсчёты, во втором 21-40, в третьем - 21-60.
Опытным путём было установлено какое там среднее скользящее, и когда для всех трёх групп отсчётов средние значения попадают в заданный диапазон, мы считаем, что событие распознано по сигнатуре, и влечёт там за собой всё что надо дальше.

Так вот, чтобы это реализовать, надо записывать в массив значения последовательно, а считывать с некоторым отставанием.

Мы задаём на входе в ноду размер этой задержки(nValue в моём коде), тип integer, принимаем импульс, по которому происходит запись и выдача нужного значения, заводим в ноду тип int, и выводим тоже его.

Я резонно рассудил, что размер массива должен быть равен nValue+1, и он должен быть динамическим.

Написал код, а он не работает, смотрю на него и не понимаю.
Даже i не считается, останавливается на единице.

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

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

Выяснил, что счётчик считает через 1, если импульс upd подавать с задержкой относительно того, как обновляются данные на входе…
Если значение на входе меняется одновременно с импульсом, то счётчик считает как надо.
задержка данных.txt (681 Bytes)

Try this out… I’ve adapted for decimal math (float). This is really nice.


#pragma XOD evaluate_on_pin disable
#pragma XOD evaluate_on_pin enable input_UPD
#pragma XOD evaluate_on_pin enable input_RST

node{
    // Internal state variables defined at this level persists across evaluations
    int i;
    float* A;
    bool full;

void evaluate(Context ctx) {
    float inValue = getValue<input_IN>(ctx);
    int nValue = getValue<input_N>(ctx);


        if (isSettingUp()) {
            A = new float[nValue];
            i=0;
        }


        if (isSettingUp() || isInputDirty<input_RST>(ctx)) {
            memset(A, 0, sizeof(float)*nValue);
            i = 0;
            full = false;
        }

    if (! (isInputDirty<input_UPD>(ctx) || isInputDirty<input_RST>(ctx)) )
        return;

    A[i] = inValue;
    float avg = 0;
    for (int ii = 0; ii < nValue; ii++) {
         avg = avg + A[ii];
    }
    avg = avg / static_cast<float>(nValue);

    i++;
    if (i>nValue-1){ 
        full = true;
        i = 0;
    }

       emitValue<output_OUT>(ctx, avg);
       emitValue<output_FULL>(ctx, full);
}
}


This is designed to have a single dimension of the array, at start time. Though, if you want your moving average to change in size, then the code I’ve given can be adjusted. I also added a flag “FULL” to signal when all the values in the array have been filled. Also, added a reset pulse. So, it resets, and takes the first value for the new average.

image

I’ve been thinking on how to do the moving average, and have only a work-around for 3x moving average. There is a moving average in a library, too. Though, this is way better. Thanks for setting it up. It enabled me to apply what I know, and learn some new stuff, to get the job done!

Here’s the Code I made:
moving-average.xodball (6.4 KB)

Thanks!
~XBX~

Thanx for answer, but you understand task wrong.
I was trying to write buffer for N values, that emits 1 value, whan at input reads N+1 value.

So at that time, I did it on my own, writing working code, but 2 kilobytes of memory allows storing only 400 samples, which turned out to be not enough for my task.

You might be able to get close to what you want by keeping a previous value & current value. To get the new average you would use ((399 * prev) + curr ) / 400. The result becomes your output and prev value. This gives you a weighted average that should be close to the running average you are looking for. You will have crazy answers your first 399 updates unless you set prev to curr on first call (how do you determine it is first call if you can’t assume it is first if prev=0?).

I think I understand you. The array method could work.
You could fill the array, as I did in the moving average. Then, when it is full, start reporting the old index value to the output node, before replacing the array index with the new value… That’s very adaptable from the example I gave.
I’ll give it a try later.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.