Thursday, August 5, 2010

PWM using the dsPIC30F3012 with internal oscillator

This time let’s generate a PWM signal using the dsPIC30F3012 running with its internal oscillator in order to have the RC15 pin available for other applications.
The internal oscillator of this device runs at 7.37MHz and is possible to multiply it by 4, or 16 using the PLL.
In this example I’m using the PLL16 which combined with the 7.37MHz internal oscillator gives a total clock frequency of 117.92MHz, or 29.48 MIPS.
I’m using the circuit depicted below.

The R2 trimmer is working as a voltage divider and feeds the AN0 input of the 12 bits-ADC. The value of the ADC result is used to modify the pulse amplitude.
image
The program is below. The parameter to calculate the PWM frequency and Duty are given by the next equations:
imageWhere:
  • PWM is the desired frequency for the PWM, in my program is 10KHz
  • PRx is the value of the register in the timer to get the frequency of the PWM, is the value that we want to calculate.
  • Fosc is the frequency of the clock, in this program, using the internal clock and the PLL I have a theoretical freq of 117.92MHz = 7.37*16.
Note: To the PRx equation add One unit
Making the calculations I got a PRx=2948.11+1 =~ 2948. Measuring the real output with oscilloscope I realized that the real frequency of the internal clock was 116.28MHz, not 117.92, so, adjusting the values I’m using a PRx value of 2906 to achieve a 10kHz of PWM frequency.
#include <30F3012.h>             //device library
#device adc=12                  //ADC output 12 bits
#fuses FRC_PLL16, PR_PLL, NOWDT //Internal RC clock and PLL by 1, No wacth dog 
//timer,The input to the PLL is the primary clock
#use delay(clock=117920000) // Using the internal RC osc 7.37MHz * 16 = 117.92 MHz
//#fuses FRC, NOWDT           //In case you don't want the PLL use the next fuses   
//#use delay(clock=7370000) // FRC 7.37 MHz
void main(){                  //Starts the main program
unsigned int16 value;         //Define variable to save the ADC result
setup_adc_ports (ALL_ANALOG);  //All the adc ports as analog inputs  
setup_adc(adc_clock_internal);//Define the clock to use with the ADC module
set_adc_channel(0);           //Selects the chennel to read
setup_timer2(TMR_INTERNAL | TMR_DIV_BY_1, 2906);   //Define the PWM frequency
//TMR_INTERNAL= It will works using 117.92MHz divided by 1
//PR=((PWMfreq*4*Tosc)^-1) +1, Tosc=1/117.92MHz
//PR=2949 for a PWMfreq=10KHz
setup_compare(1,COMPARE_PWM | COMPARE_TIMER2 ); //Using the OC1
//Use the comparator in PWM mode, comparing with the Timer2
while (TRUE){     //Infinite cycle
value=read_adc();   //Read the analog channel 
set_pwm_duty(1,2910);  //Sets the value of the ADC to the OCxRS register
//o asign the duty.
//Duty=value/PRx+1
}
}
The ADC module is working using the internal clock and a conversion size of 12 bits. All the inputs are configured as analog inputs.


NOte> still I have to determine the sampling frequency using the internal clock. The data sheet mention a A/D internal oscillator, then I suppose the ADC module has an oscillator only for the ADC module but after read many data sheets and searching in many sources I didn’t find what is the frequency of that clock or even if that clock exists. I will check that measuring the conversion time.

Video of the circuit working
http://www.ustream.tv/recorded/8762955

1 comment:

OneRichAngel said...

The ADC doesn't have an independent clock. The ADC clock uses a divider from the processor's clock.

Related Posts Plugin for WordPress, Blogger...