mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.3.7 MCP4725
This commit is contained in:
parent
7a35e28ddd
commit
87b2588e4a
@ -5,13 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.3.7] - 2023-08-25
|
||||
- fix #27 - support for multiple MCP4725
|
||||
- add two examples.
|
||||
- update readme.md
|
||||
- minor edits
|
||||
|
||||
|
||||
## [0.3.6] - 2023-07-19
|
||||
- fix #25 - buffer overflow in examples
|
||||
- update keywords.txt
|
||||
- moved code to .cpp
|
||||
- moved code to MCP4725.cpp
|
||||
- minor edits
|
||||
|
||||
|
||||
## [0.3.5] - 2023-01-17
|
||||
- update GitHub actions
|
||||
- update license
|
||||
|
@ -2,10 +2,8 @@
|
||||
// FILE: MCP4725.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: Arduino library for 12 bit I2C DAC - MCP4725
|
||||
// VERSION: 0.3.6
|
||||
// VERSION: 0.3.7
|
||||
// URL: https://github.com/RobTillaart/MCP4725
|
||||
//
|
||||
// HISTORY see changelog.md
|
||||
|
||||
|
||||
#include "MCP4725.h"
|
||||
@ -31,6 +29,7 @@ MCP4725::MCP4725(const uint8_t deviceAddress, TwoWire *wire)
|
||||
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
|
||||
bool MCP4725::begin(const uint8_t dataPin, const uint8_t clockPin)
|
||||
{
|
||||
_wire = &Wire;
|
||||
@ -48,8 +47,10 @@ bool MCP4725::begin(const uint8_t dataPin, const uint8_t clockPin)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (ARDUINO_ARCH_RP2040)
|
||||
|
||||
bool MCP4725::begin(int sda, int scl)
|
||||
@ -129,6 +130,17 @@ int MCP4725::writeDAC(const uint16_t value, const bool EEPROM)
|
||||
}
|
||||
|
||||
|
||||
// ready checks if the last write to EEPROM has been written.
|
||||
// until ready all writes to the MCP4725 are ignored!
|
||||
bool MCP4725::ready()
|
||||
{
|
||||
yield();
|
||||
uint8_t buffer[1];
|
||||
_readRegister(buffer, 1);
|
||||
return ((buffer[0] & 0x80) > 0);
|
||||
}
|
||||
|
||||
|
||||
uint16_t MCP4725::readDAC()
|
||||
{
|
||||
while(!ready());
|
||||
@ -181,7 +193,7 @@ uint8_t MCP4725::readPowerDownModeEEPROM()
|
||||
|
||||
uint8_t MCP4725::readPowerDownModeDAC()
|
||||
{
|
||||
while(!ready()); // TODO needed?
|
||||
while(!ready()); // TODO needed?
|
||||
uint8_t buffer[1];
|
||||
_readRegister(buffer, 1);
|
||||
uint8_t value = (buffer[0] >> 1) & 0x03;
|
||||
@ -195,7 +207,7 @@ uint8_t MCP4725::readPowerDownModeDAC()
|
||||
int MCP4725::powerOnReset()
|
||||
{
|
||||
int rv = _generalCall(MCP4725_GC_RESET);
|
||||
_lastValue = readDAC(); // update cache to actual value;
|
||||
_lastValue = readDAC(); // update cache to actual value;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -206,7 +218,7 @@ int MCP4725::powerOnReset()
|
||||
int MCP4725::powerOnWakeUp()
|
||||
{
|
||||
int rv = _generalCall(MCP4725_GC_WAKEUP);
|
||||
_powerDownMode = readPowerDownModeDAC(); // update to actual value;
|
||||
_powerDownMode = readPowerDownModeDAC(); // update to actual value;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -215,7 +227,7 @@ int MCP4725::powerOnWakeUp()
|
||||
int MCP4725::_writeFastMode(const uint16_t value)
|
||||
{
|
||||
uint8_t l = value & 0xFF;
|
||||
uint8_t h = ((value / 256) & 0x0F); // set C0 = C1 = 0, no PDmode
|
||||
uint8_t h = ((value / 256) & 0x0F); // set C0 = C1 = 0, no PDmode
|
||||
h = h | (_powerDownMode << 4);
|
||||
|
||||
_wire->beginTransmission(_deviceAddress);
|
||||
@ -225,17 +237,6 @@ int MCP4725::_writeFastMode(const uint16_t value)
|
||||
}
|
||||
|
||||
|
||||
// ready checks if the last write to EEPROM has been written.
|
||||
// until ready all writes to the MCP4725 are ignored!
|
||||
bool MCP4725::ready()
|
||||
{
|
||||
yield();
|
||||
uint8_t buffer[1];
|
||||
_readRegister(buffer, 1);
|
||||
return ((buffer[0] & 0x80) > 0);
|
||||
}
|
||||
|
||||
|
||||
// PAGE 19 DATASHEET
|
||||
// reg = MCP4725_DAC | MCP4725_EEPROM
|
||||
int MCP4725::_writeRegisterMode(const uint16_t value, uint8_t reg)
|
||||
@ -261,9 +262,9 @@ uint8_t MCP4725::_readRegister(uint8_t* buffer, const uint8_t length)
|
||||
{
|
||||
_wire->beginTransmission(_deviceAddress);
|
||||
int rv = _wire->endTransmission();
|
||||
if (rv != 0) return 0; // error
|
||||
if (rv != 0) return 0; // error
|
||||
|
||||
// readbytes will always be equal or smaller to length
|
||||
// readBytes will always be equal or smaller to length
|
||||
uint8_t readBytes = _wire->requestFrom(_deviceAddress, length);
|
||||
uint8_t cnt = 0;
|
||||
while (cnt < readBytes)
|
||||
@ -277,7 +278,7 @@ uint8_t MCP4725::_readRegister(uint8_t* buffer, const uint8_t length)
|
||||
// name comes from datasheet
|
||||
int MCP4725::_generalCall(const uint8_t gc)
|
||||
{
|
||||
_wire->beginTransmission(0); // _deviceAddress
|
||||
_wire->beginTransmission(0); // _deviceAddress
|
||||
_wire->write(gc);
|
||||
return _wire->endTransmission();
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// FILE: MCP4725.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: Arduino library for 12 bit I2C DAC - MCP4725
|
||||
// VERSION: 0.3.6
|
||||
// VERSION: 0.3.7
|
||||
// URL: https://github.com/RobTillaart/MCP4725
|
||||
//
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#include "Arduino.h"
|
||||
|
||||
|
||||
#define MCP4725_VERSION (F("0.3.6"))
|
||||
#define MCP4725_VERSION (F("0.3.7"))
|
||||
|
||||
|
||||
// CONSTANTS
|
||||
@ -41,7 +41,9 @@ public:
|
||||
explicit MCP4725(const uint8_t deviceAddress, TwoWire *wire = &Wire);
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
|
||||
bool begin(const uint8_t dataPin, const uint8_t clockPin);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (ARDUINO_ARCH_RP2040)
|
||||
@ -60,16 +62,22 @@ public:
|
||||
uint16_t getValue();
|
||||
|
||||
|
||||
// 0..100.0% - no input check.
|
||||
// 0..100.0% - input checked.
|
||||
// will set the closest integer value in range 0..4095
|
||||
int setPercentage(float percentage = 0);
|
||||
// due to rounding the returned value can differ slightly.
|
||||
float getPercentage();
|
||||
|
||||
|
||||
// unfortunately it is not possible to write a different value
|
||||
// to the DAC and EEPROM simultaneously or write EEPROM only.
|
||||
int writeDAC(const uint16_t value, const bool EEPROM = false);
|
||||
// ready checks if the last write to EEPROM has been written.
|
||||
// until ready all writes to the MCP4725 are ignored!
|
||||
bool ready();
|
||||
uint16_t readDAC();
|
||||
uint16_t readEEPROM();
|
||||
uint32_t getLastWriteEEPROM();
|
||||
uint32_t getLastWriteEEPROM(); // returns timestamp
|
||||
|
||||
|
||||
// experimental
|
||||
|
@ -2,8 +2,11 @@
|
||||
[![Arduino CI](https://github.com/RobTillaart/MCP4725/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
|
||||
[![Arduino-lint](https://github.com/RobTillaart/MCP4725/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/MCP4725/actions/workflows/arduino-lint.yml)
|
||||
[![JSON check](https://github.com/RobTillaart/MCP4725/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/MCP4725/actions/workflows/jsoncheck.yml)
|
||||
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/MCP4725.svg)](https://github.com/RobTillaart/MCP4725/issues)
|
||||
|
||||
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/MCP4725/blob/master/LICENSE)
|
||||
[![GitHub release](https://img.shields.io/github/release/RobTillaart/MCP4725.svg?maxAge=3600)](https://github.com/RobTillaart/MCP4725/releases)
|
||||
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/MCP4725.svg)](https://registry.platformio.org/libraries/robtillaart/MCP4725)
|
||||
|
||||
|
||||
# MCP4725
|
||||
@ -23,6 +26,10 @@ of 2.7V .. 5.5V. Check datasheet for the details.
|
||||
|
||||
## Interface
|
||||
|
||||
```cpp
|
||||
#include "MCP4725.h"
|
||||
```
|
||||
|
||||
### Constructor
|
||||
|
||||
- **MCP4725(uint8_t deviceAddress, TwoWire \*wire = &Wire)** Constructor, needs I2C address, optional set Wire bus
|
||||
@ -32,7 +39,7 @@ Returns true if deviceAddress can be found on the I2C bus.
|
||||
- **bool isConnected()** returns true if device (address) can be seen on the I2C bus.
|
||||
|
||||
|
||||
### base
|
||||
### Base
|
||||
|
||||
- **int setValue(uint16_t value = 0)** value = 0 .. 4095.
|
||||
Uses writeFastMode and does not write to EEPROM.
|
||||
@ -114,9 +121,44 @@ Check RP2040 Pinout for compatible pins.
|
||||
When Wire1 is used, it needs to be specified in the constructor with "&Wire1"
|
||||
|
||||
|
||||
## Operation
|
||||
## Multi devices on one I2C bus
|
||||
|
||||
See examples
|
||||
Normal one can have 1 to 8 MCP4725 on a I2C bus. This depends on the right
|
||||
choice of devices as 2 address bits are hard coded in the device.
|
||||
See paragraph 7.2 datasheet + address notes section above.
|
||||
|
||||
But one cannot always order the right devices.
|
||||
Especially breakout boards often have the same address-range.
|
||||
|
||||
|
||||
#### TCA9548 I2C multiplexer
|
||||
|
||||
Use an I2C multiplexer to create multiple "I2C channels" which allows then
|
||||
up to 8 devices per channel. Selecting the right devices includes setting
|
||||
the I2C multiplexer to the right channel to address the right device.
|
||||
This implies access is a bit slower and uses more code.
|
||||
|
||||
One (TCA9548) multiplexer allows one to control up to 64 MCP4725's.
|
||||
|
||||
- https://github.com/RobTillaart/TCA9548
|
||||
|
||||
Note that other multiplexers do exist.
|
||||
|
||||
|
||||
#### Use A0 address pin as a SELECT pin
|
||||
|
||||
(Experimental)
|
||||
Need to do more tests to see how this solution behaves in practice.
|
||||
Verified to work - see https://forum.arduino.cc/t/using-digital-pins-to-control-two-mcp4725-modules/1161482/7.
|
||||
|
||||
The assumption here is that the devices are all from the same address range.
|
||||
|
||||
You can control multiple MCP4725 over the hardware I2C bus with an extra IO pin per device.
|
||||
- Connect the address pin of every MCP4725 to an IO pin which will work as a **SELECT** pin.
|
||||
- Keep all IO pins **LOW** so the all have effectively the same address == 0x60.
|
||||
- To select a specific MCP4725 you set the related IO pin to **HIGH** and that one will have address == 0x61.
|
||||
- Now you can access and control the associated MCP4725 with address 0x61.
|
||||
- See **mcp4725_multiple.ino** and **mcp4725_multiple_minimal.ino**
|
||||
|
||||
|
||||
## Future
|
||||
@ -128,9 +170,18 @@ See examples
|
||||
#### Should
|
||||
|
||||
- test the powerDown modes / functions.
|
||||
- test A0 (address bit) as SELECT pin.
|
||||
|
||||
#### Could
|
||||
|
||||
- extend unit tests
|
||||
|
||||
|
||||
## 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,
|
||||
|
||||
|
@ -0,0 +1,92 @@
|
||||
//
|
||||
// FILE: mcp4725_multiple.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: test MCP4725 lib
|
||||
// URL: https://github.com/RobTillaart/MCP4725
|
||||
//
|
||||
// simple example to control more than 2 devices over
|
||||
// a single I2C bus without multiplexer.
|
||||
// The A0 address pin is used as a SELECT pin.
|
||||
//
|
||||
// Every MCP device has its own object and can be
|
||||
// accessed accordingly.
|
||||
//
|
||||
// To be tested / confirmed working with hardware.
|
||||
|
||||
|
||||
#include "Wire.h"
|
||||
#include "MCP4725.h"
|
||||
|
||||
// assume the 4 devices have the same A1 and A2
|
||||
// hard-coded address bits. (par 7.2 datasheet)
|
||||
// we will access all devices with as 0x63.
|
||||
MCP4725 MCP0(0x63);
|
||||
MCP4725 MCP1(0x63);
|
||||
MCP4725 MCP2(0x63);
|
||||
MCP4725 MCP3(0x63);
|
||||
|
||||
// connect the select pins to the A0 pins
|
||||
// of the four MCP4725's
|
||||
uint8_t selectPin[4] = { 4, 5, 6, 7 };
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("MCP4725_VERSION: ");
|
||||
Serial.println(MCP4725_VERSION);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
pinMode(selectPin[i], OUTPUT);
|
||||
digitalWrite(selectPin[i], LOW);
|
||||
}
|
||||
|
||||
select(0);
|
||||
MCP0.begin();
|
||||
select(1);
|
||||
MCP1.begin();
|
||||
select(2);
|
||||
MCP2.begin();
|
||||
select(3);
|
||||
MCP3.begin();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void select(uint8_t nr)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (i != nr) digitalWrite(selectPin[i], LOW);
|
||||
else digitalWrite(selectPin[i], HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
int x = analogRead(A0); // to create an output value.
|
||||
|
||||
// select one DAC and set the value.
|
||||
select(0);
|
||||
MCP0.setValue(x);
|
||||
delay(250);
|
||||
|
||||
select(1);
|
||||
MCP1.setValue(x * 2);
|
||||
delay(250);
|
||||
|
||||
select(2);
|
||||
MCP2.setValue(x * 3);
|
||||
delay(250);
|
||||
|
||||
select(3);
|
||||
MCP3.setValue(x * 4);
|
||||
delay(250);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,84 @@
|
||||
//
|
||||
// FILE: mcp4725_multiple_minimal.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: test MCP4725 lib
|
||||
// URL: https://github.com/RobTillaart/MCP4725
|
||||
//
|
||||
// simple example to control more than 2 devices over
|
||||
// a single I2C bus without multiplexer.
|
||||
// The A0 address pin is used as a SELECT pin.
|
||||
//
|
||||
// One MCP4725 object is used to control 4 different devices.
|
||||
// drawback is that you can only read back the last write.
|
||||
//
|
||||
// To be tested / confirmed working with hardware.
|
||||
|
||||
|
||||
#include "Wire.h"
|
||||
#include "MCP4725.h"
|
||||
|
||||
// assume the 4 devices have the same A1 and A2
|
||||
// hard-coded address bits. (par 7.2 datasheet)
|
||||
// we will access all devices with as 0x63.
|
||||
MCP4725 MCP(0x63); // 0x62 or 0x63
|
||||
|
||||
|
||||
// connect the select pins to the A0 pins
|
||||
// of the four MCP4725's
|
||||
uint8_t selectPin[4] = { 4, 5, 6, 7 };
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("MCP4725_VERSION: ");
|
||||
Serial.println(MCP4725_VERSION);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
pinMode(selectPin[i], OUTPUT);
|
||||
digitalWrite(selectPin[i], LOW);
|
||||
}
|
||||
|
||||
select(0);
|
||||
MCP.begin();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void select(uint8_t nr)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (i != nr) digitalWrite(selectPin[i], LOW);
|
||||
else digitalWrite(selectPin[i], HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
int x = analogRead(A0); // to create an output value.
|
||||
|
||||
// select one DAC and set the value.
|
||||
select(0);
|
||||
MCP.setValue(x);
|
||||
delay(250);
|
||||
|
||||
select(1);
|
||||
MCP.setValue(x * 2);
|
||||
delay(250);
|
||||
|
||||
select(2);
|
||||
MCP.setValue(x * 3);
|
||||
delay(250);
|
||||
|
||||
select(3);
|
||||
MCP.setValue(x * 4);
|
||||
delay(250);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
@ -15,9 +15,9 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/MCP4725.git"
|
||||
},
|
||||
"version": "0.3.6",
|
||||
"version": "0.3.7",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"frameworks": "*",
|
||||
"platforms": "*",
|
||||
"headers": "MCP4725.h"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=MCP4725
|
||||
version=0.3.6
|
||||
version=0.3.7
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for 12 bit I2C DAC - MCP4725
|
||||
|
Loading…
Reference in New Issue
Block a user