CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

AN889 and PPWM and sine table question.

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

AN889 and PPWM and sine table question.
PostPosted: Fri Sep 09, 2011 10:13 am     Reply with quote

First of all, sorry for my english mistakes.

Let's begin....

So people, my graduating project is to develop a 3-phase inverter.

I started to study the application notes from microchip and it is very useful.

So, I have one question by now, reading the AN889, I read this:

"The value read from the sine table is scaled based on the motor frequency input. The sine table value is multiplied with the frequency input to find the PWM duty cycle and is loaded to the corresponding PWM duty cycle register."

So, I understood the use of the table. But why i need to scale the value and after that i put into the duty cycle register?

Why can not I just put the value directly into the duty value?

For example:

I have a table with 256 values (just an example). I use the CCS compiler.

On this compiler, I am using the PIC18F4431. It is very easy to configure 3 PWM channel and their complementaries and insert the dead-time. So, my table has 256 values from 9 to 240. In order the PPWM to work, I need to insert a value between 0 and 1. For example, for a 50% duty, I need to put 0.5. Ok. No problem.

My question is, why do I need to scale my table's values?

So, in meanwhile, I will continue my study.

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 09, 2011 1:43 pm     Reply with quote

I haven't done this type of motor controller, but I scanned the documents
and came up with this explanation:

The basic answer to your question is given on the first page of AN889,
on the right side of the page:
http://ww1.microchip.com/downloads/en/AppNotes/00889b.pdf
Quote:

VF CONTROL

A discussion of induction motor control theory is
beyond the scope of this document. We will mention
here only the salient points of VF control.

The base speed of the induction motor is directly
proportional to the supply frequency and the number of
poles of the motor. Since the number of poles is fixed
by design, the best way to vary the speed of the
induction motor is by varying the supply frequency.

The torque developed by the induction motor is directly
proportional to the ratio of the applied voltage and the
frequency of supply. By varying the voltage and the
frequency, but keeping their ratio constant, the torque
developed can be kept constant throughout the speed
range. This is exactly what VF control tries to achieve.


Then on page 3, it says:
Quote:

MOTOR DRIVE

The amplitude of phase voltage is determined by the
duty cycle of the PWM signals.


On page 5:
Quote:

A potentiometer connected to a 10-bit ADC channel
(AN1) determines the motor frequency. The microcontroller
uses the ADC results to calculate the PWM duty cycle and thus,
the frequency and the amplitude of the supply to the motor.


The sine table consists of 19 values (only), ranging from 0x00 to 0xFF.
It's at the end of the vf_control_with_7x7.asm file, in this zip file:
http://ww1.microchip.com/downloads/en/AppNotes/16f7x7vfmc.zip


So based on all this explanation, I think I can create a Torque formula:

Torque = K * V/F

K is some proportionality constant. It doesn't matter. If you want
to keep the Torque constant, then you have to keep the ratio of
Voltage to Frequency (V/F) constant. If you increase the motor speed
by increasing the PWM frequency, you must increase the voltage too.

The vf_control_with_7x7.asm file says this:
Quote:
MOTOR FREQUENCY IS LIMITED BETWEEN 5Hz AND 60Hz.

So presumably, the Sine Table consists of values suitable for the lowest
expected PWM frequency of 5 Hz. (I don't know for sure).
If you want to run the motor faster, you increase the PWM frequency,
and so you have to multiply the sine table values to get a higher duty
cycle, which increases the motor voltage to keep V/F constant, and thus
keep the Torque constant over the speed range of the motor.
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Fri Sep 09, 2011 4:01 pm     Reply with quote

Thank you very much PCM Programmer!!!

Now I understood why I need to scale.

But i will tell you just one thing that I think that you understood wrong. You said:

Quote:
If you want to run the motor faster, you increase the PWM frequency...


But in the page 5 on the AN889, we can read on the end of the last paragraph right before the Figure 5:

Quote:
The frequency of the new PWM duty
cycle update
determines the motor frequency, while the
value loaded in the duty cycle register determines the
amplitude of the motor supply.


So, to change the motor speed, I change how fast the duty cycle is updated...

So, looking the figure right next this:



For example:

Imagine I running my motor with a duty cycle of 50%, if I want to speed it up, I need to adjust of the timer interrupt to overflow quickly and adjust the duty cycle in a proportional way, correct? Because maybe my sine table do not have the right duty, so I need to scale this....

So, what do you think? am I on the right direction now?

PS: I used an English dictionary on Firefox to not make spelling mistakes...

Bye
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 09, 2011 4:19 pm     Reply with quote

I just wanted to write up that one post. I didn't want to get any farther
involved in this.
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Fri Sep 09, 2011 4:52 pm     Reply with quote

This is getting pretty deep for discussion on a C compiler forum. Unless someone here has done this type of motor controller before, you really need to find a forum on motor control theory, or read some books, build some test hardware, and figure it out yourself.

This is more than just a software problem.
_________________
The search for better is endless. Instead simply find very good and get the job done.
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Fri Sep 09, 2011 6:18 pm     Reply with quote

Ok people, no problem...

I posted this same topic on the microchip forum but no replies for now...

Thanks by the way....

So, I have one question about the software that I am developing.....

A small test program where I have a sine table and update the duty cycle with the timer 1 interrupt.

In this peace of code, I need to put a value between 0 and 1 to get the right duty cycle. But my sine table has int8 values.

So, I just divided this values by 255 to get floats values to put into the PPWM formula.

My question is: If I want to avoid the task of divide the values by 255 and made a table only with the float points, is this will work?

Look my small test program. Here the PPWM is running at 1250Hz. What is the formula to calculate the frequency for the PPWM module?

And the configuration for the PPWM module that I am using is:

setup_power_pwm(PWM_FREE_RUN, 1, 0, POWER_PWM_PERIOD, 0, 1, 30);

The dead time is 30. But 30 what? 30 uS?

Code:

#include<18F4431.h>

#fuses HS, NOWDT, NOPROTECT, NOBROWNOUT, PUT, NOLVP
#use delay(clock=8000000)

#define POWER_PWM_PERIOD 1600

BYTE CONST SINE_WAVE[200] = {
128,132,136,139,143,147,150,154,158,161,165,169,172,176,179,
182,186,189,192,195,199,202,204,207,210,213,215,218,220,223,
225,227,229,231,233,235,237,238,240,241,242,243,244,245,246,
247,247,247,248,248,248,248,248,247,247,247,246,245,244,243,
242,241,240,238,237,235,233,231,229,227,225,223,220,218,215,
213,210,207,204,202,199,195,192,189,186,182,179,176,172,169,
165,161,158,154,150,147,143,139,136,132,128,124,120,117,113,
109,106,102,98,95,91,87,84,80,77,74,70,67,64,61,57,54,52,49,
46,43,41,38,36,33,31,29,27,25,23,21,19,18,16,15,14,13,12,11,
10,9,9,9,8,8,8,8,8,9,9,9,10,11,12,13,14,15,16,18,19,21,23,
25,27,29,31,33,36,38,41,43,46,49,52,54,57,61,64,67,70,74,77,
80,84,87,91,95,98,102,106,109,113,117,120,124};



BYTE sine_index;

float temp, temp1, temp2;
int8 x, y, z;
int1 aux;

#int_TIMER1              //Interrupção do Timer1
void temp1s(void)        //Funcão. O que deverá ser feiro a cada interrupão.
{
   if (aux == 0)
   {
      aux++;
      if(++sine_index==200)
      {
         sine_index=0;
      }
   }
   set_timer1 (30000);                           //Preload do Timer1
}

//=======================================
void main()

   // Setup the 4 Power PWM channels as ordinary pwm channels.
   setup_power_pwm_pins(PWM_COMPLEMENTARY,PWM_COMPLEMENTARY,PWM_COMPLEMENTARY,PWM_OFF);
   
   // 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, 1, 0, POWER_PWM_PERIOD, 0, 1, 30);
   
   set_power_pwm0_duty((int16)((POWER_PWM_PERIOD *4) * .5)); // 10%
   set_power_pwm2_duty((int16)((POWER_PWM_PERIOD *4) * .5)); // 40%
   set_power_pwm4_duty((int16)((POWER_PWM_PERIOD *4) * .5)); // 60%   
   
   setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8);   //Configuração do Timer1 para clock interno = 1E6 dividido por 8
   set_timer1 (30000);                           //Preload do Timer1
   enable_interrupts(INT_TIMER1);               //Habilita interrupção timer1
   enable_interrupts(global);                   //habilita interrupcão global
   
   while(1)
   {
      if (aux == 1)
      {
         x = SINE_WAVE[sine_index];     
         y = SINE_WAVE[sine_index+66];     
         z = SINE_WAVE[sine_index+132];
         
         temp = x/255.0;
         temp1 = y/255.0;
         temp2 = z/255.0;
         
         
         
         set_power_pwm0_duty((int16)((POWER_PWM_PERIOD *4) * temp));
         set_power_pwm2_duty((int16)((POWER_PWM_PERIOD *4) * temp1));
         set_power_pwm4_duty((int16)((POWER_PWM_PERIOD *4) * temp2));
         
         aux++;
      }
   }
}


I tried to make another table only with float points but I think it will not work:

Code:
BYTE CONST SINE_WAVE_FLOAT[200] = {
0.50,0.52,0.53,0.55,0.56,0.58,0.59,0.60,0.62,0.63,0.65,0.66,0.67,0.69,0.70,
0.71,0.73,0.74,0.75,0.76,0.78,0.79,0.80,0.81,0.82,0.84,0.84,0.85,0.86,0.87,
0.88,0.89,0.90,0.91,0.91,0.92,0.93,0.93,0.94,0.95,0.95,0.95,0.96,0.96,0.96,
0.97,0.97,0.97,0.97,0.97,0.97,0.97,0.97,0.97,0.97,0.97,0.96,0.96,0.96,0.95,
0.95,0.95,0.94,0.93,0.93,0.92,0.91,0.91,0.90,0.89,0.88,0.87,0.86,0.85,0.84,
0.84,0.82,0.81,0.80,0.79,0.78,0.76,0.75,0.74,0.73,0.71,0.70,0.69,0.67,0.66,
0.65,0.63,0.62,0.60,0.59,0.58,0.56,0.55,0.53,0.52,0.50,0.49,0.47,0.46,0.44,
0.43,0.42,0.40,0.38,0.37,0.36,0.34,0.33,0.31,0.30,0.29,0.27,0.26,0.25,0.24,0.22,0.21,0.20,0.19,
0.18,0.17,0.16,0.15,0.14,0.13,0.12,0.11,0.11,0.10,0.09,0.08,0.07,0.07,0.06,0.06,0.05,0.05,0.05,0.04,
0.04,0.04,0.04,0.04,0.03,0.03,0.03,0.03,0.03,0.04,0.04,0.04,0.04,0.04,0.05,0.05,0.05,0.06,0.06,0.07,0.07,0.08,0.09,
0.10,0.11,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.20,0.21,0.22,0.24,0.25,0.26,0.27,0.29,0.30,
0.31,0.33,0.34,0.36,0.37,0.38,0.40,0.42,0.43,0.44,0.46,0.47,0.49};


How the best way to avoid the task of the division?

Thanks again!

Matheus Lopes.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Mon Sep 12, 2011 2:18 pm     Reply with quote

on another note:

I found this info helpful when designed a 3 phase low power inverter
previously. && i just located the source again on google.

hope it helps you

http://www.google.com/url?q=http://m.wpi.edu/Pubs/E-project/Available/E-project-042507-092653/unrestricted/MQP_D_1_2.pdf&sa=U&ei=uWduTovXMcXLgQfIg9TyBQ&ved=0CBcQFjAB&usg=AFQjCNFTOypYcFGmAE32hHiPYQCAG1dSFw
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Mon Sep 12, 2011 9:10 pm     Reply with quote

Thanks.

I will take a look on the page you sent me.

bye
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Tue Sep 13, 2011 7:06 am     Reply with quote

I would either write my own version of setup_power_pwm() that takes int8 inputs. Or I would locate the hardware register that sets the actual PWM duty cycle, which I am sure is an int register, and use setup_power_pwm() only to set things up and write my own routine to quickly set just the duty cycle register.
_________________
The search for better is endless. Instead simply find very good and get the job done.
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Tue Sep 13, 2011 1:02 pm     Reply with quote

Thanks SherpaDoug for your reply, but I am new, just one year learning CCS. I do not know how to write routines like this one that you mentioned.

bye
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group