霍尔电机的霍尔信号(转向+速度)

什么是霍尔效应?

霍尔效应是电磁效应的一种,这一现象是美国物理学家霍尔(E.H.Hall,1855—1938)于1879年在研究金属的导电机制时发现的。   当电流垂直于外磁场通过半导体时,载流子发生偏转,垂直于电流和磁场的方向会产生一附加电场,从而在半导体的两端产生电势差,这一现象就是霍尔效应,这个电势差也被称为霍尔电势差。霍尔效应使用左手定则判断

 霍尔效应符合物理课本上面的左手定则,着手磁场垂直于手心,指尖是电流方向,大拇指就是安培力的方向,所以这个力拉扯电子形成电压差。

霍尔效应应用如下图

A点和B点就是产生点位差的地方, 如此可以产生一个电压。中间的铁板相当于一个霍尔传感器,电压就是相当于信号。所以有磁场就有霍尔信号。

动画详解霍尔效应原理_哔哩哔哩_bilibili

什么是霍尔电机?

利用霍尔效应驱动的电机,下面是霍尔传感器的简图:本人是搞单片机的,非结构专业不保证图是对的。

以上有两个磁铁,所以必然有两个信号代表一圈;比如霍尔A得到两个脉冲电压代表转过一圈。

霍尔电机应用+制作:
霍尔无刷电机是什么工作原理?用几块磁铁做一个,原来并不复杂_哔哩哔哩_bilibili

霍尔电机单磁极:

【有刷电机霍尔和无刷电机霍尔的科普 霍尔开关,霍尔传感器】https://www.bilibili.com/video/BV15G4y1D7ik?vd_source=4e683a72f3622d9cfc92780b0923b43a

有刷电机霍尔和无刷电机霍尔的科普 霍尔开关,霍尔传感器_哔哩哔哩_bilibili

霍尔电机单片机实践——读取霍尔信号测速+转向;

首先我也没有电机的结构图;只有一个不知名霍尔电机,电机转速测速表;

电机转速测速表:uni-t ut373迷你型的电机转速表;使用方法略;使用反光纸,转一圈就反射一次;

霍尔电机有5个线的插头是霍尔信号的:判别U (黄)   V(绿)   W(蓝) 红黑是供电线5V这样;一般通用;不保证所有霍尔电机都是这样;

1、’使用示波器连接其中一个信号线;然后电机转速测速标测实际速度;

2、使用电机控制器霍尔线连接单片机再连接电机,控制器驱动高电压线连接电机

 

示波器&&转速表的测试表

霍尔&&实测
转把PWM霍尔周期ms霍尔频率r/min(霍)备注说明测转速表(r/min)
000000
102 到8hz(不稳定转)转一下停120-170
2089.953942630.1
3013581004009
4016498404900
5016699604927
6016699604927
70167100204965
80167100204965
90167100204965
100167100204965
10.114.5870390
浮动数据浮动数据
结论:两个霍尔信号转一圈

霍尔信号与转速表成倍数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单位                                  
   }               
   
   

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值