Is this a known bug (20M2 v8.A, PWMOUT on B.1) ?

AllyCat

Senior Member
Hi,

Following on from this recent thread I was wondering if it is possible to arrange for the DVM digits to exactly correspond to the 256 levels from a variable byte. Theory suggested that it should be possible (with a reasonable quality DVM and good design) but all my practical attempts, even with careful coding, just didn't quite make it. Like in the original post, I used PWMOUT because I find the PWMDUTY command rather greedy of program code space.

It was only when I went back to the fundamentals, directly altering the PWM values, that I noticed certain changes didn't affect the output value at all (average analogue level and ultimately the pulse width itself). The attached code and 'scope waveform should indicate what is (or isn't) happening. It's not easy to show in a single screenshot, but the faint traces are the falling edges from the PWMDUTY pulses and the bold lines show the PWMOUT pulses. The vertical green cursors indicate the expected range from 10 to 20 (and correspond to the actual extent of the PWMDUTY pulses).

Looking at the Microchip base PICaxe data sheet it can be seen what's happened. The two LSBs of the 10-bit word are stored in a separate (the Command) register and the higher of these two bits appears to have got "lost" (always 0). I haven't checked any other pins, or other PICaxe versions, as I feel I've already wasted more than enough time looking for non-existent errors in my original code. :(

Rich (BB code):
; Test code to show apparent 20M2 PWMOUT bug.  AllyCat,  August 2015.
#picaxe 20m2
#no_data
#terminal 4800
do
   for w0 = 10 to 20
      pwmout PWMDIV64,b.1,255,w0
      pause 1000
   next
   pwmout b.1,off
   sertxd("PWMDUTY",cr,lf)
   pause 5000
   pwmout PWMDIV64,b.1,255,0
   for w0 = 10 to 20
      pwmduty b.1,w0
      pause 1000
   next
   sertxd("PWMOUT",cr,lf)
   pwmout b.1,off
   pause 5000
loop
20M2PWMOUTbug.jpg

Cheers, Alan.
 
Last edited:

premelec

Senior Member
Hi Alan - that's certainly interesting - and annoying - I wonder what percentage the discontinuity is - roughly how much the integrated filtered PWM deviates from linear as you constantly monotonically change it? That could certainly give trouble in some situations... thanks for your careful consideration of some of PICAXE's finer points.
 

AllyCat

Senior Member
Hi,

Yes, further tests show that the 08M2 and 14M2 are not affected. But all 4 PWM pins on the 20M2 do suffer the problem. :(

I wonder what percentage the discontinuity is - roughly how much the integrated filtered PWM deviates from linear as you constantly monotonically change it?
Well, it's basically 2 parts in 1024 (of the full Vdd supply voltage) or about 0.4% of a 2.5v analogue output level (if assuming a 5v Vdd). So just enough to take the value onto the next digit, which is why it took me so long to spot the issue.

At least there is a "workaround" (when you know it's needed) of using PWMDUTY, but that consumes another 31 bytes of program code space compared with the 5 bytes for PWMOUT. And such a macro might have an impact on execution time, it takes over 7 ms to execute (at 4 MHz), compared with a little over 1 ms for PWMOUT.

But at least I can now get back to my original target. I hope to be able to post program code within a few days, in that other thread, which maps the displayed digits perfectly to the variable byte value (at least using a moderate quality DVM) over the full supply rail range, with no additional hardware (except perhaps a LP filter for some DVMs).

Cheers, Alan.
 

hippy

Technical Support
Staff member
It does seem to be related to how the PWMOUT command is handled which had not been previously observed so please accept our apologies for that. It behaves as described, at least for the 20M2, as if bit1 of the duty value is always zero no matter what it should be.

Using PWMDUTY would be the easiest workround. For PWMOUT B.1 on a 20M2 a slightly shorter alternative is -

Code:
PwmOut PWMDIV64, B.1, $FF, duty
PeekSfr $D3, b0
bit5 = duty / 2
PokeSfr $D3, b0
The SFR used depends on PWMOUT pin -

B.1 -> $D3
C.2 -> $DA
C.3 -> $BA
C.5 -> $B3
 

AllyCat

Senior Member
Thanks hippy,

Yes, I'd worked out that it was probably SFR $D3, but due to a typo managed only to SERTXD the value 0, so assumed it was write-only. :(

Your SFR workaround is less than half the size of PWMDUTY, and I'm not sure that I would have thought of the simple "bit5 = duty / 2" construct, so that was helpful.

Cheers, Alan.
 
Top