Arduino library for DAC8571 I2C, 1 channel, 16 bit DAC.
Experimental
The DAC8571 is a small low-power, single channel, 16-bit voltage Power-On Reset to Zero output DAC.
The DAC8571 has one 16 bit DAC. The output value can be set from 0..65535. This results in a voltage which depends on a reference voltage Vref (see datasheet). At power up the channel always will start with a value of zero.
The DAC8571 has a temporary register in which a value can be preloaded. This can be used to change the DAC at a later moment.
Not supported is the broadcast function to change multiple DAC8571 (and compatibles) at the same moment by using this temporary register.
As said the library is experimental need to be tested with hardware. Feedback is always welcome, please open an issue.
Kudos to Paul for first tests.
To connect the DAC8571 to a 3V3 device one need to use level converters. (Preliminary test Paul)
From datasheet page 24.
Settling time to within the 16-bit accurate range of the DAC8571 is achievable within 10 μs for a full-scale code change at the input. Worst case settling times between consecutive code changes is typically less than 2 μs, therefore, the update rate is limited by the I2C interface.
The DAC8571 support 2 addresses by means of an A0 address pin.
Address | A0 |
---|---|
0x4C | LOW |
0x4E | HIGH |
It might be possible to connect this address pin to an IO pin and keep only one HIGH and remaining LOW to support many devices. This is not tested, feedback welcome.
To be able to reach 1 MHz (ESP32) the pull ups need to be fairly strong. Preliminary tests indicate that 2K work.
Extend table, use output of DAC8571_performance.ino
Time in microseconds.
array == write(array, length)
Assumption all write modi have similar performance.
Test Arduino UNO - version 0.1.0
Speed | function | time | notes |
---|---|---|---|
100000 | write() | ||
100000 | read() | ||
200000 | write() | ||
200000 | read() | ||
400000 | write() | ||
400000 | read() |
Test ESP32 (Kudos to Paul) - version 0.1.0
Speed | write() | read() | write(array) | Notes |
---|---|---|---|---|
50000 | 800.01 | 800.04 | ||
100000 | 439.02 | 441.18 | 2100.01 | array == 10 elements! |
200000 | 239.12 | 242.41 | 1090.82 | |
300000 | 178.05 | 181.81 | 757.57 | |
400000 | 148.94 | 156.83 | 595.24 | |
500000 | 131.57 | 142.93 | 497.99 | |
600000 | 120.68 | 136.35 | 428.59 | |
700000 | 113.19 | 130.40 | 384.64 | |
800000 | 108.12 | 128.18 | 351.85 | |
900000 | 98.21 | 106.67 | 317.45 | |
1000000 | 94.11 | 94.58 | 296.88 |
Sometimes you need to control more devices than possible with the default address range the device provides. This is possible with an I2C multiplexer e.g. TCA9548 which creates up to eight channels (think of it as I2C subnets) which can use the complete address range of the device.
Drawback of using a multiplexer is that it takes more administration in your code e.g. which device is on which channel. This will slow down the access, which must be taken into account when deciding which devices are on which channel. Also note that switching between channels will slow down other devices too if they are behind the multiplexer.
- https://github.com/RobTillaart/AD5680 (18 bit DAC)
- https://github.com/RobTillaart/DAC8550
- https://github.com/RobTillaart/DAC8551
- https://github.com/RobTillaart/DAC8552
- https://github.com/RobTillaart/DAC8554
- https://github.com/RobTillaart/DAC8571
- https://github.com/RobTillaart/DAC8574
- https://github.com/RobTillaart/MCP_DAC
- https://github.com/RobTillaart/MCP_ADC
#include "DAC8571.h"
- DAC8571(uint8_t address = 0x4C, TwoWire *wire = &Wire) constructor with I2C address. Default is 0x4C, optional set the WireN I2C bus.
- bool begin(uint16_t value = 0) Set initial value for the DAC, typical zero (power on default). Returns false if address out of range, or if device cannot be seen on the I2C bus. Returns true if successful.
- bool isConnected() test to see if address can be reached on the I2C bus.
- uint8_t getAddress() returns address set in constructor.
The DAC8571 has one 16 bit DAC. The output value can be set from 0..65535.
- bool write(uint16_t value) writes a value 0..65535 to the DAC. No default, user must explicit set value.
- uint16_t lastWrite() get last value written from cache (fast).
- uint16_t read() get last written value from device.
Percentage wrappers
- bool setPercentage(float perc) set 0.00 .. 100.00, returns true on success.
- float getPercentage() returns 0.0 .. 100.0 from cache.
The DAC8571 can be written in different modi (datasheet page 19). Not all modi are supported yet, these need investigation and testing.
- void setWriteMode(uint8_t mode = DAC8571_MODE_NORMAL)
- uint8_t getWriteMode()
Setting the mode will be applied for all writes until mode is changed.
Mode | Meaning |
---|---|
DAC8571_MODE_STORE_CACHE | store value in temporary register. Preparation for (2, 3 and 4) |
DAC8571_MODE_NORMAL | update DAC with value written. DEFAULT. |
DAC8571_MODE_WRITE_CACHE | writes the temporary register to DAC, ignores new value. |
DAC8571_MODE_BRCAST_0 | broadcast update. See below. |
other | maps onto default DAC8571_MODE_NORMAL. |
DAC8571_MODE_BRCAST_1 | broadcast update. Not supported yet. See below. |
DAC8571_MODE_BRCAST_2 | broadcast update. Not supported yet. See below. |
With DAC8571_MODE_STORE_CACHE one can fill a buffer and the device will set that when a value is written in DAC8571_MODE_WRITE_CACHE. Especially useful for multichannel synchronuous update.
The maximum length depends on the internal I2C BUFFER of the board. For Arduino this is typical 32 bytes so it allows 14 values.
- void write(uint16_t arr[n], uint8_t length) Writes a buffer with max 14 values in one I2C call. The last value written will be remembered in lastWrite().
This function can be used for a defined fast ramp up / down.
To investigate: Mixes also with broadcast ==> complex API.
- void powerDown(uint8_t pdMode = 0) default low power.
- void wakeUp(uint16_t value = 0) wake up, DAC value set to zero by default.
See table 6, page 22 datasheet for details.
Power Down Mode | value | Meaning |
---|---|---|
DAC8571_PD_LOW_POWER | 0 | 170 uA |
DAC8571_PD_FAST | 1 | 250 uA |
DAC8571_PD_1_KOHM | 2 | 200 nA, GND 1 KOhm |
DAC8571_PD_100_KOHM | 3 | 200 nA, GND 100 KOhm |
DAC8571_PD_HI_Z | 4 | 200 nA, open circuit, high impedance |
Different ways possible, need to investigate API. (page 19)
Three broadcast commands exists:
Mode | Meaning | Notes |
---|---|---|
DAC8571_MODE_BRCAST_0 | Load all channels from temporary register | |
DAC8571_MODE_BRCAST_1 | Load all channels with data. | not supported |
DAC8571_MODE_BRCAST_2 | Power down all devices | not supported |
- int lastError() always check this value after a read() / write() to see if it was DAC8571_OK. After the call to lastError() the error value is reset to DAC8571_OK.
Error code | Value | Notes |
---|---|---|
DAC8571_OK | 0x00 | |
DAC8571_I2C_ERROR | 0x81 | |
DAC8571_ADDRESS_ERROR | 0x82 | |
DAC8571_BUFFER_ERROR | 0x83 | write(arr, length) length error |
- get hardware to test
- improve documentation
- test different write modi
- extend / fill performance table
- replace magic numbers
- derived classes DAC7571 (12 bit) DAC6571 (10 bit)?
- add examples
- investigate broadcast support
If you appreciate my libraries, you can support the development and maintenance. Improve the quality of the libraries by providing issues and Pull Requests, or donate through PayPal or GitHub sponsors.
Thank you,