Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 找到两个最差的值,并将其总和删除_C_Microcontroller_Stm32 - Fatal编程技术网

C 找到两个最差的值,并将其总和删除

C 找到两个最差的值,并将其总和删除,c,microcontroller,stm32,C,Microcontroller,Stm32,微控制器的任务是采样ADC值(模数转换)。由于这些零件受到公差和噪声的影响,删除4个最差值可显著提高精度。查找和删除确实需要时间,但这并不理想,因为它会增加周期时间 假设频率为100MHz,因此软件的每个命令处理时间为10ns,命令越多,控制器被阻止执行下一组采样的时间就越长 因此,我的目标是尽可能快地完成排序过程。我目前使用这段代码,但这只删除了最差的两个 uint16_t getValue(void){ adcval[8] = {}; uint16_t min = 1638

微控制器的任务是采样ADC值(模数转换)。由于这些零件受到公差和噪声的影响,删除4个最差值可显著提高精度。查找和删除确实需要时间,但这并不理想,因为它会增加周期时间

假设频率为100MHz,因此软件的每个命令处理时间为10ns,命令越多,控制器被阻止执行下一组采样的时间就越长

因此,我的目标是尽可能快地完成排序过程。我目前使用这段代码,但这只删除了最差的两个

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个)。但第二种情况会删除值5和6以及15和16。但这在理论上会使计算变得更糟,因为删除10,11,15,16会更好。有没有快速删除4个最大偏差的解决方案?

如果您有一个固定大小的数组,硬编码的排序网络应该能够正确地对整个数组进行排序,只需19次比较。目前您已经有了8+2*8=24个比较,尽管编译器可能会展开循环,给您留下16个比较。可以想象,根据微控制器硬件的不同,排序网络可以实现一定程度的并行性——也许您还必须顺序查询adc值,这将使您有机会在等待比较时对它们进行预排序

最佳分拣网络应可在线搜索。他有一些建议

因此,您将得到如下代码:

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

从这张优化排序网络的图片()可以看出,一个完整的排序需要19次比较。但是,如果只想提取中间的4个值,则不严格需要其中的3个。因此,您可以进行16次比较

  • 如果ADC返回的值为5到16 14位,电压参考值为3.3V,则电压范围为1mV到3mV。很可能是正确的读数。为14位ADC设计好的输入电路是非常困难的

  • 最好按平均水平运行。平均值是多少?它是软件低通滤波器。 蓝色为ADC的读数,红色为运行平均值

  • 第二个信号是极低振幅正弦波(9-27mV-假设14位和3.3Vref)

    算法:

    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;
    }
    
    如果
    级别
    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;
    }
    
    静态int平均值;
    int运行_平均值(int val,int level)
    {
    平均-=平均>>水平;
    平均+=val>水平;
    }
    无效初始_平均值(int val,int level)
    {
    平均值=val
    删除8个样本中最差的4个值

    有关方法的说明,您可以实现适合自己的最佳方法

    我决定使用
    SWAP()
    宏生成对8个元素的数组进行排序所需的最佳排序算法。然后我创建了一个小型C程序,该程序将在我的排序函数上测试8个元素数组的任何组合。然后,因为我们只关心4个元素的组,所以我对每个
    SWAP()执行了一些bruteforce操作
    macros我试图注释宏,看看程序是否仍然成功。我可以注释5个
    SWAP
    macros,留下14个比较,以确定8个样本数组中最小的4个元素

    /**
     * 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;
    }
    
    /**
    *对数组进行排序,但仅使4个一组的数组起作用。
    *由4个最小元素和4个最大元素组成
    *我会整理好的。
    *s[0]…s[3]将具有最低的4个元素
    *所以他们必须被“删除”
    *s[4]…s[7]将具有最高的4个值
    */
    无效排序但有4个问题(int s[8]){
    #定义交换(x,y)do{\
    如果(s[x]>s[y]){\
    常数int t=s[x]\
    s[x]=s[y]\
    s[y]=t\
    } \
    }而(0)
    互换(0,1);
    //互换(2,3);
    互换(0,2);
    //互换(1,3);
    //互换(1,2);
    互换(4,5);
    互换(6,7);
    互换(4,6);
    互换(5,7);
    //互换(5,6);
    互换(0,4);
    互换(1,5);
    互换(1,4);
    互换(2,6);
    互换(3,7);
    //互换(3,6);
    互换(2,4);
    互换(3,5);
    互换(3,4);
    #未定义交换
    }
    /*-----测试代码*/
    
    #include.x86\u64上使用gcc-O2的
    sort\u but\u4\u matter
    编译到小于100条指令。

    这个答案是一个主题,因为它推荐了一个硬件解决方案,但是如果需要性能,并且MCU无法实现p\uj\uu的解决方案,那么这是您的下一个最佳选择

    您似乎想从输入信号中去除噪声。这可以通过使用DSP()的软件来实现,但也可以通过不同的硬件配置来实现

    通过在ADC前的适当空间添加适当的滤波器,可以从ADC输出中去除大量(外部)噪声。(当然,不能低于ADC固有的一定数量,但遗憾的是。)

    有几个问题和答问

    • 一种解决方案是增加一个电容器来过滤一些高频噪声
    • 通过建议RC、Sallen-Key和Sallen-Key滤波器级联来实现连续信号滤波器
    • 是Microchip关于“降低ADC电路中系统噪声的技术”的模拟设计说明

      设计一个低噪声的12位模数转换器 转换器(ADC)板甚至10位板都很容易。这是 是的,除非你忽略了低噪音设计的基础 例如,人们会认为大多数放大器和电阻器都能工作 在12位或10位环境中有效。但是,较差的设备 选择成为决定项目成败的主要因素 电路。另一个经常被忽视的领域,贡献很大 对于噪声,是传导噪声
      /**
       * 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;
      }