Software PWM on any pin on Fez Cerberus or other open source hardware
While unable to use the Signal Generator (a.k.a Output Compare) class to generate a simple PWM signal, I decided to write my own. I want to generate 8 PWM signals, and since my Fez Cerberus doesn’t support that many, and since the driver for the 16-port PulseInOutModule (http://www.ghielectronics.com/catalog/product/392) is not yet released, I am making slow progress on a fancy cerberus robot.
The SoftwarePWM operates on a thread that cycles indefinitely while started, trying to use as much CPU time as possible - undoubtedly not the best solution, but I was having difficulties trusting Thread.Sleep(ms) to give consistent results - no doubt because of NETMF threading logic.
I intend to implement an 8-servo controller using an array to keep track of the next event needed to execute (a pin up or down), so I should post that within a week).
++GHI + NETMF
Lawren, thanks for the contribution! However, the Cerberus has 9 usable PWM pins which may be better for your project. See this discussion.
I think if you looked used an oscilloscope to look a the generated signals with your code,
you will find that with eight threads running, your outputs are not what
You will only get what you expect with one thread, with a bit of jitter.
There is only one processor on the board. Each thread will get the CPU for
20ms before the dispatcher takes it away and gives it to another thread.
With 8 threads, an output will be what you expect for 20ms, freeze
for 140ms, and then have another 20ms good period.
I’m fairly confident the hardware itself is capable of 16 PWM outputs, on a variety of different pins. To the Register class!
Have you tried using a system timer? I’m interested in how the results would compare with your original Thread.Sleep solution.
Lawren, Thanks for the software PWM.
I have used your software PWM on a ST32F4 for LEDs. Sometimes the hardware PWM’s are simply not enough.
The ST32F4 unfortunately even some pins as a Cerb.
For the LEDs I’ve changed the code a bit:
private const int FrequencyHz = 100;
private const int MaxDutyCycle = 10000;
private const int MinDutyCycle = 0;
This is a fabulous example of precisely what the CLR should not be used for
Indeed. Especially on hardware as capable as the STM32F4, which has no fewer than 17 timers. Quoth the datasheet:
[em]The STM32F40x include 4 full-featured general-purpose timers: TIM2, TIM5, TIM3, and
TIM4.The TIM2 and TIM5 timers are based on a 32-bit auto-reload up/downcounter
and a 16-bit prescaler. The TIM3 and TIM4 timers are based on a 16-bit auto-reload
up/downcounter and a 16-bit prescaler. They all feature 4 independent channels for
input capture/output compare, PWM or one-pulse mode output. This gives up to 16
input capture/output compare/PWMs on the largest packages.[/em]
Yeah, you read that right, 16 hardware PWMs.
Yes, but only 9 are exposed on the Cerberus.
The Cerberus hardware is capable of a lot of things that the firmware doesn’t expose.