Найдите два худших значения и удалите в сумме - PullRequest
3 голосов
/ 26 февраля 2020

Микроконтроллер выполняет выборку значений AD C (аналого-цифровое преобразование). Поскольку на эти детали влияют допуск и шум, точность можно значительно повысить, удалив 4 худших значения. Поиск и удаление требуют времени, которое не является идеальным, поскольку это увеличит время цикла.

Представьте себе частоту 100 МГц, поэтому каждая команда программного обеспечения занимает 10 нс для обработки, чем больше команд, тем дольше Контроллер заблокирован от выполнения следующего набора выборок

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

uint16_t getValue(void){

    adcval[8] = {};
    uint16_t min = 16383 //14bit full
    uint16_t max = 1;    //zero is physically almost impossible!
    uint32_t sum = 0;    //variable for the summing

    for(uint8_t i=0; i<8;i++){
     if(adc[i] > max) max = adc[i];
     if(adc[i] < min) min = adc[i];
     sum=sum+adcval[i];
    }
    uint16_t result = (sum-max-min)/6;   //remove two worst and divide by 6
    return result;
}

Теперь я хотел бы расширить эту функцию, чтобы удалить 4 худших значения из 8 выборок, чтобы получить большую точность. Любой совет, как это сделать?

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

uint16_t adc1[8] {5,6,10,11,11,12,20,22};
uint16_t adc2[8] {5,6,7,7,10,11,15,16};

Первый случай получит точность по описанному механизму (удалите 4 худших). Но во втором случае удалялись бы значения 5 и 6, а также 15 и 16. Но это теоретически ухудшило бы вычисления, поскольку удаление 10,11,15,16 было бы лучше. Есть ли какое-нибудь быстрое решение удаления 4 самых отклоняющихся?

Ответы [ 4 ]

5 голосов
/ 27 февраля 2020
  1. Лучше запустить скользящее среднее. Что такое скользящее среднее? Это программный фильтр нижних частот. x Голубые показания из AD C, среднее значение красного хода

Второй сигнал - синусоида с очень низкой амплитудой (9-27 мВ - при условии 14 бит и 3.3Vref) enter image description here

Алгоритм:

static int average;
int running_average(int val, int level)
{
    average -= average / level;
    average += val * level;
    return average / level;
}

void init_average(int val, int level)
{
    average = val * level;
}

, если level является степенью 2. Эта версия требует только 6 инструкций (без ветвей) для вычисления среднего.

static int average;

int running_average(int val, int level)
{
    average -= average >> level;
    average += val << level;
    return average >> level;
}

void init_average(int val, int level)
{
    average = val << level;
}

Я предполагаю, что среднее значение не будет переполнено. Если да, вам нужно выбрать больший тип

1 голос
/ 29 февраля 2020

Этот ответ является своего рода топи c, поскольку он рекомендует аппаратное решение, но если требуется производительность и MCU не может реализовать решение P__J __, то это ваша следующая лучшая вещь.

Кажется, вы хотите удалить шум из вашего входного сигнала. Это можно сделать в программном обеспечении, используя DSP ( цифровая обработка сигналов ) , но , это также можно сделать, настроив ваше оборудование по-другому.

Добавив соответствующий фильтр в нужное пространство перед вашим AD C, можно будет удалить большой (внешний) шум из вашего выхода AD C. (Вы, конечно, не можете go ниже определенной суммы, которая является врожденной в AD C, но увы.)

Есть несколько вопросов и ответов на electronics.stackexchange.com .

  • Одним из решений является добавление конденсатора для фильтрации высокочастотного шума. Как отмечает DerStorm8
  • У Фотона есть еще одно замечательное решение , предложив R C, Sallen-Key и каскад фильтров Sallen-Key для непрерывного фильтр сигналов.
  • Здесь (ADN007) - это примечание по аналоговой конструкции от Microchip по «Методам, снижающим шум системы в AD C Цепи»

    Может показаться, что разработка малошумящей 12-разрядной платы аналого-цифрового преобразователя (AD C) или даже 10-разрядной платы - это просто. Это верно, если не игнорировать основы дизайна с низким уровнем шума. Например, можно подумать, что большинство усилителей и резисторов эффективно работают в 12-разрядных или 10-разрядных средах. Тем не менее, плохой выбор устройства становится основным фактором успеха или отказа схемы. Другой, часто игнорируемой, областью, которая вносит большой шум, является проводимый шум. К тому времени, когда сигнал поступает на вход AD C, кондуктивный шум уже присутствует на плате. Наиболее эффективный способ устранения этого шума - использование фильтра нижних частот (сглаживание) до AD C. Включение обводных конденсаторов и использование заземления также устранят этот тип шума. Третьим источником шума является излучаемый шум. Основными источниками этого типа шума являются электромагнитные помехи (EMI) или емкостная связь сигналов от трассировки к трассе. Если все три из этих проблем решены, то правда, что проектирование 12-битной платы AD C с низким уровнем шума - это просто.

    И их рекомендуемый путь решения:

    Легко спроектировать настоящую 12-битную систему AD C, используя несколько ключевых рекомендаций по низкому уровню шума. Сначала проверьте ваши устройства (резисторы и усилители), чтобы убедиться в их низком уровне шума. Во-вторых, используйте плоскость заземления, когда это возможно. В-третьих, включите фильтр нижних частот в тракте сигнала, если вы меняете сигнал с аналогового на цифровой. Наконец, всегда включайте байпасные конденсаторы. Эти конденсаторы не только удаляют шум, но и способствуют стабильности схемы.

  • Здесь - хорошая статья Analog Devices о входном шуме. Здесь они отмечают, что «в некоторых случаях входной шум может быть полезен для достижения более высокого разрешения».

    Все аналого-цифровые преобразователи (АЦП) имеют определенное количество входных сигналов шум - смоделирован как источник шума, соединенный последовательно с входом бесшумного AD C. Связанный с входом шум не следует путать с шумом квантования, который представляет интерес только тогда, когда AD C обрабатывает изменяющиеся во времени сигналы. В большинстве случаев меньше входного шума лучше; однако в некоторых случаях входной шум может быть полезен для достижения более высокого разрешения. Если сейчас это не имеет смысла, читайте дальше, чтобы узнать, как шум может быть хорошим.

0 голосов
/ 27 февраля 2020

для удаления 4 худших значений из 8 выборок

Методы описаны для geeksforgeeks k самых больших (или самых маленьких) элементов в массиве , и вы может реализовать лучший метод, который вам подходит.

Я решил использовать этот хороший сайт для генерации лучшего алгоритма сортировки с макросами SWAP(), необходимыми для сортировки массива из 8 элементов. Затем я создал небольшую C программу, которая будет проверять любую комбинацию из 8 элементов массива в моей функции сортировки. Затем, поскольку мы заботимся только о группах из 4 элементов, я сделал что-то грубое - для каждого из макросов SWAP() я попытался прокомментировать макрос и посмотреть, будет ли программа по-прежнему успешной. Я мог бы прокомментировать 5 SWAP макросов, оставив 14 сравнений, необходимых для идентификации наименьших 4 элементов в массиве из 8 выборок.

/**
 * Sorts the array, but only so that groups of 4 matter.
 * So group of 4 smallest elements and 4 biggest elements
 * will be sorted ok.
 * s[0]...s[3] will have lowest 4 elements
 *     so they have to be "deleted"
 * s[4]...s[7] will have the highest 4 values
 */
void sort_but_4_matter(int s[8]) {
#define SWAP(x, y)  do { \
        if (s[x] > s[y]) { \
            const int t = s[x]; \
            s[x] = s[y]; \
            s[y] = t; \
        } \
    } while(0)
    SWAP(0, 1);
    //SWAP(2, 3);
    SWAP(0, 2);
    //SWAP(1, 3);
    //SWAP(1, 2);
    SWAP(4, 5);
    SWAP(6, 7);
    SWAP(4, 6);
    SWAP(5, 7);
    //SWAP(5, 6);
    SWAP(0, 4);
    SWAP(1, 5);
    SWAP(1, 4);
    SWAP(2, 6);
    SWAP(3, 7);
    //SWAP(3, 6);
    SWAP(2, 4);
    SWAP(3, 5);
    SWAP(3, 4);
#undef SWAP
}

/* -------- testing code */

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int cmp_int(const void *a, const void *b) {
    return *(const int*)a - *(const int*)b;
}

void printit_arr(const int *arr, size_t n) {
    printf("{");
    for (size_t i = 0; i < n; ++i) {
        printf("%d", arr[i]);
        if (i != n - 1) {
            printf(" ");
        }
    }
    printf("}");
}

void printit(const char *pre, const int arr[8], 
        const int in[8], const int res[4]) {
    printf("%s: ", pre);
    printit_arr(arr, 8);
    printf(" ");
    printit_arr(in, 8);
    printf(" ");
    printit_arr(res, 4);
    printf("\n");
}

int err = 0;
void test(const int arr[8], const int res[4]) {
    int in[8];
    memcpy(in, arr, sizeof(int) * 8);
    sort_but_4_matter(in);
    // sort for memcmp below
    qsort(in, 4, sizeof(int), cmp_int);
    if (memcmp(in, res, sizeof(int) * 4) != 0) {
        printit("T", arr, in, res);
        err = 1;
    }
}

void test_all_combinations() {
    const int result[4] = { 0, 1, 2, 3 }; // sorted
    const size_t n = 8;
    int num[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
    for (size_t j = 0; j < n; j++) {
        for (size_t i = 0; i < n-1; i++) {
            int temp = num[i];
            num[i] = num[i+1];
            num[i+1] = temp;
            test(num, result);
        }
    }
}

int main() {
    test_all_combinations();
    return err;
}

Проверено на кресте . sort_but_4_matter с g cc -O2 на x86_64 компилируется менее чем в 100 инструкций.

0 голосов
/ 26 февраля 2020

Учитывая, что у вас есть массив фиксированного размера, жестко закодированная сортировочная сеть должна иметь возможность правильно сортировать весь массив только с 19 сравнениями. В настоящее время у вас уже есть 8 + 2 * 8 = 24 сравнений, хотя вполне возможно, что компилятор развернет l oop, в результате чего у вас будет 16 сравнений. Возможно, что в зависимости от аппаратного обеспечения микроконтроллера, сеть сортировки может быть реализована с некоторой степенью параллелизма - возможно, вам также придется запрашивать значения объявлений c последовательно, что даст вам возможность предварительно отсортировать их во время ожидания для сравнения.

Оптимальная сеть сортировки должна быть доступна для поиска в Интернете. Википедия имеет несколько указателей.

Итак, вы получите такой код:

sort_data(adcval);
return (adcval[2]+adcval[3]+adcval[4]+adcval[5])/4;

Обновление:

sorting networks

Как видно из этой картины ( источник ) сетей оптимальной сортировки, полная сортировка занимает 19 сравнений. Однако 3 из них не являются строго необходимыми, если вы хотите извлечь только средние 4 значения. Таким образом, вы получите 16 сравнений.

...