Page 3 of 4

Re: PWM + Сapture + Сomparison

Posted: Thu Dec 19, 2024 10:45 pm
by mnfisher
What do the results look like - are they reasonable?

One issue I see is
CCP1CONbits.CCP1M =~CCP1CONbits.CCP1M;
//change rising - falling front
This won't actually swap from rising to falling edge (or vice versa) -
CCP1M = 0b0100 for every falling edge and 0b0101 (not the inverse of the other)

You could do this with if
CCP1CONbits.CCP1M1 = ~CCP1CONbits.CCP1M1; // Toggle single bit

Also - measuring for 650 'ticks' of TMR0 (which if the speed shown is correct) is a short interval - why not just use a small delay (3ms?) I would measure for longer - the display update will be unpleasant.

As demonstrated in my code - I would disable the peripheral interrupts whilst displaying the values.

In the interrupt enable you have

Code: Select all

CCPR1H=0;
CCPR1L=0;
Which is unnecessary these values are set from TMR1H/L on an interrupt.

In the C block

Code: Select all

TMR1H = 236;  // Preset for Timer1 MSB register
 TMR1L = 120; // preset for timer1 LSB register
- will 'skew' the first value but have no effect thereafter.

In my code - I clear TMR1H and L on each interrupt - this seemed simpler than subtracting one value from another to give the pulse time - so if you want to time a 'single' pulse - set TMR1H and L to 0 on a rising pulse then the count on a falling pulse is the pulse length - no need to subtract the value?

I would be tempted to use a (global) bool variable 'rising' (initially true) - this is true when we are watching for a rising pulse.

So (in pseudocode - a description of what you want the MCU to do..) in CAP_RE:
if rising: //FC
set CCP1CONbits.CCP1M1 for falling //C
TMR1H = 0; //C
TMR1L = 0; //C
else
CCP1CONbits.CCP1M1 for rising //C
PulseLength = (CCPR1H << 8) + CCPR1L; // C
then
rising = ~rising //FC - toggle direction

Re: PWM + Сapture + Сomparison

Posted: Fri Dec 20, 2024 8:04 pm
by carworker
Hi Martin! With my code the results look disgusting. 650 "ticks" TMR0 is for Proteus. It works slowly compared to real hardware. 6500 for hardware. I assumed that TMR1H = 236; TMR1L = 120; will make a tick of 1 ms Timer 1 when 20 MHz quartz. This is what the PIC calculator gave. Thanks for the recommendations. I will try to understand and fix everything. Best regards, Peter

Re: PWM + Сapture + Сomparison

Posted: Fri Dec 20, 2024 9:58 pm
by mnfisher
Hi Peter,

I've not used Proteus - though it seems popular.
Setting TMR1H/L would give a tick (time to overflow) for TMR1 of 1ms (I haven't checked the maths) - but here we are using TMR1 to time the interval between capture interrupts. The time 'tick' here is a function of the clock (used - I used FOSC (/4)) and pre-scaler options ( I used 1:1 - but also tested 1:4).
It is slightly confusing using tick with two meanings - one for a timer causing an overflow interrupt (like a clock 'tick') and the other for the individual 'counts' made by the timer. So - an '8bit timer' would 'count' or 'tick' 256 times before causing an overflow and increasing the 'time' (or 'tick' - though 'time' is probably a better name?)

You could set TMR0 initial value to adjust the time of each tick - but the values need to be reloaded on each (timer overflow) interrupt generated. I'd probably just use a delay however - for ease.

Let us know how you get on!

Martin

Re: PWM + Сapture + Сomparison

Posted: Sat Jan 04, 2025 8:15 am
by carworker
Happy New Year! It looks like I got what I wanted. But there is one big problem. If you look at my example lowcode implementation of capture you will see that I blocked the TMR0 component because it affects the CCP interrupts. However, I need TMR0 in the main program. How to get rid of the influence of TMR0?
Best regards Peter
test913capture.jpg
test913capture.jpg (174.14 KiB) Viewed 1898 times

Re: PWM + Сapture + Сomparison

Posted: Sat Jan 04, 2025 9:52 am
by mnfisher
I don't have access to a computer until later - but I notice in CAP_RE you have if(0) which will never be true. Was this intended?

Martin

Re: PWM + Сapture + Сomparison

Posted: Sat Jan 04, 2025 3:03 pm
by carworker
Flowcode understands this as reading bit M0 in the register of the CCP1CON
cap_re.jpg
cap_re.jpg (74.07 KiB) Viewed 1882 times

Re: PWM + Сapture + Сomparison

Posted: Sat Jan 04, 2025 7:31 pm
by carworker
Again my inattention. I understood what you were talking about and found the error. if (PIR1bits.CCP1IF); is nothing. It should be if(PIR1 & (1 << CCP1IF));//CCP1 interrupt capture event occurred if flag CCP1IF=1 in PIR1. You wrote about this. Now TMR0 is in action. Thank you.
Best regards Peter

Re: PWM + Сapture + Сomparison

Posted: Sat Jan 04, 2025 7:51 pm
by mnfisher
Flowcode understands this as reading bit M0 in the register of the CCP1CON
Yes - I see. I'd used the online FC viewer (thanks to Ben - it's often a great help) on my phone - and it just decoded it as if(0)...

Glad it's all coming together...
if (PIR1bits.CCP1IF); is nothing. It should be if(PIR1 & (1 << CCP1IF));//CCP1 interrupt capture event occurred if flag CCP1IF=1 in PIR1
I think the issue is just the ';' at then end of the line...

so if(true) ; - will do nothing it needs:

Code: Select all

if(true) {
   stuff to do if true;
}
The semi colon just gives an empty expression...

This is still wrong in the last upload:

Code: Select all

if (PIR1bits.CCP1IF)  //  ';' is wrong here !
{
FCM_%n(); //read int in body
PIR1bits.CCP1IF = 0;  // Clear interrupt flag
}
Then should work correctly.. Note that on an interrupt (with the semicolon) - this would check if CCP1IF was set and do nothing if it was (;) then the following code would always be executed which would always call CP_RE(), and clear CCP1IF

Martin

Re: PWM + Сapture + Сomparison

Posted: Mon Jan 06, 2025 11:28 am
by carworker
Hi Martin! My joy is premature. if (PIR1bits.CCP1IF) //bad.Flowcode doesn't understand this. TMR0 interrupts affect CCP capture. My 65 are in no hurry to cooperate with the C language. However, in a couple of weeks I understand something thanks to you Martin. I noticed that a program in pure C and inserting a personal code into the Flowcode component are two big differences. Perhaps there are special rules?
Quote Microchip -
1. CCP Interrupt Flag (CCPxIF) bit is set. The interrupt flag must be cleared in software. Does Flowcode fulfill this condition?
2. If another capture occurs before the value in the CCPRx register is read, the old captured value is overwritten by the new captured value. I think that if the condition "if (PIR1bits.CCP1IF)" is met, then TMR0 should not affect.
3. If an event occurs during a 2-byte read, the high and low-byte data will be from different events. It is recommended that, while reading the CCPRx register pair, to either disable the module or read the register pair twice for data integrity. I don't know what this is about. Perhaps entries like PIR1bits.CCP1IF should be avoided.
What do you say?

Re: PWM + Сapture + Сomparison

Posted: Mon Jan 06, 2025 11:43 am
by mnfisher
The interrupt enable code does clear the interrupt flag.

It should read

Code: Select all

if (PIR1bits.CCP1IF)  //  ';' is wrong here ! or use: PIR1 & (1 << CCP1IF)
{
FCM_%n(); //read int in body (this calls CP_RE)
PIR1bits.CCP1IF = 0;  // Clear interrupt flag
}
Hopefully that will get us another step forward...