|
|
View previous topic :: View next topic |
Author |
Message |
johenrod
Joined: 05 Oct 2020 Posts: 8
|
Doubts in a PWM code |
Posted: Mon May 08, 2023 8:41 am |
|
|
Greetings, could you help me please?
I am trying to make a pwm control to control a 110 volt motor. I have a clear power stage with optocoupler and mosfet, I try to make the pwm output greater than 5 kHz so that there is no noise on the motor plates. (In the example code it says that period (T) is close to 8 kHz).
I have an example program that I can't understand, I don't see the call to the interrupt, then I leave the lines of code in which I require explanation and then the complete program, thanks in advance.
Code: |
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(FALSE);
setup_counters(RTCC_INTERNAL,WDT_288MS);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_1,255,1);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_PWM);
enable_interrupts(global);
|
Code: |
#include <16F873A.h>
#device ADC=10
#fuses HS,WDT,NOPROTECT
#device ADC=10
#use delay(crystal=8MHz)
long ADCValue=0;
long ADCValueOld=1;
#byte portA = 0X05
#byte portB = 0X06
#byte portC = 0X07
void main()
{
set_tris_A(0b00101011);
set_tris_B(0b00000001);
set_tris_C(0b00000000);
portA=0X00;
portB=0X00;
portC=0X00;
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(FALSE);
setup_counters(RTCC_INTERNAL,WDT_288MS);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_1,255,1);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_PWM);
enable_interrupts(global);
set_adc_channel(0);
delay_us(10);
while(true)
{
ADCValue = Read_ADC();
delay_ms(100); // monitor 10 times a second
if ( ADCValue != ADCValueOld )
{
set_pwm2_duty(ADCValue);
ADCValueOld = ADCValue;
}
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Mon May 08, 2023 9:24 am |
|
|
There are several things that are not really 'right'.
The first is selecting 'ALL_ANALOGS'. This means that every input pin
is fed to the analog multiplexer. Problem is that this tends to introduce
noise into the ADC, that will degrade it's accuracy. Much better to only
select the channels that are going to be read. In this case AN0.
Fortunately, because the TRIS is set to only set a few pins to analog,
this won't be too bad.
Then your comment on the interrupt. No interrupt is actually enabled,
so no interrupt will be 'called'. You never physically 'call' an interrupt
it is called by the enabled event. There is no event actually enabled.
ADC_CLOCK_INTERNAL is also wrong. If you read the chip data sheet,
you will find that this clock is not recommended above 1MHz operation,
unless you put the processor to sleep for the conversion. Again degrades
accuracy (this time a lot). Again the data sheet will tell you what clock
should be used. I think DIV_4.
Then the next huge problem. You have the WDT enabled, and nothing
to reset the watchdog. Means this code will keep crashing, and give
erratic timings.
The period will be:
8000000/(4*(255+1)) = 7812Hz |
|
|
johenrod
Joined: 05 Oct 2020 Posts: 8
|
|
Posted: Tue May 09, 2023 9:51 am |
|
|
Ttelmah wrote: | There are several things that are not really 'right'.
The first is selecting 'ALL_ANALOGS'. This means that every input pin
is fed to the analog multiplexer. Problem is that this tends to introduce
noise into the ADC, that will degrade it's accuracy. Much better to only
select the channels that are going to be read. In this case AN0.
|
Thank you very much for your answer, I'm trying to learn how to properly use the pwm module in the PIC.
I found this other code, is it better implemented?
Code: | // Por: Sergio Andres Castaño
// https://controlautomaticoeducacion.com/
//___________________________________________________________________________
#include <16f887.h>
#device ADC=10
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT,INTRC_IO
#use delay(clock=4000000)
int16 duty=0;
int Timer2,Poscaler;
void main() {
// Generemos una Señal cuadrada de 1 Khz
Timer2=249; //Se carga timer 2 con 249 como lo vimos en la pagina
//Preescaler=4; //Preescaler solo puede tomar valores de: 1 - 4 - 16
//Para el preescaler colocamos "t2_div_by_4"
Poscaler=1; //Preescaler solo puede tomar valores de: 1
setup_timer_2(t2_div_by_4,Timer2,Poscaler); //Configuracion de Timer 2 para establecer frec. PWM a 1kHz
setup_ccp1(ccp_pwm); //Configurar modulo CCP1 en modo PWM
setup_adc_ports(all_analog); //Configurar ADC
setup_adc(adc_clock_internal);
while(1)
{
set_adc_channel(0);
delay_us(100);
duty=read_adc();
set_pwm1_duty(duty);
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Wed May 10, 2023 1:03 am |
|
|
One word answer.
No.
Look at what I posted, and what it does. Still the same faults. |
|
|
|
|
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
|