User avatar
By eriksl
#52345 Now been busy debugging and finally it appears that the FRC1 interrupt simply isn't called. Doesn't matter what I change, it never gets called. So I changed the code little bit to use the FRC NMI timer, like the SDK PWM code does and then it works!

I think it has to do with either the newest SDK code using the FRC1 timer for something internal, or it doesn't work because I am using software timers.

Now with NMI interrupt it works, but it looks like all timings are off. It seems that simply replacing this code makes the timer use the NMI interrupt source:

Code: Select all   //ETS_FRC_TIMER1_INTR_ATTACH(pwm_intr_handler, NULL);
   ETS_FRC_TIMER1_NMI_INTR_ATTACH(pwm_intr_handler);


Can you help me check and help with some calculations?

Formerly (with the SDK PWM code), I had period at 3000, which gives me a period of around 600 Hz (apparently, that's what my frequency counter tells me). At a period of 3000, one has a resolution of almost 16 bits, duty = 0 to almost 65535.

Currently, with your code, I am using a period of 65536 and indeed, the counter says 100% duty at that value, so that's good. But the cycle frequency is only 67 Hz. While I had 600 Hz earlier. Do you have an idea how that comes? Can it be the the frequency is different for the NMI clock or that it has another address to load the value? It doesn't seem so, from what I find. Very strange.
User avatar
By StefanB
#52402
eriksl wrote:I think it has to do with either the newest SDK code using the FRC1 timer for something internal, or it doesn't work because I am using software timers.


Of course using the FRC1 for both the PWM and software timers is not possible, as both are need exclusive access to the timer.

eriksl wrote:Formerly (with the SDK PWM code), I had period at 3000, which gives me a period of around 600 Hz (apparently, that's what my frequency counter tells me). At a period of 3000, one has a resolution of almost 16 bits, duty = 0 to almost 65535.


The SDK uses 40ns as base unit for the PWM duty and 1us for the period. 3000us equals a frequency of 333 Hz. So, why is your frequency counter (correctly!) telling you ~600Hz:

The SDK splits the period in a fine and coarse adjustment cycle, please have a look at the first scope trace from my blog post. The frequency counter sees a short pulse (t<5.3us) and a longer pulse (5.3us<t<period) in each period. As the fine adjustment cycle adds 100us to the period, the frequency counter reports: 2 [pulses] / (3000us + 100us) = 645 Hz. Actually, the period is 323 Hz.

eriksl wrote:Currently, with your code, I am using a period of 65536 and indeed, the counter says 100% duty at that value, so that's good. But the cycle frequency is only 67 Hz. While I had 600 Hz earlier. Do you have an idea how that comes? Can it be the the frequency is different for the NMI clock or that it has another address to load the value? It doesn't seem so, from what I find. Very strange.


As you correctly calculated, a 200ns stepsize times 65536 steps results in 67 Hz. As the SDK uses 40ns, it seems to be better by a factor of 5. Actually, it is not, for a number of reasons:

1. The shortest pulse the SDK generates is 80ns. If the fine adjustment is "1", it generates a pulse of 80ns. For "2", it generates a pulse of -- 80ns. For "3", the pulse length is 120ns and then linearly ramps up to 5320ns. Due to the nonlinear response curve for light current versus perceived brightness, the lower steps are the most important, so the useable resolution is 80ns instead of 40ns.

2. Switching time of power MOSFETs is limited by input capacitance and drive current. On the H801 LED controller, I have measured a rise time of ~120ns and a fall time of ~150ns. Thus for pulses shorter than 100ns, the MOSFET will not turn on.

3. Every time the fine adjustment has ramped up to 5.3us, on the next duty increment the coarse adjustment will increase by 5.3us and the fine adjustment will be set to 0. E.g. you will have to pulses of t ~ 5.3us, and after the increment you have one pulse of ~ 10.6us. Due to the MOSFET switching behaviour, the brightness may jump up considerably or even go down.

My implementation is strictly monotonic from 0% to 100% duty cycle. If you set the period to 300Hz, you get a resolution of 14 bits. At this resolution, I am not able to see any brighness steps even at the lowest (and most sensitive) brightness settings, nor any flicker.