lijinzhi 发表于 2011-11-15 20:42:06

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

STM32 BLDC开发板
提供原理图和相应的原代码,源代码是基于免费开源CoOS(UCOS类似)操作系统上写的,在学习无刷电机的控制同时还能学习到操作系统的知识。同时提供用Matlab的GUI编写的串口接收程序和开源的代码,实时接收速度和电流信息,便于PID测试,并且有CAN(TJA1050)接口。同时自己可以进行修改学习Matlab的GUI编程。
1.        STM32F103RB处理器 时钟72M Flash 64K RAM 20K
2.        MOSFET SUD35N05-26L55V 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无刷电机驱动板       
http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_695593HBAIHL.jpg
电源开发板无刷电机图片 (原文件名:电源开发板无刷电机图片.jpg)                
软件资料:
有无刷电机转速调节的PID程序(基于免费开源CoOS操作系统)
自己做的Matlab GUI串口PID调试程序(开源,自己可以改进)
自己以前做的STM32程序
http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_695592HO14HQ.jpg
电机运行时PID调节图 (原文件名:电机运行时PID调节图.jpg)

http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_695593HBAIHL.jpg
电源开发板无刷电机图片 (原文件名:电源开发板无刷电机图片.jpg)

http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_695594EYKJMZ.jpg
无刷电机的图片 (原文件名:无刷电机的图片.jpg)

http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_695595GHD8IZ.jpg
只有开发板的图片 (原文件名:只有开发板的图片.jpg)

lijinzhi 发表于 2011-11-15 20:43:57

回复【楼主位】lijinzhi
-----------------------------------------------------------------------
QQ:2572051223

liurangzhou 发表于 2011-11-15 21:12:00

广告?

lijinzhi 发表于 2011-11-16 08:02:56

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

racede 发表于 2011-11-16 08:24:26

回复【楼主位】lijinzhi
-----------------------------------------------------------------------

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

zhousun 发表于 2011-11-16 08:27:10

对你的无刷电机风扇感兴趣,哪里买的?

ground 发表于 2011-11-16 09:27:25

大概描述技术细节,比如有没有用库?做了多少改进?

lgcHR 发表于 2011-11-16 10:10:34

楼主好强大,膜拜!价格嘛稍微有点贵,不过也值了。

lijinzhi 发表于 2011-11-16 10:13:05

有电机和电源还有板子  我没有用库程序

HYLG 发表于 2011-11-16 10:18:32

顶下楼主。论坛要的是分享的精神,想买或需要的人自然会买的。建议早上资料。

lijinzhi 发表于 2011-11-16 10:32:57

开发板的资料ourdev_695691EPDAW2.rar(文件大小:20.49M) (原文件名:BLDC开发板.rar)
这是板子的资料

yangyh75 发表于 2011-11-16 11:08:00

这个好,以玩养玩,不图赚钱,可以让大家好好学习。网上stm32的bldc开源代码很少,非库的就更加少了。顶楼主。

designlife 发表于 2011-11-16 11:24:05

回复【4楼】racede
回复【楼主位】lijinzhi   
-----------------------------------------------------------------------
来看lz最后一面...260不觉得卖得很便宜...估计利润达150%...lz还是看看版规再发帖吧...
-----------------------------------------------------------------------

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

changhui0222 发表于 2011-11-16 11:24:57

不错。MARK!

eastwood 发表于 2011-11-16 13:14:40

很好啊,顶一下。

jade1988 发表于 2011-11-16 14:25:43

很好啊,顶一下。

HYLG 发表于 2011-11-16 14:31:27

原来是带霍尔的。

zgx8 发表于 2011-11-16 17:00:36

現在很多無霍尔的

zzz1367 发表于 2011-11-17 10:05:46

顶一下

yanxuerui12345 发表于 2011-11-17 10:20:49

能搞个无霍尔的吗?能在大学搞出个这样的东东来,很不错唉。感觉自己大学白读了,没学到啥,自己也没整出个啥。

yanxuerui12345 发表于 2011-11-17 10:23:22

不过260有点点贵了,别人用8位的就能解决了,价格估计是200以下,不过这种精神难得,顶一下!

2006612 发表于 2011-11-17 15:52:53

很不错!自然要顶!

pisayisi 发表于 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

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
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 toHallSensoren 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, theHallSensorEvent
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 motorspeed 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
}
}

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 islow 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 = 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
// 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 =   // 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;
BL1 = BLDC_BRIDGE_STATE_VORWARD;

BH2 = BLDC_BRIDGE_STATE_VORWARD;
BL2 = BLDC_BRIDGE_STATE_VORWARD;

BH3 = BLDC_BRIDGE_STATE_VORWARD;
BL3 = BLDC_BRIDGE_STATE_VORWARD;

// **** 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);
    }
}
}

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;

kingboy100 发表于 2011-11-18 08:41:40

mark

gycsy 发表于 2011-11-18 08:45:09

回复【12楼】designlife
-----------------------------------------------------------------------

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

Ranlee 发表于 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希望得到大家的指点,谢谢!

danceman_uk 发表于 2011-11-20 22:52:01

mark!

gylsxcn 发表于 2011-11-21 00:20:45

飘过

fydzaa 发表于 2011-11-21 00:38:31

标记

lijinzhi 发表于 2011-11-21 07:59:28

右移就是把TIM3->CCR1除以2然后再把值赋给TIM3->CCR2然后好像去触发TIM1 的COM事件进行换向

flyunlimit 发表于 2011-11-21 08:52:08

回复【25楼】gycsy
回复【12楼】designlife
-----------------------------------------------------------------------
按你的理解,为环保 环境 和平 等等奔波的人,都是SB中的战斗机.
-----------------------------------------------------------------------

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

xingkongyao 发表于 2011-11-21 11:07:00

mark

Ranlee 发表于 2011-11-21 12:24:59

回复【31楼】lijinzhi
-----------------------------------------------------------------------

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

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

Ranlee 发表于 2011-11-21 12:34:31

楼主的板子还有货吗?我只想买个实验板 不需要电源和电机,这样可以吗?

Felix257 发表于 2011-11-21 13:29:20

mark之

qilindao 发表于 2011-11-21 13:58:04

回复【35楼】Ranlee
-----------------------------------------------------------------------

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

kinsno 发表于 2011-11-21 16:07:57

1、BLDC嘛,只要你用过一次就会了,不关乎片子啥事。
2、但玩好了,不容易,需要长时间来玩,特别是功率大了以后,脑门都是疼。

_yuming 发表于 2011-11-21 16:13:53

BLDC转起来很容易,玩好了难呀

x357728745 发表于 2011-11-21 19:22:02

不错哦

wpnx 发表于 2011-11-21 22:58:57

mark

Ranlee 发表于 2011-11-21 23:41:35

回复【38楼】kinsno
-----------------------------------------------------------------------

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

FORESTD 发表于 2011-11-22 16:48:19

不错不错,店主很好,买了他的东西,感觉用料很实在,资料也全。。

Ranlee 发表于 2011-11-22 23:26:25

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

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

pb486 发表于 2011-11-22 23:51:58

学习

Ranlee 发表于 2011-11-23 22:04:10

这个贴子不错,大家不要只make啊。帮帮我这小菜鸟吧

dabaishali 发表于 2011-11-24 09:49:46

mark

gycsy 发表于 2011-11-24 11:09:59

回复【32楼】flyunlimit飞行面条
-----------------------------------------------------------------------

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

Ranlee 发表于 2011-11-24 12:29:15

我只想看到我的问题被回答。大家不如关注一下技术本身,扯其他的没意义,并且伤感情

lijinzhi 发表于 2011-11-24 15:40:13

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

Ranlee 发表于 2011-11-24 17:54:17

对时基进行编程:向TIMx_ARR写入最大值(计数器必须由TI1的变化清0).设置预分频器
来取得一个最大的计数器周期.该周期要长于传感器上两个相邻的变化经历的时间.


我查资料时遇到的,我想应该是这个原因才除以2的
http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_698648PLJ8EI.jpg
    (原文件名:未命名.jpg)

pisayisi 发表于 2011-11-25 03:25:59

回复【楼主位】lijinzhi
-----------------------------------------------------------------------

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_698782U1T7PI.jpg
(原文件名:hall tim.jpg)

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_698783Z194S6.jpg
(原文件名:tim1 .jpg)

pisayisi 发表于 2011-11-25 03:37:36

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_698784JUFGUS.jpg
(原文件名:steps.jpg)

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_698785CK769H.jpg
(原文件名:modes.jpg)

pisayisi 发表于 2011-11-25 03:42:33

http://cache.amobbs.com/bbs_upload782111/files_48/ourdev_698786N5URL6.jpg
(原文件名:pwm adc .jpg)

pinocchio 发表于 2011-11-25 08:44:11

mark

abcdzhy 发表于 2011-11-25 09:15:26

mark

admityou 发表于 2011-11-26 09:26:12

不错,谢谢楼主啊

lijinzhi 发表于 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)
这是我最近看看的一些资料分享一下

lijinzhi 发表于 2011-11-28 09:12:00

我现在把控制芯片从STM32换到了TMS320F28035,现在一直用DSP,可能STM32无刷电机也做的不是很深没有回答好请大家原谅!

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

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

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

Ranlee 发表于 2011-11-28 22:26:41

回复【60楼】lijinzhi
-----------------------------------------------------------------------

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

lihe 发表于 2011-12-6 09:51:59

mark

shizhijian 发表于 2011-12-13 13:09:28

学习

226lm 发表于 2011-12-14 10:20:21

mark

StephenCui 发表于 2011-12-14 10:26:16

Mark

chenqi 发表于 2011-12-14 10:47:55

mark

lijinzhi 发表于 2011-12-19 18:04:59

DSP的BLDC原理图ourdev_705926XE1CFZ.pdf(文件大小:173K) (原文件名:F28035_BLDC.pdf)
这是最近做的DSP无刷电机控制器 正在画PCB 大家有空帮我检查一下看看原理上有什么错误,这是仿照TI无刷电机开发板做的

673285421 发表于 2011-12-19 18:21:41

cpu风扇还需要怎么大一控制板吗?我们基本上都是一个霍尔传感器就搞定了的,你要做无刷马达控制器,必须做大功率的。

lijinzhi 发表于 2011-12-20 11:26:40

恩是的!我现在在用DSP做大功率的

lijinzhi 发表于 2011-12-20 12:14:34

改后的STM32开发板的程序ourdev_706100H5BWC9.rar(文件大小:6.65M) (原文件名:BLDC.rar)
使用手册ourdev_706101X63PO3.doc(文件大小:917K) (原文件名:开发板使用手册.doc)

manong 发表于 2011-12-20 13:50:19

不错,学习了。

dingliming 发表于 2011-12-20 19:49:47

mark

four_zhg 发表于 2011-12-25 17:02:09

呵呵,好好学习一下

ma699 发表于 2012-1-3 10:08:51

楼主,有用STM32做过无霍尔无刷电机控制器吗

1234zhouju 发表于 2012-1-4 11:32:06

学习了,可以!!!!

hopefly 发表于 2012-1-18 11:35:45

mark

STM32_tasy 发表于 2012-1-18 20:41:10

见到Matlab了,学习了!

brbl 发表于 2012-1-18 21:41:16

学习了,谢谢!

babaiwangqi 发表于 2012-2-27 10:06:17

好贴要顶一下!!!

苹果520 发表于 2012-4-3 17:13:29

支持下,~~~ {:smile:}

lixin91985 发表于 2012-4-3 17:48:41

建议LZ 有空搞一个 四象限 速度伺服的玩下。。

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

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

Qhjh 发表于 2012-4-3 18:52:24

呵呵.8S的大概是903的吧. 可商用(成熟)的还是比较值钱的.无感,就现在来说,已经没有太大技术难度,和无刷一前辈聊过,06/07年那时,真的难---可参考的资料太少了!

hopefly2 发表于 2012-4-5 16:17:39

mark,无刷带传感器电机控制,多谢楼主分享

lijinzhi 发表于 2012-4-7 14:44:05

我一直在做毕业设计 做大功率的异步电机空间矢量控制 这个大功率太花钱了已经用了自己四千多我还在努力财力不足啊
这几天抽空新做了一款BLDC电机控制
板子是8cm*10cm的

yst1571661 发表于 2012-4-24 16:12:23

正在拜读LZ的程序,很给力,其中有几点迷惑:
1.看了原理图,霍尔元件是通过TIM3的通道1,2,3接入的,TIM3的初始化程序如下
void BLDC_TIM3Config(void)
{
   TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;                           //基本结构体变量定义
   TIM_ICInitTypeDef TIM_ICInitStructure;                      //定义结构体变量
   TIM_OCInitTypeDefTIM_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好人,恳请指导啊!先谢过了~

136420962 发表于 2012-4-26 09:49:01

先标记..有需要用到..

zhxlx_2012 发表于 2012-4-26 10:13:33

学习一下,准备山寨一个,呵呵!{:tongue:}

LGDSTM 发表于 2012-5-6 11:20:01

非常感谢

MATT_C 发表于 2012-5-16 11:47:03

Ranlee 发表于 2011-11-24 17:54 static/image/common/back.gif
对时基进行编程:向TIMx_ARR写入最大值(计数器必须由TI1的变化清0).设置预分频器
来取得一个最大的计数器周 ...

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

SanKeKe 发表于 2012-5-16 12:20:25

学习,感谢楼主

shunda 发表于 2012-5-16 12:45:11

标记学习

Ca_guo 发表于 2012-5-16 14:00:02

调试用那个GUI做得不错,学习了{:smile:}

gyhg1206 发表于 2012-5-22 00:13:51

不让mark?

wscjun 发表于 2012-5-30 17:43:43

谢谢楼主

Vano 发表于 2012-6-29 10:48:47

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

forever868xl 发表于 2012-7-24 11:04:38

       mark

forever868xl 发表于 2012-7-24 11:06:32

lijinzhi 发表于 2011-11-16 08:02 static/image/common/back.gif
可能是吧! 这是我自己做的东西卖的很便宜,一套才260元,http://item.taobao.com/item.htm?id=1319869 ...

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

zhangmao710 发表于 2012-7-25 18:14:56

不错,我也在学习BLDC

6810289frank 发表于 2012-7-28 11:15:42

标记一下呀

wtliu 发表于 2012-8-22 09:48:11

学习{:handshake:}

holyfire 发表于 2012-8-22 10:08:27

看着还不错

Bicycle 发表于 2012-8-22 10:46:05

记下来看……
页: [1] 2 3
查看完整版本: 自己做的STM32 BLDC直流无刷电机控制器