|
|
View previous topic :: View next topic |
Author |
Message |
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
Soft Start PWM With PIC16F886 |
Posted: Sun May 26, 2019 4:36 am |
|
|
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
|
|
Posted: Sun May 26, 2019 4:49 am |
|
|
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
|
|
Posted: Sun May 26, 2019 8:12 am |
|
|
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
|
|
Posted: Sun May 26, 2019 9:02 pm |
|
|
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
|
|
Posted: Sun May 26, 2019 11:47 pm |
|
|
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
|
|
Posted: Mon May 27, 2019 11:25 am |
|
|
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
|
|
Posted: Mon May 27, 2019 1:55 pm |
|
|
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
|
|
Posted: Mon May 27, 2019 2:32 pm |
|
|
Ok, it will take effect when I go to my computer.
Thanks. _________________ All is well even in the well! |
|
|
|
|
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
|