Open soundanalogous opened 9 years ago
looks like this is simply analogWrite() on pin A0 of the Arduino Zero, but it's 10-bit instead of 8-bit.
Teensy 3.1/3.2 has a 12-bit DAC on its A14/DAC pin.
Arduino Due has 2 DACs. A future Teensy will too.....
SYSEX extension:
0 START_SYSEX (0xF0)
1 sysex command (0x00-0x7F) ? Can be assigned any available
2 pin (0-127)
3 lsb
4 msb
N END_SYSEX (0xF7)
... which actually looks a lot like https://github.com/firmata/protocol/blob/master/protocol.md#extended-analog
The way DAC works on Arduino is you simply use analogWrite. Now that I think about it, a new protocol should not even be necessary for writing the value at least. It should just work if you send the value on the appropriate pin. So for a 10-bit DAC you'd send between 0 and 1024, for a 12-bit you'd send between 0 and 4096, etc. I just need to make sure Firmata is not limiting the value when it's passed to analogWrite.
However, I will have to add a way to set the analogWriteResolution value.
Thinking more about this, there are 3 options for adding DAC support:
Any preferences? I'm leaning towards 2 or 3. My concern is 1 or 2 may be too Arduino-specific.
@soundanalogous I'm currently implementing a host library based on the Arduino Firmata for an EFM32. I have a slightly different problem that goes beyond just support for a DAC (my preference would be for option 3). The BGM111 MCU that I am looking to support has an IDAC instead of a typical DAC. It'd be great to have a way to set up and configure what analogWrite() is actually doing, possibly through a new SYSEX command which defines what peripheral that analogWrite() is targetting.
Does the BGM111 currently use analogWrite for the DAC?
The BGM111 does not have a Voltage DAC so I've implemented analogWrite() to use PWM at this moment in time. I'd like to support the use of the Current DAC but am not sure the best means to support it with Firmata as of right now. IMO it should be mappable to the analogWrite() function with some means to be able to choose how you drive it, i.e. be able to select if you want to use PWM, Voltage DAC, Current DAC, etc. on a specific Pin.
Revisiting your earlier comment https://github.com/firmata/protocol/issues/32#issuecomment-152777878, I think number 2 would actually make more sense for this kind of implementation.
Ideally Arduino would implement a way consistent way to write to a DAC or IDAC in their HAL and Firmata would simply use that API rather than having to maintain different implementations for different boards.
That would be ideal; even so, you'd still need a way to choose (from a Firmata client) between which peripheral that you wanted to drive the analogPin?
Looking again at how you write to the DAC on an Arduino, it requires 2 functions calls, especially if you're also writing to a PWM pin at a different resolution than the DAC. So if you wanted to write a value to a 12 bit DAC then write an 8-bit PWM value to another pin you'd have to do something like this:
analogWriteResolution(12);
analogWrite(DAC_PIN, val12bit);
analogWriteResolution(8);
analogWrite(PWM_PIN, val8bit);
With Firmata that would require sending 4 separate messages which is slightly inefficient. Considering that, it may be better to add a DAC_WRITE
message to Firmata. The DAC resolution for any supported pins would already be known (configured in Boards.h) so the resolution could be set automatically without having to pass a separate message, then set back to the default PWM resolution immediately afterwards. Much simpler IMO.
0 START_SYSEX (0xF0)
1 DAC_WRITE (0x5B)
2 pin (0-127)
3 bits 0-6 (least significant byte)
4 bits 7-13 (most significant byte)
... additional bytes may be sent if more bits are needed
N END_SYSEX (0xF7)
In Arduino code:
// something like this would be added to StandardFirmata in the
// existing sysexCallback function
void sysexCallback(byte command, byte argc, byte *argv)
{
// ...
switch (command) {
// ...
case DAC_WRITE:
if (argc > 1) {
byte pin = argv[0];
int val = argv[1];
if (argc > 2) val |= (argv[2] << 7);
if (argc > 3) val |= (argv[3] << 14);
analogWriteResolution(DEFAULT_DAC_RESOLUTION); // define in Boards.h
analogWriteCallback(pin, val);
analogWriteResolution(DEFAULT_PWM_RESOLUTION); // already defined in Boards.h
}
break;
// ...
}
}
The Arduino Zero has 1 10-bit DAC pin. Draft a protocol to add DAC support to Firmata.