Files
Chassis/project/code/GrayscaleSensor.c
T
2026-06-06 21:26:08 +08:00

122 lines
4.2 KiB
C

#include "GrayscaleSensor.h"
#include "zf_driver_adc.h"
#include "zf_driver_gpio.h"
#include "zf_driver_delay.h"
#define AD2 B8
#define AD1 B9
#define AD0 B14
#define FILTER_ALPHA 0.5f //位置滤波系数,范围 [0, 1],值越大响应越快但噪声越大
volatile static uint16 adc_white[8] = {4096,4096,4096,4096,4096,4096,4096,4096}; // 存储8路灰度传感器的白色参考值,初始值为满量程
volatile static uint16 adc_black[8] = {0,0,0,0,0,0,0,0}; // 存储8路灰度传感器的黑色参考值,初始值为0
volatile static uint16 adc_range[8] = {4096,4096,4096,4096,4096,4096,4096,4096}; // 存储8路灰度传感器的动态范围,初始值为满量程
volatile static uint16 adc_raw_value[8] = {0}; // 存储8路灰度传感器的原始 ADC 值
static float adc_normalized[8] = {0}; // 存储8路灰度传感器的归一化值,范围 [0, 1]
static float adc_normalized_sum = 0; // 归一化值的总和,用于计算位置
volatile float grayscale_sensor_position_prev = 0; // 存储小车相对于黑线的位置
volatile float grayscale_sensor_position = 0; // 存储小车相对于黑线的位置
static const int position[8] = {-4, -3, -2, -1, 1, 2, 3, 4}; // 每个传感器对应的位置
void grayscale_sensor_set_white(void)
{
for(uint8 i=0;i<8;i++)
{
adc_white[i] = adc_raw_value[i];
adc_range[i] = adc_white[i] - adc_black[i];
}
}
void grayscale_sensor_set_black(void)
{
for(uint8 i=0;i<8;i++)
{
adc_black[i] = adc_raw_value[i];
adc_range[i] = adc_white[i] - adc_black[i];
}
}
void grayscale_sensor_init(void)
{
adc_init(ADC1_CH5_B18, ADC_12BIT);
gpio_init(AD2, GPO, GPIO_LOW, GPO_PUSH_PULL);
gpio_init(AD1, GPO, GPIO_LOW, GPO_PUSH_PULL);
gpio_init(AD0, GPO, GPIO_LOW, GPO_PUSH_PULL);
gpio_set_level(AD2, 1);
gpio_set_level(AD1, 1);
gpio_set_level(AD0, 1);
}
/*真值表
AD2 AD1 AD0
0 0 0 CH1
0 0 1 CH2
0 1 0 CH3
0 1 1 CH4
1 0 0 CH5
1 0 1 CH6
1 1 0 CH7
1 1 1 CH8
*/
void grayscale_sensor_scan(void)
{
gpio_set_level(AD2, 0);
gpio_set_level(AD1, 0);
gpio_set_level(AD0, 0); // CH1
system_delay_us(1);
adc_raw_value[0]=adc_mean_filter_convert(ADC1_CH5_B18, 15);
gpio_set_level(AD2, 0);
gpio_set_level(AD1, 0);
gpio_set_level(AD0, 1); // CH2
system_delay_us(1);
adc_raw_value[1]=adc_mean_filter_convert(ADC1_CH5_B18, 15);
gpio_set_level(AD2, 0);
gpio_set_level(AD1, 1);
gpio_set_level(AD0, 0); // CH3
system_delay_us(1);
adc_raw_value[2]=adc_mean_filter_convert(ADC1_CH5_B18, 15);
gpio_set_level(AD2, 0);
gpio_set_level(AD1, 1);
gpio_set_level(AD0, 1); // CH4
system_delay_us(1);
adc_raw_value[3]=adc_mean_filter_convert(ADC1_CH5_B18, 15);
gpio_set_level(AD2, 1);
gpio_set_level(AD1, 0);
gpio_set_level(AD0, 0); // CH5
system_delay_us(1);
adc_raw_value[4]=adc_mean_filter_convert(ADC1_CH5_B18, 15);
gpio_set_level(AD2, 1);
gpio_set_level(AD1, 0);
gpio_set_level(AD0, 1); // CH6
system_delay_us(1);
adc_raw_value[5]=adc_mean_filter_convert(ADC1_CH5_B18, 15);
gpio_set_level(AD2, 1);
gpio_set_level(AD1, 1);
gpio_set_level(AD0, 0); // CH7
system_delay_us(1);
adc_raw_value[6]=adc_mean_filter_convert(ADC1_CH5_B18, 15);
gpio_set_level(AD2, 1);
gpio_set_level(AD1, 1);
gpio_set_level(AD0, 1); // CH8
system_delay_us(1);
adc_raw_value[7]=adc_mean_filter_convert(ADC1_CH5_B18, 15);
// 计算小车相对于黑线的位置
grayscale_sensor_position = 0;
adc_normalized_sum = 0;
for(uint8 i=0;i<8;i++)
{
adc_normalized[i] = ((float)(adc_white[i] - adc_raw_value[i])) / adc_range[i];
grayscale_sensor_position += adc_normalized[i] * position[i];
adc_normalized_sum += adc_normalized[i];
}
if(adc_normalized_sum > 0)
{
grayscale_sensor_position /= adc_normalized_sum;
}
else
{
grayscale_sensor_position = 0; // 避免除以零,默认位置为0
}
grayscale_sensor_position = grayscale_sensor_position_prev + FILTER_ALPHA * (grayscale_sensor_position - grayscale_sensor_position_prev);
grayscale_sensor_position_prev = grayscale_sensor_position;
}