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

Soft Start PWM With PIC16F886

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



Joined: 25 May 2018
Posts: 51
Location: Nigeria

View user's profile Send private message

Soft Start PWM With PIC16F886
PostPosted: Sun May 26, 2019 4:36 am     Reply with quote

Soft Start PWM With PIC16F886
I am experimenting with this 28Pins PIC PIC16F886 as a beginner and got confused somewhere.
If a start the PWM module , in this case CPP1, the device will get hanged and will not work again. Initially I thought it is software simulation issue but to my surprise I found out that it is the same thing on the Hardware Simulation.
If I compile the code with PWM settings and without the interrupt Timer Delays, it will work and I compile without the PWM it will also work. So now I need help regarding the relationship between the CPP PWM and Interrupt Timer Delay. Are there things I am missing in the code please? Why can't they co-operate?

I work with CCS C ver1. 140.

Code:
#include <16F886.h>
#device ADC = 10
#FUSES NOWDT,HS,PUT,NOPROTECT,NOMCLR,NOCPD NOBROWNOUT,NOIESO,FCMEN,
#FUSES NOLVP,NOWRT,
#use delay(clock = 8000000)

#define HIGH_START 0xFF -250 //500us INT_RTCC


#define SYS       PIN_B2
#define MS_ON     PIN_B4
#define RL1       PIN_C6
#define MOK       PIN_C7
#define BEEPER    PIN_B6
#define CHG_CTR   PIN_B7

short TabPos,ResetFlag;

short DL2_5s,SDL2_5s;

long MS,CDL2_5s,Counter_sys_1s,Counter_1s,Counter_5s;

const unsigned char PW_Tab[71]= {
0,10,20,30,41,51,61,71,82,92,102,112,123,133,143,153,164,174,184,194,205,
215,225,235,246,256,266,276,286,297,307,317,327,338,348,358,368,379,
389,399,409,420,430,440,450,461,471,481,491,502,512,522,532,543,553,
563,573,584,594,604,614,624,635,645,655,665,676,686,696,706};//70%

void init(void)                                  // Hardware initialization
{

  ResetFlag=0;
  setup_oscillator(OSC_8MHZ | OSC_INTRC);
  setup_adc(ADC_CLOCK_DIV_32);      // 8Tosc ADC conversion time
  setup_adc_ports(sAN9);                 // Select Analog Inputs
  setup_ccp1(CCP_PWM);         // Configure CCP1 as standard PWM
  setup_timer_2(T2_DIV_BY_16,255,1);  // Set PWM frequency to 488Hz?
  set_pwm1_duty(0L);
  setup_comparator(NC_NC_NC_NC);         // disable comparator module

  set_rtcc(HIGH_START);
  setup_counters(RTCC_INTERNAL, RTCC_DIV_4);
  enable_interrupts(INT_RTCC);
  enable_interrupts(global);
 
  SDL2_5s=false; 
  DL2_5s=false; 


}

//   the timer is incremented (8000000/4)/4 or 500000 times a sond (2 us).
//   250 x 2us = 500us

#INT_RTCC

void clock_isr(void)
  { 
   

    {

     
if (SDL2_5s)
        {
        if (++CDL2_5s>=(5000*2))
            {
             SDL2_5s=false;
             DL2_5s=true;
            }
        }
      else CDL2_5s=0;
}                     


{   
if (++Counter_SYS_1s>=(1000*2))
            {
            Counter_sys_1s=0;
            output_toggle(SYS);
            }
}
if (input_state(MOK)==1)
{
if (++Counter_1s >=(1000*2))
            {
            Counter_1s=0;
            output_low(BEEPER);
            }

if (++Counter_5s >=(5000*2))
            {
            Counter_5s=0;
            output_high(BEEPER);
            }
}           

    }

 void main (void)
{
   init();                           // Configure peripherals/hardware

 while(1)
 {

/////////MS Settings/////////MS Settings/////////MS Settings/////////

{
  set_adc_channel(9);               // Select channel AN9
  delay_ms(1);                       // Wait 1ms
  MS = read_adc();                   // Read from AN9 and  store in MS
  delay_ms(1);                       // Wait 1ms
   
if(MS >= 84 && MS <= 177) // >= 0.410V && <= 0.864V //  >= 140V & <=250V


{
   
      SDL2_5s=true; // 15 seconds delay before MS Changeover
      if(DL2_5s)               
     {
     output_high(MS_ON);
     DL2_5s=false;
     }
}     
      else SDL2_5s=false;
 
if(MS <= 53 || MS >= 258)// <= 0.260V || >=1.26V// Below <= 120V and >= 276V
 
      {
      output_low(MS_ON);// MS is not within usable range
      }
     
}
if (input_state(MOK)==1)

{
     output_low(RL1);
}

if (input_state(MOK)==0)
{
     output_high(RL1);
}

if (input_state(CHG_CTR)==1 && ResetFlag) // PWM Starts
      {
       ResetFlag=0;
       for (TabPos=0;TabPos<=10;++TabPos)
      {
         {
            set_pwm1_duty(PW_Tab[TabPos]);
            delay_ms(50); //  =3 sec
         }
      }
      } 
if (input_state(CHG_CTR)==0) // PWM Stops

      {
        ResetFlag=1;
        set_pwm1_duty(0L);
      }

 }
}

_________________
All is well even in the well!
temtronic



Joined: 01 Jul 2010
Posts: 9242
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun May 26, 2019 4:49 am     Reply with quote

If you're saying that if the ISR is used, the PIC hangs then it can be that the ISR has too much to execute. ISR code needs to be short and FAST! Only set 'flags', no math, no prints, no complicated code. Have 'main()' read the flags and act accordingly.
Just to execute an ISR takes 50-60 cyles PLUS whatever you code inside.

also...
you should add comments at the ends of line of code like
//what this line does
// meanings of variable names

It not only helps you, but US as well debug what the program is supposed to do.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Sun May 26, 2019 8:12 am     Reply with quote

Comment 1.
Don't use 'short'and 'long'. Problem is the meaning of these changes with
different compilers and chips. Much safer to use explicit sizes (int1, int16
etc.). Then as a habit, use variable names that 'say' what size they are
I found it almost impossible to be sure what size your variables are.
DL2_5s, as an int1, while CDL2_5s is an int16. Aaargh!....
Something like DL2_5s_flag 'says' this is a bit flag, while CDL2_5s_ctr
says this is a variable that can hold an number.

The your table of times for the PWM is wrong. You are declaring this as
'unsigned char', but expecting it to hold numbers up to 706....
Needs to be int16.

There is no "relationship between the CPP PWM and Interrupt Timer Delay".
The failure must mean that something in the code resulting from the
two blocks of code is leading to the hang. You need to work your way
through every variable and every possible state and see what is giving
the hang.

Why this?
set_adc_channel(9); // Select channel AN9
delay_ms(1); // Wait 1ms
MS = read_adc(); // Read from AN9 and store in MS
delay_ms(1); // Wait 1ms

Set the channel _once_ in your init code. Then provided there is at least
10uSec delay, you can read as fast as you want. No need for longer
delays.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 26, 2019 9:02 pm     Reply with quote

You've got all these variables that have very similar names.
This makes the code harder to understand for someone reading it
and it makes it more error prone when writing it:
Quote:

if(SDL2_5s)
{
if(++CDL2_5s >= 10000)
{
SDL2_5s=false;
DL2_5s=true;

// Also:
long Counter_sys_1s, Counter_1s;


Also, you have very cryptic constant names. RL1 is probably "Relay 1",
but I don't know for sure. The rest, I don't know.
Quote:
#define SYS PIN_B2
#define MS_ON PIN_B4
#define RL1 PIN_C6
#define MOK PIN_C7
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Sun May 26, 2019 11:47 pm     Reply with quote

The obvious thing that will stop the code from doing what is expected,
is that when the PWM is being used, it sits looping through the pulse
widths for half a second. All this time any changes in the voltage,
NOK and CHG_CTR inputs, are ignored.
Much better to have one master external loop. Have this do the tests
and if the pwn is being used, increment the counter, change the value
and loop again. This way these signals will still be responded to....
mcmsat



Joined: 25 May 2018
Posts: 51
Location: Nigeria

View user's profile Send private message

PostPosted: Mon May 27, 2019 11:25 am     Reply with quote

PCM programmer wrote:
You've got all these variables that have very similar names.
This makes the code harder to understand for someone reading it
and it makes it more error prone when writing it:
Quote:

if(SDL2_5s)
{
if(++CDL2_5s >= 10000)
{
SDL2_5s=false;
DL2_5s=true;

// Also:
long Counter_sys_1s, Counter_1s;


Also, you have very cryptic constant names. RL1 is probably "Relay 1",
but I don't know for sure. The rest, I don't know.
Quote:
#define SYS PIN_B2
#define MS_ON PIN_B4
#define RL1 PIN_C6
#define MOK PIN_C7


SYS = System LED
MS_ON = Mains_On
RL1 = Relay1
MOK = Mains_OK

SDL2_xx is a Variable (Start_Delay5s)
Because I use more than two 5sec delay for more than one function that is why they have SDL1_5s, SDL2_5s and so on. With these delays my PIC will not hang a task the delay starts. But "Delay_ms()' gives me a weird experience when I started learning MCU coding few months ago.

long Counter_sys_1s, Counter_1s; I use this to toggle my SYS LED any way I want without the MCU waiting for the delay for other tasks. For example:

Code:
#INT_RTCC
void clock_isr()
  {
//**********************SYSTEM LED Flash Settings******************************

if(CS <= 675 && BS >=189 && BS <= 279)//CS>=3.3V && BS>=0.92V && BS<=1.36V
{   
if (++Counter_SYS_1s>=(1000*2))
            {
            Counter_sys_1s=0;
            output_toggle(SYS);
            }
}
else
{   
if (++Counter_SYS_1s>=(200*2))
            {
            Counter_sys_1s=0;
            output_toggle(SYS);
            }
}
}


In the above example, CS means Current Sense and BS means Battery Sense
If the battery level and the system current are ok, the System LED blinks at 1000ms else 200ms when these conditions are otherwise.

Though these never give me a problem since I have been using them, till I introduced PWM in my experiments They don't co-operate at all.

Please is there any other easier way for me to use these type of delays better than the way i do it here? It is part of learning, Sir.
_________________
All is well even in the well!
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Mon May 27, 2019 1:55 pm     Reply with quote

So take advantage of long name support, and give things names that
explain what they are. SYS_LED for example. It helps _you_, when you
come back to the code in a year or more, and have forgotten the short names.
Good variable naming, is a huge part of your comments for the code.

Now prove to yourself that the issue is not the PWM. Simply turn it on
but get rid of your loops that change it's timing. If it works, then the issue
is the delays that these loops are creating, not the PWM itself.
mcmsat



Joined: 25 May 2018
Posts: 51
Location: Nigeria

View user's profile Send private message

PostPosted: Mon May 27, 2019 2:32 pm     Reply with quote

Ok, it will take effect when I go to my computer.

Thanks.
_________________
All is well even in the well!
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