View previous topic :: View next topic |
Author |
Message |
yadelim
Joined: 14 Aug 2012 Posts: 4
|
Power pwm H-bridge motor control. help me |
Posted: Tue Aug 14, 2012 5:59 pm |
|
|
Good day.
I'm sorry for bad English.
I would like to use H-bridge motor drive, mosfet driver fan7382.
http://www.fairchildsemi.com/pf/FA/FAN7382.html
#Device18f2431.
Code: |
#use delay (clock = 20000000)
unsigned Int16 period = 249;
int1 yon;
signed int16 pwmayar;
// code is wrong with the following ?
setup_power_pwm_pins (PWM_COMPLEMENTARY, PWM_OFF, PWM_OFF, PWM_OFF); // use ppwm 1-0
setup_power_pwm (PWM_CLOCK_DIV_4 | PWM_FREE_RUN | PWM_DEAD_CLOCK_DIV_4, 1.0, period, 0,1,50); // 20 khz setting
.........
if (pwmayar >125) pwmayar = 125;
if (pwmayar <(-125)) pwmayar = (-125);
if (yon) {set_power_pwm0_duty ((int16)(499 + (4 * pwmayar)));}
else {set_power_pwm0_duty ((int16)(499 - (4 * pwmayar)));} |
Last edited by yadelim on Tue Aug 14, 2012 6:06 pm; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 15, 2012 3:55 pm |
|
|
Here's an example of complementary PWM output on pins B0 and B1
with an 18F4431. I tested this in hardware with compiler vs. 4.135.
It should also work with the 18F2431 because it's in the same PIC family.
Code: |
#include <18F4431.h>
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=20M)
// Note: The following numbers work with a 20 MHz oscillator frequency.
#define POWER_PWM_PERIOD 249 // Gives 20 KHz pwm frequency
#define DEAD_TIME 2 // Gives dead time of 1.6 usec
//=======================================
void main()
{
// Setup PWM0 and PWM1 pins as complementary PWM outputs.
// All other PWM pins are configured as OFF (not used).
setup_power_pwm_pins(PWM_COMPLEMENTARY, 0, 0, 0);
// Mode = Free Run
// Postscale = 1 (1-16) Timebase output postscaler
// TimeBase = 0 (0-65355) Initial value of PWM Timebase
// Period = 2000 (0-4095) Max value of PWM TimeBase
// Compare = 0 (Timebase value for special event trigger)
// Compare Postscale = 1 (Postscaler for Compare value)
// Dead Time
setup_power_pwm(PWM_FREE_RUN | PWM_CLOCK_DIV_4 | PWM_DEAD_CLOCK_DIV_16, 1, 0, POWER_PWM_PERIOD, 0, 1, DEAD_TIME);
// This setting gives a 50% duty cycle. For example, the last value
// of .5 gives 50%. A last value of .4 would give a 40% duty cycle.
set_power_pwm0_duty((int16)((POWER_PWM_PERIOD *4) * .5));
while(1);
} |
|
|
|
yadelim
Joined: 14 Aug 2012 Posts: 4
|
|
Posted: Thu Aug 16, 2012 7:30 am |
|
|
Dear pcm prgrammer...
Firstly thanks to your kindly reply. The problem is not to produce complementary pwm signals.
It doesn't show the problem when i write to duty the numbers 0-999
but its a problem when i write the variable (pwmayar) to duty... the code under line.
Pwm duty must between 0-999 but always low. I see the pwmayar changing on the lcd but duty doesn't change. Whats the problem?
Code: |
signed int16 pwmayar;
int1 yon;
if (pwmayar >125) pwmayar = 125; // pwmayar max:125
if (pwmayar <(-125)) pwmayar = (-125); // pwmayar min:-125
if (yon) {set_power_pwm0_duty ((int16)(499 + (4 * pwmayar)));}
else {set_power_pwm0_duty ((int16)(499 - (4 * pwmayar)));} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 16, 2012 12:12 pm |
|
|
Quote: | Pwm duty must between 0-999.
|
Why does it have to be a number in that range ? Why can't you use a
decimal fraction, like 0.00 to 1.00 ?
Example:
Code: |
float pwm_duty;
.
.
.
pwm_duty = 0.50; // 50% duty cycle
set_power_pwm0_duty((int16)((POWER_PWM_PERIOD *4) * pwm_duty); |
|
|
|
yadelim
Joined: 14 Aug 2012 Posts: 4
|
|
Posted: Thu Aug 16, 2012 1:38 pm |
|
|
"yon" according to the variable, the direction of the engine change.
yon = 1
When I press the x button. engine, turn left,
When I press the y button. engine, turn right,
yon = 0
When I press the x button. engine, turn right,
When I press the y button. engine, turn left,
According to me my will.
and according to your description;
will be as follows?
(sorry for bad english)
Code: |
int8 pwmayar;
int1 yon;
float pwm_duty;
if (pwmayar >250) pwmayar =250; // pwmayar max:250
if (pwmayar <1) pwmayar = 1; // pwmayar min:1
pwm_duty=(float) (pwmayar/250);
if (yon){ set_power_pwm0_duty((int16)((POWER_PWM_PERIOD *4) * pwm_duty));}
else {pwm_duty=(float)(1-pwm_duty);
set_power_pwm0_duty((int16)((POWER_PWM_PERIOD *4) *pwm_duty));} |
it does not cause?;
Code: |
if (pwmayar >125) pwmayar = 125;
if (pwmayar <(-125)) pwmayar = (-125);
if (yon) {set_power_pwm0_duty ((int16)(499 + (4 * pwmayar)));}
else {set_power_pwm0_duty ((int16)(499 - (4 * pwmayar)));} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 16, 2012 3:29 pm |
|
|
You have to tell the compiler to do floating math, by making at least one
of the numbers in the division into a floating point number.
See below how I have edited the 250 into 250.0 - this will now make it do
floating point math:
Quote: |
pwm_duty=(float) (pwmayar/250.0); |
|
|
|
yadelim
Joined: 14 Aug 2012 Posts: 4
|
|
Posted: Fri Aug 17, 2012 5:52 am |
|
|
Dear pcm programmer
thanx for your kindly reply to solve our problem...
best regards |
|
|
|