什么是霍尔效应?
霍尔效应是电磁效应的一种,这一现象是美国物理学家霍尔(E.H.Hall,1855—1938)于1879年在研究金属的导电机制时发现的。当电流垂直于外磁场通过半导体时,载流子发生偏转,垂直于电流和磁场的方向会产生一附加电场,从而在半导体的两端产生电势差,这一现象就是霍尔效应,这个电势差也被称为霍尔电势差。霍尔效应使用左手定则判断
霍尔效应符合物理课本上面的左手定则,着手磁场垂直于手心,指尖是电流方向,大拇指就是安培力的方向,所以这个力拉扯电子形成电压差。
霍尔效应应用如下图
A点和B点就是产生点位差的地方,如此可以产生一个电压。中间的铁板相当于一个霍尔传感器,电压就是相当于信号。所以有磁场就有霍尔信号。
动画详解霍尔效应原理_哔哩哔哩_bilibili
什么是霍尔电机?
利用霍尔效应驱动的电机,下面是霍尔传感器的简图:本人是搞单片机的,非结构专业不保证图是对的。
以上有两个磁铁,所以必然有两个信号代表一圈;比如霍尔A得到两个脉冲电压代表转过一圈。
霍尔电机应用+制作:
霍尔无刷电机是什么工作原理?用几块磁铁做一个,原来并不复杂_哔哩哔哩_bilibili
霍尔电机单磁极:
【有刷电机霍尔和无刷电机霍尔的科普 霍尔开关,霍尔传感器】/video/BV15G4y1D7ik?vd_source=4e683a72f3622d9cfc92780b0923b43a
有刷电机霍尔和无刷电机霍尔的科普 霍尔开关,霍尔传感器_哔哩哔哩_bilibili
霍尔电机单片机实践——读取霍尔信号测速+转向;
首先我也没有电机的结构图;只有一个不知名霍尔电机,电机转速测速表;
电机转速测速表:uni-t ut373迷你型的电机转速表;使用方法略;使用反光纸,转一圈就反射一次;
霍尔电机有5个线的插头是霍尔信号的:判别U (黄) V(绿) W(蓝) 红黑是供电线5V这样;一般通用;不保证所有霍尔电机都是这样;
1、’使用示波器连接其中一个信号线;然后电机转速测速标测实际速度;
2、使用电机控制器霍尔线连接单片机再连接电机,控制器驱动高电压线连接电机
示波器&&转速表的测试表
霍尔信号与转速表成倍数2的关系
得到结论:两个方波表一圈:
单片机利用霍尔信号的测速方案:
1、利用外部中断;两个上升沿+定时器的时间*2=得到转速
2、利用捕获:上升沿捕获*2=转速
但是先上波形;霍尔信号的波形
ps如下的波形频率85*60=5100r/min符合 测试表的转把PWM的20 。如下为判定。
1、排除掉里面的频率很高杂波,如果里面的不是杂波,那么频率应该达到15.3khz。
一、转速不符合实际转速,变大了几千倍15.3k*60=918k r/min。
二、或者,测转速表转速已经和脉冲成为了千倍关系,电机里面的磁极有几千个,才符合测速表的测量转速(电机的一个磁极转一圈一个脉冲)。
所以得出结论:80hz方波里面面的为杂波;
图霍尔信号的波形
图霍尔里面的杂波
ps:由杂波频率可以知道频率为15.3khz,为了保证有低于这个15.3频率一点点的杂波出现,应该选择低筒截止频率在10khz左右。因为非干扰波,最高频率只用到1khz
截止频率运算
以上提到截止频率,怎么运算。怎么去滤波?
采用LC RC低通滤波器,这里采用RC滤波器;
怎么选取参数,360R和33nf
附上公式链接:
参考别人的
RC低通滤波器截止频率公式推导_rc低通滤波电路_月光疾風的博客-CSDN博客
自己运算的:
RC滤波分析计算——信号与系统_qq_36658033的博客-CSDN博客
如果采取光耦隔离:输入单片机的波形
就要在光耦两边都用上;具体参数按照计算方法字节选取;为了方便硬件我选取了单电容滤波;这个弊端很大;波形会变得十分的差;
如下是滤除好的波,频率越高上升沿弯曲严重;但是勉强可用;
计算方法还是:将电容换成频域;(不保证对不对,瞎几把写的)
c的频域为=1/jwc
假设截至频率也是2分之根号2=|1/jwc|模;
如截止频率运算
那么经过计算0.1的uf的大概频率截至在2.3M这样
所以经过计算和更换选用0.22uf的,其实可以选更大的选mf的试试(没试过);
速度和转向程序;
测量原理:在霍尔信号处理好没有毛刺的输入单片机情况下;用定时器的us级别作为捕获,测量一个信号的周期;因为3个极对,一个极两个信号为转一圈;测量的周期x2就得到了转一圈的时间;即r/s
转向可以通过三个霍尔来标定;比如在A发送情况后B发生,正向;A发生后C发生就反向;(是例如哦)
底层驱动文件
#include "Drv_hall_capture.h"#include "public.h"#include "hk32f0xx.h"static uint32_t line10_counter_B = 0, line11_counter_C = 0 ,*p_get_TIM1_captrue1_counter;static char front_turn;void Drv_external_interrup_init(){GPIO_InitTypeDef GPIO_InitStruct;EXTI_InitTypeDef EXTI_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE );GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 |GPIO_Pin_11 ;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN ;GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;GPIO_Init( GPIOA, &GPIO_InitStruct);EXTI_InitStruct.EXTI_Line = /* EXTI_Line9 |*/EXTI_Line10 | EXTI_Line11;EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt ;EXTI_InitStruct.EXTI_Trigger= EXTI_Trigger_Falling ;EXTI_InitStruct.EXTI_LineCmd= ENABLE;EXTI_Init( &EXTI_InitStruct);NVIC_InitStruct.NVIC_IRQChannel = EXTI4_15_IRQn;NVIC_InitStruct.NVIC_IRQChannelPriority = 2;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init( &NVIC_InitStruct);gx.hall_value.hall_V_B =& line10_counter_B;gx.hall_value.hall_W_C =& line11_counter_C;gx.hall_value.front_break_turn =& front_turn;}/*hall 外部中断处理 hall信号中断就标记,如果在捕获到A之后立即再判断一次外中断;如果外中断B就是正向,C就是反向;*/static uint32_t external_counter;void Drv_interruo_external_PA9_PA10_PA11(void){bool A_to_next_B , A_to_next_C;if( EXTI_GetFlagStatus( EXTI_Line10)){ A_to_next_B = true;line10_counter_B++;}if( EXTI_GetFlagStatus( EXTI_Line11)){A_to_next_C = true;line11_counter_C++; }if( external_counter != *p_get_TIM1_captrue1_counter ){//if( *p_get_TIM1_captrue1_counter >= 60000 ) { *p_get_TIM1_captrue1_counter = 0; } //防止溢出处理external_counter = *p_get_TIM1_captrue1_counter;if( A_to_next_B == true ) { front_turn = 0; } //负向else if( A_to_next_C == true) { front_turn = 1; } //正} EXTI_ClearFlag( EXTI_Line10|EXTI_Line11); }void EXTI4_15_IRQHandler(){Drv_interruo_external_PA9_PA10_PA11( );}/**** 霍尔捕获,一个霍尔信号是方波 ***/static uint32_t TIM1_captrue2; //捕获ic2 static uint32_t TIM1_period; //捕获信号的 周期static uint32_t TIM1_captrue2_counter; // 捕获ic2 的计数static uint32_t TIM1_update_counter; // 一个信号内的 更新计数累加static uint32_t TIM1_captrue2_update_counter; // ic2捕获到了之后,记录当前更新计数;void Drv_time1_capture_init( uint16_t prescaler ,uint16_t reload ){GPIO_InitTypeDef GPIO_InitStruct;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_ICInitTypeDef TIM_ICInitStruct;NVIC_InitTypeDef NVIC_InitStruct;RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 ;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF ;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP ;GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3 ;GPIO_Init( GPIOA, & GPIO_InitStruct);GPIO_PinAFConfig(GPIOA, GPIO_PinSource9 , GPIO_AF_2 );TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up ;TIM_TimeBaseInitStruct.TIM_Prescaler = prescaler - 1;TIM_TimeBaseInitStruct.TIM_Period = reload -1;TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);TIM_ICInitStruct.TIM_Channel = TIM_Channel_2 ;TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising ;TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI ;TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1 ;TIM_ICInitStruct.TIM_ICFilter = 1 ;TIM_ICInit(TIM1, &TIM_ICInitStruct);TIM_ARRPreloadConfig( TIM1, ENABLE);TIM_ITConfig( TIM1, TIM_IT_CC2 , ENABLE );TIM_ITConfig( TIM1, TIM_IT_Update, ENABLE );NVIC_InitStruct.NVIC_IRQChannel = TIM1_CC_IRQn ;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE ;NVIC_InitStruct.NVIC_IRQChannelPriority = 1;NVIC_Init( & NVIC_InitStruct);NVIC_InitStruct.NVIC_IRQChannel = TIM1_BRK_UP_TRG_COM_IRQn ;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE ;NVIC_InitStruct.NVIC_IRQChannelPriority = 1;NVIC_Init( & NVIC_InitStruct);TIM_Cmd( TIM1, ENABLE );gx.TIM1_captrue.p_captrue2 = & TIM1_captrue2;gx.TIM1_captrue.p_captrue2_counter = &TIM1_captrue2_counter;p_get_TIM1_captrue1_counter = &TIM1_captrue2_counter; //提供给外部中断gx.TIM1_captrue.p_period = & TIM1_period;}/* 更新 ic2 捕获 中断处理*/void Drv_captrue2_interrup( void );void TIM1_CC_IRQHandler(){if( TIM_GetITStatus( TIM1,TIM_IT_CC2 ) ){ Drv_captrue2_interrup( );}TIM_ClearITPendingBit( TIM1, TIM_IT_CC2 ); }void TIM1_BRK_UP_TRG_COM_IRQHandler( ){if( TIM_GetITStatus( TIM1, TIM_IT_Update ) ){TIM1_update_counter++; led_off_open( );}TIM_ClearITPendingBit( TIM1, TIM_IT_Update );}/* 捕获ic2驱动:跳过第一次捕获每次捕获都记录当前更新中断的次数,并且清零更新中断每次捕获完了都清除计数器;每次捕获清除更新次数。 */void Drv_captrue2_interrup( void ){static uint8_t cnt1;if(cnt1 == 0){ cnt1 ++;//第一次的边沿读取,并且清零计数器;}else{TIM1_captrue2_counter++; // 第二次捕获之后才进行捕获计数; TIM1_captrue2 = TIM_GetCapture2( TIM1);TIM1_captrue2_update_counter = TIM1_update_counter;TIM1_period = TIM1_captrue2 +( TIM1_captrue2_update_counter * TIM1_CAPTRUE_RELOAD);} TIM_SetCounter( TIM1, 0);TIM1_update_counter = 0 ; //每次处理捕获1之后 都清了掉计数}void Drv_speed_drectiong_hall( uint32_t **period ,char **direction ,uint32_t **update1){*period=& TIM1_period ;*direction =& front_turn ;*update1 =& TIM1_captrue2_update_counter ;}
链接文件
#include "link_speed_drection.h"#include "public.h"static uint32_t *period_cnt ,*p_update1,*p_revolution_s =& gx.motor_parameter.motor_revolution_s ;static char *direction_flag =& gx.motor_parameter.motor_direction;void Link_get_revolution_speed_and_direction( void ){static uint8_t cnt;uint32_t T_us;if( cnt == 0 ){cnt++; Drv_speed_drectiong_hall(&period_cnt , &direction_flag ,&p_update1);}else{T_us = (*period_cnt * 2 ); // 三个极对 ,两个周期算一圈;*p_revolution_s = 1000000 / T_us ; // f = 1 / T .现在T是us单位 }}