|
|
View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Fri Dec 21, 2012 6:58 am |
|
|
It's the difference between an 'original' 12F683, and the current ones. The data sheet from 2004, has this as a problem, the 2007 one doesn't.
I haven't seen any actual screenshots of, this problem. The earlier screen shots, were of the problem at the top of the cycle, rather that the short cycle a little later.
As you say, it is almost impossible to program round, if you use 100% duty.
Best Wishes |
|
|
GOBER
Joined: 22 Jul 2010 Posts: 41
|
|
Posted: Sun Dec 23, 2012 3:23 am |
|
|
Hey guys and sorry for being late. I Was a little bit busy.
Here's what happens when i use T's code:
http://www.4shared.com/photo/i7OrhWns/new.html?
The fifth duty cycle gets smaller. AND, it is the fifth one Mike. I used Gpsmikey's point and checked out.
The complete Code is
Code: |
#include <12F683.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES CPD //Data EEPROM Code Protected
#FUSES PROTECT //Code protected from reads
#FUSES MCLR //Master Clear pin enabled
#FUSES PUT //Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#use delay(clock=8000000)
int16 i=0;
int16 fb;
const int16 duty_cycle[32]={0, 36, 71, 105, 138, 171, 201, 230, 257, 280, 302, 320, 335, 346, 355, 361, 365, 361, 355, 346, 335, 320, 302, 280, 257, 230, 201, 171, 138, 105, 71, 36};
#int_TIMER2
void TIMER2_isr(void)
{
static int1 toggle=0;
int16 new_value;
if(++i==32) {
i=0;
toggle^=1;
}
if (i==1)
{
output_low(PIN_A1);
output_low(PIN_A5);
if (toggle)
{
output_high(PIN_A5);
}
else
{
output_high(PIN_A1);
}
}
new_value=duty_cycle[i]; //all the slow work of the table lookup
//has now been done
while (get_timer2() >10) ;
set_pwm1_duty(new_value);
}
void main()
{
setup_adc_ports(sAN3|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_16);
set_adc_channel(3);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_1,124,5);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0);
setup_comparator(NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
setup_oscillator(OSC_8MHZ);
output_high(PIN_A1);
output_low(PIN_A5);
while(1);
}
|
I'm just using a 32 point array and this is what's happening. I wonder what else will happen if the array gets bigger!!
Anyway, I looked back into Tahmid's blog. Tahmid did not have this problem as he used a resolution of 8 bits. And in my case, where the resolution is almost nine bits according to the formula, I am having troubles. So, i will check out at what duty cycle value the problem starts to appear, and then use this point as the maximum duty cycle allowed, not taking the resolution i got from the formula. OR, just use 8-bit resolution as T suggested. By this, i will have to rewind my transformer to maybe 7-0-7 to 250, just as Tahmid's one. Now this may not be the right solution but it is a solution. It's been long. This has taken a lot of time. I'm damn full of curiosity to know the real cause of my problem, but i really can't wait any more. I really appreciate what all of You have tried to do. At least you pointed me to how inversion is done and when to change the duty cycle values when feedback is implemented. Perhaps you will have time to figure out what was really causing the problem, and i hope so. For then, I thank You.
If any new troubles, well, i know where and who to ask
Regards guys |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Dec 23, 2012 3:46 am |
|
|
Hi GOBER,
I've got a horrible feeling that Ttelmah's hit the nail on the head.
Your problem only appears at high duty ratios (>~80%)
Do some tests over this range only, (forget everything else, attack the one issue).
If he's right then you could:-
1). Prepare say four sets of valid values to feed into the two registers CCP1CON, CCPR1L. (You need to be feeding four DIFFERENT values into each of the two registers.
2). Run your code as before, (i.e. ASAP after a timer2 overflow, whilst PWM O/P is still high) write the four valid values to the PWM registers in turn. If the Ttelmah's correct, the fault will still be there.
3). Run your code but disable the PWM, load the PWM registers, re-enable PWM. See what happens.
4). If fault goes away you have a solution:-
4a) Run both 2) & 3) in succession. That way you should be able to see everything at once.
4b) For >50% duty PWM's you wait for the PWM to go low before writing, for <50% you write ASAP after timer2 overflow.
5). If fault is still present, you need another solution.
5a) You're stuck with the problem
5b) You should be able to reduce the loading of the two PWM registers to ~10 machine cycles. That way you limit your PWM duty ratio to ~90%, if that's acceptable. In other words, prepare the values for the two PWM duty registers, wait for timer2 overflow, wait for PWM to be low, write to registers. It no longer matters that the PWM terminates early as it's already gone!
5c) Use a different chip, one without the PWM write problem.
5d) Check the date codes on your chips, make certain you've got the latest silicon.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Sun Dec 23, 2012 3:49 am |
|
|
Whoa.
You don't have to rewind your transformer. The amplitude of the output will remain exactly the same.
All you need do is divide your PWM values by 4, and change the variable declarations to int8. This will then be automatically multiplied by 4 by the hardware!...
When you load an 8bit value, it is loaded, as the _high_ eight bits of the 10bit PWM value.
So only changes:
Code: |
const int8 duty_cycle[32]={0, 9, 18, 26, 35, 43, 50, 58, 64, 70, 76, 80, 84, 87, 89, 90, 91, 90, 89, 87, 84, 80, 76, 70, 64, 58, 50, 43, 35, 26, 18, 9};
//and declare 'new_value' as int8
|
The key to understand is that if the set_pwmx_duty function, is given an int8, it automatically just stores it directly into the 8bit register that gives the high eight bits of the PWM. This means it takes just one cycle to load. Whereas with the ten bit value, the high eight bits are taken (two rotations needed), and put into this register, and then the two low bits are masked, and transferred into the two separate bits. Lots of time and work. Not to mention that reading the number in the first place takes twice as long.....
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Dec 23, 2012 4:00 am |
|
|
GOBER
The question you still have to answer is:-
Is the silicon problem highlighted in the errata an issue in 8bit mode?
Mike |
|
|
GOBER
Joined: 22 Jul 2010 Posts: 41
|
|
Posted: Sun Dec 23, 2012 12:52 pm |
|
|
hey guys
I did what mike suggested. The problem still exists at higher duty cycles. I also checked the chip. It's a 2009 one.
I will now move to eight bits and will feed you back if the problem persists.
regards |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Mon Dec 24, 2012 4:19 pm |
|
|
GOBER
OK. I've found time to have go myself. (It is Xmas!)
I've:-
1) Used a PIC18F1320. I don't have any smaller devices.
2) Used the first 32 16bit entries of a 320 element array.
3) Included the extra delay to ensure setting PWM duty ahead of timer2 overflow.
4) Got exactly the expected pulse widths throughout.
5) Got no prematurely terminated pulses.
6) Used a spare pin to confirm the new PWM_duty is set within one PWM pulse.
My conclusion, the device I've used behaves just as you want.
Mike |
|
|
GOBER
Joined: 22 Jul 2010 Posts: 41
|
|
Posted: Tue Dec 25, 2012 12:42 am |
|
|
Hey Mike
I've been trying now using 350 as the maximum value duty cycle. The array for now has 292 entreis. NO PREMATURE PULSES FOR NOW. I will continue adding entries and testing. The array will eventually have 640 entries. Will you post your program. Perhaps I was missing something
Regards |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Dec 25, 2012 2:53 am |
|
|
GOBER wrote: | Hey Mike
I've been trying now using 350 as the maximum value duty cycle. The array for now has 292 entreis. NO PREMATURE PULSES FOR NOW. I will continue adding entries and testing. The array will eventually have 640 entries. Will you post your program. Perhaps I was missing something
Regards | I was simply using yours with anything surplus removed.
As I see it you're missing nothing.
I'll tidy it up and post.
Merry christmas.
Mike |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Dec 26, 2012 3:55 am |
|
|
As promised, the code I used.
I've obviously played with your code.
I've forced a test pulse near the peak of the waveform, as that's where you were having problems
I've forced a test pulse around the set_duty() to check that it all happened within one timer2 period.
I've double checked with my DSO, (which I trust).
I'm making no other claims about the code, I've not done anything clever or special.
Mike
Code: |
#include <18f1320.h>
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
// #FUSES HS // Use optional Xtal
#use delay(clock=8000000)
int16 i=0;
const int16 duty_cycle[320]={0, 49, 98, 145, 191, 236, 278, 317, //0
354, 387, 416, 441, 462, 478, 490, 498,
500, 498, 490, 478, 462, 441, 416, 387,
354, 317, 278, 236, 191, 145, 98, 49,
0, 49, 98, 145, 191, 236, 278, 317, //1 //Dummy data to fill array
354, 387, 416, 441, 462, 478, 490, 498,
500, 498, 490, 478, 462, 441, 416, 387,
354, 317, 278, 236, 191, 145, 98, 49,
0, 49, 98, 145, 191, 236, 278, 317, //2
354, 387, 416, 441, 462, 478, 490, 498,
500, 498, 490, 478, 462, 441, 416, 387,
354, 317, 278, 236, 191, 145, 98, 49,
0, 49, 98, 145, 191, 236, 278, 317, //3
354, 387, 416, 441, 462, 478, 490, 498,
500, 498, 490, 478, 462, 441, 416, 387,
354, 317, 278, 236, 191, 145, 98, 49,
0, 49, 98, 145, 191, 236, 278, 317, //4
354, 387, 416, 441, 462, 478, 490, 498,
500, 498, 490, 478, 462, 441, 416, 387,
354, 317, 278, 236, 191, 145, 98, 49,
0, 49, 98, 145, 191, 236, 278, 317, //5
354, 387, 416, 441, 462, 478, 490, 498,
500, 498, 490, 478, 462, 441, 416, 387,
354, 317, 278, 236, 191, 145, 98, 49,
0, 49, 98, 145, 191, 236, 278, 317, //6
354, 387, 416, 441, 462, 478, 490, 498,
500, 498, 490, 478, 462, 441, 416, 387,
354, 317, 278, 236, 191, 145, 98, 49,
0, 49, 98, 145, 191, 236, 278, 317, //7
354, 387, 416, 441, 462, 478, 490, 498,
500, 498, 490, 478, 462, 441, 416, 387,
354, 317, 278, 236, 191, 145, 98, 49,
0, 49, 98, 145, 191, 236, 278, 317, //8
354, 387, 416, 441, 462, 478, 490, 498,
500, 498, 490, 478, 462, 441, 416, 387,
354, 317, 278, 236, 191, 145, 98, 49,
0, 49, 98, 145, 191, 236, 278, 317, //9
354, 387, 416, 441, 462, 478, 490, 498,
500, 498, 490, 478, 462, 441, 416, 387,
354, 317, 278, 236, 191, 145, 98, 49};
#int_TIMER2
void TIMER2_isr(void)
{
++i;
if(i==32)
{
i=0; // Reset array index here
}
if (i==16) // Force a sync pulse near peak
{
output_high(PIN_A0);
output_low(PIN_A0);
}
while (get_timer2() >10) {};
output_high(PIN_A1); // Pulse to see start of PWM write
set_pwm1_duty(duty_cycle[i]);
output_low(PIN_A1); // Pulse to see end of PWM write
}
void main()
{
setup_oscillator(OSC_8MHZ);
setup_timer_2(T2_DIV_BY_1,124,5);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
SET_TRIS_B(0); // Should not need, but my compiler does not handle TRIS_B correctly
while(1);
} |
|
|
|
mytheen07
Joined: 09 Feb 2015 Posts: 4
|
Reply |
Posted: Fri Jul 31, 2015 1:28 am |
|
|
Hi Gober,
Thanks for Your Code. Its works for me.
thanks lot & No words to explain. But i made some changes in Interrupt loop. _________________ Mytheen Muhammed |
|
|
thwcs
Joined: 09 Feb 2017 Posts: 1
|
|
Posted: Sun Feb 19, 2017 4:51 am |
|
|
GOBER wrote: | Hey guys and sorry for being late. I Was a little bit busy.
Here's what happens when i use T's code:
http://www.4shared.com/photo/i7OrhWns/new.html?
The fifth duty cycle gets smaller. AND, it is the fifth one Mike. I used Gpsmikey's point and checked out.
.
.
.
|
I do not know how to use the ADC in this project. Feedback signal? Can you help me connect diagrams ?
Thank you! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9255 Location: Greensville,Ontario
|
|
Posted: Sun Feb 19, 2017 7:15 am |
|
|
OK, I've been lurking here, pondering 'this and that' and have to ask...
What happens if you run the program without the driver/transformer part of the circuit connected? Just the PIC and say a couple load resistors?
Then there's the other question ,what happens if the table is filled with different data (IE NOT a 'sine wave' set of values?)
Just trying to think 'outside the box' here.
Jay |
|
|
|
|
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
|