{"id":13893898,"url":"https://github.com/RobTillaart/MCP_DAC","last_synced_at":"2025-07-17T08:31:28.842Z","repository":{"id":45321434,"uuid":"335932458","full_name":"RobTillaart/MCP_DAC","owner":"RobTillaart","description":"Arduino library for MCP_DAC MCP48xx and MCP49xx series SPI-DAC","archived":false,"fork":false,"pushed_at":"2025-02-01T13:26:51.000Z","size":78,"stargazers_count":35,"open_issues_count":0,"forks_count":10,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-02T22:01:39.732Z","etag":null,"topics":["arduino","dac"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RobTillaart.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"RobTillaart","custom":"https://www.paypal.me/robtillaart"}},"created_at":"2021-02-04T11:25:30.000Z","updated_at":"2025-03-09T09:27:50.000Z","dependencies_parsed_at":"2024-04-13T10:24:30.807Z","dependency_job_id":"96cdd2e6-1d49-48ff-ae36-a8a6889ad952","html_url":"https://github.com/RobTillaart/MCP_DAC","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/RobTillaart/MCP_DAC","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FMCP_DAC","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FMCP_DAC/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FMCP_DAC/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FMCP_DAC/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobTillaart","download_url":"https://codeload.github.com/RobTillaart/MCP_DAC/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FMCP_DAC/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265585296,"owners_count":23792714,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","dac"],"created_at":"2024-08-06T18:01:19.269Z","updated_at":"2025-07-17T08:31:28.826Z","avatar_url":"https://github.com/RobTillaart.png","language":"C++","funding_links":["https://github.com/sponsors/RobTillaart","https://www.paypal.me/robtillaart"],"categories":["C++"],"sub_categories":[],"readme":"\n[![Arduino CI](https://github.com/RobTillaart/MCP_DAC/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)\n[![Arduino-lint](https://github.com/RobTillaart/MCP_DAC/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/MCP_DAC/actions/workflows/arduino-lint.yml)\n[![JSON check](https://github.com/RobTillaart/MCP_DAC/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/MCP_DAC/actions/workflows/jsoncheck.yml)\n[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/MCP_DAC.svg)](https://github.com/RobTillaart/MCP_DAC/issues)\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/MCP_DAC/blob/master/LICENSE)\n[![GitHub release](https://img.shields.io/github/release/RobTillaart/MCP_DAC.svg?maxAge=3600)](https://github.com/RobTillaart/MCP_DAC/releases)\n[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/MCP_DAC.svg)](https://registry.platformio.org/libraries/robtillaart/MCP_DAC)\n\n\n# MCP_DAC\n\nArduino library for Microchip SPI DAC's:  8, 10, 12 bits, 1, 2 channel.\n\n\n## Description\n\nThe MCP_DAC is a library for DAC's from Microchip in the MCP48xx en MCP49xx series.\nThe library is not tested with all different devices however stable.\n\nPlease post an issue if there are problems with a specific device.\n\n\n|  Type   |  Channels  |  Bits  |  MaxValue  |  Voltage reference  |\n|:--------|:----------:|:------:|:----------:|:-------------------:|\n| MCP4801 |     1      |   8    |    255     |   internal 2.048 V  |\n| MCP4802 |     2      |   8    |    255     |   internal 2.048 V  |\n| MCP4811 |     1      |   10   |    1023    |   internal 2.048 V  |\n| MCP4812 |     2      |   10   |    1023    |   internal 2.048 V  |\n| MCP4821 |     1      |   12   |    4095    |   internal 2.048 V  |\n| MCP4822 |     2      |   12   |    4095    |   internal 2.048 V  |\n| MCP4901 |     1      |   8    |    255     |   external          |\n| MCP4902 |     2      |   8    |    255     |   external          |\n| MCP4911 |     1      |   10   |    1023    |   external          |\n| MCP4912 |     2      |   10   |    1023    |   external          |\n| MCP4921 |     1      |   12   |    4095    |   external          |\n| MCP4922 |     2      |   12   |    4095    |   external          |\n\n\nThe output voltage of the MCP_DAC depends on the voltage supplied,\nwhich is in the range of 2.7V .. 5.5V. Check datasheet for the details.\n\n\n### 0.5.0 Breaking change\n\nVersion 0.5.0 introduced a breaking change to improve handling the SPI dependency.\nThe user has to call **SPI.begin()** or equivalent before calling **MCP.begin()**.\nOptionally the user can provide parameters to the **SPI.begin(...)**\n\n\n### 0.4.0 Breaking change\n\nThe version 0.4.0 has breaking changes in the interface. \nThe rationale is that the programming environment of the **Arduino ESP32 S3** \nboard uses a remapping by means of the include file **io_pin_remap.h**.\nThis file remaps the pins of several core Arduino functions. \nThe remapping is implemented by #define macros and these implement \"hard\" text \nreplacements without considering context. \nThe effect is that methods from this class (and several others) which have the same \nname as those Arduino core functions will be remapped into something not working.\n\nThe following library functions have been renamed:\n\n|  old name        |  new name    |  notes  |\n|:-----------------|:-------------|:--------|\n|  analogRead()    |  read()      |\n|  analogWrite()   |  write()     |\n|  pinMode()       |  pinMode1()  |\n|  digitalRead()   |  read1()     |\n|  digitalWrite()  |  write1()    |\n\n\n\n### 0.3.0 breaking change\n\nThe version 0.3.0 has breaking changes in the interface. The essence is that the\ndependency of Wire (ESP32 / RP2040) is removed from the library.\nThis makes it possible to support the **ESP32-S3** and other processors in the future.\nAlso it makes the library a bit simpler to maintain.\n\n\n### Related\n\n- https://github.com/RobTillaart/MCP_ADC\n- https://github.com/RobTillaart/DAC8550 1 channel, 16 bit\n- https://github.com/RobTillaart/DAC8551 1 channel, 16 bit\n- https://github.com/RobTillaart/DAC8552 2 channel, 16 bit\n- https://github.com/RobTillaart/DAC8554 4 channel, 16 bit\n- https://github.com/RobTillaart/MCP_DAC 1, 2 channel, 8,10,12 bit\n- https://github.com/RobTillaart/AD5680  (18 bit DAC)\n- https://github.com/RobTillaart/MAX520 I2C, 4, 8 channel, 8 bit\n- https://github.com/RobTillaart/MCP4725 I2C, 1 channel, 12 bit\n\n\n## Interface\n\n```cpp\n#include \"MCP_DAC.h\"\n```\n\n### Constructor\n\n- **MCP_DAC(SPIClassRP2040 \\*mySPI = \u0026SPI)** Constructor base class for RP2040, hardware SPI.\n- **MCP_DAC(SPIClass \\*mySPI = \u0026SPI)** Constructor base class other platforms, hardware SPI.\n- **MCP_DAC(uint8_t dataOut = 255, uint8_t clock = 255)** Constructor base class, software SPI.\nOther devices just use their name as class object e.g. **MCP4801()** with same parameters.\n- **begin(uint8_t select)** defines the select pin.\nThe select pin is used for device selection in case of multiple SPI devices.\n- **uint8_t channels()** returns the number of channels, 1 or 2.\n(note channel numbers are 0 or 1).\n- **uint16_t maxValue()** returns the maximum value that can be set.\nThis relates to the number of bits, see table above.\n\n\n### Gain\n\nIn **reset()** the gain is default set to 1x as that gives the lowest output voltages.\nThis is the safest option, although datasheet 4.1.1.1 states default = 2x.\n\n- **bool setGain(uint8_t gain = 1)** gain is 1 (default) or 2. \nValues of 0 or larger than 2 return false and won't change the current setting.\n- **uint8_t getGain()** returns gain set, default 1.\n\nNote: The analog output cannot go beyond the supply voltage.  \nSo if Vref is connected to 5V, gain = 2 will not output 10 Volts.\n\n\n### Write\n\n- **bool write(uint16_t value, uint8_t channel = 0)** writes value to channel.\nDefault for channel 0 as that works for the single DAC devices.\nThe value is limited to maxValue.\nReturns false in case of an invalid channel.\n- **uint16_t lastValue(uint8_t channel = 0)** returns last written value. \nDefault for channel 0 as that works for the single DAC devices.\n- **void setPercentage(float percentage, uint8_t channel = 0)** percentage = 0..100.0%.  \nWrapper around **write()**.\n- **float getPercentage(uint8_t channel = 0)** returns percentage. \nReads from cache.\n- **void fastWriteA(uint16_t value)** faster version to write to channel 0. \nDoes not check flags and does not update **lastValue()**\n- **void fastWriteB(uint16_t value)** faster version to write to channel 1. \nDoes not check flags and does not update **lastValue()**\n- **bool increment(uint8_t channel = 0)** returns true if channel is incremented, false otherwise.\n- **bool decrement(uint8_t channel = 0)** returns true if channel is decremented, false otherwise.\n\nFor fastest speed there is an example added **MCP4921_standalone.ino**.\nThat squeezes the most performance out of it for now.\nCode for the other MCP4xxx can be written in same way.\n\n\n### Shutdown\n\n- **void shutDown()** shuts down the device, optional one might need to **triggerLatch()**.\n- **bool isActive()** returns false if device is in shutdown mode.\nNote: any **write()** operation will set active to true again.\n\n\n### Hardware SPI\n\nTo be used only if one needs a specific speed.\nCheck datasheet for details.\n\n- **void setSPIspeed(uint32_t speed)** set SPI transfer rate.\n- **uint32_t getSPIspeed()** returns SPI transfer rate.\n\n\n### LDAC\n\n- **void setLatchPin(uint8_t latchPin)** defines the latchPin, this is optional. \nThe latchPin is used for simultaneous setting a value in both DAC registers.\nIt can also be used to synchronize the setting of multiple devices.\nNote the latchPin must be the same for all instances that need to be triggered together.\n- **triggerLatch()** toggles the defined latchPin, and all devices that are connected to it.\n\nNote: pre 0.2.0 versions have the LDAC signal incorrectly inverted.\n\n\n### Buffered\n\n**MCP49xxx series only**, see page 20 ==\u003e not functional for MCP48xx series.\n\n- **void setBufferedMode(bool mode = false)** set buffered mode on/off. \nThe default mode == false == unbuffered.\n- **bool getBufferedMode()** returns set value.\n\n\n### Debug\n\n- **void reset()** resets internal variables to initial value. (use with care!).\n- **bool usesHWSPI()** returns true if HW SPI is used.\n\n\n## ESP32 specific\n\nSeveral functions removed in 0.3.0 as they were too processor specific,\nand prevented support for the ESP32-S3.\n\n\n### ESP32 connections to MCP4922 (example)\n\nESP32 (first series) has **four** SPI peripherals from which two can be used.\n\nSPI0 and SPI1 are used to access flash memory. \nSPI2 and SPI3 are \"user\" SPI controllers a.k.a. HSPI and VSPI.\n\n\n|   MCP4922  |  HSPI = SPI2  |  VSPI = SPI3  |\n|:----------:|:-------------:|:-------------:|\n|    CS      |  SELECT = 15  |  SELECT = 5   |\n|    SCK     |  SCLK   = 14  |  SCLK   = 18  |\n|    SDI     |  MOSI   = 13  |  MOSI   = 23  |\n|  not used  |  MISO   = 12  |  MISO   = 19  |\n\nBy using different **SELECT** pins multiple DAC's can be controlled over one SPI bus.\n\n\nThe ESP32-S3 introduces user access to FSPI (which is reused from flash memory).\nDepending on ESP32 series e.g. HSPI is different, see code snippet below.\n\n```cpp\n#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3\n#define FSPI  0\n#define HSPI  1  \n#else  \n#define FSPI  1 //SPI bus attached to the flash (can use the same data lines but different SS)  \n#define HSPI  2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins  \n#if CONFIG_IDF_TARGET_ESP32  \n#define VSPI  3 //SPI bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins  \n#endif  \n#endif\n```\n\n## RP2040 specific\n\n### SPI port selection\n\nThe SPI Port selections happens in the hardware constructor with e.g. \u0026SPI, \u0026SPI1 etc.\nIn pre-0.3.0 an experimental feature **void setGPIOpins** was supported to adjust the\nhardware pins however this should now be handled by the user outside the library.\n\n\n### Pico connections to MCP4922 (example)\n\nThe RP2040 has **two** SPI peripherals from which two can be used.\n\nSPI (SPI0) and SPI1 can both be used to connect devices.\n\n\n| MCP4922  |   SPI / SPI0  |      SPI1     |\n|:--------:|:-------------:|:-------------:|\n|  CS      |  SELECT = 17  |  SELECT = 13  |\n|  SCK     |  SCLK   = 18  |  SCLK   = 14  |\n|  SDI     |  MOSI   = 19  |  MOSI   = 15  |\n| not used |  MISO   = 16  |  MISO   = 12  |\n\nBy using different **SELECT** pins multiple DAC's can be controlled over one SPI bus.\n\n\n## Operation\n\nSee examples\n\n\n## Future\n\n#### Must\n\n- test test test and ....\n- improve documentation.\n\n#### Should\n\n\n#### Could\n\n- functional names for magic masks.\n- refactor the API (how).\n\n#### Wont\n\n- **useSPI1** and **useHSPI** are functional identical indicators.\n  - how to refactor to a generic model? Should work for all libraries.\n  - int8_t HWSPIport = 0, 1, 2, 3, 4, ....  (-1 == SW SPI ?).\n    - numbers are not self-documenting.\n    - **selectSPIport(int)** ?\n  - would reduce conditional code.\n  - does not improve library\n\n\n## Support\n\nIf you appreciate my libraries, you can support the development and maintenance.\nImprove the quality of the libraries by providing issues and Pull Requests, or\ndonate through PayPal or GitHub sponsors.\n\nThank you,\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobTillaart%2FMCP_DAC","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRobTillaart%2FMCP_DAC","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobTillaart%2FMCP_DAC/lists"}