analogWrite() is used to create a PWM wave on a pin.
Note
On the Maple, calling analogWrite() is the same as calling pwmWrite(). We recommend writing pwmWrite() instead of analogWrite().
This is because PWM is not true analog output (it’s not the output of a DAC), so the function is very badly named. For instance, analogWrite() has nothing to do with analogRead(), which can be confusing.
We provide analogWrite() for the sake of compatibility with Arduino only.
Contents
There are a few important differences between Arduino’s analogWrite() and Maple’s pwmWrite() that you should keep in mind. In each case, we have some recommendations you can use to help converting from Arduino to Maple.
The first and most important difference is that the largest possible value for the duty cycle is much bigger on the Maple. Using Arduino’s analogWrite(), the duty cycle ranges between 0–255 (always off – always on)[1]. Using Maple’s pwmWrite(), the duty cycle ranges from 0–65,535 by default[2].
This is a good thing! The greater range of values on the Maple gives you much more precise control over the duty cycle of your PWM output.
If you’re porting code from the Arduino and want a quick-and-dirty fix, one solution is to map the argument to analogWrite() into the right range:
// Arduino code:
analogWrite(pin, duty);
// Becomes Maple code:
analogWrite(pin, map(duty, 0, 255, 0, 65535));
This will convert values in the range 0-255 to values in the range 0–65,535, which is the correct default range for all of the timers which control PWM output. See the timers reference for more information.
Another fix is to consult your board’s pin maps to find the timer which controls PWM on the pin you’re using, then set that timer’s overflow to 255. Subsequent calls to analogWrite() should work as on the Arduino (with the same loss of precision). Note, however, that that affects the overflow for the entire timer, so other code relying on that timer (such as any interrupts the timer controls) will likely need to be modified as well.
The second difference is that on the Maple, you must set up the pin for PWM output using pinMode(), with argument PWM. This should just be one extra line of code in your setup() function. Example:
void setup() {
// set up pin 9 for PWM
pinMode(9, PWM);
}
This also means that you can’t later call digitalRead() or digitalWrite() on that pin (unless some time in between, you use pinMode() to reconfigure that pin for INPUT or OUTPUT; see the pinMode() page for more information).
On the Maple, the pins which support PWM are: 0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 24, 27, and 28 or fifteen pins in total. That’s more PWM-capable pins as any Arduino board, but there are differences in which pins support PWM.
In all cases, Arduino boards support PWM on pin 10, unlike Maple. We did our best to make PWM as pin-compatible as possible; however, circuit layout constraints prevented us from achieving perfect compatibility.
The “safest” pins to use for PWM output are pins 9 and 11. These pins work on any Arduino board and on Maple. The “safe” pins, which work on most recent Arduino boards, the Arduino Mega and the Maple, are pins 3, 5, 6, 9, and 11. Thus, if you want your project to be as portable as possible between Maple and Arduino, we recommend using the “safest” pins first, then the “safe” pins, then any other pins, as necessary.
The frequency of the PWM signal (i.e., the frequency of a complete on/off cycle) on the Arduino is approximately 490 Hz.
On the Maple, the frequency is configurable, defaulting to about 1100 Hz, or 1.1 KHz. This is because the PWM frequency is the frequency of the timer which controls PWM output on the particular pin (the PWM tutorial has the details).
If your application definitely requires Arduino’s PWM frequency, then the steps are:
Be aware that this will change the period for the entire timer, and will affect anything else in your program that depends on that timer. The important examples are timer interrupts and PWM.
Footnotes
[1] | This is because the value for the duty cycle on Arduino must fit in 1 byte of memory, and an unsigned (i.e., nonnegative) integer with size 1 byte can hold the values between 0 and 255. |
[2] | This is because the value for the duty cycle on the Maple uses 2 bytes of memory, and an unsigned (i.e., nonnegative) integer with size 2 bytes can hold the values between 0 and 65,535. |
License and Attribution
Portions of this page were adapted from the Arduino Reference Documentation, which is released under a Creative Commons Attribution-ShareAlike 3.0 License.