• AVR Freaks

Hot!PIC18F26K83: Question on PWM modules

Author
SpokaneNexus
Super Member
  • Total Posts : 432
  • Reward points : 0
  • Joined: 2013/02/05 14:53:25
  • Location: 0
  • Status: offline
2020/01/24 17:01:49 (permalink)
0

PIC18F26K83: Question on PWM modules

The PIC18F26K83 family lists four CCP modules and four PWM modules, which suggests you could have a total of eight PWM outputs from a single device. That would be very useful in an upcoming project. I'm very familiar with Microchip's CCP modules and have used them successfully in PWM mode many times, but the dedicated PWM module is new to me so I'm studying it before we commit to a PCB based on it.

Section 24 of the data sheet documents the PWM module. The introduction, in 24.0 on page 341, says "Each PWM module can select the timer source that controls the module."
 
Yet in section 24.1.1 it says "The period is common to all PWM modules".
 
Meanwhile, register CCPTMRS1 (Register 24-2 on page 346) specifically shows the ability to select different timers for different PWM modules.
 
If you can connect to a different Timer, you should be able to get a different period.

Which is correct? Given the existence of CCPTMRS1, I'd argue that you can indeed have different periods with different PWM modules. But then what is the meaning of 24.1.1 and its "The period is common to all PWM modules"?

Thanks!
#1

14 Replies Related Threads

    ric
    Super Member
    • Total Posts : 25592
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: PIC18F26K83: Question on PWM modules 2020/01/24 18:02:55 (permalink)
    0
    My money is on that being a copy and paste error.
    I agree, the period is controlled by TxPR, so does NOT have to be the same.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    SpokaneNexus
    Super Member
    • Total Posts : 432
    • Reward points : 0
    • Joined: 2013/02/05 14:53:25
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/26 15:34:24 (permalink)
    0
    That's my interpretation as well, but I was hoping someone had used this part and confirmed the behavior.
    #3
    SpokaneNexus
    Super Member
    • Total Posts : 432
    • Reward points : 0
    • Joined: 2013/02/05 14:53:25
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/26 17:32:27 (permalink)
    0
    While we're on the topic of these PWM modules...

    How do you obtain glitchless operation when changing the duty cycle when the duty cycle is very small? Say, for example, that you want to smoothly ramp up the duty cycle. You're presently at 1% and it's time to switch to 2%. The risk here is that a "missed match" could permit the duty cycle to go as high as 100% for one period, until the Timer wraps and the newly written value is reached.

    Section 24.1.1 says, in part: The PWMxDCH and PWMxDCL registers are double buffered. The buffers are updated when Timer2 matches T2PR. Care should be taken to update both registers before the timer match occurs.

    Updating simultaneously from double buffers makes good sense, but it implies that your code is synchronized to the last match AND that you have sufficient instruction cycles to update both registers. At small duty cycles and fast PWM frequencies, that time window could be really narrow.

    One way to do it would be to interrupt on PWM/Timer match (so you know when the window opens). However, I don't see any interrupt options coming out of the PWM modules. The interrupts coming out of the Timer2/4/6 modules relate to a match at the Timer's own comparator, which is unrelated to PWM matches.

    A really kludgy way to do it would be a tight loop that monitors the Timer value, detects the match, and then quickly writes the new value. But that puts the firmware "on hold" every time you want to update the duty cycle, which could be rather often if 1) you're ramping it up or down as described above, and 2) you have multiple PWM modules active at one time.

    Another unpleasant option might be to "freeze" the PWM module after manually switching its output pin to normal I/O mode and writing the appropriate level in the pin's latch, thereby holding the pin while you make changes to the PWM module, then returning the PWM module back to normal operation with control over the I/O pin. I haven't dug through the details to confirm this is even possible - it may be that the PWM module cannot be manipulated this way. And again, this is a terrible option if you're ramping multiple independent PWM modules simultaneously. This chip has a CAN module too, and a networked environment can't just be ignored like that. (And if you drove the CAN module via interrupt, then you could be in the ISR handling received CAN data when you needed to update the PWM module.)

    The goal here is to be able to smoothly change the duty cycle while preventing glitches caused by Timer wrap. Anyone have experience with that? Thanks!
    #4
    SpokaneNexus
    Super Member
    • Total Posts : 432
    • Reward points : 0
    • Joined: 2013/02/05 14:53:25
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/26 18:13:41 (permalink)
    0
    I had the thought that perhaps the two DC registers were interlocked, such that an update wasn't staged for writing into the actual comparator value until both bytes had been written (there are a few examples of that in the PIC lineup). This would reduce the sensitivity to a single byte write. Nothing I can find in the spec sheet suggests that's true for these two values.
     
    However, that led to another idea. If you don't need the full 10 bit resolution, simply ignore the two LSB's of the duty cycle, always leaving them cleared.  Then DC updates would be a single byte write with ~0.4% resolution. Technically you could not achieve full 100% DC (max would be 99.6%) but for many applications that would be enough. And if a true 100% was more important than a true 0%, you could move the "lost" 0.4% to the bottom of the range by setting (and leaving) the two LSB's to yield 0.4 through 100.0% dynamic range instead of 0.0 through 99.6%.

    This technique needs testing, of course, but should avoid glitches with no weird firmware tricks required. Just write the new duty cycle upper register and worst case you'll get one more period with the old duty cycle, but no chance of a Timer wrap and the associated stretched pulse.
    post edited by SpokaneNexus - 2020/01/26 18:15:44
    #5
    LdB_ECM
    Super Member
    • Total Posts : 236
    • Reward points : 0
    • Joined: 2019/04/16 22:01:25
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/26 20:52:27 (permalink)
    0
    Doesn't the match produce have the ability to generate an interrupt?
     
    Usually  for that sort of thing I just change the next value you want in the interrupt. On some devices you may have a minimum pulse width you can't go below because of interrupt latency but that is easy to calculate.
    #6
    ric
    Super Member
    • Total Posts : 25592
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: PIC18F26K83: Question on PWM modules 2020/01/26 21:27:58 (permalink)
    +1 (1)
    SpokaneNexus
    ...
    The interrupts coming out of the Timer2/4/6 modules relate to a match at the Timer's own comparator, which is unrelated to PWM matches.

    Think that through further.
    The Timer match is also the start of the PWM cycle.
    If you update the PWM duty cycle right at the start of the timer ISR, you should be safe.



    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #7
    SpokaneNexus
    Super Member
    • Total Posts : 432
    • Reward points : 0
    • Joined: 2013/02/05 14:53:25
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/26 21:46:34 (permalink)
    0
    LdB_ECMDoesn't the match produce have the ability to generate an interrupt?

    As I said earlier, "I don't see any interrupt options coming out of the PWM modules". Looking at Figure 24-1, the PWM Block Diagram, there's no interrupt outputs.
     
    Usually  for that sort of thing I just change the next value you want in the interrupt. On some devices you may have a minimum pulse width you can't go below because of interrupt latency but that is easy to calculate.

    Agreed, but it's clear the PWM module is intended to run autonomously without requiring ISR support. Hence the absence of interrupt outputs. Unlike the CCR module, which does have interrupt outputs and in many modes does expect to be "handled" or "maintained" on every cycle, the PWM module looks like it is meant to run autonomously once configured.
    #8
    SpokaneNexus
    Super Member
    • Total Posts : 432
    • Reward points : 0
    • Joined: 2013/02/05 14:53:25
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/26 22:03:42 (permalink)
    0
    ric
    SpokaneNexus
    ...
    The interrupts coming out of the Timer2/4/6 modules relate to a match at the Timer's own comparator, which is unrelated to PWM matches.

    Think that through further. The Timer match is also the start of the PWM cycle. If you update the PWM duty cycle right at the start of the timer ISR, you should be safe.

    OK, I see what you're suggesting. Even though the PWM module doesn't have an interrupt output, you could enable the TIMER's interrupt (which controls the period) and, even if you didn't need ISR support for the PWM or Timer in any other way, use it to write a new duty cycle value immediately after a new period starts. Good idea!

    You still have the risk of the current duty cycle timing out before the new value was written (basically, insufficient instruction cycles between the interrupt and the end of the duty cycle). Normally the only downside would be one more period with the "old" duty cycle, but since the PWM and Timer module hardware keeps running even though you're inside the ISR, there is a nonzero chance that the ISR would write just one byte of the new DC value and then a match would occur before the second byte was written. In that case, the match would update the half-correct new DC value and start the next period. Meanwhile, the ISR would write the second byte of the new DC value, and then the new, full, two-byte DC value would get updated... when? Depending upon how the values interact, this could generate a too-short pulse, a too-long pulse, or possibly an infinitely long pulse if the resulting bastardized value is effectively greater than T2PR. A match would never occur, so the hardware would not update the new two-byte value, and the output would remain active per section 24.1: "When the value is greater than or equal to T2PR, the PWM output is never cleared (100% duty cycle)."

    I like your observation that you can "know" when a period starts based on the Timer interrupt, but then we're right back to the original question of avoiding a non-atomic two byte write. This can't be disabled via interrupts because the update operation in question is in hardware, which is why I earlier discussed the idea of (temporarily) disabling the hardware when an update is being performed. There's a race condition risk here. I think my one-byte write solution avoids it, but at the expense of PWM resolution.
    #9
    pcbbc
    Super Member
    • Total Posts : 1507
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/27 01:03:55 (permalink)
    0
    Depending upon how the values interact, this could generate a too-short pulse, a too-long pulse, or possibly an infinitely long pulse if the resulting bastardized value is effectively greater than T2PR. A match would never occur, so the hardware would not update the new two-byte value, and the output would remain active per section 24.1: "When the value is greater than or equal to T2PR, the PWM output is never cleared (100% duty cycle)."

    Not an infinitely long one no - a cycle at 100% duty, which is what you were aiming for - is it not?

    Because for this edge case to occur at all you must either already have set, or be setting, PWMxDCH equal to T2PR. So either you are already at 100% (and ramping down, in which case the new PWMxDCH must be less than T2PR = no issue) or ramping up to 100% in which case the low order PWMxDCL bits (whatever they are currently set to) are irrelevant. And in that case you will (presumably) be setting the low order 2 bits to zero next anyway, otherwise you’re aiming for >100% duty!

    So your worst case is one cycle with 0.4% error due to the 2 low order PWMxDCL bits not having been updated correctly at the instant T2 rolls over and latches them. And then only in the following cases...

    Ramping UP:
    PWMxDCH/PWMxDCL
    SAME/UP = no issues
    UP/UP = worst case is an intermediate pulse width between widths, but in the ramping up direction
    UP/DOWN = problem: possible error due to “late” update of low 2 bits
     
    Ramping DOWN:
    PWMxDCH/PWMxDCL
    SAME/DOWN = no issues
    DOWN/DOWN = worst case is an intermediate pulse between widths, but in the ramping down direction
    DOWN/UP = problem: possible error due to “late” update of low 2 bits
     
    If the edge case “problems” are an issue for you, it seems a simple matter to check T2TMR is “sufficiently less” than T2PR before writing PWMxDCH. By sufficiently less I mean such that you can guarantee writing both PWMxDCH and PWMxDCL before T2TMR reaches T2PR and causes a latch. If it is not, wait a few cycles and then update once the latch and T2 reset have just occurred.
     
    Something like....
    x = T2PR - n;
    while (T2TMR >= x);
    PWMxDCH = h;
    PWMxDCL = l;

     
    Have I missed anything?
    post edited by pcbbc - 2020/01/27 01:13:13
    #10
    SpokaneNexus
    Super Member
    • Total Posts : 432
    • Reward points : 0
    • Joined: 2013/02/05 14:53:25
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/27 11:10:51 (permalink)
    0
    Your test for "sufficiently less" is what I was talking about above when I said "a tight loop that monitors the Timer value". I really hate things like that, since they waste CPU cycles and stall out everything else in the system (including CAN, which is on this processor and which we'll need to use). If you disable CAN interrupts you could miss data on a high speed network due to overruns, if you leave CAN interrupts enabled they could cause your tight loop to miss the  Timer window, etc. Not a good solution IMHO, YMMV.

    As to your point about PR values vs. DC, you could avoid the edge case by carefully analyzing the 8+2 bit values every time (!!!) and then choosing a write order that specifically avoids the edge cases. What a PITA, and totally avoidable if Microchip had implemented this the way they do with their 16 bit timer modules. For example, from section 14.4 of the PIC18F66K80 spec sheet:

    read from TMR1L loads the contents of the high byte of Timer1 into the Timer1 High Byte Buffer register. This provides the user with the ability to accurately read all 16 bits of Timer1 without having to determine whether a read of the high byte, followed by a read of the low byte, has become invalid due to a rollover between reads. A write to the high byte of Timer1 must also take place through the TMR1H Buffer register. The Timer1 high byte is updated with the contents of TMR1H when a write occurs to TMR1L. This allows a user to write all 16 bits at once to both the high and low bytes of Timer1. (emphasis mine)


    Had Microchip done this for their PWM module, this entire discussion would be moot.
    #11
    pcbbc
    Super Member
    • Total Posts : 1507
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/27 11:54:24 (permalink)
    0
    SpokaneNexusYour test for "sufficiently less" is what I was talking about above when I said "a tight loop that monitors the Timer value". I really hate things like that, since they waste CPU cycles and stall out everything else in the system (including CAN, which is on this processor and which we'll need to use). If you disable CAN interrupts you could miss data on a high speed network due to overruns, if you leave CAN interrupts enabled they could cause your tight loop to miss the  Timer window, etc. Not a good solution IMHO, YMMV.

    Agreed, but probably not many.  Depends on your T2 clock frequency compared to Fosc.  You haven't said.  The worst case is when T2 is slow compared with Fosc, but then you only need to avoid updating if T2TMR = T2PR - 1.
     
    However, if you really can not wait you still have other options.  For example arranging for an interrupt which is guaranteed to be offset from T2 roll-overs, or postponing the update if you detect a T2TMR >= x condition.

    As to your point about PR values vs. DC, you could avoid the edge case by carefully analysing the 8+2 bit values every time (!!!) and then choosing a write order that specifically avoids the edge cases.

    No you can't avoid the edge cases.  If steadily increasing duty cycle in steps of 1 you will see that after incrementing any more than 3 steps you will always arrive at an edge case.  Similarly for decrementing.
     
    The only other way to avoid those is - as you suggested previously - keep the low order bits fixed.
     
    What a PITA, and totally avoidable if Microchip had implemented this the way they do with their 16 bit timer modules.

    Yes I understand.  But for 16-bit timers on an 8-bit device there really is no other easily workable option other than to handle it in hardware.
    #12
    SpokaneNexus
    Super Member
    • Total Posts : 432
    • Reward points : 0
    • Joined: 2013/02/05 14:53:25
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/27 12:37:08 (permalink)
    0
    Yes I understand.  But for 16-bit timers on an 8-bit device there really is no other easily workable option other than to handle it in hardware.

    Precisely my point! They could have, and should have, handled this in hardware just as they did for the 16 bit timers. It's still a two-byte write, even though six of the bits aren't active. It's the only way to make a 16 bit write an atomic operation in an eight bit architecture (unless the CPU provides a dedicated word-write instruction, and I'm not aware of one in the PIC18 instruction set).
     
    There's another little anomaly in the PWM modules that I suspect will only be resolved with physical testing. From section 24.1.4: "The 8-bit timer T2TMR register is concatenated with the two Least Significant bits of 1/FOSC, adjusted by the Timer2 prescaler to create the 10-bit time base. The system clock is used if the Timer2 prescaler is set to 1:1."

    My interpretation of the phrase "two Least Significant bits of 1/FOSC" is that the two LSB's of the /4 counter that derives the instruction clock from the oscillator are used as the LSB's of the PWM's 10 bits, and the resulting 10 bit "timer" is then clocked by the Timer2 prescaler. But then we have that last sentence, which says "The system clock is used if the Timer2 prescaler is set to 1:1." This implies that if, and ONLY if, the prescaler is set to 1:1 then the (non-divided-by-four) system clock directly clocks the PWM's 10 bits. In other words, the effective clock frequency driving the 10 bit value doesn't change by "one bit" between prescaler settings of 1:1 vs. 1:2, but THREE bits due to the elimination of the extra /4 counter stage PLUS the additional /2 from the prescaler.

    I can spin that paragraph a number of ways depending upon how I interpret the commas, where I presume the commas should have been, what precisely is meant by "two LSB's of 1/Fosc", etc. But apparently there is some sort of difference between 1:1 and every other prescaler setting because otherwise the first sentence is unnecessary and meaningless.

    I generally like Microchip's spec sheets, but the PWM module's documentation - while short - leaves a lot of questions hanging in the air.

    EDIT: Corrected grammar
    post edited by SpokaneNexus - 2020/01/27 14:18:06
    #13
    pcbbc
    Super Member
    • Total Posts : 1507
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/28 01:33:14 (permalink)
    +1 (1)
    SpokaneNexus
    Yes I understand.  But for 16-bit timers on an 8-bit device there really is no other easily workable option other than to handle it in hardware.

    Precisely my point! They could have, and should have, handled this in hardware just as they did for the 16 bit timers. It's still a two-byte write, even though six of the bits aren't active. It's the only way to make a 16 bit write an atomic operation in an eight bit architecture (unless the CPU provides a dedicated word-write instruction, and I'm not aware of one in the PIC18 instruction set).

    But for the PWM modules it either is not a problem, or if it is there are workable alternatives. You just don’t like any of them! That was my point...
     
    I expect Microchips reasoning was for the edge causes, and where this will generate just an error in only the least significant 2 bits (not even a whole 8 byte of precision), that it is not worth the cost of the extra silicon.
     
    Where do you draw the line with your 16 bit read/write mantra? Do we also need it on the CCP capture register for the odd edge case where there is a second capture between reading the first and second bytes? Or should the user have to check the CxIF again after reading to ensure this hasn’t happened?
     
    Loads of extra complexity, for very little extra gain. Not to mention all of the coding bugs and headaches introduced when users don’t read the datasheet and read the bytes in the wrong order....
    #14
    SpokaneNexus
    Super Member
    • Total Posts : 432
    • Reward points : 0
    • Joined: 2013/02/05 14:53:25
    • Location: 0
    • Status: offline
    Re: PIC18F26K83: Question on PWM modules 2020/01/28 09:45:33 (permalink)
    +1 (1)
    When I see a problem, and there's an obvious, existing, already-implemented, better solution - and they chose NOT to use it - I wonder why. My first inclination is to presume I'm missing something, and I dig into the available data to find the reason that they intentionally chose not to do what seems like a better option. Part of that available data is RTFM, and another part is the collective wisdom of folks who may have already used the part(s) in question. The latter is why I created this thread.

    So far, no one has proposed a better solution than variations on the kludgy ones I described right up front. That suggests I haven't missed something in the spec sheet; there really are edge cases for which better hardware solutions were not implemented in this particular peripheral, despite being known and used in others (even on the same part!).

    I hope for comment regarding my last question, on "two Least Significant bits of 1/FOSC".
    #15
    Jump to:
    © 2020 APG vNext Commercial Version 4.5