aboutsummaryrefslogtreecommitdiffstats
path: root/source/arduino/analogwrite.rst
diff options
context:
space:
mode:
Diffstat (limited to 'source/arduino/analogwrite.rst')
-rw-r--r--source/arduino/analogwrite.rst223
1 files changed, 134 insertions, 89 deletions
diff --git a/source/arduino/analogwrite.rst b/source/arduino/analogwrite.rst
index 64ecd5b..d04f485 100644
--- a/source/arduino/analogwrite.rst
+++ b/source/arduino/analogwrite.rst
@@ -1,116 +1,161 @@
+.. highlight:: cpp
+
.. _arduino-analogwrite:
analogWrite()
=============
-TODO
-
-In libmaple, analogWrite is just a convenience alias for
-:ref:`pwmWrite`. This is because PWM is not true analog output (i.e.,
-is not the output of a DAC), so the name was badly-chosen; however,
-for the sake of compatibility, the alias was provided.
-
-.. doxygenfunction:: pwmWrite
-
-Description
------------
-
-Writes an analog value
-(`PWM wave <http://arduino.cc/en/Tutorial/PWM>`_) to a pin. Can be
-used to light a LED at varying brightnesses or drive a motor at
-various speeds. After a call to **analogWrite()**, the pin will
-generate a steady square wave of the specified duty cycle until the
-next call to **analogWrite()** (or a call to **digitalRead()** or
-**digitalWrite()** on the same pin). The frequency of the PWM
-signal is approximately 490 Hz.
-
-
-
-On most Arduino boards (those with the ATmega168 or ATmega328),
-this function works on pins 3, 5, 6, 9, 10, and 11. On the Arduino
-Mega, it works on pins 2 through 13. Older Arduino boards with an
-ATmega8 only support analogWrite() on pins 9, 10, and 11. You do
-not need to call pinMode() to set the pin as an output before
-calling analogWrite().
-
-
-
-The *analogWrite* function has nothing whatsoever to do with the
-analog pins or the *analogRead* function.
-
-
-
-Syntax
-------
-
-analogWrite(pin, value)
-
-
-
-Parameters
-----------
-
-pin: the pin to write to.
-
-
-
-value: the duty cycle: between 0 (always off) and 255 (always on).
-
-
-
-Returns
--------
+.. note::
+
+ On the Maple, calling analogWrite() is the same as calling
+ :ref:`wirish-pwmwrite`\ ; see that function's documentation for more
+ information.
+
+ This is because PWM is not true analog output (i.e., is not the
+ output of a `DAC
+ <http://en.wikipedia.org/wiki/Digital-to-analog_converter>`_\ ), so
+ the function is badly named. For instance, **analogWrite() has
+ absolutely nothing to do with** :ref:`arduino-analogread`\ , which
+ is potentially confusing.
+
+ The alias of analogWrite() to pwmWrite() is provided (sigh) for the
+ sake of compatibility with Arduino, but we recommend using
+ :ref:`wirish-pwmwrite` when writing new software, for clarity.
+
+.. contents:: Contents
+ :local:
+
+Arduino Compatibility
+---------------------
+
+There are a few important differences between Arduino's `analogWrite()
+<http://arduino.cc/en/Reference/AnalogWrite>`_ and Maple's
+:ref:`wirish-pwmwrite` that you should keep in mind. In each case, we
+have some recommendations you can use to help converting from Arduino
+to Maple.
+
+Difference 1: Duty cycle range is different
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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)\ [#fbytemax]_\ . Using Maple's pwmWrite(), the duty cycle
+ranges from 0--65,535 by default\ [#fuint16max]_\ .
+
+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 :ref:`map <arduino-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,635, which is the correct default range for all of the timers
+which control PWM output. See the :ref:`timers reference <timers>`
+for more information.
+
+Another fix is to consult the :ref:`pin mapping mega table
+<pin-mapping-mega table>` 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
+:ref:`interrupts <arduino-attachinterrupt>` the timer controls) will
+likely need to be modified as well.
+
+Difference 2: You must use pinMode() to set up PWM
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The second difference is that on the Maple, you **must** set up the pin
+for PWM output using :ref:`arduino-pinmode`\ , with argument ``PWM``.
+This should just be one extra line of code in your
+:ref:`arduino-setup` function. Example::
+
+ void setup() {
+ // set up pin 9 for PWM
+ pinMode(9, PWM);
+ }
-nothing
+This also means that you can't later call :ref:`arduino-digitalread`
+or :ref:`arduino-digitalwrite` on that pin (unless some time in
+between, you use pinMode() to reconfigure that pin for ``INPUT`` or
+``OUTPUT``; see the :ref:`arduino-pinmode` page for more information).
+Difference 3: No PWM on pin 10
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+On the Maple, the pins which support PWM are: 0, 1, 2, 3, 5, 6, 7, 8,
+9, 11, 12, and 14, or twelve pins in total. That is at least as
+*many* PWM pins as any Arduino board, but there are differences in
+*which* pins support it.
-Notes and Known Issues
-----------------------
+* On **most Arduino boards** (those with the ATmega168 or ATmega328;
+ this includes the **Arduino Uno**), this function works on pins 3,
+ 5, 6, 9, 10, and 11, or six pins total. Note that these boards
+ support PWM on pin 10, while Maple does not.
-The PWM outputs generated on pins 5 and 6 will have
-higher-than-expected duty cycles. This is because of interactions
-with the millis() and delay() functions, which share the same
-internal timer used to generate those PWM outputs. This will be
-noticed mostly on low duty-cycle settings (e.g 0 - 10) and may
-result in a value of 0 not fully turning off the output on pins 5
-and 6.
+* On the **Arduino Mega**, PWM works on pins 2 through 13, or twelve pins
+ total. Note that this board supports PWM on pins 4, 10, and 13,
+ while the Maple does not. Maple supports PWM on pins 0, 1, and 14,
+ which the Mega does not, making the total number of pins supporting
+ PWM equal on these boards.
+* **Older Arduino boards** with an ATmega8 only support analogWrite() on
+ pins 9, 10, and 11. Maple does not support PWM on pin 10.
+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.
-Example
--------
+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, as necessary.
-Sets the output to the LED proportional to the value read from the
-potentiometer.
+Difference 4: PWM frequency
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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 (\
+:ref:`the PWM tutorial has the details <pwm>`\ ).
-::
+If your application absolutely requires Arduino's PWM frequency (it
+probably doesn't), then the steps are:
-
- int ledPin = 9; // LED connected to digital pin 9
- int analogPin = 3; // potentiometer connected to analog pin 3
- int val = 0; // variable to store the read value
-
- void setup()
- {
- pinMode(ledPin, OUTPUT); // sets the pin as output
- }
-
- void loop()
- {
- val = analogRead(analogPin); // read the input pin
- analogWrite(ledPin, val / 4); // analogRead values go from 0 to 1023, analogWrite values from 0 to 255
- }
+1. Figure out which timer controls PWM output on your pin (\ :ref:`this table <pwm-timer-table>` is your friend here). Let's say it's ``Timern``\ , where ``n`` is some number 1, 2, 3, or 4.
+2. Call ``Timern.setPeriod(2041)``\ . This will set the timer's period to approximately 2041 microseconds, which is a frequency of approximately 490 Hz.
+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. One example is :ref:`interrupts <timers-attachinterrupt>`\ .
+You've been :ref:`warned <timers-pwm-conflicts>`\ .
See also
--------
+- :ref:`Maple PWM tutorial <pwm>`
-- `analogRead <http://arduino.cc/en/Reference/AnalogRead>`_\ ()
-- `Tutorial: PWM <http://arduino.cc/en/Tutorial/PWM>`_
+.. rubric:: Footnotes
+.. [#fbytemax] 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.
+.. [#fuint16max] 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.