PWM Duty Cycle in 4.2

Moving our EMX application from 4.1 to 4.2 (EMX v4.2.4.0 SDK 0.0.5), which fixes our lock-up problem and has a nice fast boot-up.

Changed the PWM for the LEDs to the new Microsoft version, but noticed that the LEDs now won’t turn off completely.

In 4.1, a duty cycle of 0 meant the signal was off all the time, 100% had it on all the time. With 4.2, I’m seeing 0% gives the same output as 1%, and 100% gives the same output as 99%.

We’re running at 10kHz,. On the CRO I see a period on 100uS, with the on-time bumping up/down in 1uS steps, except there is no change between 0% and 1%, and 99% and 100%. And at 1% the LEDs are still reasonably bright.

I didn’t do the conversion myself, but the code looks ok, and tracing it under the debugger it appears to be setting the correct value (0).

Is this a known issue, or are we doing something wrong?

David

We will double check.

Check these threads:

http://www.tinyclr.com/forum/topic?id=8603
http://www.tinyclr.com/forum/topic?id=9123

We just tested setting PWM to a range of values, including a duty cycle of 0.01, 0.0, 0.99 and 1.0. Measuring it with a oscilloscope, all appears to be fine. Do you have some simple sample code that we could try to see the problem?

Hi Steven,

Here is an example that is easy to see on the CRO. It starts at a 50% duty cycle, then goes to 4% and steps down by 1% each 3 seconds, to a 0% duty cycle, which should be off, then loops back to 4%.
However on the CRO you can see it steps to a 1% duty cycle, then stays at 1% when it should be 0%, then back to 4%.
I’ve tried with a 0.5% before the 0%, and it stays at the 0.5%.
I then tried with 0.0000005%, but this time it stayed at the 1%, so it looks like if the input value is less that some value, it isn’t actually applied.

Something similar must be happening at the top end, stepping up in 1% increments stops at 99% instead of getting to 100%.

Regards, David


using System;
using Microsoft.SPOT;
using System.Threading;
using Microsoft.SPOT.Hardware;
using GHI.Premium.Hardware;
using GHI.Premium.IO;


namespace PWM_Test
{
    public class Program
    {
        public static void Main()
        {

            PWM GLedFader;

            GLedFader = new PWM(Cpu.PWMChannel.PWM_2, 10000, 0.5, false);
            GLedFader.Start();

            while (true)
            {
                Debug.Print("Duty Cycle = 4%");
                GLedFader.DutyCycle = 0.04;
                GLedFader.Start();
                Thread.Sleep(3000);
                Debug.Print("Duty Cycle = 3%");
                GLedFader.DutyCycle = 0.03;
                GLedFader.Start();
                Thread.Sleep(3000);
                Debug.Print("Duty Cycle = 2%");
                GLedFader.DutyCycle = 0.02;
                GLedFader.Start();
                Thread.Sleep(3000);
                Debug.Print("Duty Cycle = 1%");
                GLedFader.DutyCycle = 0.01;
                GLedFader.Start();
                Thread.Sleep(3000);

                // 0% stays the same as 1%. If I change the 1% to 0.5%, 0% stays at 0.5%.
                // It appears that if the duty cycle to be set is less than some value, it isn't actually changed.
                Debug.Print("Duty Cycle = 0%");
                GLedFader.DutyCycle = 0.0;
                GLedFader.Start();
                Thread.Sleep(3000);
            }
        }
    }
}

Is there a specific reason you are calling Start() after setting every value? I ran your code, skipping the start calls, and was able to properly set the duty cycle to 0%, and the signal is now off 100% of the time.

The engineer who did the conversion from 4.1 to 4.2 told me he spent a lot of time trying to get it to work, until he realized that it didn’t function without a Start() call. I just took his converted code (which wouldn’t go to 0%) and reduced it to a minimal demonstration case, I didn’t question the need for the Start() calls. I won’t be back in the office for a few days now to try it, but I can see what you are saying, thank you.
That calling Start() repeatedly whilst a 0% duty cycle is set causes repeated glitches has to be incorrect operation, and hopefully will be fixed, it sounds like we have a workaround.

Steven, I’m now back in the office, and had a chance to try removing the Start() calls, as you suggested.
The resulting code (below) does indeed result in a correct 0% duty cycle, however when the duty cycle is set back up to 4% the next time through the loop, it doesn’t come back at all, the signal never returns. In fact it needs a Start() call before the operating recommences, so it looks like the original information about needing to call Start() repeatedly was correct.


using System;
using Microsoft.SPOT;
using System.Threading;
using Microsoft.SPOT.Hardware;
using GHI.Premium.Hardware;
using GHI.Premium.IO;


namespace PWM_Test
{
    public class Program
    {
        public static void Main()
        {

            PWM GLedFader;

            GLedFader = new PWM(Cpu.PWMChannel.PWM_2, 10000, 0.5, false);
            GLedFader.Start();

            while (true)
            {
                Debug.Print("Duty Cycle = 4%");
                GLedFader.DutyCycle = 0.04;
                Thread.Sleep(3000);
                Debug.Print("Duty Cycle = 3%");
                GLedFader.DutyCycle = 0.03;
                Thread.Sleep(3000);
                Debug.Print("Duty Cycle = 2%");
                GLedFader.DutyCycle = 0.02;
                Thread.Sleep(3000);
                Debug.Print("Duty Cycle = 1%");
                GLedFader.DutyCycle = 0.01;
                Thread.Sleep(3000);
                Debug.Print("Duty Cycle = 0%");
                GLedFader.DutyCycle = 0.0;
                Thread.Sleep(3000);
            }
        }
    }
}

In case anyone is following this thread and wondered if the problem was ever resolved, I’ve just seen it duplicated over in the 4.2 Beta topic, http://www.tinyclr.com/forum/topic?id=9458 , where Steven says it is fixed and will be in the final release.