Monday, December 30, 2013

Driving ESC from STM32F4-DISCOVERY

It's way easier by simply driving ESC to make the 750kv HP2217 three phase BLDC motor rotate. The motor is far away smaller than the electric scooter I had in the summer. The control is way more suitable than the previous bldc motor. I do not need extra driver for rotating clockwise and counterclockwise. The direction is fixed to either CW or COUNTER CW.

The connection is easy for just driving the motor to rotate using the ESC. BLACK Wire from the ESC go to the GND to the discovery board. Do not connect red cable, so far i still do not know why the ESC has the red cable and without BEC.

And the White wire is the signal in wire, go to the PWM output pin of the Discovery board. And I guess it is the TTL rule of voltage recognition not CMOS.

Anyway it works for me, just changing the original code to 50hz and pulse to 1ms-1.2ms.

 PrescalerValue = (uint16_t) ((SystemCoreClock /2) / 1000000) - 1;//generate 1Mz frequency

  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 20000-1;//down to 50hz
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;//84-1

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
uint16_t CCR1_Val = 1000-1;
uint16_t CCR2_Val = 1200-1;


It is not really surprising as thinking in time domain. 20ms for one period and 1ms or 1.2ms pulse. 1ms it will turn off the motor and 1.2ms will probably make it rotate CW or CCW, it depends on the connection from ESC  to motor.

Code in github: https://github.com/bli19/UAV_Compete-Source

Sunday, December 29, 2013

 STM32F4  PWM MODE simple code (1 Channel for LED blink )

Editing the example PWM output code from 大舟 by changing the routine a little bit and the code is more close the original example from ST. Either could be the PWM1 or other pins with PWM mode. It can add more channels as long as the timer module could support. I found that it is a little bit abstract and vague when just using the example from ST, which is just can observe the voltage difference from voltmeter. And oscilloscope is way too expensive.

Here's part of code, hardly to say the period is what, this is what i confuse now. In the ST example:

 ARR = (TIM3 counter clock / TIM3 output clock) - 1= 665

It said that  28Mhz for the counter clock and 30 KHz for the output clock, this is probably a wrong calculation since it will got 933 but not 665.

Anyway, ARR itself is just a counter from 0 to TIM_Period for up counting in this post. There is a prescaler configure library function from ST is very easily to yse,

void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode)

Here using TIM3. And to make the output more visible, using probably 3 or 5hz for update.

TIM_PrescalerConfig(TIM3, PrescalerValue, TIM_PSCReloadMode_Immediate);

 PrescalerValue = (uint16_t) ((SystemCoreClock /2) / 500000) - 1;

In this case, the Value would be 168.

Also TIM_TimeBaseStructure.TIM_Period = 65535; this is important so that it will cycle counting.

 To enable the compare mode interrupt, using :

TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);


The CCR1_Val is about the pulse value assignment, which i prefer large value such as 54618 so that its result is visible.Other wise need to change the ISR, which could be very headache.

I delete some if statement for the original code. It works for the Green LED on the stm32f4-discovery:
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);

if(CCR1_Val==5000)
{
STM_EVAL_LEDOn(LED4); //PD12=0。ARR增加5000后,到达这条语句。
CCR1_Val=2500; //所以低电平的百分比为5000/7500=2/3。即占空比为1/3
}
else
{
STM_EVAL_LEDOff(LED4); //PD12=1
CCR1_Val=5000;
}
capture = TIM_GetCapture1(TIM3);
TIM_SetCompare1(TIM3, capture + CCR1_Val);//在原来的CCR1(即capture)基础上加5000,则再过5000,又会触发中断
//另外,有个问题,进入中断时,当ARR计数器快加到65535,而又不足5000时,不是会有数据多余,而产生波形的移动吗?
//回答:不用担心。例如进入中断是,ARR=65000,65000+5000=70000>65535,那么高位会舍去,即为70000-65536=4464
//等于是来了个循环,两次中断间ARR的增量还是5000。所以为了波形的稳定,初始化时,必须要有TIM_Period = 65535
}


}


The setup of the interrupt is easy as long as using the ST Library code, but maybe need to worry if ST begin charging some fees for that, who knows...

NVIC_InitTypeDef NVIC_InitStructure;

  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  /* Enable the TIM3 gloabal Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  /* Initialize Leds mounted on STM32F4-Discovery board */
  STM_EVAL_LEDInit(LED4);
  STM_EVAL_LEDInit(LED3);
  STM_EVAL_LEDInit(LED5);
  STM_EVAL_LEDInit(LED6);

  /* Turn on LED4, LED3, LED5 and LED6 */
  STM_EVAL_LEDOn(LED4);
  STM_EVAL_LEDOn(LED3);
  STM_EVAL_LEDOn(LED5);
  STM_EVAL_LEDOn(LED6);



Also need to #include "stm32f4_discovery.h", it is necessary for turn on the LED to see the toggeling frequency of the LED. Here is the formula of calculating the toggling frequency.

 CC1 update rate = TIM3 counter clock / CCR1_Val
  Toggling CC1 update rate/2 HZ
Other parts are the same as the original code from ST, the LED will blink at 9.1/2=4.5 Hz. Which means it blinks 4.5 times per second.