十八届智能车负压电磁组(一):电感摆放以及adc读取、处理篇

文章目录


前言

本篇将介绍电感摆放以及单片机stc32g12k128读取adc值的处理方案

一、电感摆放

对于负压电磁组,电感就相当于眼睛,是最重要的传感器,一个好的电感摆放方式将会十分有利于车模的控制。

我也查过往届取得优秀成绩的组别采用的电感摆放方式,最后确定为4电感循迹,3电感判断元素。电感摆放方式为三水平、两竖直、两内八,具体摆放位置如图:

 其中最外两水平电感以及两竖直电感用来循迹,两内八电感和中间水平电感用来判断圆环以及坡道。

二、adc值读取

对于adc值的读取,提供3种方案,前面两种相似

(1)直接取均值

//-------------------------------------------------------------------------------------------------------------------
//  @brief      ADC均值滤波
//  @param      adcn            选择ADC通道
//  @param      count      		采集次数
//  @param      resolution      分辨率		
//  @return     void
//  Sample usage:               adc_mean_filter(ADC_P10, 10,ADC_10BIT);
//-------------------------------------------------------------------------------------------------------------------
uint16 adc_mean_filter(ADCN_enum adcn, uint8 count,ADCRES_enum resolution)
{
	uint8 i;
	uint16 adc_value = 0;
	for (i = 0;i < count;i++)
	{	
		adc_value += adc_once(adcn,resolution);
	}
	adc_value = adc_value / count;
	return adc_value;
}

 (2)去除最大值以及最小值取均值

//-------------------------------------------------------------------------------------------------------------------
//  @brief      ADC均值滤波去除最大值和最小值 默认精度为12位
//  @param      adcn            选择ADC通道
//  @param      count      		采集次数
//  @param      resolution      分辨率	
//  @return     void
//  Sample usage:               adc_mean_filter_remove_max_min(ADC_P10, 10,ADC_10BIT);
//-------------------------------------------------------------------------------------------------------------------
uint16 adc_mean_filter_remove_max_min(ADCN_enum adcn, uint8 count,ADCRES_enum resolution)
{
	uint8 i;
	uint16 adc_value = 0;
	uint16 max = 0,min = 4096;
	uint16 dat = 0;
	for (i = 0;i < count + 2;i++)
	{
		dat = adc_once(adcn,resolution);//使用变量dat读取一次ADC即可,避免多次读取ADC
		adc_value += dat;
		if(max < dat)
			max = dat;
		if(min > dat)
			min = dat;
	}
	adc_value = (adc_value - max - min)/ count;
	return adc_value;
}

 (3)滑动滤波

#define filter_n 3//数组长度
float adc_buf[7][filter_n + 1]={0};
uint8 adc_buf_flag[7] = {0};
/*
adcn:adc通道
resolution:精度
L_n:第几个电感
*/
uint16 adc_slid_filter(ADCN_enum adcn,ADCRES_enum resolution,uint8 L_n)
{
	uint8 i;
	uint16 filter_sum = 0;
	adc_buf[L_n][filter_n] = adc_once(adcn,resolution);//放入最后一个位置
	
	if(adc_buf_flag[L_n] < filter_n)//还没获取到filter_n个
	{
		adc_buf_flag[L_n] += 1;
		for(i=0;i<filter_n;i++)
		{
			adc_buf[L_n][i] = adc_buf[L_n][i+1];//所有数据左移
			adc_buf[L_n][i+1] = 0;//将i+1数据置为0,下一次循环会重新赋值
			filter_sum += adc_buf[L_n][i];
		}
		return filter_sum / adc_buf_flag[L_n];
	}
	else 
	{
		for(i=0;i<filter_n;i++)
		{
			adc_buf[L_n][i] = adc_buf[L_n][i+1];//所有数据左移
			adc_buf[L_n][i+1] = 0;//将i+1数据置为0,下一次循环会重新赋值
			filter_sum += adc_buf[L_n][i];
		}
		return filter_sum / filter_n;
	}
}

对adc原始值做处理是为了避免噪声干扰,引起adc值变化较大。

二、电感归一化

归一化是为了让车模适应不同赛道,根据今年赛道来说,赛道上采出来的adc值比在平时跑的场地adc值会大不少,故归一化十分重要!!!

typedef struct 
{
	uint16 L_lsp_real; //左水平电感实际值
    uint16 L_lsz_real; //左竖直电感实际值
    uint16 L_lx_real; //左斜电感实际值
	uint16 L_mid_real; //中间水平电感实际值
    uint16 L_rx_real; //右斜电感实际值
    uint16 L_rsz_real; //右竖直电感实际值
    uint16 L_rsp_real; //右水平电感实际值

    uint16 L_lsp_max;//左水平电感检测到的最大值
    uint16 L_lsz_max;//左竖直电感检测到的最大值
    uint16 L_lx_max;//左斜电感检测到的最大值
	uint16 L_mid_max;//中间水平电感检测到的最大值
    uint16 L_rx_max;//右斜电感检测到的最大值
    uint16 L_rsz_max;//右竖直电感检测到的最大值
    uint16 L_rsp_max;//右水平电感检测到的最大值

    float L_lsp_once;//左水平电感一次归一化后
    float L_lsz_once;//左竖直电感一次归一化后
    float L_lx_once;//左斜电感一次归一化后
	float L_mid_once;//中间水平电感一次归一化后
    float L_rx_once;//右斜电感一次归一化后
    float L_rsz_once;//右竖直电感一次归一化后
    float L_rsp_once;//右水平电感一次归一化后


    float L_lsp_twice;//左水平电感二次归一化后
    float L_lsz_twice;//左竖直电感二次归一化后
    float L_lx_twice;//左斜电感二次归一化后
	float L_mid_twice;//中间水平电感二次归一化后
    float L_rx_twice;//右斜电感二次归一化后
    float L_rsz_twice;//右竖直电感二次归一化后
    float L_rsp_twice;//右水平电感二次归一化后
}DG_state;	
//滑动滤波
void Get_ADC_values_slid_filter(void)
{
	dg_state.L_lsp_real = adc_slid_filter(L_lsp,ADC_12BIT,0);//10次滑动
	dg_state.L_lsz_real = adc_slid_filter(L_lsz,ADC_12BIT,1);//10次滑动
	dg_state.L_lx_real = adc_slid_filter(L_lx,ADC_12BIT,2);//10次滑动
	dg_state.L_mid_real = adc_slid_filter(L_mid,ADC_12BIT,3);//10次滑动
	dg_state.L_rx_real = adc_slid_filter(L_rx,ADC_12BIT,4);//10次滑动
	dg_state.L_rsz_real = adc_slid_filter(L_rsz,ADC_12BIT,5);//10次滑动
	dg_state.L_rsp_real = adc_slid_filter(L_rsp,ADC_12BIT,6);//10次滑动
}

void DG_Normal(void)
{
	//	Get_ADC_values_mean_filter();//均值获取电感值
	Get_ADC_values_slid_filter();//滑动滤波获取电感值
	
	//一次归一化
	dg_state.L_lsp_once = ((float)dg_state.L_lsp_real) * 100 / dg_state.L_lsp_max;
	dg_state.L_lsz_once = ((float)dg_state.L_lsz_real) * 100 / dg_state.L_lsz_max;
	dg_state.L_lx_once = ((float)dg_state.L_lx_real) * 100 / dg_state.L_lx_max;
	dg_state.L_mid_once = ((float)dg_state.L_mid_real) * 100 / dg_state.L_mid_max;
	dg_state.L_rx_once = ((float)dg_state.L_rx_real) * 100 / dg_state.L_rx_max;
	dg_state.L_rsz_once = ((float)dg_state.L_rsz_real) * 100 / dg_state.L_rsz_max;
	dg_state.L_rsp_once = ((float)dg_state.L_rsp_real) * 100 / dg_state.L_rsp_max;
	
	dg_state.L_lsp_once = constrain_float(dg_state.L_lsp_once,0,100);//限幅0-100
	dg_state.L_lsz_once = constrain_float(dg_state.L_lsz_once,0,100);//限幅0-100
	dg_state.L_lx_once = constrain_float(dg_state.L_lx_once,0,100);//限幅0-100
	dg_state.L_mid_once = constrain_float(dg_state.L_mid_once,0,100);//限幅0-100
	dg_state.L_rx_once = constrain_float(dg_state.L_rx_once,0,100);//限幅0-100
	dg_state.L_rsz_once = constrain_float(dg_state.L_rsz_once,0,100);//限幅0-100
	dg_state.L_rsp_once = constrain_float(dg_state.L_rsp_once,0,100);//限幅0-100
	
	//二次归一化
	dg_state.L_lsp_twice = dg_state.L_lsp_once;//处理待定
    dg_state.L_lsz_twice = dg_state.L_lsz_once;//处理待定
    dg_state.L_lx_twice = dg_state.L_lx_once;//处理待定
	dg_state.L_mid_twice = dg_state.L_mid_once;//处理待定
    dg_state.L_rx_twice = dg_state.L_rx_once;//处理待定
    dg_state.L_rsz_twice = dg_state.L_rsz_once;//处理待定
    dg_state.L_rsp_twice = dg_state.L_rsp_once;//处理待定
}

在程序中,出现了电感二次归一化的变量,该变量最开始想着需要对电感进行二次归一化,使电感值归一化计算偏差时,使得偏差线性,然而在实际测试时发现只需要一次归一化就可以,就没删。

至此adc读取以及处理完成,下一篇将介绍舵机方向控制。

十八届智能车负压电磁组(二):舵机方向控制篇

  • 10
    点赞
  • 142
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值