View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Wed Dec 19, 2012 4:09 pm |
|
|
Doesn't work for me. It is probably blocked by the firewalls I run inside (NSA4), but the funny thing is that the scope pictures are fine.
Best Wishes |
|
|
GOBER
Joined: 22 Jul 2010 Posts: 41
|
|
Posted: Wed Dec 19, 2012 4:22 pm |
|
|
mike
wether fifth or first. there i a problem that i must solve. please help me work it out
thanks |
|
|
GOBER
Joined: 22 Jul 2010 Posts: 41
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Dec 19, 2012 4:49 pm |
|
|
GOBER wrote: | mike
wether fifth or first. there i a problem that i must solve. please help me work it out
thanks | Yes. I agree, but:-
You can't get the right answer 'til you ask the right question.
It doesn't help if you're looking in the wrong place.
Gpsmikey's idea should help you pin down where the problem lies.
I'll dig out some gear out and try a few ideas.
Mike |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Dec 20, 2012 3:52 am |
|
|
OK. So I've slept on it.
Try this:- Code: | while (get_timer2() >10) {};
set_pwm1_duty(duty_cycle[i]); | Normally when you get to the setting duty cycle stage timer2 has counted to at least 40. Your set duty cycle code itself takes 10's of cycles to execute.
The idea here is that the code waits till timer2 overflows, then sets the duty cycle with less risk of being near timer2 overflowing again.
Even better, lookup the array value, then feed that into 'set_pwm1_duty()' and save the array manipulation time.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Thu Dec 20, 2012 5:16 am |
|
|
and (obviously), reduce the count before interrupt, from 5 to 4. The interrupt will now load the duty on the second cycle after it is called.
I'd actually suggest:
Code: |
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);
}
|
This way you lookup the next value to load (takes the longest time), _then_ wait for the next cycle update.
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Dec 20, 2012 6:39 am |
|
|
Ttelmah wrote: | and (obviously), reduce the count before interrupt, from 5 to 4. The interrupt will now load the duty on the second cycle after it is called.
I'd actually suggest:
Code: |
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);
}
|
This way you lookup the next value to load (takes the longest time), _then_ wait for the next cycle update.
Best Wishes |
I think the count before interrupt stays at 5. It should not matter that one of the overflows is now inside the ISR.
I was leaving GOBER to work out the new_value section.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Thu Dec 20, 2012 7:39 am |
|
|
Yes, the postscaler is independant of the interrupt being cleared.
Was forgetting this.
As another comment, I wonder if he has considered not having an ISR at all. Just polling the interrupt bit in the main loop. Then all the preloading etc., can be done here, then pause waiting for the update, and loop again. Potentially much better timings.
Best Wishes |
|
|
GOBER
Joined: 22 Jul 2010 Posts: 41
|
|
Posted: Thu Dec 20, 2012 2:46 pm |
|
|
Guys I went with your suggestion but still having the same problem. I will try T's idea of doing everything n the main loop. Will feed you back with results. If any other ideas please Let me know |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Thu Dec 20, 2012 3:53 pm |
|
|
Seriously, post what you are now using. With the array 'pre-read' into a local variable, the transfer will only take a couple of machine cycles. Timing should not be your problem, you have plenty of time to do what you were showing without problems, your fault is somewhere else. This is what Mike has been (strongly) hinting, and you really need to work out what is actually going on.
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Dec 20, 2012 5:37 pm |
|
|
Ttelmah wrote: | Seriously, post what you are now using. With the array 'pre-read' into a local variable, the transfer will only take a couple of machine cycles. Timing should not be your problem, you have plenty of time to do what you were showing without problems, your fault is somewhere else. This is what Mike has been (strongly) hinting, and you really need to work out what is actually going on.
Best Wishes | Yes. I agree, it's beginning to look like timing's not the real issue. Even with the array lookup, the entire ISR (getting in, code, getting out) takes less than the 125 cycles from one timer2 overflow to the next. (That is with the 16F and 18F parts I've tried. I guess the 12F performance should roughly match that for the 16F.)
Mike
I believe that the data transfer to the PWM takes somewhat more than a couple of cycles. When I tried the code on a 16F877A, my compiler created code with eight instructions between writing to CCPR1L and the CCP1CON register. The processor takes time to convert a 16bit value to an 8bit one for CCPR1L and the 2bits for the PWM LSBs in CCP1CON. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Fri Dec 21, 2012 2:38 am |
|
|
Yes. That is (of course), because of the odd layout of the two extra bits.
As a further 'saves a hell of a lot of time' comment, 'why use 10bit PWM'?.
If the PWM table was 8bit, you would massively reduce the time needed to fetch the numbers, and get rid of this overhead as well. With the 125 being used for the divisor now, you'd still get more than 6bits of accuracy, and about halve the total time needed. You'd also double how large the table can be before page overflows occur, and make the tables small enough, that two could be fitted into RAM. So you could have the interrupt code using RAM tables (much faster to access), and selecting between two of these according to a 'flag', and then in the main, copy into the 'unused' table the one you want to use to adjust the power, and switch the flag to say 'use this one'.
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Dec 21, 2012 3:07 am |
|
|
I consider there's another good reason for going to 8bit.
With a 125 divisor there's only 7 bit resolution in the time direction, so little point in exceeding 8bit in amplitude.
But there's still the nagging question. What's the fundamental cause of the problem being encountered? My initial thought was it was somehow related to CCPR1L and CCP1CON registers being written at different times. If it was the case, the error should only be in the two LSBs, the amplitude error shown on the 'scope traces is much greater then that. So, the underlying cause is elsewhere.
As yet we've not been shown traces indicating whether the problem is with the fifth or first pulse. In that respect we don't know where to start looking.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19569
|
|
Posted: Fri Dec 21, 2012 4:28 am |
|
|
The PIC itself synchronises the two registers. When the timer match occurs, it latches the two extra bits 'into' the actually10bit CCPR1H register, and then copies the whole 10bit value into the timing register. Effectively the registers are double buffered to avoid the problem of the update timing.
However I wonder about the little erratum for the chip:
"The PWM module may generate a premature
pulse when changing the duty cycle.
For sensitive applications, disable the
PWM module prior to modifying the duty
cycle."
This is quite awkward to do. Given that the standard point at which the chip interrupts, is while the signal is driving high. I think you'd need to read the pin (use fast_io mode), till it goes low, and disable the PWM, then update the timing ASAP, and re-enable the module.
This only applied to older chips - wonder if Proteus is simulating a fault that is not there on current chips. Again the question 'does it do this for real' applies.... (pre 2007)
Might be the problem.
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Dec 21, 2012 6:28 am |
|
|
Ttelmah wrote: | The PIC itself synchronises the two registers. When the timer match occurs, it latches the two extra bits 'into' the actually10bit CCPR1H register, and then copies the whole 10bit value into the timing register. Effectively the registers are double buffered to avoid the problem of the update timing.
However I wonder about the little erratum for the chip:
"The PWM module may generate a premature
pulse when changing the duty cycle.
For sensitive applications, disable the
PWM module prior to modifying the duty
cycle."
This is quite awkward to do. Given that the standard point at which the chip interrupts, is while the signal is driving high. I think you'd need to read the pin (use fast_io mode), till it goes low, and disable the PWM, then update the timing ASAP, and re-enable the module.
This only applied to older chips - wonder if Proteus is simulating a fault that is not there on current chips. Again the question 'does it do this for real' applies.... (pre 2007)
Might be the problem.
Best Wishes |
I did look through the data sheet but missed the errata you've found. Does the errata apply to 12F parts only, or is it more general? Certainly looks like a plausible reason for the fault.
However I can see it being very awkward to apply the work round. The duty cycle ranges from zero to 100%. So, sometimes you'ld be looking to update the PWM when the output signal was low, and others when it's high! I'm sure it could be done.
GOBER is showing some DSO traces from real silicon. Are the chips old? (Date codes?) |
|
|
|