Hello all,
I'm fairly new to PIC programming, and I'm working on a project dealing with PWM (gasp! another PWM post). Here are the details:
I'm using a PIC18F45K20 (the demo board with the PICKit3), so I'm using the built-in PWM function. The frequency and other parameters are established as you would expect, and the duty cycle is controlled with the external potentiometer on the demo board. Essentially, an analog voltage is established at RA0 (AN0) and converted with the ADC, compared, and the duty cycle is set. I've also implemented two other funcitons that aren't really important, but they basically set the max duty cycle (with an external trimpot) and the minimum duty cycle (with another external trimpot).
My question is as follows: Is there a way anyone can think of to gradually increase the duty cycle of the PWM signal with an abrupt change to the voltage applied to RA0 based on an external analog input? In other words, I don't want the duty cycle to go from 0% to 50% instantly, I want it to slowly ramp up to it. However, I would like to be able to change this "ramp" time based on a 3.3V analog input (lower voltage, slower ramp; higher voltage, faster ramp).
My first thought was to use a for loop that ramps up the value in the register that controls duty cycle slowly based on the external input. This is the code I wrote for that (unfortunately it doesn't work...I think it's something to do with the numbuf array):
#include <system.h>
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
unsigned int ADC_ramp()
{
unsigned int ramp0;
adcon0 = 0b00110001;
set_bit(adcon0,1);
while (adcon0.1);
ramp0 = adresl;
return ramp0 += (adresh << 8);
}
unsigned int ADC_duty()
{
unsigned int duty0;
adcon0 = 0b00000001;
set_bit(adcon0,1);
while (adcon0.1);
duty0 = adresl; // Get the 8 bit LSB result
return duty0 += (adresh << 8); // Get the 2 bit MSB result
}
void main()
{
unsigned int ramp;
unsigned int duty;
unsigned int ramp_delay;
adcon2 = 0b10111101;
adcon1 = 0b00000000;
trisa = 0b00000111;
porta = 0;
ansel = 0b00000111;
trisc = 0;
portc = 0;
osccon = 0b11010111;
pr2 = 0b11111001;
t2con = 0b00000111;
trisb = 0b00000001;
portb = 0;
anselh = 0b00010000;
ramp = ADC_ramp();
duty = ADC_duty();
for (int i = 0; i <= duty; ++i) {
char numbuf [2];
itoa (i, numbuf, 2);
ramp_delay = ramp*2;
// return numbuf;
delay_ms(ramp_delay);
}
}
The first two functions read the ADC for the duty cycle and ramp values. The ramp function is implemented in main. Like I said, I'm new, so please take it easy on me . I'm going to try playing around with the ADC time now and see if I can make any progress there. Even just pointers would be greatly appreciated (I'm not looking for someone to write my code for me). Thanks in advance.
I'm fairly new to PIC programming, and I'm working on a project dealing with PWM (gasp! another PWM post). Here are the details:
I'm using a PIC18F45K20 (the demo board with the PICKit3), so I'm using the built-in PWM function. The frequency and other parameters are established as you would expect, and the duty cycle is controlled with the external potentiometer on the demo board. Essentially, an analog voltage is established at RA0 (AN0) and converted with the ADC, compared, and the duty cycle is set. I've also implemented two other funcitons that aren't really important, but they basically set the max duty cycle (with an external trimpot) and the minimum duty cycle (with another external trimpot).
My question is as follows: Is there a way anyone can think of to gradually increase the duty cycle of the PWM signal with an abrupt change to the voltage applied to RA0 based on an external analog input? In other words, I don't want the duty cycle to go from 0% to 50% instantly, I want it to slowly ramp up to it. However, I would like to be able to change this "ramp" time based on a 3.3V analog input (lower voltage, slower ramp; higher voltage, faster ramp).
My first thought was to use a for loop that ramps up the value in the register that controls duty cycle slowly based on the external input. This is the code I wrote for that (unfortunately it doesn't work...I think it's something to do with the numbuf array):
#include <system.h>
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
unsigned int ADC_ramp()
{
unsigned int ramp0;
adcon0 = 0b00110001;
set_bit(adcon0,1);
while (adcon0.1);
ramp0 = adresl;
return ramp0 += (adresh << 8);
}
unsigned int ADC_duty()
{
unsigned int duty0;
adcon0 = 0b00000001;
set_bit(adcon0,1);
while (adcon0.1);
duty0 = adresl; // Get the 8 bit LSB result
return duty0 += (adresh << 8); // Get the 2 bit MSB result
}
void main()
{
unsigned int ramp;
unsigned int duty;
unsigned int ramp_delay;
adcon2 = 0b10111101;
adcon1 = 0b00000000;
trisa = 0b00000111;
porta = 0;
ansel = 0b00000111;
trisc = 0;
portc = 0;
osccon = 0b11010111;
pr2 = 0b11111001;
t2con = 0b00000111;
trisb = 0b00000001;
portb = 0;
anselh = 0b00010000;
ramp = ADC_ramp();
duty = ADC_duty();
for (int i = 0; i <= duty; ++i) {
char numbuf [2];
itoa (i, numbuf, 2);
ramp_delay = ramp*2;
// return numbuf;
delay_ms(ramp_delay);
}
}
The first two functions read the ADC for the duty cycle and ramp values. The ramp function is implemented in main. Like I said, I'm new, so please take it easy on me . I'm going to try playing around with the ADC time now and see if I can make any progress there. Even just pointers would be greatly appreciated (I'm not looking for someone to write my code for me). Thanks in advance.