vinayakdabholkar
Advanced Member level 4
- Joined
- Nov 29, 2009
- Messages
- 114
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1,296
- Location
- goa
- Activity points
- 2,195
/*Example Source Code For PIC Timers
* THis blinks LEDs on PORTB to show interrupt rates
*
* Barton Dring
* Dring Engineering Services
* www.eng-serve.com
*
* Example only! Use any code at your own risk.
*/
// Interrupt Handler
void interrupt()
{
// Timer0 Interrupt - Freq = 500000.00 Hz - Period = 0.000002 seconds
if (INTCON.TMR0IF ==1) // timer 0 interrupt flag
{
LATC.RC0 = 0; // Toggle PORTB bit0 LED
INTCON.TMR0IF = 0; // clear the flag
INTCON.TMR0IE = 1; // reenable the interrupt
TMR0L = 250;
// reset the timer preset count
}
}
// code starts here...
void main()
{
// setup portb to show the interrupts by blibking LEDs
TRISC = 0x00; // PORT is all output...to show the interrupts
PORTC = 0; // start with all outputs low
//Timer0 Registers Prescaler= 1 - TMR0 Preset = 246 - Freq = 500000.00 Hz - Period = 0.000002 seconds
T0CON.T0CS = 0; // bit 5 TMR0 Clock Source Select bit...0 = Internal Clock (CLKO) 1 = Transition on T0CKI pin
T0CON.T0SE = 0; // bit 4 TMR0 Source Edge Select bit 0 = low/high 1 = high/low
T0CON.PSA = 1; // bit 3 Prescaler Assignment bit...0 = Prescaler is assigned to the WDT
T0CON.T0PS2 = 0; // bits 2-0 PS2:PS0: Prescaler Rate Select bits
T0CON.T0PS1 = 0;
T0CON.T0PS0 = 0;
T0CON.T08bit = 1;
TMR0L = 246; // preset for timer register
// Interrupt Registers
INTCON = 0; // clear the interrpt control register
INTCON.TMR0IE = 1; // bit5 TMR0 Overflow Interrupt Enable bit...1 = Enables the TMR0 interrupt
INTCON.TMR0IF = 0; // bit2 clear timer 0 interrupt flag
INTCON.GIE = 1;
LATC.RC0=1; // bit7 global interrupt enable
T0CON.TMR0ON=1;
while(1) //endless loop
{
LATC.RC0=1;
}
}
The problem isn't clear at all. If you want to set the output permanently high, this can be achieved more easily. :smile:
In fact also the 2 us pulse width can't be exact as long as it's generated in software. Programming timer CCP outputs is the only way to get cycle accurate timing.
//Definations of different variables used in the code
#define BOOL unsigned char
#define TRUE 1
#define FALSE 0
//PID definations
float PID_Kp, PID_Ki, PID_Kd;
float PID_Integrated;
float PID_Prev_Input;
float PID_MinOutput, PID_MaxOutput;
BOOL PID_First_Time;
float control;
float setpoint=246;
//PWM definations
unsigned short current_duty, old_duty, current_duty1, old_duty1;
float InputValue;
//function declarations
float PID_Calculate(float Setpoint, float InputValue);
void Reset_PID();
void Init_PID(float Kp, float Ki, float Kd, float MinOutput, float MaxOutput);
void ADCInit();
unsigned int ADCRead(unsigned char ch);
void main()
{
TRISC=0;
PORTC=0;
AN0_bit=1;
ADCInit(); //TRISD=0x00;
PWM1_Init(5000000); // Initialize PWM1 module at 500KHz
PWM2_Init(5000000); // Initialize PWM2 module at 500KHz
Reset_PID();
init_PID(10,10,10,225,276); // just inserted values for understanding. Here Kp=10,Ki=10,Kd=10, min_output and max_output also defined
while(1) // voltage ripple of 10% has been considered which comes to 120m. Max_out=1.32(26.4%) and Min_out=1.08(21.6%)
{ //so for simplicity 22 and 27 percent of 5V is considerd which results in Max_out=1.35 and Min_out=1.1
//need to call this function after definate period for simplicity
InputValue=ADCRead(0); // call this function to get the feed back voltage value
control=PID_Calculate(setpoint,InputValue);
current_duty = control; // initial value for current_duty
current_duty1 = control;
PWM1_Set_Duty(current_duty); // Set current duty for PWM1
PWM2_Set_Duty(current_duty1); // Set current duty for PWM2
PWM1_Start(); // start PWM1
Delay_us(1);
PWM2_Start();
//LATD=val;
//LATC=(val>>8);
// start PWM2
}
}
//function definations
float PID_Calculate(float Setpoint, float InputValue)
{
float Err, ErrValue, DiffValue, Result;
Err = SetPoint - InputValue;
// --- calculate proportional value ---
ErrValue = Err * PID_Kp;
// --- Calculate integrated value ---
PID_Integrated = PID_Integrated + (Err * PID_Ki);
// limit it to output minimum and maximum
if (PID_Integrated < PID_MinOutput)
PID_Integrated = PID_MinOutput;
if (PID_Integrated > PID_MaxOutput)
PID_Integrated = PID_MaxOutput;
// --- calculate derivative value ---
if (PID_First_Time)
{
// to avoid a huge DiffValue the first time (PID_Prev_Input = 0)
PID_First_Time = FALSE;
PID_Prev_Input = InputValue;
}
DiffValue = (InputValue - PID_Prev_Input) * PID_Kd;
PID_Prev_Input = InputValue;
// --- calculate total ---
Result = ErrValue + PID_Integrated - DiffValue; // mind the minus sign!!!
// limit it to output minimum and maximum
if (Result < PID_MinOutput)
Result = PID_MinOutput;
if (Result > PID_MaxOutput)
Result = PID_MaxOutput;
return (Result);
}
void Reset_PID()
{
PID_Integrated = 0.0; //
PID_Prev_Input = 0.0;
PID_First_Time = TRUE; //after reset PID being called will be first time and first_time has been defined as a boolean and 1 means TRUE
}
void Init_PID(float Kp, float Ki, float Kd, float MinOutput, float MaxOutput)
{
PID_Kp = Kp;
PID_Ki = Ki;
PID_Kd = Kd;
PID_MinOutput = MinOutput;
PID_MaxOutput = MaxOutput;
PID_Integrated = 0.0;
PID_Prev_Input = 0.0;
PID_First_Time = TRUE;
}
//initialize ADC
void ADCInit()
{
CMCON =CMCON | 0x07; // Disable comparators
// ADCON0= 0x00; // ADC off Channel 0
ADCON1= 0x30;
ADCON2= 0x92;
}
//Read ADC value
unsigned int ADCRead(unsigned char ch)
{
ADCON0=0x00;
if (ch>13) return 0;
ADCON0= (ch<<2);
ADON_bit=1;
GO_DONE_bit=1;
while(GO_DONE_bit);
ADON_bit=0;
return ADRES;
}
PWM1_Init(5000000); // Initialize PWM1 module at 500KHz
PWM2_Init(5000000); // Initialize PWM2 module at 500KHz
Thanks for correcting me there. changed the frequency to 500k, but still its not what i am expectingSets PWM frequency of 5MHz.Code:PWM1_Init(5000000); // Initialize PWM1 module at 500KHz PWM2_Init(5000000); // Initialize PWM2 module at 500KHz
If i got you right , in mikroC it takes the frequency when making the project(new project wizard, which in my case is 20M). In code there is no need to specifyI'm not familiar with mikroC, how do you specify the clock frequency in your application?
It hasn't been set correctly for simulation in your previously supplied *.dsn file, however.If i got you right , in mikroC it takes the frequency when making the project(new project wizard, which in my case is 20M). In code there is no need to specify
void interrupt()
{
// Timer0 Interrupt - Freq = 500000.00 Hz - Period = 0.000002 seconds
if (INTCON.TMR0IF ==1) // timer 0 interrupt flag
{
LATC.RC0 = 0; // Toggle PORTB bit0 LED
INTCON.TMR0IF = 0; // clear the flag
INTCON.TMR0IE = 1; // reenable the interrupt
TMR0L = 250;
// reset the timer preset count
}
}
when timer 0 will overflow then it must be reloaded with 246 ,think.why 250?
In so far I think, it's a MikroC or Proteus problem which is neither my business.
#include<p18f4520.h>
#include<timers.h>
#include<delays.h>
void init_PWM();
//unsigned short control=0x0003;
//--------------------------------------------------------------------------------------------------
//VARIABLE DEFINITIONS
unsigned short control;
#define BOOL unsigned char
#define TRUE 1
#define FALSE 0
//PID definations
float PID_Kp, PID_Ki, PID_Kd;
float PID_Integrated;
float PID_Prev_Input;
float PID_MinOutput, PID_MaxOutput;
BOOL PID_First_Time;
unsigned short control;
float mapped_value;
float Setpoint=246;
//PWM definations
unsigned short current_duty, old_duty, current_duty1, old_duty1;
float InputValue;
float resultmap;
float MinOutput=225;
float MaxOutput=275;
float Kp=1;
float Ki=1;
float Kd=1;
//----------------------------------------------------------------------------------------------------
//FUNCTION DECLARATIONS
void init_PWM();
void set_dutycycle(unsigned short control);
unsigned short mapping_control(float result);
int round(float Du);
float PID_Calculate(float Setpoint, float InputValue);
void Reset_PID();
void Init_PID(float Kp, float Ki, float Kd, float MinOutput, float MaxOutput);
void ADCInit();
unsigned int ADCRead(unsigned char ch);
//---------------------------------------------------------------------------------------------------
void main(void)
{
TRISC=0;
PORTC=0;
TRISA=0xFF;
void Reset_PID();
void Init_PID(float Kp,float Ki,float Kd,float MinOutput,float MaxOutput);
void init_PWM();
void ADCInit();
InputValue=ADCRead(0);
resultmap=PID_Calculate(Setpoint,InputValue);
control=mapping_control(resultmap);
set_dutycycle(control);
//while(1);
}
void init_PWM()
{
PR2=0x09;
T2CON=0b00000100;
CCP1CON=0b00001100;
//void set_dutycycle( unsigned short control);
}
void set_dutycycle(unsigned short control)
{
//CCPR1L=0b00000000;
//CCP1CON=0b00111100;
CCPR1L=(control>>2);
CCP1CON |=(control<<4);
}
//-----------------------------------------------------------------------------------------------------
// this function is designed to map the output of PID calculate to the range between 0-39 of duty cycle
unsigned short mapping_control(float resultmap)
{
float Du;
unsigned short mapped_value;
if(resultmap>=275)
Du=39;
else if (resultmap>=225)
Du=(resultmap-225)*39/50;
else
Du=0;
mapped_value=round(Du);
return mapped_value;
}
int round(float Du)
{
float a;
int R,b;
a=Du;
b=(int)a;
if(Du-b >=0.5)
R=b+1;
else
R=b;
return R;
}
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
float PID_Calculate(float Setpoint, float InputValue)
{
float Err, ErrValue, DiffValue, Result;
Err = Setpoint - InputValue;
// --- calculate proportional value ---
ErrValue = Err * PID_Kp;
// --- Calculate integrated value ---
PID_Integrated = PID_Integrated + (Err * PID_Ki);
// limit it to output minimum and maximum
if (PID_Integrated < PID_MinOutput)
PID_Integrated = PID_MinOutput;
if (PID_Integrated > PID_MaxOutput)
PID_Integrated = PID_MaxOutput;
// --- calculate derivative value ---
if (PID_First_Time)
{
// to avoid a huge DiffValue the first time (PID_Prev_Input = 0)
PID_First_Time = FALSE;
PID_Prev_Input = InputValue;
}
DiffValue = (InputValue - PID_Prev_Input) * PID_Kd;
PID_Prev_Input = InputValue;
// --- calculate total ---
Result = ErrValue + PID_Integrated - DiffValue; // mind the minus sign!!!
// limit it to output minimum and maximum
if (Result < PID_MinOutput)
Result = PID_MinOutput;
if (Result > PID_MaxOutput)
Result = PID_MaxOutput;
return (Result);
}
//---------------------------------------------------------------------------------------------------------------------------------------------
void Reset_PID()
{
PID_Integrated = 0.0; //
PID_Prev_Input = 0.0;
PID_First_Time = TRUE; //after reset PID being called will be first time and first_time has been defined as a boolean and 1 means TRUE
}
//----------------------------------------------------------------------------------------------------------------------------------------------
void Init_PID(float Kp, float Ki, float Kd, float MinOutput, float MaxOutput)
{
PID_Kp = Kp;
PID_Ki = Ki;
PID_Kd = Kd;
PID_MinOutput = MinOutput;
PID_MaxOutput = MaxOutput;
PID_Integrated = 0.0;
PID_Prev_Input = 0.0;
PID_First_Time = TRUE;
}
//------------------------------------------------------------------------------------------------------------------------------------------------
//initialize ADC
void ADCInit()
{
CMCON =CMCON | 0x07; // Disable comparators
// ADCON0= 0x00; // ADC off Channel 0
ADCON1= 0x30;
ADCON2= 0x92;
}
//------------------------------------------------------------------------------------------------------------------------------------------------
//Read ADC value
unsigned int ADCRead(unsigned char ch)
{
ADCON0=0x00;
if (ch>13) return 0;
ADCON0= (ch<<2);
ADCON0bits.ADON=1;
ADCON0bits.GO_DONE=1;
while( ADCON0bits.GO_DONE);
ADCON0bits.ADON=0;
return ADRES;
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?