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 CCS Technical Support

Doubts in a PWM code

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



Joined: 05 Oct 2020
Posts: 8

View user's profile Send private message AIM Address

Doubts in a PWM code
PostPosted: Mon May 08, 2023 8:41 am     Reply with quote

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: 19539

View user's profile Send private message

PostPosted: Mon May 08, 2023 9:24 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Tue May 09, 2023 9:51 am     Reply with quote

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: 19539

View user's profile Send private message

PostPosted: Wed May 10, 2023 1:03 am     Reply with quote

One word answer.
No.

Look at what I posted, and what it does. Still the same faults.
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