搜索
bottom↓
回复: 206

自己做的STM32 BLDC直流无刷电机控制器

  [复制链接]

出0入0汤圆

发表于 2011-11-15 20:42:06 | 显示全部楼层 |阅读模式
STM32 BLDC开发板
提供原理图和相应的原代码,源代码是基于免费开源CoOS(UCOS类似)操作系统上写的,在学习无刷电机的控制同时还能学习到操作系统的知识。同时提供用Matlab的GUI编写的串口接收程序和开源的代码,实时接收速度和电流信息,便于PID测试,并且有CAN(TJA1050)接口。同时自己可以进行修改学习Matlab的GUI编程。
1.        STM32F103RB处理器 时钟72M Flash 64K RAM 20K
2.        MOSFET SUD35N05-26L  55V 35A Rds=0.02
3. MOSFET驱动 IR2101S
输入开发板电源
电源 10到20V
最大电流 20A
无刷电机
额定电压 12V
额定电流  2.26A
额定转速  13027RPM
无刷电机接口:
黄色线: Vcc +5V
灰色: GND
棕色:霍尔S1
蓝色:霍尔S2
橙色:霍尔S3
红色:A相
黑色:B相
绿色:C相

开发板配置:
1.无刷电机驱动
2.串口通信接口
3.CAN通信接口
4.有AD接口能检测电压和电流
5.两个按键和一个复位键
6.一个LED
7.JLINK调试接口
开发板配件:
交流220V转直流12V 6A电源  
带霍尔无刷电机 12V 2.26A          
STM32无刷电机驱动板       

电源开发板无刷电机图片 (原文件名:电源开发板无刷电机图片.jpg)                
软件资料:
有无刷电机转速调节的PID程序(基于免费开源CoOS操作系统)
自己做的Matlab GUI串口PID调试程序(开源,自己可以改进)
自己以前做的STM32程序

电机运行时PID调节图 (原文件名:电机运行时PID调节图.jpg)


电源开发板无刷电机图片 (原文件名:电源开发板无刷电机图片.jpg)


无刷电机的图片 (原文件名:无刷电机的图片.jpg)


只有开发板的图片 (原文件名:只有开发板的图片.jpg)

出0入0汤圆

 楼主| 发表于 2011-11-15 20:43:57 | 显示全部楼层
回复【楼主位】lijinzhi
-----------------------------------------------------------------------
QQ:2572051223

出0入0汤圆

发表于 2011-11-15 21:12:00 | 显示全部楼层
广告?

出0入0汤圆

 楼主| 发表于 2011-11-16 08:02:56 | 显示全部楼层
可能是吧! 这是我自己做的东西卖的很便宜,一套才260元,http://item.taobao.com/item.htm?id=13198690287&stp=13198690287
 
把自己做的小东西卖去出,你体会到其中的乐趣。钱只是其中的副产品,作为一个大学生我没有经济来源,把做的东西卖了可以维持我再做一些东西,否则我那来这么多钱做这些阿!期望大家理解。我会过些时候把做的资料都给传上来!

出0入0汤圆

发表于 2011-11-16 08:24:26 | 显示全部楼层
回复【楼主位】lijinzhi  
-----------------------------------------------------------------------

来看LZ最后一面...260不觉得卖得很便宜...估计利润达150%...LZ还是看看版规再发帖吧...

出0入0汤圆

发表于 2011-11-16 08:27:10 | 显示全部楼层
对你的无刷电机风扇感兴趣,哪里买的?

出50入0汤圆

发表于 2011-11-16 09:27:25 | 显示全部楼层
大概描述技术细节,比如有没有用库?做了多少改进?

出0入0汤圆

发表于 2011-11-16 10:10:34 | 显示全部楼层
楼主好强大,膜拜!价格嘛稍微有点贵,不过也值了。

出0入0汤圆

 楼主| 发表于 2011-11-16 10:13:05 | 显示全部楼层
有电机和电源还有板子  我没有用库程序

出0入0汤圆

发表于 2011-11-16 10:18:32 | 显示全部楼层
顶下楼主。论坛要的是分享的精神,想买或需要的人自然会买的。建议早上资料。

出0入0汤圆

 楼主| 发表于 2011-11-16 10:32:57 | 显示全部楼层
开发板的资料ourdev_695691EPDAW2.rar(文件大小:20.49M) (原文件名:BLDC开发板.rar)
这是板子的资料

出0入0汤圆

发表于 2011-11-16 11:08:00 | 显示全部楼层
这个好,以玩养玩,不图赚钱,可以让大家好好学习。网上stm32的bldc开源代码很少,非库的就更加少了。顶楼主。

出0入0汤圆

发表于 2011-11-16 11:24:05 | 显示全部楼层
回复【4楼】racede
回复【楼主位】lijinzhi   
-----------------------------------------------------------------------
来看lz最后一面...260不觉得卖得很便宜...估计利润达150%...lz还是看看版规再发帖吧...
-----------------------------------------------------------------------

白送的话你会更喜欢,知识不能创造财富是你我搞技术之辈的悲哀。

出0入0汤圆

发表于 2011-11-16 11:24:57 | 显示全部楼层
不错。MARK!

出0入0汤圆

发表于 2011-11-16 13:14:40 | 显示全部楼层
很好啊,顶一下。

出0入0汤圆

发表于 2011-11-16 14:25:43 | 显示全部楼层
很好啊,顶一下。

出0入0汤圆

发表于 2011-11-16 14:31:27 | 显示全部楼层
原来是带霍尔的。

出0入0汤圆

发表于 2011-11-16 17:00:36 | 显示全部楼层
現在很多無霍尔的

出0入0汤圆

发表于 2011-11-17 10:05:46 | 显示全部楼层
顶一下

出0入0汤圆

发表于 2011-11-17 10:20:49 | 显示全部楼层
能搞个无霍尔的吗?能在大学搞出个这样的东东来,很不错唉。感觉自己大学白读了,没学到啥,自己也没整出个啥。

出0入0汤圆

发表于 2011-11-17 10:23:22 | 显示全部楼层
不过260有点点贵了,别人用8位的就能解决了,价格估计是200以下,不过这种精神难得,顶一下!

出0入0汤圆

发表于 2011-11-17 15:52:53 | 显示全部楼层
很不错!自然要顶!

出0入0汤圆

发表于 2011-11-18 00:50:56 | 显示全部楼层
回复【22楼】2006612
-----------------------------------------------------------------------

this not the most efficient way to control bldc motor.you did not use commutation event triggering method as internal commutation with xored hall sensor change.

you can use information below

Code for the HallSensor timer
Internal Connection from Hall/Enc Timer to Motor Timer. The HALL Timer Output is direct connected to the Motor Timer Commutation Trigger. If the correct combination of Motor and Hall/Enc Timer is selected then this is done for you. If you can not use the internal Connection you have to do this in an Interrupt manually.

Only following Combinations are possible[1]

If Motor is on Timer1 this is possible

•Hall/Enc is Timer 2 → Motor is Timer 1 → use TIM_TS_ITR1
•Hall/Enc is Timer 3 → Motor is Timer 1 → use TIM_TS_ITR2
•Hall/Enc is Timer 4 → Motor is Timer 1 → use TIM_TS_ITR3
•Hall/Enc is Timer 5 → Motor is Timer 1 → use TIM_TS_ITR0
If Motor is on Timer8 this is possible

•Hall/Enc is Timer 1 → Motor is Timer 1 → use TIM_TS_ITR0
•Hall/Enc is Timer 2 → Motor is Timer 1 → use TIM_TS_ITR1
•Hall/Enc is Timer 4 → Motor is Timer 1 → use TIM_TS_ITR2
•Hall/Enc is Timer 5 → Motor is Timer 1 → use TIM_TS_ITR3
void configHallSensorTimer(void) {

// Timer 3 decodes the 3 HallSensor input lines  
// see referenze manual page 305
  
// define timer clock
// between two changes on the hall sensor lines on the lowest rotation
// speed (eg. 1/100 from max. speed)  the timer must not overflow
// define timer counter clock appropriate

// enable port pins for hall inputs
RCC_APB2PeriphClockCmd(...);  
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_...;
GPIO_InitStructure.GPIO_Mode = ...
GPIO_Init(..., &GPIO_InitStructure);

RCC_APB1PeriphClockCmd(TIM4_CLK, ENABLE);

  // timer base configuration
  // 126 => 3,5s till overflow ; 285,714kHz TimerClock [36MHz/Prescaler]
  TIM_TimeBaseStructure.TIM_Prescaler = 126;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
   
  // enable hall sensor
  // T1F_ED will be connected to  HallSensoren Imputs
  // TIM4_CH1,TIM4_CH2,TIM4_CH3
  TIM_SelectHallSensor(TIM4, ENABLE);

  //  TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
  //  uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
  
  // HallSensor event is delivered with singnal TI1F_ED
  // (this is XOR of the three hall sensor lines)
  // Signal TI1F_ED: falling and rising ddge of the inputs is used
  TIM_SelectInputTrigger(TIM4, TIM_TS_TI1F_ED);
  
  // On every TI1F_ED event the counter is resetted and update is tiggered
  TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);

  // Channel 1 in input capture mode
  // on every TCR edge (build from TI1F_ED which is a HallSensor edge)  
  // the timervalue is copied into ccr register and a CCR1 Interrupt
  // TIM_IT_CC1 is fired

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  // listen to T1, the  HallSensorEvent
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_TRC;
  // Div:1, every edge
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  // noise filter: 1111 => 72000kHz / factor (==1) / 32 / 8 -> 281kHz
  // input noise filter (reference manual page 322)
  TIM_ICInitStructure.TIM_ICFilter = 0xF;
  TIM_ICInit(TIM4, &TIM_ICInitStructure);
  
  // channel 2 can be use for commution delay between hallsensor edge
  // and switching the FET into the next step. if this delay time is
  // over the channel 2 generates the commutation signal to the motor timer
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_Pulse = 1; // 1 is no delay; 2000 = 7ms
  TIM_OC2Init(TIM4, &TIM_OCInitStructure);
  
  // clear interrupt flag
  TIM_ClearFlag(TIM4, TIM_FLAG_CC2);
  
  //TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);
  // TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_OC1);
  // timer2 output compate signal is connected to TRIGO
  TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_OC2Ref);
  
  // Enable channel 2 compate interrupt request
  // TIM_IT_CC1 | TIM_IT_CC2
  TIM_ITConfig(TIM4, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);

  // Enable output compare preload
  //TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
  
  // Enable ARR preload
  //TIM_ARRPreloadConfig(TIM4, ENABLE);
  
  // Enable update event
  //TIM_ClearFlag(TIM4, TIM_FLAG_Update);
  //TIM_ITConfig(TIM4, TIM_IT_Update, DISABLE);

  // we use preemption interrupts here,  BLDC Bridge switching and
  // Hall has highest priority
  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  // -------------------
  // HallSensor is now configured, if BLDC Timer is also configured
  // after enabling timer 4
  // the motor will start after next overflow of the hall timer because
  // this generates the first startup motor cummutation event
  TIM_Cmd(TIM4, ENABLE);
}

void incCommutationDelay(void) {
  TIM4->CCR2 = (TIM4->CCR2) + 1;
}

void decCommutationDelay(void) {
  TIM4->CCR2 = (TIM4->CCR2) - 1;
}

// ------------- HallSensor interrupt handler -----------------

// this handles TIM4 irqs (from HallSensor)
void TIM4_IRQHandler(void) {      
  if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET)
  {
    TIM_ClearITPendingBit(MOTOR_TMC603_HALLENC_TIM, TIM_IT_CC1);
    // calculate motor  speed or else with CCR1 values
    hallccr1 = TIM4->CCR1;
    ...
  }
  else if (TIM_GetITStatus(TIM4, TIM_IT_CC2) != RESET)
  {
    TIM_ClearITPendingBit(MOTOR_TMC603_HALLENC_TIM, TIM_IT_CC2);
    // this interrupt handler is called AFTER the motor commutaton event
    // is done
    // after commutation the next motor step must be prepared
    // use inline functions in irq handlers static __INLINE funct(..) {..}
    BLDCMotorPrepareCommutation();
  } else {
    ; // this should not happen
  }
}

[Bearbeiten] Code for BLDC motor control timer
void configMotorBridgeTimer(void) {

// define timer clock, motor timer can be TIM1 or TIM8
RCC_APB2PeriphClockCmd(...);

// define the 6 output pins for the bridge, if needed define
// the input pin for emergeny stop

// Chopper Frequency (PWM for the FETs)
// 18kHz was good in empiric tests
// ARR = SystemCoreClock / ChopperFreq
// ARR defines also the resolution of the Chopper PWM
#define BLDC_CHOPPER_PERIOD ((uint16_t)4000)

  // Time Base configuration

  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_Period = BLDC_CHOPPER_PERIOD;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  // Channel 1, 2, 3 – set to PWM mode - all 6 outputs
  // per channel on output is  low side fet, the opposite is for high side fet

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 0; // BLDC_ccr_val

  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;

  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
  TIM_OC2Init(TIM1, &TIM_OCInitStructure);
  TIM_OC3Init(TIM1, &TIM_OCInitStructure);

  // activate preloading the CCR register
  TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
  TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
  TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);

  /* automatic output enable, break off, dead time ca. 200ns and

  // no lock of configuration */

  TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
  TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
  TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;

  // DeadTime value n=1 bis 31: from 14ns to 1,7us
  // DeadTime value n=129 bis 159: from 1,7us to 3,5ms
  // DeadTime value 7 => 98ns
  // ... see programmers reference manual

  // DeadTime[ns] = value * (1/SystemCoreFreq) (on 72MHz: 7 is 98ns)
  TIM_BDTRInitStructure.TIM_DeadTime = 7; // 98ns

  TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;

  // enabel this if you use emergency stop signal
  // TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
  // TIM_BDTRInitStructure.TIM_BreakPolarity = MOTOR_TMC603_EMSTOP_POLARITY;

  TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;

  TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);

  // preload ARR register
  TIM_CCPreloadControl(TIM1, ENABLE);

  // activate COM (Commutation) Event from Slave (HallSensor timer)
  // through TRGI
  enableHallCommutateSignal();

  // Internal connection from Hall/Enc Timer to Motor Timer
  // eg. TIM1 (BLDC Motor Timer) is Slave of TIM3 (Hall Timer)
  // Internal connection from Hall/Enc Timer to Motor Timer

  // Choose carefully from the following possible combination
  // check programmers reference manual
  // TIM_SelectInputTrigger(TIM1, TIM_TS_ITR0);
  // MotorTimer = TIM1, HallTimer = TIM5
  // TIM_SelectInputTrigger(TIM1, TIM_TS_ITR1);
  // MotorTimer = TIM1, HallTimer = TIM2
  // TIM_SelectInputTrigger(TIM1, TIM_TS_ITR2);
  // MotorTimer = TIM1, HallTimer = TIM3
TIM_SelectInputTrigger(TIM1, TIM_TS_ITR3);
  // MotorTimer = TIM1, HallTimer = TIM4
  // TIM_SelectInputTrigger(TIM8, TIM_TS_ITR0);
  // MotorTimer = TIM8, HallTimer = TIM1
  // TIM_SelectInputTrigger(TIM8, TIM_TS_ITR1);
  // MotorTimer = TIM8, HallTimer = TIM2
  // TIM_SelectInputTrigger(TIM8, TIM_TS_ITR2);
  // MotorTimer = TIM8, HallTimer = TIM4
  // TIM_SelectInputTrigger(TIM8, TIM_TS_ITR3);
  // MotorTimer = TIM8, HallTimer = TIM5

  // Enable interrupt, motor commutation has high piority and has
  // a higher subpriority then the hall sensor
  NVIC_InitStructure.NVIC_IRQChannel = TIM1_TRG_COM_IRQn;

  // highest priority
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  // highest priority
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  // Interrupt for hardwired EmergencyStop
(if needed)
  // Timer 1 Motor Emergency Break Input
  // NVIC_InitStructure.NVIC_IRQChannel = TIM1_BRK_IRQn;
  // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
  // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  // NVIC_Init(&NVIC_InitStructure);

  // --------- activate the bldc bridge ctrl. ----------
  // in a project this will be done late after complete
  // configuration of other peripherie

  // enable COM (commutation) IRQ
  TIM_ITConfig(TIM1, TIM_IT_COM, ENABLE);

  // enable motor timer
  TIM_Cmd(TIM1, ENABLE);

  // enable motor timer main output (the bridge signals)
  TIM_CtrlPWMOutputs(TIM1, ENABLE);
}

// enable the connection between HallTimer and MotorTimer
void enableHallCommutateSignal() {
   TIM_SelectCOM(TIM1, ENABLE);
}

// disable the connection between HallTimer and MotorTimer
void disableHallCommutateSignal() {
   TIM_SelectCOM(TIM1, DISABLE);
}

// BLDC motor steps
// every row from 1 to 6 is called by a hall state
// every column a FET from 3-phase bridge
// motor off is at row 0 BLDC_BRIDGE_STATE_VORWARD[0]
// cw - rechtslauf - positiv
// {    1H,1L      ,      2H,2L      ,     3H,3L    }
// BLDC motor steps
// every row from 1 to 6 is one of the 6 motor vector state
// every column a FET from 3-phase bridge
// all FETs off at row 0 or 8 (this pattern should not come from the hallsensor)
// cw - rechtslauf - positiv
// {    1H,1L      ,      2H,2L      ,     3H,3L    }
static const uint8_t BLDC_BRIDGE_STATE_VORWARD[8][6] =   // Motor step
{
   { FALSE,FALSE   ,   FALSE,FALSE   ,  FALSE,FALSE },  // 0
   { FALSE,TRUE    ,   TRUE ,FALSE   ,  FALSE,FALSE },  // 2
   { FALSE,FALSE   ,   FALSE,TRUE    ,  TRUE ,FALSE },  // 4
   { FALSE,TRUE    ,   FALSE,FALSE   ,  TRUE ,FALSE },  // 3
   { TRUE ,FALSE   ,   FALSE,FALSE   ,  FALSE,TRUE  }   // 6
   { FALSE,FALSE   ,   TRUE ,FALSE   ,  FALSE,TRUE  },  // 1
   { TRUE ,FALSE   ,   FALSE,TRUE    ,  FALSE,FALSE },  // 5
   { FALSE,FALSE   ,   FALSE,FALSE   ,  FALSE,FALSE },  // 0
};

// This function handles motor timer trigger and commutation interrupts
// can be used for calculation...
void TIM1_TRG_COM_IRQHandler(void)
{
  TIM_ClearITPendingBit(TIM1, TIM_IT_COM);
  // commutationCount++;
}

/* This is called from HALL timer interrupt handler
   remember:
     if hall a hall edge is detected
     first the motor commutation event is done
     next this routine is called which has to prepare the next motor step
     (which FET must be switched on or off)
   active freewhelling is used to minimize power loss
  
   code should be easy to understand and to debug... for practical use
   you should optimize it */

static __INLINE void BLDCMotorPrepareCommutation(void)
{
  // next bridge step calculated by HallSensor inputs
  // if there was an hall event without changing the hall position,
  // do nothing.
  //
  // In principle, on every hall event you can go to the next motor
  // step but i had sometimes problems that the motor was running
  // on an harmonic wave (??) when the motor was without load
  uint16_t newhallpos = ((GPIO_ReadInputData(GPIOD) & 0x7000) >> 12);

  if (newhallpos == hallpos) return;
  lasthallpos = hallpos;

  hallpos = newhallpos;

  // this is only for motor direction forward  

  BH1 = BLDC_BRIDGE_STATE_VORWARD[hallpos][0];
  BL1 = BLDC_BRIDGE_STATE_VORWARD[hallpos][1];

  BH2 = BLDC_BRIDGE_STATE_VORWARD[hallpos][2];
  BL2 = BLDC_BRIDGE_STATE_VORWARD[hallpos][3];

  BH3 = BLDC_BRIDGE_STATE_VORWARD[hallpos][4];
  BL3 = BLDC_BRIDGE_STATE_VORWARD[hallpos][5];  

  // **** this is with active freewheeling ****  

  // Bridge FETs for Motor Phase U
  if (BH1) {

    // PWM at low side FET of bridge U
    // active freewheeling at high side FET of bridge U
    // if low side FET is in PWM off mode then the hide side FET
    // is ON for active freewheeling. This mode needs correct definition
    // of dead time otherwise we have shoot-through problems

    TIM_SelectOCxM(TIM1, TIM_Channel_1, TIM_OCMode_PWM1);

    TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Enable);

    TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Enable);

  } else {

    // Low side FET: OFF
    TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Disable);

    if (BL1){

     // High side FET: ON
     TIM_SelectOCxM(TIM1, TIM_Channel_1, TIM_ForcedAction_Active);

      TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Enable);

    } else {

      // High side FET: OFF
      TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Disable);

    }

  }

  // Bridge FETs for Motor Phase V

  if (BH2) {
    TIM_SelectOCxM(TIM1, TIM_Channel_2, TIM_OCMode_PWM1);
    TIM_CCxCmd(TIM1, TIM_Channel_2, TIM_CCx_Enable);
    TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Enable);
  } else {
    TIM_CCxCmd(TIM1, TIM_Channel_2, TIM_CCx_Disable);

    if (BL2){
      TIM_SelectOCxM(TIM1, TIM_Channel_2, TIM_ForcedAction_Active);
      TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Enable);
    } else {
      TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Disable);
    }
  }

  // Bridge FETs for Motor Phase W

  if (BH3) {
    TIM_SelectOCxM(TIM1, TIM_Channel_3, TIM_OCMode_PWM1);
    TIM_CCxCmd(TIM1, TIM_Channel_3, TIM_CCx_Enable);
    TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Enable);
  } else {
    TIM_CCxCmd(TIM1, TIM_Channel_3, TIM_CCx_Disable);

  if (BL3){
      TIM_SelectOCxM(TIM1, TIM_Channel_3, TIM_ForcedAction_Active);
      TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Enable);
    } else {
      TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Disable);
    }
  }
}

[Bearbeiten] Some things good to know
// You can manually generate an commutation event (like the hall sensor)
TIM_GenerateEvent(TIM1, TIM_EventSource_COM);

// how to change the PWM value
TIM1->CCR1 = new_ccr_val;
TIM1->CCR2 = new_ccr_val;
TIM1->CCR3 = new_ccr_val;

出0入0汤圆

发表于 2011-11-18 08:41:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-18 08:45:09 | 显示全部楼层
回复【12楼】designlife  
-----------------------------------------------------------------------

按你的理解,为环保 环境 和平 等等奔波的人,都是SB中的战斗机.

出0入0汤圆

发表于 2011-11-20 17:50:00 | 显示全部楼层
疑问
在中断文件中
if(TIM3->SR&0x0040)                //TIF触发中断标记   
  {
    TIM3->SR&=0xffbf;                  //清中断标志
        TIM3->CCR2=TIM3->CCR1>>1; //计算换向点

这条:TIM3->CCR2=TIM3->CCR1>>1; 应该怎样理解呢?
我初学stm32和BLDC希望得到大家的指点,谢谢!

出0入0汤圆

发表于 2011-11-20 22:52:01 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-11-21 00:20:45 | 显示全部楼层
飘过

出0入0汤圆

发表于 2011-11-21 00:38:31 | 显示全部楼层
标记

出0入0汤圆

 楼主| 发表于 2011-11-21 07:59:28 | 显示全部楼层
右移就是把TIM3->CCR1除以2然后再把值赋给TIM3->CCR2然后好像去触发TIM1 的COM事件进行换向

出0入0汤圆

发表于 2011-11-21 08:52:08 | 显示全部楼层
回复【25楼】gycsy  
回复【12楼】designlife  
-----------------------------------------------------------------------
按你的理解,为环保 环境 和平 等等奔波的人,都是SB中的战斗机.
-----------------------------------------------------------------------

人家说的是知识创造财富,和你说的有个屁关系。装什么道德高人,有本事你上班不要工资。

出0入0汤圆

发表于 2011-11-21 11:07:00 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-21 12:24:59 | 显示全部楼层
回复【31楼】lijinzhi  
-----------------------------------------------------------------------

首先谢谢lijinzhi给予及时解答!
但是为什么要除2呢?

还有一点,为什么必须将CCR1的值赋给CCR2,而不直接用CH1去触发TIM1进行换相?
希望lijinzhi能解释一下,再次表示感谢。

出0入0汤圆

发表于 2011-11-21 12:34:31 | 显示全部楼层
楼主的板子还有货吗?我只想买个实验板 不需要电源和电机,这样可以吗?

出0入0汤圆

发表于 2011-11-21 13:29:20 | 显示全部楼层
mark之

出0入0汤圆

发表于 2011-11-21 13:58:04 | 显示全部楼层
回复【35楼】Ranlee
-----------------------------------------------------------------------

回复【1楼】lijinzhi
回复【楼主位】lijinzhi  
-----------------------------------------------------------------------
qq:2572051223
-----------------------------------------------------------------------

出0入0汤圆

发表于 2011-11-21 16:07:57 | 显示全部楼层
1、BLDC嘛,只要你用过一次就会了,不关乎片子啥事。
2、但玩好了,不容易,需要长时间来玩,特别是功率大了以后,脑门都是疼。

出0入0汤圆

发表于 2011-11-21 16:13:53 | 显示全部楼层
BLDC转起来很容易,玩好了难呀

出0入0汤圆

发表于 2011-11-21 19:22:02 | 显示全部楼层
不错哦

出0入0汤圆

发表于 2011-11-21 22:58:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-21 23:41:35 | 显示全部楼层
回复【38楼】kinsno  
-----------------------------------------------------------------------

kinsno一定是高手,能不能帮忙看看34楼的问题,谢谢!

出0入0汤圆

发表于 2011-11-22 16:48:19 | 显示全部楼层
不错不错,店主很好,买了他的东西,感觉用料很实在,资料也全。。

出0入0汤圆

发表于 2011-11-22 23:26:25 | 显示全部楼层
“当在一个通道上需要互补输出时,预装载位有OCxM、CCxE和CCxNE。在发生COM换相事件时,这些预装载位被传送到影子寄存器。这样你就可以预先设置好下一步骤配置,并在同一个时刻同时修改所有通道的配置。COM可以通过设置TIMx_EGR寄存器的COM位由软件产生,或在TRGI上升沿由硬件产生。”

开始启动时没产生com事件  OCxM、CCxE和CCxNE的配置会生效吗?

出0入0汤圆

发表于 2011-11-22 23:51:58 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-11-23 22:04:10 | 显示全部楼层
这个贴子不错,大家不要只make啊。帮帮我这小菜鸟吧

出0入0汤圆

发表于 2011-11-24 09:49:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-24 11:09:59 | 显示全部楼层
回复【32楼】flyunlimit  飞行面条
-----------------------------------------------------------------------

靠,疯狗一样.大把高尚的人,你不能理解,也绝对轮不到你们讽刺.我有说我高尚,你个SB.

出0入0汤圆

发表于 2011-11-24 12:29:15 | 显示全部楼层
我只想看到我的问题被回答。大家不如关注一下技术本身,扯其他的没意义,并且伤感情

出0入0汤圆

 楼主| 发表于 2011-11-24 15:40:13 | 显示全部楼层
回复【34楼】 Ranlee
因为检测到霍尔信号后延时一些时间再去换相,我也是看了网上的资料有这么做的那样是等霍尔信号稳定。我现在想起来我哪个PID也有些问题,其实本来我也没加D的只是看看了一些资料,把积分改成遇限削弱积分,然后想把微分也加上做一下改进,可是最后还是没想去来怎么改!

出0入0汤圆

发表于 2011-11-24 17:54:17 | 显示全部楼层
对时基进行编程:向TIMx_ARR写入最大值(计数器必须由TI1的变化清0).设置预分频器
来取得一个最大的计数器周期.该周期要长于传感器上两个相邻的变化经历的时间.


我查资料时遇到的,我想应该是这个原因才除以2的

    (原文件名:未命名.jpg)

出0入0汤圆

发表于 2011-11-25 03:25:59 | 显示全部楼层
回复【楼主位】lijinzhi
-----------------------------------------------------------------------


(原文件名:hall tim.jpg)


(原文件名:tim1 .jpg)

出0入0汤圆

发表于 2011-11-25 03:37:36 | 显示全部楼层

(原文件名:steps.jpg)


(原文件名:modes.jpg)

出0入0汤圆

发表于 2011-11-25 03:42:33 | 显示全部楼层

(原文件名:pwm adc .jpg)

出0入0汤圆

发表于 2011-11-25 08:44:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-25 09:15:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-26 09:26:12 | 显示全部楼层
不错,谢谢楼主啊

出0入0汤圆

 楼主| 发表于 2011-11-28 08:59:47 | 显示全部楼层
if(TIM3->SR&0x0040)进入这个中断时候,说明霍尔有变化(每一次计数会被清零),需要换相,TIM3->CCR1是转60度的计算时间,TIM3->CCR2=TIM3->CCR1>>1;当计数器计数值与TIM3->CCR2相等是就触发换相
TI公司资料ourdev_699683LBT1OQ.rar(文件大小:98K) (原文件名:controlsuiteinstaller.rar)
PIC公司电机方面的资料ourdev_699684GGU9FS.rar(文件大小:55.56M) (原文件名:PIC公司解决方案.rar)
Atmel公司电机方面资料ourdev_699685UJQQEC.rar(文件大小:9.95M) (原文件名:Atmel公司解决方案.rar)
这是我最近看看的一些资料分享一下

出0入0汤圆

 楼主| 发表于 2011-11-28 09:12:00 | 显示全部楼层
我现在把控制芯片从STM32换到了TMS320F28035,现在一直用DSP,可能STM32无刷电机也做的不是很深没有回答好请大家原谅!

还有我想如果有些人对STM32一点度不熟悉,建议就不要去买这块开发板!因为我淘宝店最近收到一个差评,买家是这样写的

"一块没有任何功能的板子,铁石乡,没想到你们也好意思说是开发板,硬件设计存在问题和缺陷,根本就对不上实物,没有调速功能,没有换向功能,速度也很不平稳,PID调节效果很差,还跟我说把精力放在其他上面,看来不能相信学校的老师做的东西了。希望你们以后做的东西要真实一点,我们买你的东西是希望能派上用场,如果连这个都没做到的话,那我们还有必要买你的东西吗?如果有需要买这块板的买家建议不要再买了,需要这块板子的资料的朋友可以联系我,QQ:1641856703。"

我也很无语,他测试时把板子短路烧了,要求我给他免费修理,不修理就写了这样评价。我想这块板价格和性能还是能够平衡的。希望对单片机这一块不是很熟悉的人就不要买这块板,以免给我带来不必要的麻烦!

出0入0汤圆

发表于 2011-11-28 22:26:41 | 显示全部楼层
回复【60楼】lijinzhi  
-----------------------------------------------------------------------

不管别人怎么说,我还是要感谢楼主的,楼主贡献了所有相关资料就已经说明了诚意!加油!

出0入0汤圆

发表于 2011-12-6 09:51:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-13 13:09:28 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-12-14 10:20:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-14 10:26:16 | 显示全部楼层
Mark

出0入0汤圆

发表于 2011-12-14 10:47:55 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2011-12-19 18:04:59 | 显示全部楼层
DSP的BLDC原理图ourdev_705926XE1CFZ.pdf(文件大小:173K) (原文件名:F28035_BLDC.pdf)
这是最近做的DSP无刷电机控制器 正在画PCB 大家有空帮我检查一下看看原理上有什么错误,这是仿照TI无刷电机开发板做的

出0入0汤圆

发表于 2011-12-19 18:21:41 | 显示全部楼层
cpu风扇还需要怎么大一控制板吗?我们基本上都是一个霍尔传感器就搞定了的,你要做无刷马达控制器,必须做大功率的。

出0入0汤圆

 楼主| 发表于 2011-12-20 11:26:40 | 显示全部楼层
恩是的!我现在在用DSP做大功率的

出0入0汤圆

 楼主| 发表于 2011-12-20 12:14:34 | 显示全部楼层
改后的STM32开发板的程序ourdev_706100H5BWC9.rar(文件大小:6.65M) (原文件名:BLDC.rar)
使用手册ourdev_706101X63PO3.doc(文件大小:917K) (原文件名:开发板使用手册.doc)

出0入0汤圆

发表于 2011-12-20 13:50:19 | 显示全部楼层
不错,学习了。

出0入0汤圆

发表于 2011-12-20 19:49:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-25 17:02:09 | 显示全部楼层
呵呵,好好学习一下

出0入0汤圆

发表于 2012-1-3 10:08:51 | 显示全部楼层
楼主,有用STM32做过无霍尔无刷电机控制器吗

出0入0汤圆

发表于 2012-1-4 11:32:06 | 显示全部楼层
学习了,可以!!!!

出0入0汤圆

发表于 2012-1-18 11:35:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-18 20:41:10 | 显示全部楼层
见到Matlab了,学习了!

出0入0汤圆

发表于 2012-1-18 21:41:16 | 显示全部楼层
学习了,谢谢!

出0入0汤圆

发表于 2012-2-27 10:06:17 | 显示全部楼层
好贴要顶一下!!!

出0入0汤圆

发表于 2012-4-3 17:13:29 | 显示全部楼层
支持下,~~~

出0入22汤圆

发表于 2012-4-3 17:48:41 | 显示全部楼层
建议LZ 有空搞一个 四象限 速度伺服的玩下。。

至于有无HALL 那个是次要的,虽然无HALL的看起来很高端,很有技术难度,
当你使用起来 后你会痛苦不堪。

目前本人 拥有 8S 和32系列的HALL 和sensorless代码。有空发个上来给大家玩下。

出0入0汤圆

发表于 2012-4-3 18:52:24 | 显示全部楼层
呵呵.8S的大概是903的吧. 可商用(成熟)的还是比较值钱的.  无感,就现在来说,已经没有太大技术难度,和无刷一前辈聊过,06/07年那时,真的难---可参考的资料太少了!

出0入0汤圆

发表于 2012-4-5 16:17:39 | 显示全部楼层
mark,无刷带传感器电机控制,多谢楼主分享

出0入0汤圆

 楼主| 发表于 2012-4-7 14:44:05 | 显示全部楼层
我一直在做毕业设计 做大功率的异步电机空间矢量控制 这个大功率太花钱了已经用了自己四千多我还在努力财力不足啊
这几天抽空新做了一款BLDC电机控制
板子是8cm*10cm的

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-4-24 16:12:23 | 显示全部楼层
正在拜读LZ的程序,很给力,其中有几点迷惑:
1.看了原理图,霍尔元件是通过TIM3的通道1,2,3接入的,TIM3的初始化程序如下
void BLDC_TIM3Config(void)
{
   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;                           //基本结构体变量定义
   TIM_ICInitTypeDef TIM_ICInitStructure;                      //定义结构体变量
   TIM_OCInitTypeDef  TIM_OCInitStructure;                     //输出结构体变量定义
      
   TIM_DeInit(TIM3);

   TIM_TimeBaseStructure.TIM_Prescaler = 71;                                   //TIM基本初始化
   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
   TIM_TimeBaseStructure.TIM_Period =65535;
   TIM_TimeBaseStructure.TIM_ClockDivision = 0;
   TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

   TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);     
      
   TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;            //选择通道1
   TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //输入上升沿捕获  
   TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_TRC;  //配置通道为输入,并映射到哪里
   TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;       //输入捕获预分频值
   TIM_ICInitStructure.TIM_ICFilter = 10;                      //输入滤波器带宽设置

   TIM_ICInit(TIM3, &TIM_ICInitStructure);                     //输入通道配置

   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;                     //TIM输出通道初始化
   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;            
   TIM_OCInitStructure.TIM_Pulse =1023;
   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;      
  
   TIM_OC2Init(TIM3,&TIM_OCInitStructure);

   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;                     //TIM输出通道初始化
   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;            
   TIM_OCInitStructure.TIM_Pulse =65535;
   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;      
  
   TIM_OC4Init(TIM3,&TIM_OCInitStructure);

   TIM_SelectHallSensor(TIM3,ENABLE);                          //使能TIMx的霍尔传感器接口
   
   TIM_SelectInputTrigger(TIM3, TIM_TS_TI1F_ED);               //输入触发源选择   
  
   TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);             //从模式选择

   TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);//主从模式选择        
   
   TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_OC2Ref);      //选择输出触发模式(TRGO端)

   TIM_ITConfig(TIM3, TIM_IT_Trigger|TIM_IT_CC4, ENABLE);      //开定时器中断
   //TIM_Cmd(TIM3,ENABLE);
}
其中初始化通道1为输入,又初始化了通道2和通道4为输出,这是怎么回事?
2.其中在stm32f10x_it.c中TIM1的触发与通信中断程序如下
void TIM1_TRG_COM_IRQHandler(void)
{
  TIM1->SR&=0;           //清中断标志
   
   huanxiang();                     //调用换向函数
}
我知道这个中断程序功能是换向,不过不太清楚这个中断函数何时触发?
LZ好人,恳请指导啊!先谢过了~

出0入0汤圆

发表于 2012-4-26 09:49:01 | 显示全部楼层
先标记..有需要用到..

出0入0汤圆

发表于 2012-4-26 10:13:33 | 显示全部楼层
学习一下,准备山寨一个,呵呵!

出0入0汤圆

发表于 2012-5-6 11:20:01 | 显示全部楼层
非常感谢

出0入0汤圆

发表于 2012-5-16 11:47:03 | 显示全部楼层
Ranlee 发表于 2011-11-24 17:54
对时基进行编程:向TIMx_ARR写入最大值(计数器必须由TI1的变化清0).设置预分频器
来取得一个最大的计数器周 ...

根据图来看的话,我感觉那个>>1,只是为了一个延时,等待霍尔稳定,然后使TRGO为高,通知TIM1换向。
但是我又想了一个问题就是,霍尔信号有变化,然后换向不是越快越好吗
如果这个是延时作用的话,这个延时有1/2个霍尔周期是不是太大了.
还有就是TRGO这个信号,通知TIM1的时候到底是脉冲信号还是电平信号啊.
求教..

出0入0汤圆

发表于 2012-5-16 12:20:25 | 显示全部楼层
学习,感谢楼主

出0入0汤圆

发表于 2012-5-16 12:45:11 来自手机 | 显示全部楼层
标记学习

出0入0汤圆

发表于 2012-5-16 14:00:02 | 显示全部楼层
调试用那个GUI做得不错,学习了

出0入0汤圆

发表于 2012-5-22 00:13:51 | 显示全部楼层
不让mark?

出0入0汤圆

发表于 2012-5-30 17:43:43 | 显示全部楼层
谢谢楼主

出0入0汤圆

发表于 2012-6-29 10:48:47 | 显示全部楼层
LZ 您好 我看你的板子 我正好也在做这方面的东西 有些问题希望能得到您的指点 还有OURDEV最近都不能下载了 你发的资料 都没法下载了 能麻烦你留个联系方式吗 以方便以后小弟向你请教 万分感谢 (另外 以前下载到资料的大哥 也方便留个联系方式吗)

出0入0汤圆

发表于 2012-7-24 11:04:38 | 显示全部楼层
       mark

出0入0汤圆

发表于 2012-7-24 11:06:32 | 显示全部楼层
lijinzhi 发表于 2011-11-16 08:02
可能是吧! 这是我自己做的东西卖的很便宜,一套才260元,http://item.taobao.com/item.htm?id=1319869 ...

现在还有货吗~我想买来学学~qq494859283

出0入0汤圆

发表于 2012-7-25 18:14:56 | 显示全部楼层
不错,我也在学习BLDC

出0入0汤圆

发表于 2012-7-28 11:15:42 | 显示全部楼层
标记一下呀

出0入0汤圆

发表于 2012-8-22 09:48:11 | 显示全部楼层
学习

出0入0汤圆

发表于 2012-8-22 10:08:27 | 显示全部楼层
看着还不错

出0入0汤圆

发表于 2012-8-22 10:46:05 来自手机 | 显示全部楼层
记下来看……
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-4 12:57

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表