Tuesday, 6 March 2012

How To Use Pulse Width Modulation (PWM) To Control Electrical Speed Controller (ESC)?

In this post we will have some specific talk about AVR since I have experience with.
The objective is to make a pulse with period of 10 ms and pulse width less than 2 ms and more than 1 ms. [1ms,2ms].
At first we look at a case where we have an external 16 MHz clock and we are using 16 bits timer.
If you have a 16 MHz clock then the possible clocks for your PWM are the followings:
16/1 = 16 MHz
16/8 = 2 MHz
16/64 = 0.25 MHz = 250kHz
16/256 = 0.0625 MHz = 62.5 kHz
16/1024 = 0.015625 MHz = 15.625 kHz
So now we will find which of the following will gives us 10 ms period.
we start with the one with lowest period which is working at 16 MHz.
1/(16*10^6) * 2^16  = 0.004096 = ~ 4 ms
This is too fast. We need at least 10ms. so we try with 2MHz
1/(2*10^6) * 2^16  = 0.032768 = ~ 33 ms
This means that this timer will give us a period of 33 ms before overflow.
We know that every 1/(2*10^6) timer counts one, therefore our resolution is 1/(2*10^6) = 0.0000005s = 0.5us
10 ms / 0.5 us = 10 ms / 0.0005 ms =  20,000
20,000 indicates that after this number we have to start from zero. (resetting the timer)

1 ms / 0.5 us = 1 ms / 0.0005 ms =  2,000 steps for minimum speed
2 ms / 0.5 us = 2 ms / 0.0005 ms =  4,000 steps for maximum speed

Here I do not want to talk abou PWM I will do it here, so I will just leave the required value of registers in order to achieve what it is explained above:
//defining I/Os as output so later on we will generate the waveform on these pins


// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=0 State6=0 State5=0 State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0xE0;


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 2000.000 kHz
// Mode: Fast PWM top=ICR1
// OC1A output: Non-Inv.
// OC1B output: Non-Inv.
// OC1C output: Non-Inv.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
// Compare C Match Interrupt: Off
TCCR1A=0xAA;
TCCR1B=0x1A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x4E;
ICR1L=0x20;
OCR1AH=0x07;
OCR1AL=0xD0;
OCR1BH=0x07;
OCR1BL=0xD0;
OCR1CH=0x07;
OCR1CL=0xD0;

This will make the PWM to work in the way that we want. (This code was tested in real life) It will give three different PWMs.

Now this is the function that will change the pulse width for output A from timer 1.


void motor_x(unsigned int speed )
{
OCR1AH = speed >> 8;
OCR1AL = speed;
}


I guess now you have got the idea, if there was any issue just post your questions in the comments.

No comments:

Post a Comment