diff --git a/App/Inc/anemometer_dev.h b/App/Inc/anemometer_dev.h index 563ed85..52843a1 100644 --- a/App/Inc/anemometer_dev.h +++ b/App/Inc/anemometer_dev.h @@ -155,6 +155,18 @@ typedef struct _error_log{ extern error_log g_error_log; #pragma pack(pop) +#define MAX_VALUES 50 +typedef struct { + uint16_t values[MAX_VALUES]; + uint16_t count; + uint16_t currentIndex; + uint16_t ave; +} AverageCalculator; +extern AverageCalculator Test1; +extern AverageCalculator Test2; +extern AverageCalculator Test3; +extern AverageCalculator Test4; + // 切换通道 void change_channel(uint32_t channel); diff --git a/App/Inc/frt_protocol.h b/App/Inc/frt_protocol.h index 04b3f26..15a6d68 100644 --- a/App/Inc/frt_protocol.h +++ b/App/Inc/frt_protocol.h @@ -71,6 +71,10 @@ typedef enum FRT_REGISTER_LINEAR_POINT_Y_4 = 48, /* ԲֵУ׼4 */ FRT_REGISTER_LINEAR_POINT_Y_5 = 49, /* ԲֵУ׼5 */ FRT_REGISTER_LINEAR_ENABLE = 50, /* Բֵʹ */ + FRT_REGISTER_TEST1 = 51, /* ԼĴ */ + FRT_REGISTER_TEST2 = 52, /* ԼĴ */ + FRT_REGISTER_TEST3 = 53, /* ԼĴ */ + FRT_REGISTER_TEST4 = 54, /* ԼĴ */ }FRT_MsgRegister; #pragma pack(push,1) diff --git a/App/Src/anemometer_dev.c b/App/Src/anemometer_dev.c index 478880d..572f567 100644 --- a/App/Src/anemometer_dev.c +++ b/App/Src/anemometer_dev.c @@ -22,8 +22,28 @@ arm_rfft_fast_instance_f32 s; float32_t rfft_float_buf[FFT_DATA_LEN]; // fft结果 float32_t fft_out_f32[ADC_VAL_LEN] = {0}; -// +// 波形最大点 +void addValue(AverageCalculator *calc, uint16_t value) { + calc->values[calc->currentIndex] = value; + calc->currentIndex = (calc->currentIndex + 1) % MAX_VALUES; + if (calc->count < MAX_VALUES) { + calc->count++; + } + uint32_t sum = 0; + for (int i = 0; i < calc->count; i++) { + sum += calc->values[i]; + } + calc->ave = sum / calc->count; +} +AverageCalculator Test1; +AverageCalculator Test2; +AverageCalculator Test3; +AverageCalculator Test4; +uint16_t wave_max_val1; +uint16_t wave_max_val2; +uint16_t wave_max_val3; +uint16_t wave_max_val4; int16_t adc_val[ADC_VAL_LEN]; int16_t adc_val1[ADC_VAL_LEN]; @@ -101,7 +121,8 @@ float32_t RSSI; float32_t buf[ADC_VAL_LEN]; float32_t buf2[ADC_VAL_LEN]; /*****************滤波器BUFF**********/ -float32_t cal_tof(q15_t* x,uint32_t len) +float32_t cal_tof(q15_t* x,uint32_t len, int16_t *maxVal) +// float32_t cal_tof(q15_t* x,uint32_t len) { q15_t max_val,dc_offset; float32_t echo_p = 0,echo_dt = 0; @@ -132,6 +153,7 @@ float32_t cal_tof(q15_t* x,uint32_t len) // arm_float_to_q15(buf2,firFilterTestOutData,len); for(i= 0 ;ivalues[calc->currentIndex] = value; + calc->currentIndex = (calc->currentIndex + 1) % MAX_VALUES; + if (calc->count < MAX_VALUES) { + calc->count++; + } + uint32_t sum = 0; + for (int i = 0; i < calc->count; i++) { + sum += calc->values[i]; + } + calc->ave = sum / calc->count; +} +AverageCalculator Test1; +AverageCalculator Test2; +AverageCalculator Test3; +AverageCalculator Test4; +uint16_t wave_max_val1; +uint16_t wave_max_val2; +uint16_t wave_max_val3; +uint16_t wave_max_val4; + +int16_t adc_val[ADC_VAL_LEN]; +int16_t adc_val1[ADC_VAL_LEN]; + + +#define AV_SPEED_LEN 5 +float32_t speed[AV_SPEED_LEN]={0}; +float32_t angle[AV_SPEED_LEN]={0}; +float32_t speedx[AV_SPEED_LEN]={0}; +float32_t speedy[AV_SPEED_LEN]={0}; + +uint32_t speedi = 0; +float32_t av_speed; +float32_t av_angle; +float32_t av_speedx= 0; +float32_t av_speedy=0; + +Weather_param weather_info={0x00}; +mcs_para g_stMcs_Para={0x00}; +error_log g_error_log={0x00}; + + + + +void update_mcs_param(float new_wind_speed, float new_wind_dirction); + + + + +float32_t max_val_f32; + +int32_t max_val_index_f32; + +// 多项式插值 +// 返回值是最大值 +float32_t find_maxVal_by_interpolation(float32_t a,float32_t b,float32_t c) +{ + float32_t d1=0; + //到达极值点的时间Xmax + d1 = (a-c)/2.0f/(a-2.0f*b+c); + return 0.5f*a*d1*(d1-1.0f)-b*(d1-1.0f)*(d1+1.0f)+0.5f*c*d1*(d1+1.0f); +} + + +// 余弦插值找最大值所在的位置 +// 返回值是相位 + +float32_t find_maxValPosition_by_sinInterpolation(float32_t a,float32_t b,float32_t c) +{ + // sin 插值 寻找最大值 + float32_t w_val,sin_val,y_val; + b=b+0.0000001f; + + w_val = acosf((a+c)/2.0f/b); + + sin_val = sinf(w_val)+0.0000001f; + + y_val = atanf((a-c)/2.0f/b/sin_val); + +// if(isnan(w_val)||isnan(sin_val)||isnan(y_val)) +// { +// term_printf("isnan \r\n"); +// +// } + + return (0.0f-y_val)/(w_val+0.0000001f); + +} + + + +float32_t RSSI; + +/*****************滤波器BUFF**********/ +float32_t buf[ADC_VAL_LEN]; +float32_t buf2[ADC_VAL_LEN]; +/*****************滤波器BUFF**********/ +float32_t cal_tof(q15_t* x,uint32_t len, int16_t *maxVal) +// float32_t cal_tof(q15_t* x,uint32_t len) +{ + q15_t max_val,dc_offset; + float32_t echo_p = 0,echo_dt = 0; + uint32_t max_val_p; + uint32_t i=0;//stop_position = 0; + + static uint32_t fft_200khz_pos; + + // 计算直流分量 因为数据前端是没有回波的 计算50个数据求平均值 获取直流分量 + arm_mean_q15(x,50,&dc_offset); + // 信号减去直流分量 + arm_offset_q15(x,-dc_offset,x,len); + + /*****************滤波器**********/ +// arm_mean_q15(x,50,&dc_offset); +// // 信号减去直流分量 +// arm_offset_q15(x,-dc_offset,x,len); + // 转换成浮点数 + // arm_q15_to_float(x,buf,len); + + for(i= 0 ;i>>>>>> MAX_WAVE + x[i] = (int16_t)(buf2[i]); + } + /*****************滤波器**********/ + + // fft 中 200khz 所在的位置。 + fft_200khz_pos=(uint32_t)roundf((0.2f/(ADC_SAMP_RATE_MHz/FFT_DATA_LEN))); + + // 查找数组中的最大值和最大值所在的索引 + arm_max_q15(x,len,&max_val,&max_val_p); + + // 最大值前后128个点数据的地址这里预防数组越界 + q15_t* fft_data_q15_buf; + uint32_t fft_data_add; + if(max_val_p>=FFT_DATA_LEN/2) + fft_data_add=max_val_p-FFT_DATA_LEN/2; + else + fft_data_add = 0; + // 找到最大值前128个点的地址 + fft_data_q15_buf = &(x[fft_data_add]); + + // 转换成浮点数 + arm_q15_to_float(fft_data_q15_buf,rfft_float_buf,FFT_DATA_LEN); + + // fft进行转换。 + arm_rfft_fast_f32(&s,rfft_float_buf,fft_out_f32,0); + // 对fft结果取模 + arm_cmplx_mag_f32(fft_out_f32,rfft_float_buf,FFT_DATA_LEN); + // 统计200khz 附近的信号强度 + RSSI = rfft_float_buf[fft_200khz_pos-2]+rfft_float_buf[fft_200khz_pos-1]+ rfft_float_buf[fft_200khz_pos]+rfft_float_buf[fft_200khz_pos+1]+rfft_float_buf[fft_200khz_pos+2]; + // 如果RSSI小于 + // 可变RSSI范围 +// if(RSSI<0.2) + if(RSSI < ((float)g_stConfigInfo.RSSI_range/100.0)) + return -1; + // 取出最大值 + *maxVal = max_val; + +// 可变参数 + uint16_t max_val_zero_1R5 = max_val * g_stConfigInfo.transducer_cfg_1R5/100; + uint16_t max_val_zero_4R5 = max_val * g_stConfigInfo.transducer_cfg_4R5/100; + uint16_t max_val_zero_8R0 = max_val * g_stConfigInfo.transducer_cfg_8R0/100; + +// // 大宇换能器参数 开始 +// // 最大值的0.18倍 +// uint16_t max_val_zero_1R5 = (max_val*15/100); +// // 最大值的0.45倍 +// uint16_t max_val_zero_4R5 = (max_val*45/100); +// // 最大值的0.8倍 +// uint16_t max_val_zero_8R0 = (max_val*80/100); +// // 大宇换能器参数 + +// // 无锡电声换能器参数 +// // 最大值的0.18倍 +// uint16_t max_val_zero_1R5 = (max_val*10/100); +// // 最大值的0.45倍 +// uint16_t max_val_zero_4R5 = (max_val*35/100); +// // 最大值的0.8倍 +// uint16_t max_val_zero_8R0 = (max_val*65/100); + + + //如果最大值位置大于8个周波 则从最大值前前8周波位置开始寻找起始波形。 + // 优化的地方,从最大值位置开始找到达波,可以最大限度排除偶然噪声干扰, + // 因为噪声在波形到达出 噪声不是很大 + //优化性能,如果不需要则从数组0位置开始寻找其实波形 + if(max_val_p>=(uint32_t)(8*ADC_SAMP_RATE_MHz/DRIVE_FREQ_MHz)) + { + i = max_val_p-(uint32_t)(8*ADC_SAMP_RATE_MHz/DRIVE_FREQ_MHz); + }else + { + i = 0; + } + // 在最大值前寻找起始波形 + for( ; i < max_val_p ; i++) + { + // 建议判断顶点,但是容易遇到偶然数据异常 类似于 28 29 28 30 29 28这种情况 + // if( x[i-1] < x[i] && x[i]> x[i+1] ) + // 排除以上数据异常情况,但是有可能就无法检测到30 这个顶点。 + // 故需要检测下一个周期的顶点,然后再减去一个周期的时间。 + if( x[i-2]=x[i+1] && x[i+1]>x[i+2]) + { + // 减去偏置电压 + //temp_val_zero = arr[i]-2048; + // 判断顶点是否在 15%-%45之间。 + if(x[i] >= max_val_zero_1R5 && x[i] <= max_val_zero_4R5 ) + { + // 如果找到 函数退出 + //echo_dt = (x[i-1]-x[i+1])/2.0/(x[i-1]-2*x[i]+x[i+1]); + echo_dt = find_maxValPosition_by_sinInterpolation(x[i-1],x[i],x[i+1]); + echo_p = (float32_t)i+echo_dt-0*(float32_t)(ADC_SAMP_RATE_MHz/DRIVE_FREQ_MHz); + + return echo_p; + } + + // 如果15% ~45%之间的数据未找到,则找45-80%的顶点。 + // 判断顶点是否在 45% -- 80% 之间 + if(x[i] >= max_val_zero_4R5 && x[i] <= max_val_zero_8R0) + { + // 如果找到 函数推出 + //echo_dt = (x[i-1]-x[i+1])/2.0/(x[i-1]-2*x[i]+x[i+1]); + echo_dt = find_maxValPosition_by_sinInterpolation(x[i-1],x[i],x[i+1]); + // 换算成第二个顶点的位置。 + echo_p = (float32_t)i+echo_dt - 1*(float32_t)(ADC_SAMP_RATE_MHz/DRIVE_FREQ_MHz); + + return echo_p; + } + } + } + // term_printf("bad wave of echo signal \r\n"); + return -1; +} + + + +/* +C B A +0 0 0 X0 +0 0 1 X1 +0 1 0 X2 +0 1 1 X3 +1 0 0 X4 +1 0 1 X5 +*/ +void change_channel(uint32_t channel) +{ + // 复位全部通道IO + HAL_GPIO_WritePin(GPIOC, GPIO_PWM_C_Pin|GPIO_PWM_B_Pin|GPIO_PWM_A_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOC, GPIO_RX_A_Pin|GPIO_RX_B_Pin|GPIO_RX_C_Pin, GPIO_PIN_RESET); + + switch(channel) + { + case 0x01: + // N tx S rx + //HAL_GPIO_WritePin(GPIOC, GPIO_RX_A_Pin, GPIO_PIN_SET); + // 接收通道 + HAL_GPIO_WritePin(GPIOC, GPIO_RX_A_Pin, GPIO_PIN_SET); + break; + + case 0x02: + // N rx S tx + HAL_GPIO_WritePin(GPIOC, GPIO_PWM_A_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOC, GPIO_RX_B_Pin, GPIO_PIN_SET); + break; + + case 0x03: + // W tx E rx + HAL_GPIO_WritePin(GPIOC, GPIO_PWM_B_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOC, GPIO_RX_A_Pin|GPIO_RX_B_Pin, GPIO_PIN_SET); + break; + + case 0x04: + // W rx E tx + HAL_GPIO_WritePin(GPIOC, GPIO_PWM_A_Pin|GPIO_PWM_B_Pin, GPIO_PIN_SET); + //HAL_GPIO_WritePin(GPIOC, GPIO_RX_A_Pin, GPIO_PIN_SET); + break; + } +} + + + + +void play_one_measure(int16_t* result_data,uint32_t len) +{ + // 重新初始化PWM定时器 + MX_TIM15_Init(); + //MX_TIM6_Init(); + // adc驱动定时器,保证每次使用前处于停止状态 + HAL_TIM_Base_Stop(&htim6); + // 计数器复位 + __HAL_TIM_SET_COUNTER(&htim6,0); + // 校准adc + //HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED); + // adc dma初始化 + HAL_ADC_Start_DMA(&hadc1,(uint32_t *)result_data,len); + //禁止全局中断 + + // 停止定时器 + __HAL_TIM_DISABLE(&htim7); + // 重置计数器 + __HAL_TIM_SET_COUNTER(&htim7,0); + __set_PRIMASK(1); + // 发送超声波驱动信号 + HAL_TIM_PWM_Start(&htim15,TIM_CHANNEL_1); + // 延时 REV_MUTE_DELAY us + //HAL_GPIO_WritePin(GPIOC,GPIO_ACK_LED_Pin,0); + // 启定时器 + __HAL_TIM_ENABLE(&htim7); + // 等待定时到达 + while(__HAL_TIM_GET_COUNTER(&htim7)wind_c = DISTANCE/2.0f*(1.0f/tofx+1.0f/tofy); +// // v = L*dtof/2/tofx/tofy/cos +// if(direction == WIND_DIRECTION_X) +// { +// parm->wind_velocity_x = 0-DISTANCE*dtof/1.41422f/tofx/tofx; +// //parm->wind_velocity_x = DISTANCE*c_dtof/1.41422/tofx/tofx; +// } +// else +// { +// parm->wind_velocity_y = DISTANCE*dtof/1.41422f/tofx/tofx; +// //parm->wind_velocity_y = DISTANCE*c_dtof/1.41422/tofx/tofx; +// } +//} + + +void wind_task(void const * argument) +{ + //错误次数统计,南北,东西分开(接受信号很小) + uint8_t tof_error_log_NS = 0; + uint8_t tof_error_log_WE = 0; +// int flag_init_msc_value = 1; + + arm_rfft_fast_init_f32(&s,FFT_DATA_LEN); + firFilterInit(); + // 一阶低通滤波器初始化,x,y方向分别滤波 + initLowPassFilter(&low_pass_filter_x, LOW_PASS_ALPHA); + initLowPassFilter(&low_pass_filter_y, LOW_PASS_ALPHA); + for(;;) + { + __HAL_TIM_DISABLE(&htim16); + // 采集X轴风速耗时 22ms,两轴采集完44ms + __HAL_TIM_SET_COUNTER(&htim16,0); + + // 开启定时器,统计算法时间 + __HAL_TIM_ENABLE(&htim16); + + // 通道1 通道2 测试南北风速 + // 通道1发送 通道2接收 + change_channel(0x01); + // 等待通道切换稳定 + // adc开启采集数据有个固定的延时,这里取消等待 + //HAL_Delay(0); + // 发送pwm 并启动adc采集数据 + play_one_measure(adc_val,ADC_VAL_LEN); + //HAL_Delay(5); + osDelay(1); + // 通道2发送 通道1接收 + change_channel(0x02); + // 等待通道切换稳定 + //HAL_Delay(0); + // 发送pwm 并启动adc采集数据 + play_one_measure(adc_val1,ADC_VAL_LEN); + + + tofx = cal_tof(adc_val,ADC_VAL_LEN, &wave_max_val1);addValue(&Test1, wave_max_val1); + tofy = cal_tof(adc_val1,ADC_VAL_LEN, &wave_max_val2);addValue(&Test2, wave_max_val2); + + + // 接受信号很小 + if(tofx<0||tofy<0) + { + tof_error_log_NS ++; + // 放弃本次采样,可以有效筛选雨滴等导致的异常大的风速数据 + // 但是持续的遮挡会导致风速数据保持不变。 + // 连续10次采样有问题判定为有遮挡,置错误标志位,将声速与风速分量置0 + if(tof_error_log_NS >= COVER_TINE) + { + g_error_log.tof_error_NS = 1; + + weather_info.wind_c_NS = 0; + weather_info.wind_velocity_x = 0; + } + else + { + continue; + } + // 手动设置渡越时间差为0,会在探头受遮挡的时候输出0,持续遮挡的时候也输出0,但是计算出声速将变得很大 +// tofx = tofx/ADC_SAMP_RATE_MHz+REV_MUTE_DELAY_US-1.0f/DRIVE_FREQ_MHz+0.0001f; +// tofy = tofy/ADC_SAMP_RATE_MHz+REV_MUTE_DELAY_US-1.0f/DRIVE_FREQ_MHz+0.0001f; +// dtof = 0; + }else{ +// 遮挡没有之后数据正常,将标志位取消,错误计数置零 + tof_error_log_NS = 0; + g_error_log.tof_error_NS = 0; + // 计算成us + tofx = ((tofx-FIR_PHASE_DELAY)/ADC_SAMP_RATE_MHz)+REV_MUTE_DELAY_US-1.0f/DRIVE_FREQ_MHz+0.0001f - 2.0f; + tofy = ((tofy-FIR_PHASE_DELAY)/ADC_SAMP_RATE_MHz)+REV_MUTE_DELAY_US-1.0f/DRIVE_FREQ_MHz+0.0001f - 2.0f; + // 通过各通道渡越时间求时间差 + dtof = tofx-tofy; + + weather_info.wind_c_NS = (g_stConfigInfo.transducer_distace_NS * 2.0f)/2.0f*(1.0f/tofx+1.0f/tofy); +// weather_info.wind_velocity_x = 0-DISTANCE*dtof/1.41422f/tofx/tofx; +// 修正公式 + weather_info.wind_velocity_x = 0-(g_stConfigInfo.transducer_distace_NS * 2.0f)*dtof/TWO_COS45/tofx/tofy; + } + + // 通道3 通道4 测试东西风速 + // 通道3发送 通道4接收 + change_channel(0x03); + // 等待通道切换稳定 + //HAL_Delay(0); + // 发送pwm 并启动adc采集数据 + play_one_measure(adc_val,ADC_VAL_LEN); + //HAL_Delay(5); + osDelay(1); + // 通道4发送 通道3接收 + change_channel(0x04); + // 等待通道切换稳定 + //HAL_Delay(0); + // 发送pwm 并启动adc采集数据 + play_one_measure(adc_val1,ADC_VAL_LEN); + + + tofx = cal_tof(adc_val,ADC_VAL_LEN, &wave_max_val3);addValue(&Test3, wave_max_val3); + tofy = cal_tof(adc_val1,ADC_VAL_LEN, &wave_max_val4);addValue(&Test4, wave_max_val4); + + // 如果测量的信号幅值过小。 + if(tofx<0||tofy<0) + { + tof_error_log_WE ++; + // 放弃本次采样,可以有效筛选雨滴等导致的异常大的风速数据 + // 但是持续的遮挡会导致风速数据保持不变。 + // 连续10次采样有问题判定为有遮挡,置错误标志位,将声速与风速分量置0 + if(tof_error_log_WE >= COVER_TINE) + { + g_error_log.tof_error_WE = 1; + + weather_info.wind_c_WE = 0; + weather_info.wind_velocity_y = 0; + } + else + { + continue; + } + // 手动设置渡越时间差为0,会在探头受遮挡的时候输出0,持续遮挡的时候也输出0,但是计算出声速将变得很大 +// tofx = tofx/ADC_SAMP_RATE_MHz+REV_MUTE_DELAY_US-1.0f/DRIVE_FREQ_MHz+0.0001f; +// tofy = tofy/ADC_SAMP_RATE_MHz+REV_MUTE_DELAY_US-1.0f/DRIVE_FREQ_MHz+0.0001f; +// // 通过各通道渡越时间求时间差 +// dtof = 0; + + }else{ +// 遮挡没有之后数据正常,将标志位取消,错误计数置零 + tof_error_log_WE = 0; + g_error_log.tof_error_WE = 0; + // 计算成us + tofx = ((tofx-FIR_PHASE_DELAY)/ADC_SAMP_RATE_MHz)+REV_MUTE_DELAY_US-1.0f/DRIVE_FREQ_MHz+0.000001f - 2.0f; + tofy = ((tofy-FIR_PHASE_DELAY)/ADC_SAMP_RATE_MHz)+REV_MUTE_DELAY_US-1.0f/DRIVE_FREQ_MHz+0.000001f - 2.0f; + // 通过各通道渡越时间求时间差 + dtof = tofx-tofy; + + weather_info.wind_c_WE = (g_stConfigInfo.transducer_distace_WE * 2.0f)/2.0f*(1.0f/tofx+1.0f/tofy); +// weather_info.wind_velocity_y = DISTANCE*dtof/1.41422f/tofx/tofx; +// 修正公式 + weather_info.wind_velocity_y = (g_stConfigInfo.transducer_distace_WE * 2.0f)*dtof/TWO_COS45/tofx/tofy; + } + + weather_info.wind_velocity = sqrtf(weather_info.wind_velocity_x*weather_info.wind_velocity_x + weather_info.wind_velocity_y*weather_info.wind_velocity_y); + // 分母加0.0001 保证分母不为0 + weather_info.wind_angle = acosf(weather_info.wind_velocity_x/(weather_info.wind_velocity+0.000001f)); + + + // 关闭定时器· + __HAL_TIM_DISABLE(&htim16); + // 显示时间 单位us + run_time_us = __HAL_TIM_GET_COUNTER(&htim16) * 100;// htim16).Instance->CNT; + + speedx[speedi] = weather_info.wind_velocity_x; + speedy[speedi] = weather_info.wind_velocity_y; + speed[speedi] = weather_info.wind_velocity; + angle[speedi++] = weather_info.wind_angle*180/PI; + + if(speedi>=AV_SPEED_LEN) + { + speedi=0; + arm_mean_f32(speedx,AV_SPEED_LEN,&av_speedx); + arm_mean_f32(speedy,AV_SPEED_LEN,&av_speedy); + /* 一阶低通滤波器 */ + av_speedx = updateFilter(&low_pass_filter_x, av_speedx); + av_speedy = updateFilter(&low_pass_filter_y, av_speedy); + /* 一阶低通滤波器 */ + av_speed = sqrtf(av_speedx*av_speedx + av_speedy*av_speedy); + av_angle = acosf(av_speedx/(av_speed+0.00000001))/2/PI*360; + + // 有错时风速风向归零 + if(g_error_log.tof_error_NS || g_error_log.tof_error_WE) + { + av_speed = 0; + av_angle = 0; + } + // 360一圈 + if(av_speedy<0) + av_angle = 360-av_angle; + + //针对粘度进行校准 + av_speed = av_speed * ((float)g_stConfigInfo.Coefficient/10000.0); + + // 速度太小视为0风速 + if(fabs(av_speed)<0.1) + { + av_speed = 0; + av_angle = 0; + } +/// term_printf("x:%.2f y:%.2f win_speed %.2f m/s angle %.2f \r\n",av_speedx,av_speedy,av_speed,av_angle); + } + //算法求出的瞬时风速风向 + weather_info.instantaneous_wind_direction = av_angle; + weather_info.instantaneous_wind_speed = av_speed; + ///term_printf("win_speed %.2f \r\n",weather_info.wind_velocity); + //HAL_Delay(1); + //osDelay(3// + //kan ni osDelay(6); +#if 0 + if(cnt < 10){ + wind_speed_data[cnt].fValue = weather_info.wind_c; + wind_direcion_data[cnt].fValue = weather_info.wind_velocity; + cnt++; + }else{ + cnt=0; + U_DataType tmp_wind_speed_value = filter_middle(wind_speed_data,10, FILTER_DATA_TYPE_FLOAT); + U_DataType tmp_wind_direction_value = filter_middle(wind_direcion_data,10, FILTER_DATA_TYPE_FLOAT); + update_mcs_param(tmp_wind_speed_value.fValue, tmp_wind_direction_value.fValue); + } +#endif + //osDelay(38); +// if(flag_init_msc_value== 1){ +// flag_init_msc_value = 0; +// g_stMcs_Para.min_wind_direction = weather_info.wind_c; +// g_stMcs_Para.average_wind_direction = weather_info.wind_c; +// g_stMcs_Para.max_wind_direction = 0; +// +// g_stMcs_Para.min_wind_speed = weather_info.wind_velocity; +// g_stMcs_Para.average_wind_speed = weather_info.wind_velocity; +// g_stMcs_Para.max_wind_speed = 0; +// } +// update_mcs_param(weather_info.wind_velocity, weather_info.wind_c); + } + /* USER CODE END wind_task */ +} + +/* 更新微气象站气象数据 */ +/* 风向、风向瞬时值:3s的滑动平均值,以1s为步长 + * 风速、风向平均值:以1min为步长,求xx分钟的滑动平均值,默认10分钟平均风速风向 + * 最大风速、风向:从10min平均风速中选取; +*/ +#define K_3S (3*1/3) +#define K_1MIN (3*3/60) +#define K_10MIN (3*60/600) + + int time_1s=0,time_11s=0,time_111s=0; + int flag_time_1s=0,flag_time_3s=0,flag_time_1min=0,flag_time_10min=0; + float Yn_sp_3s_average_value=0.0,Yn_1_sp_3s_average_value=0.0,yn_3s_sp_value=0.0; + float Yn_sp_1min_average_value=0.0,Yn_1_sp_1min_average_value=0.0,yn_1min_sp_value=0.0; + float Yn_sp_10min_average_value=0.0,Yn_1_sp_10min_average_value; + + float Yn_dir_3s_average_value=0.0,Yn_1_dir_3s_average_value=0.0,yn_3s_dir_value=0.0; + float Yn_dir_1min_average_value=0.0,Yn_1_dir_1min_average_value=0.0,yn_1min_dir_value=0.0;; + float Yn_dir_10min_average_value=0.0,Yn_1_dir_10min_average_value; + + float max_speed_value=0.0,max_direction_value=0.0,min_speed_value,min_direction_value=0.0; + + + +void update_mcs_param(float new_wind_speed, float new_wind_dirction) +{ + static int flag1=0; + static int flag11=0; + static int flag111=0; + + + time_1s++; + if(time_1s==3){ + time_1s=0; + flag_time_3s=1; + } + + time_11s++; + if(time_11s==20){ + time_11s=0; + flag_time_1min=1; + } + + time_111s++; + if(time_111s==g_usrConfigInfo.speed_average_time*60){ + time_111s=0; + flag_time_10min = 1; + } + + /* 以1s为步长,计算3s风速风向滑动平均值 */ + flag_time_1s=1; + if(flag_time_1s){ + + if(flag1 ==0){ + Yn_1_sp_3s_average_value = new_wind_speed; + Yn_1_dir_3s_average_value=new_wind_dirction; + flag1=1; + } + + + //flag_time_1s=0; + Yn_sp_3s_average_value = K_3S*(new_wind_speed - Yn_1_sp_3s_average_value) + Yn_1_sp_3s_average_value; + Yn_1_sp_3s_average_value = Yn_sp_3s_average_value; + + Yn_dir_3s_average_value = K_3S*(new_wind_dirction - Yn_1_dir_3s_average_value) + Yn_1_dir_3s_average_value; + Yn_1_dir_3s_average_value = Yn_dir_3s_average_value; + + } + + /* 以3s为步长,计算1min滑动平均风速 */ + if(flag_time_3s){ + if(flag11 ==0){ + Yn_1_sp_1min_average_value = Yn_sp_3s_average_value; + Yn_1_dir_1min_average_value = Yn_dir_3s_average_value; + flag11=1; + } + + + flag_time_3s=0; + Yn_sp_1min_average_value = K_1MIN*(Yn_sp_3s_average_value - Yn_1_sp_1min_average_value) + Yn_1_sp_1min_average_value; + Yn_1_sp_1min_average_value = Yn_sp_1min_average_value; + + Yn_dir_1min_average_value = K_1MIN*(Yn_dir_3s_average_value - Yn_1_dir_1min_average_value) + Yn_1_dir_1min_average_value; + //Yn_1_dir_1min_average_value = Yn_dir_1min_averの‘dvv,f;age_value; + } + + /* 以1min为步长,计算10min滑动平均风速 */ + if(flag_time_1min){ + + if(flag111 ==0){ + Yn_1_sp_10min_average_value = Yn_sp_1min_average_value; + Yn_1_dir_10min_average_value = Yn_dir_1min_average_value; + flag111=1; + } + + flag_time_1min = 0; + Yn_sp_10min_average_value = K_10MIN*(Yn_sp_1min_average_value - Yn_1_sp_10min_average_value) + Yn_1_sp_10min_average_value; + Yn_1_sp_10min_average_value = Yn_sp_10min_average_value; + + Yn_dir_10min_average_value = K_10MIN*(Yn_dir_1min_average_value - Yn_1_dir_10min_average_value) + Yn_1_dir_10min_average_value; + Yn_1_dir_10min_average_value = Yn_dir_10min_average_value; + } + + /* 统计最大风速风向,及平均风速 */ + if(flag_time_10min){ + flag_time_10min = 0; + if(max_direction_value < Yn_dir_10min_average_value){ + max_direction_value = Yn_dir_10min_average_value; + } + if(min_direction_value > Yn_dir_10min_average_value){ + min_direction_value = Yn_dir_10min_average_value; + } + + if(max_speed_value < Yn_sp_10min_average_value){ + max_speed_value = Yn_sp_10min_average_value; + } + if(min_speed_value > Yn_sp_10min_average_value){ + min_speed_value = Yn_sp_10min_average_value; + } + + g_stMcs_Para.min_wind_direction = min_direction_value; + g_stMcs_Para.average_wind_direction = Yn_dir_10min_average_value; + g_stMcs_Para.max_wind_direction = max_direction_value; + + g_stMcs_Para.min_wind_speed = min_speed_value; + g_stMcs_Para.average_wind_speed = Yn_sp_10min_average_value; + g_stMcs_Para.max_wind_speed = max_speed_value; + + } +} + +SlidingWindow_10min win_10min = {0}; +SlidingWindow_3s win_3s = {0}; +//求和函数 +float sum(float arr[], int n) +{ + float total = 0; + for(int i = 0; i < n; i++) + { + total += arr[i]; + } + return total; +} + +//int times_1s_3sec = 0; +//int times_1s_1min = 0; + +// 线性插值函数 +//float linear_interpolation(float x0, float y0, float x1, float y1, float x) { +float linear_interpolation(float x) { + float y; + //开始插值 + uint8_t num_point = 0; + float x1 = ((float )g_stConfigInfo.linear_point_1_x)/10; + float y1 = ((float )g_stConfigInfo.linear_point_1_y)/10; + float x2 = ((float )g_stConfigInfo.linear_point_2_x)/10; + float y2 = ((float )g_stConfigInfo.linear_point_2_y)/10; + float x3 = ((float )g_stConfigInfo.linear_point_3_x)/10; + float y3 = ((float )g_stConfigInfo.linear_point_3_y)/10; + float x4 = ((float )g_stConfigInfo.linear_point_4_x)/10; + float y4 = ((float )g_stConfigInfo.linear_point_4_y)/10; + float x5 = ((float )g_stConfigInfo.linear_point_5_x)/10; + float y5 = ((float )g_stConfigInfo.linear_point_5_y)/10; +// 插值点个数 + num_point = x5!=0?5:x4!=0?4:x3!=0?3:x2!=0?2:x1!=0?1:0; +// 未使能直接返回原始值,插值点小于2个返回原始值 + if(g_stConfigInfo.linear_enable != 0x01||num_point < 2) + { + return x; + } +// 小于0点返回0 + if(x=x1&&x=2)||(x>=x2&&num_point==2)) + { + y = y1 + (x - x1) * (y2 - y1) / (x2 - x1); + return y; + } +// 在前2,3点中间 或者 只有三个点,在3点后 + else if((x>=x2&&x=3)||(x>=x3&&num_point==3)) + { + y = y2 + (x - x2) * (y3 - y2) / (x3 - x2); + return y; + } +// 在前3,4点中间 或者 只有四个点,在4点后 + else if((x>=x3&&x=4)||(x>=x4&&num_point==4)) + { + y = y3 + (x - x3) * (y4 - y3) / (x4 - x3); + return y; + } +// 在前4,5点中间 或者 只有五个点,在5点后 + else if((x>=x4&&x=5)||(x>=x5&&num_point==5)) + { + y = y4 + (x - x4) * (y5 - y4) / (x5 - x4); + return y; + } +// 其他情况 + else + { + return x; + } +} + +void my_update_mcs_param(float new_wind_speed, float new_wind_dirction) +{ +///// 三秒滑动平均 +// win_3s.speed_data[win_3s.index] = new_wind_speed; +// win_3s.direction_data[win_3s.index] = new_wind_dirction; +// if(win_3s.count < 3) +// { +// win_3s.count++; +// } +// //计算三秒风速滑动平均值当作瞬时值 +// win_3s.ave_speed_data = sum(win_3s.speed_data, win_3s.count) / win_3s.count; +// //计算三秒风向滑动平均值,风向滑动平均值需要过零算法 +// float temp_sin_sum_3s = 0; +// float temp_cos_sum_3s = 0; +// for(int i = 0; i < win_3s.count; i++) +// { +// temp_sin_sum_3s += sinf(win_3s.direction_data[i] * PI/180); +// temp_cos_sum_3s += cosf(win_3s.direction_data[i] * PI/180); +// } +// win_3s.ave_direction_data = atanf(temp_sin_sum_3s / (temp_cos_sum_3s + 0.00001)) * 180/PI; +// // 不同象限不一样 +// // 1象限真实角度=本身 +// // 2象限真实角度=+180 +// // 3象限真实角度=+180 +// // 4象限真实角度=+360 +// if((temp_sin_sum_3s > 0 && temp_cos_sum_3s < 0) || (temp_sin_sum_3s < 0 && temp_cos_sum_3s < 0)) +// { +// win_3s.ave_direction_data += 180; +// }else if (temp_sin_sum_3s < 0 && temp_cos_sum_3s > 0) +// { +// win_3s.ave_direction_data += 360; +// } +// g_stMcs_Para.instantaneous_wind_direction = win_3s.ave_direction_data; +// +// /** 线性插值 **/ +// /** win_3s.ave_speed_data[win_3s.index]为风速 **/ +// /** win_3s.ave_direction_data[win_3s.index]为风向 **/ +// /** 风向不要插值 **/ +// /** 只用插值瞬时风速,10min便会是插值后的值 **/ +// g_stMcs_Para.instantaneous_wind_speed = linear_interpolation(win_3s.ave_speed_data); +// /** 线性插值 **/ +//// 更新索引 +// win_3s.index = (win_3s.index + 1) % 3; + /** 线性插值 **/ + /** 风向不要插值 **/ + /** 只用插值瞬时风速,10min便会是插值后的值 **/ + g_stMcs_Para.instantaneous_wind_speed = linear_interpolation(new_wind_speed); + /** 线性插值 **/ + g_stMcs_Para.instantaneous_wind_direction = new_wind_dirction; + + +/// 十分钟滑动平均值 + win_10min.speed_data[win_10min.index] = g_stMcs_Para.instantaneous_wind_speed; //添加新数据 + win_10min.direction_data[win_10min.index] = g_stMcs_Para.instantaneous_wind_direction; + + if(win_10min.count < g_usrConfigInfo.speed_average_time /*AVE_TIME*/) + { + win_10min.count++; + } + + if(win_10min.count > g_usrConfigInfo.speed_average_time/*AVE_TIME*/){win_10min.count = /*AVE_TIME*/g_usrConfigInfo.speed_average_time;} + //计算10min风速滑动平均值 + win_10min.ave_speed_data[win_10min.index] = sum(win_10min.speed_data, win_10min.count) / win_10min.count; + //计算10min风向滑动平均值,风向滑动平均值需要过零算法 + float temp_sin_sum = 0; + float temp_cos_sum = 0; + for(int i = 0; i < win_10min.count; i++) + { + temp_sin_sum += sinf(win_10min.direction_data[i] * PI/180); + temp_cos_sum += cosf(win_10min.direction_data[i] * PI/180); + } + win_10min.ave_direction_data[win_10min.index] = atanf(temp_sin_sum / (temp_cos_sum + 0.0001)) * 180/PI; + // 不同象限不一样 + // 1象限真实角度=本身 + // 2象限真实角度=+180 + // 3象限真实角度=+180 + // 4象限真实角度=+360 + if((temp_sin_sum > 0 && temp_cos_sum < 0) || (temp_sin_sum < 0 && temp_cos_sum < 0)) + { + win_10min.ave_direction_data[win_10min.index] += 180; + }else if (temp_sin_sum < 0 && temp_cos_sum > 0) + { + win_10min.ave_direction_data[win_10min.index] += 360; + } + + //默认第一个数据为最大或者最小 + float temp_min_direction = win_10min.ave_direction_data[0]; + float temp_max_direction = win_10min.ave_direction_data[0]; + float temp_min_speed = win_10min.ave_speed_data[0]; + float temp_max_speed = win_10min.ave_speed_data[0]; + float temp_trough_min_speed = win_10min.speed_data[0]; + float temp_peak_max_speed = win_10min.speed_data[0]; + float temp_trough_min_direction = win_10min.direction_data[0]; + float temp_peak_max_direction = win_10min.direction_data[0]; + //遍历10min内所有数据寻找最大最小极大极小 + for (int i = 0; i < win_10min.count; i++) { +// 最大最小 + if (win_10min.ave_direction_data[i] < temp_min_direction) { + temp_min_direction = win_10min.ave_direction_data[i]; // 更新风向最小值 + } + else if (win_10min.ave_direction_data[i] > temp_max_direction) { + temp_max_direction = win_10min.ave_direction_data[i]; // 更新风向最大值 + } + if (win_10min.ave_speed_data[i] < temp_min_speed) { + temp_min_speed = win_10min.ave_speed_data[i]; // 更新风速最小值 + } + else if (win_10min.ave_speed_data[i] > temp_max_speed) { + temp_max_speed = win_10min.ave_speed_data[i]; // 更新风速最大值 + } +// 极大极小 + if (win_10min.speed_data[i] < temp_trough_min_speed) { + temp_trough_min_speed = win_10min.speed_data[i]; // 更新风速极小值 + } + else if (win_10min.speed_data[i] > temp_peak_max_speed) { + temp_peak_max_speed = win_10min.speed_data[i]; // 更新风速极大值 + } + if (win_10min.direction_data[i] < temp_trough_min_direction) { + temp_trough_min_direction = win_10min.direction_data[i]; // 更新风向极小值 + } + else if (win_10min.direction_data[i] > temp_peak_max_direction) { + temp_peak_max_direction = win_10min.direction_data[i]; // 更新风向极大值 + } + } +// 更新最大最小极大极小风速风向 + g_stMcs_Para.min_wind_direction = temp_min_direction; + g_stMcs_Para.average_wind_direction = win_10min.ave_direction_data[win_10min.index]; + g_stMcs_Para.max_wind_direction = temp_max_direction; + + g_stMcs_Para.min_wind_speed = temp_min_speed; + g_stMcs_Para.average_wind_speed = win_10min.ave_speed_data[win_10min.index]; + g_stMcs_Para.max_wind_speed = temp_max_speed; + +// 极大极小风速与极大极小风向 + g_stMcs_Para.trough_wind_speed = temp_trough_min_speed; + g_stMcs_Para.peak_wind_speed = temp_peak_max_speed; + g_stMcs_Para.trough_wind_direction = temp_trough_min_direction; + g_stMcs_Para.peak_wind_direction = temp_peak_max_direction; + + win_10min.index = (win_10min.index + 1) % /*AVE_TIME*/g_usrConfigInfo.speed_average_time;//更新索引 +} + +void tem_hum_update_task(void const * argument) +{ + int time_s_temp_humi = 0; + uint32_t time_s_1Day = 0; + + float backupTemperature; + +// 开机先采集一次大气压温湿度 + { +// 采集HP203B传感器数据(大气压) + if(get_HP203_data(&backupTemperature, &g_stMcs_Para.pressure) == FALSE) + { + g_error_log.temp_error_HP203B = 1; +/// 错误处理 + } +// 采集SHT30传感器数据(温湿度) + if(get_temp_humi_data(&g_stMcs_Para.temperature, &g_stMcs_Para.humidity) == FALSE) + { + g_error_log.temp_error_SHT30 = 1; +/// 错误处理 + g_stMcs_Para.temperature = backupTemperature; + } + } + + while(1) + { + osDelay(1000); + time_s_temp_humi ++; + time_s_1Day ++; +// 温湿度大气压更新 + if (time_s_temp_humi >= g_usrConfigInfo.temp_hum_update_time) + { +// 采集HP203B传感器数据(大气压) + if(get_HP203_data(&backupTemperature, &g_stMcs_Para.pressure) == FALSE) + { + g_error_log.temp_error_HP203B = 1; +/// 错误处理 + } + else + { + // 没出问题清除错误日志 + g_error_log.temp_error_HP203B = 0; + } +// 采集SHT30传感器数据(温湿度) + if(get_temp_humi_data(&g_stMcs_Para.temperature, &g_stMcs_Para.humidity) == FALSE) + { + g_error_log.temp_error_SHT30 = 1; +/// 错误处理 + g_stMcs_Para.temperature = backupTemperature; + } + else + { + // 没出问题清除错误日志 + g_error_log.temp_error_SHT30 = 0; + } +// 计时重置 + time_s_temp_humi = 0; + } +// 一天重启 + if (time_s_1Day >= 86400) + { + __iar_builtin_set_FAULTMASK(1); + NVIC_SystemReset(); + } +// 风速风向更新 + my_update_mcs_param(weather_info.instantaneous_wind_speed, weather_info.instantaneous_wind_direction); + } +} + + + diff --git a/App/Src/frt_protocol.c b/App/Src/frt_protocol.c index 7407694..cbeadf9 100644 --- a/App/Src/frt_protocol.c +++ b/App/Src/frt_protocol.c @@ -81,6 +81,11 @@ static u_int16_t FRT_WriteRegPoint_3Y(void *pMsg); static u_int16_t FRT_WriteRegPoint_4Y(void *pMsg); static u_int16_t FRT_WriteRegPoint_5Y(void *pMsg); static u_int16_t FRT_WriteRegLinearEnable(void *pMsg); +/* 测试 */ +static u_int16_t FRT_ReadRegTest1(void *pMsg); +static u_int16_t FRT_ReadRegTest2(void *pMsg); +static u_int16_t FRT_ReadRegTest3(void *pMsg); +static u_int16_t FRT_ReadRegTest4(void *pMsg); static void pdebug_mcs_info(); @@ -121,10 +126,10 @@ FRT_RegProcTable_s g_RegTbl[] = { FRT_REGISTER_TRANSDUCER_CFG_8R0, FRT_ReadRegTransducerCFG8R0 }, /* 读换能器参数寄存器值8R0 */ { FRT_REGISTER_RSSI_RANGE, FRT_ReadRegRSSIRange }, /* 读RSSI有效范围 */ { FRT_REGISTER_COEFFICIENT, FRT_ReadRegCoefficient }, /* 读粘度修正系数 */ - { FRT_REGISTER_DISTANCE_NS, FRT_ReadRegDISTANCE_NS }, /* 读南北探头表面有效距离 */ + { FRT_REGISTER_DISTANCE_NS, FRT_ReadRegDISTANCE_NS }, /* 读南北探头表面有效距离 */ { FRT_REGISTER_DISTANCE_WE, FRT_ReadRegDISTANCE_WE }, /* 读东西探头表面有效距离 */ { FRT_REGISTER_ERROR_LOG, FRT_ReadRegErrorData }, /* 读错误日志 */ - { FRT_REGISTER_WIND_C_NS, FRT_ReadRegWindC_NS }, /* 读计算得到的南北风速 */ + { FRT_REGISTER_WIND_C_NS, FRT_ReadRegWindC_NS }, /* 读计算得到的南北风速 */ { FRT_REGISTER_WIND_C_WE, FRT_ReadRegWindC_WE }, /* 读计算得到的东西风速 */ { FRT_REGISTER_LINEAR_POINT_X_1, FRT_ReadRegPoint_1X }, /* 线性插值原始点1 */ { FRT_REGISTER_LINEAR_POINT_X_2, FRT_ReadRegPoint_2X }, /* 线性插值原始点2 */ @@ -137,6 +142,10 @@ FRT_RegProcTable_s g_RegTbl[] = { FRT_REGISTER_LINEAR_POINT_Y_4, FRT_ReadRegPoint_4Y }, /* 线性插值校准点4 */ { FRT_REGISTER_LINEAR_POINT_Y_5, FRT_ReadRegPoint_5Y }, /* 线性插值校准点5 */ { FRT_REGISTER_LINEAR_ENABLE, FRT_ReadRegLinearEnable }, /* 线性插值使能 */ + { FRT_REGISTER_TEST1, FRT_ReadRegTest1 }, /* 测试寄存器 */ + { FRT_REGISTER_TEST2, FRT_ReadRegTest2 }, /* 测试寄存器 */ + { FRT_REGISTER_TEST3, FRT_ReadRegTest3 }, /* 测试寄存器 */ + { FRT_REGISTER_TEST4, FRT_ReadRegTest4 }, /* 测试寄存器 */ }; /* 写寄存器处理表 */ @@ -797,6 +806,47 @@ static u_int16_t FRT_ReadRegLinearEnable(void *pMsg) return FRT_swap_endian_16(value); } +/** + * @brief 111111111111111 + * @param + * @retval + */ +static u_int16_t FRT_ReadRegTest1(void *pMsg) +{ + u_int16_t value=(u_int16_t)(Test1.ave); + return FRT_swap_endian_16(value); +} +/** + * @brief 111111111111111 + * @param + * @retval + */ +static u_int16_t FRT_ReadRegTest2(void *pMsg) +{ + u_int16_t value=(u_int16_t)(Test2.ave); + return FRT_swap_endian_16(value); +} +/** + * @brief 111111111111111 + * @param + * @retval + */ +static u_int16_t FRT_ReadRegTest3(void *pMsg) +{ + u_int16_t value=(u_int16_t)(Test3.ave); + return FRT_swap_endian_16(value); +} +/** + * @brief 111111111111111 + * @param + * @retval + */ +static u_int16_t FRT_ReadRegTest4(void *pMsg) +{ + u_int16_t value=(u_int16_t)(Test4.ave); + return FRT_swap_endian_16(value); +} + /** * @brief 写换能器参数寄存器值1R5 * @param @@ -1106,7 +1156,7 @@ void FRT_MsgProc_ReadRegister(device_handle device, void *pMsg) start_reg_addr < 0x00 ||\ (start_reg_addr > FRT_REGISTER_PRESSURE && start_reg_addr < FRT_REGISTER_DEVICE_ADDR) ||\ (start_reg_addr > FRT_REGISTER_TEMPHUM_UPDATE_TIME && start_reg_addr < FRT_REGISTER_TRANSDUCER_CFG_1R5) ||\ - start_reg_addr > FRT_REGISTER_LINEAR_ENABLE \ + start_reg_addr > FRT_REGISTER_TEST4 \ ) { @@ -1118,7 +1168,7 @@ void FRT_MsgProc_ReadRegister(device_handle device, void *pMsg) reg_num < 0x01 ||\ (((reg_num + start_reg_addr - 1) > FRT_REGISTER_PRESSURE) && ((reg_num + start_reg_addr - 1) < FRT_REGISTER_DEVICE_ADDR)) ||\ (((reg_num + start_reg_addr -1) > FRT_REGISTER_TEMPHUM_UPDATE_TIME) && ((reg_num + start_reg_addr -1) < FRT_REGISTER_TRANSDUCER_CFG_1R5)) ||\ - ((reg_num + start_reg_addr -1) > FRT_REGISTER_LINEAR_ENABLE) \ + ((reg_num + start_reg_addr -1) > FRT_REGISTER_TEST4) \ ) {