firmata / arduino

Firmata firmware for Arduino
GNU Lesser General Public License v2.1
1.54k stars 516 forks source link

Add DAC support #200

Open soundanalogous opened 9 years ago

soundanalogous commented 9 years ago

Arduino Zero has 1 10-bit DAC pin.

Start with protocol: https://github.com/firmata/protocol/issues/32.

soundanalogous commented 9 years ago

Turns out this DAC support relies on analogWriteResolution(numBits) after all. Punting DAC support to Firmata 2.6 since I want to formally release v2.5 so people can start using the new Serial feature sooner than later.

rwaldron commented 9 years ago

Thanks for the update!

cstawarz commented 4 years ago

Turns out this DAC support relies on analogWriteResolution(numBits) after all.

I don't know what the situation was four years ago when you made this comment, but this isn't true at present.

Currently, analogWriteResolution alters the expected range of input values to analogWrite for both DAC and PWM outputs. You can see this in the implementation of analogWrite for the Arduino Zero: In both the DAC and PWM code paths, mapResolution is called to convert the input value from the input resolution (either the default or the value set by analogWriteResolution) to the "native" resolution of the output.

The upshot is that, even without a prior call to analogWriteResolution, analogWrite can still output values between 0 and Vref (i.e. 3.3V) on the DAC pin. It's just that the number of available steps between 0 and Vref is constrained by the write resolution. Similarly, if you change the write resolution from the default of 8 to 10, then you can exercise the full output range of a PWM pin by passing values between 0 and 1023 to analogWrite, but the value you specify will be mapped into whatever range is appropriate to the pin (which, for the Zero, appears to be 16 bits).

I mention this here because I think it points to a way to provide basic support for DAC on Arduino devices, without requiring any changes to the Firmata protocol (i.e. /firmata/protocol#32). In the case of the Zero, the only thing (*) that prevents controlling the DAC via the existing EXTENDED_ANALOG sysex is the fact that IS_PIN_PWM returns false for pin 14. While it's technically correct that pin 14 supports DAC, not PWM, the distinction doesn't matter as far as analogWrite is concerned.

(*) Actually, there's another thing: Setting the pin mode to OUTPUT before calling analogWrite messes things up. At least, this is true on the Adafruit Feather M0 that I've tested on, which does its best to look like a Zero to the IDE. In any case, seeing as the docs explicitly say "You do not need to call pinMode() to set the pin as an output before calling analogWrite()", maybe that line can just be removed?

I'd be happy to submit a PR with these changes.