PWM + Сapture + Сomparison

Post here to discuss any new features, components, chips, etc, that you would like to see in Flowcode.
mnfisher
Valued Contributor
Posts: 1453
http://meble-kuchenne.info.pl
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 135 times
Been thanked: 707 times

Re: PWM + Сapture + Сomparison

Post 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

carworker
Posts: 28
Joined: Sun Jan 01, 2023 11:01 am
Location: UA
Been thanked: 3 times
Contact:

Re: PWM + Сapture + Сomparison

Post 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

mnfisher
Valued Contributor
Posts: 1453
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 135 times
Been thanked: 707 times

Re: PWM + Сapture + Сomparison

Post 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

carworker
Posts: 28
Joined: Sun Jan 01, 2023 11:01 am
Location: UA
Been thanked: 3 times
Contact:

Re: PWM + Сapture + Сomparison

Post 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 1890 times
Attachments
Test 913_TMR1_TMR0_capture.rar
(73.63 KiB) Downloaded 43 times

mnfisher
Valued Contributor
Posts: 1453
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 135 times
Been thanked: 707 times

Re: PWM + Сapture + Сomparison

Post 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

carworker
Posts: 28
Joined: Sun Jan 01, 2023 11:01 am
Location: UA
Been thanked: 3 times
Contact:

Re: PWM + Сapture + Сomparison

Post 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 1874 times

carworker
Posts: 28
Joined: Sun Jan 01, 2023 11:01 am
Location: UA
Been thanked: 3 times
Contact:

Re: PWM + Сapture + Сomparison

Post 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
Attachments
Test 913_TMR1_TMR0_capture.rar
(73.63 KiB) Downloaded 43 times

mnfisher
Valued Contributor
Posts: 1453
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 135 times
Been thanked: 707 times

Re: PWM + Сapture + Сomparison

Post 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

carworker
Posts: 28
Joined: Sun Jan 01, 2023 11:01 am
Location: UA
Been thanked: 3 times
Contact:

Re: PWM + Сapture + Сomparison

Post 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?

mnfisher
Valued Contributor
Posts: 1453
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 135 times
Been thanked: 707 times

Re: PWM + Сapture + Сomparison

Post 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...

Post Reply