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