I have been using GCB for the last couple of years, but only recently delved into using CCP ports using interrupts with 'relative' ease to control LED output based upon pulse width duty cycle input. However, I have am now wanting to use two CCP ports on a PIC16F1829 with both ports using Timer1.
I have been working on this for a week now and cannot for the life of me figure out how to manage the ISR's correctly with both CCP1 and CCP4 operating using Interrupts with Timer1 (i.e. 16 bit). If I comment out the first to two LOOP 'Calls' for CCP1, then CCP4 works fine and visa versa, commenting out CCP4 makes CCP1 work fine. But they will not work if both are left to function consecutively - I have been using Proteus simulator to test.
Once I can get this working, then I will want to expand this to 4 x CCP through Timer1, which I should be able to do, once I understand what I am doing wrong to get this working with just 2 x CCP's.
I am pulling out what little hair I have and I know I am not handling the Interrupts/ISR's correctly, but cannot work out exactly where the problem is?!
I have attached the code below and am hoping someone can help me before I am completely bald!
NOTE: "I should have made it a little more clear, I am using internal weak pull ups, so I have reversed the pulse width high and low variable names accordingly.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think I would need a simple description of what you are trying to achieve. I am not sure I understand from the intro.
A comment... On Interrupt Timer1Overflow Call IncCounter these do the same thing. I cannot see that you are clearing the bit PIE1.TMR1IE there is no point in setting more than once.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I just took the code you posted and tried to start from first principles. Many questions already.
I have changed SOU and TOU to suit the board I had to hand.
But, as you will see SOU is toggling as the program logic, so far, does not make sense to me.
I do not recommend that you/we all post and repost this to the forum. Can you move this code to GitHub where folks can edit and help online?
Evan
#Chip16F1829, 32
#OptionExplicit
#CONFIGMCLRE=OFF'******WEAK PULL UP CONFIGURATION******SetNot_WPUEN=0'Enable pullups in general.SetWPUA0=0SetWPUA1=0SetWPUA2=0SetWPUA3=0SetWPUA4=0SetWPUA5=0SetWPUB4=0SetWPUB5=0SetWPUB6=0SetWPUB7=0SetWPUC0=0SetWPUC1=0SetWPUC2=0SetWPUC3=0SetWPUC4=0SetWPUC5=1'RCL - CCP1 (Pin 5)SetWPUC6=1'TIN - CCP4 (Pin 8)SetWPUC7=0'******Input IO config******
#defineRCLRC5'PWM INPUT (CCP1)
#defineTINRC6'PWM INPUT (CCP4)
#defineSOURC1'LED OUTPUT BASED ON CONDITION OF INPUT (I.E. PORTC.5) ERV Changed to suit my board
#defineTOURC2'LED OUTPUT BASED ON CONDITION OF INPUT (I.E. PORTC.6) ERV Changed to suit my board'******Dir Config******DIRRCLINDIRTININDirSOUOUTDirTOUOUT'******DIM Variable Config******DIMRCLPWHASWORD'PORTC.5 - PULSE HIGH MEASUREMENTDIMRCLPWLASWORD'PORTC.5 - PULSE LOW MEASUREMENTDIMTINPWHASWORD'PORTC.6 - PULSE HIGH MEASUREMENTDIMTINPWLASWORD'PORTC.6 - PULSE LOW MEASUREMENTDIMRCLDCPCASWORD'LOGIC TO DECIDE WHAT TO DO WITH PORTC.5 INPUT PULSE WIDTH DUTY CYCLEDIMTINDCPCASWORD'LOGIC TO DECIDE WHAT TO DO WITH PORTC.6 INPUT PULSE WIDTH DUTY CYCLEDIMRCLPeriodASWORD'VARIABLE FOR CALCULATING PORTC.5 PULSE PERIODDIMTINPeriodASWORD'VARIABLE FOR CALCULATING PORTC.6 PULSE PERIODDIMCounterValueasWord'VARIABLE FOR IncCounter 'COUNTERVALUE'DIMRCLFreqasWord'VARIABLE FOR CALCULATING PORTC.5 PULSE FREQUENCYDIMTINFreqasWord'VARIABLE FOR CALCULATING PORTC.6 PULSE FREQUENCY'Setup timerInitTimer1OSC, PS1_8'Counter Value Initialized ValueCounterValue=0OnInterruptTimer1OverflowCallIncCounter'Set "On Interrupt"'At this point Timer1 is not runningdoCallPWMRCL'MEASURE PORTC.5 PULSE WIDTH HIGH AND LOW TIMER VALUESloopSubIncCounter'ON INTERRUPT CounterCounterValue++EndSubSubPWMRCLCCP1CON=4'Set the Capture mode: every falling edgeStartTimer1'Start the timer... but, is the valie of CounterValue important ? I guess not. 'Now timer is running and CounterValue is incrementingCCP1IF=0'Clear the CCP1F interrupt flag, but, we have not enabled the CCP1 interrupt. Will CCP1IF ever become 1?dowhileCCP1IF=0IfCounterValue>=1Then'The chances of CounterValue are pretty high as CCP1IF will always be 0CallRCLISREndIfloopEndSubSubRCLISRSOU=!SOUEndSub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Basically, at this stage I am just wanting to take a duty cycle measurement from each CCP input and apply a corresponding output to an LED. for example, If CCP1 duty cycle is between 50% to 100%, Then LED1 (SOU in my code) will turn on, otherwise it will be off. At the same time, if CCP4 input duty cycle is between 1% and 49% then LED2 (TOU in my code) will turn on. 0% is the off state for both LEDs. The LEDs will operate independently of each other, so CCP1 (RCL) will only control output SOU, while CCP4 (TIN) will only control output TOU.
Thanks for the feedback re the clearing of bit PIE1.TMR1IE! I have had a look in other open discussions over the last half hour and the usage i have found is in assembly code examples (I am not proficient in assembly.... but, you probably guessed that already! :-) Is it possible to include it in SynWrite? If yes, where should it be placed? Perhaps even a previous open discussion if you are aware of one that has already covered the PIE1.TMR1IE usage would be very much appreciated!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am using Timer1 to measure/time the pulse width high and low, so I can calculate the duty cycle. If the duty cycle is 0% or 100% I am wanting to use an interrupt to handle this. If 0% duty cycle, SOU = 0, if 100% SOU = 1 . The duty cycle from 1% to 99% will turn SOU either on or off, depending upon what duty cycle values I determine. Say anything from 50% up, SOU = 1, anything below 50% SOU = 0.
My understanding is when working with 0% and 100% duty, an ISR is needed to manage this. While I have got this working with CCP1 on TMR1 (somehow, given I appear to be way off!), I want to do the same thing with CCP4, with CCP4 also using Timer1.
I included the IncCounter because it was included in one of the the GCB 16f887A help pages... I used it to help me get started when first getting started with Interrupts and just realized that I never took it out and is totally pointless for my project.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi there,
I have been using GCB for the last couple of years, but only recently delved into using CCP ports using interrupts with 'relative' ease to control LED output based upon pulse width duty cycle input. However, I have am now wanting to use two CCP ports on a PIC16F1829 with both ports using Timer1.
I have been working on this for a week now and cannot for the life of me figure out how to manage the ISR's correctly with both CCP1 and CCP4 operating using Interrupts with Timer1 (i.e. 16 bit). If I comment out the first to two LOOP 'Calls' for CCP1, then CCP4 works fine and visa versa, commenting out CCP4 makes CCP1 work fine. But they will not work if both are left to function consecutively - I have been using Proteus simulator to test.
Once I can get this working, then I will want to expand this to 4 x CCP through Timer1, which I should be able to do, once I understand what I am doing wrong to get this working with just 2 x CCP's.
I am pulling out what little hair I have and I know I am not handling the Interrupts/ISR's correctly, but cannot work out exactly where the problem is?!
I have attached the code below and am hoping someone can help me before I am completely bald!
Thanks in advance!!
Last edit: Phil D 2022-03-17
NOTE: "I should have made it a little more clear, I am using internal weak pull ups, so I have reversed the pulse width high and low variable names accordingly.
Interesting.
I think I would need a simple description of what you are trying to achieve. I am not sure I understand from the intro.
A comment... On Interrupt Timer1Overflow Call IncCounter these do the same thing. I cannot see that you are clearing the bit PIE1.TMR1IE there is no point in setting more than once.
I just took the code you posted and tried to start from first principles. Many questions already.
I have changed SOU and TOU to suit the board I had to hand.
But, as you will see SOU is toggling as the program logic, so far, does not make sense to me.
I do not recommend that you/we all post and repost this to the forum. Can you move this code to GitHub where folks can edit and help online?
Evan
Thanks Evan, I have attached the file in my original post.
OK, yes, I see there is a fair bit not correct, surprised it even works for me even using just one CCP.
Looking into your Serial debug attachment now...
The attachment has Serial debug added and version control.
By showing the value of PIR1.. the CCP1IF bit never changes. From this basis - what am I missing?
Last edit: Anobium 2022-03-17
Hi Anobium,
Thanks for the quick response!
Basically, at this stage I am just wanting to take a duty cycle measurement from each CCP input and apply a corresponding output to an LED. for example, If CCP1 duty cycle is between 50% to 100%, Then LED1 (SOU in my code) will turn on, otherwise it will be off. At the same time, if CCP4 input duty cycle is between 1% and 49% then LED2 (TOU in my code) will turn on. 0% is the off state for both LEDs. The LEDs will operate independently of each other, so CCP1 (RCL) will only control output SOU, while CCP4 (TIN) will only control output TOU.
Thanks for the feedback re the clearing of bit PIE1.TMR1IE! I have had a look in other open discussions over the last half hour and the usage i have found is in assembly code examples (I am not proficient in assembly.... but, you probably guessed that already! :-) Is it possible to include it in SynWrite? If yes, where should it be placed? Perhaps even a previous open discussion if you are aware of one that has already covered the PIE1.TMR1IE usage would be very much appreciated!
Back basics, so I can understand your design goals.
You are using timer1 to do what? at the moment islt simlple increments and (in my code does nothing), are you waiting for an event on Ccp1 input?
I am using Timer1 to measure/time the pulse width high and low, so I can calculate the duty cycle. If the duty cycle is 0% or 100% I am wanting to use an interrupt to handle this. If 0% duty cycle, SOU = 0, if 100% SOU = 1 . The duty cycle from 1% to 99% will turn SOU either on or off, depending upon what duty cycle values I determine. Say anything from 50% up, SOU = 1, anything below 50% SOU = 0.
My understanding is when working with 0% and 100% duty, an ISR is needed to manage this. While I have got this working with CCP1 on TMR1 (somehow, given I appear to be way off!), I want to do the same thing with CCP4, with CCP4 also using Timer1.
I included the IncCounter because it was included in one of the the GCB 16f887A help pages... I used it to help me get started when first getting started with Interrupts and just realized that I never took it out and is totally pointless for my project.
Have you reviewed this ? http://ww1.microchip.com/downloads/en/appnotes/01473a.pdf
No I haven't but I will! Thanks Evan and will let you know how I get on.