Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for MCP4725’s power-down mode #9

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 54 additions & 14 deletions Adafruit_MCP4725.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@
@brief Instantiates a new MCP4725 class @brief Instantiates a new MCP4725 class
*/ */
/**************************************************************************/ /**************************************************************************/
Adafruit_MCP4725::Adafruit_MCP4725() { Adafruit_MCP4725::Adafruit_MCP4725(uint8_t addressPin) {
_addressPin = addressPin;

if(_addressPin != MCP4725_ADDRESS_PIN_DISABLED) {
pinMode(_addressPin, OUTPUT);
}
} }


/**************************************************************************/ /**************************************************************************/
Expand All @@ -44,7 +49,6 @@ Adafruit_MCP4725::Adafruit_MCP4725() {
void Adafruit_MCP4725::begin(uint8_t addr) { void Adafruit_MCP4725::begin(uint8_t addr) {
_i2caddr = addr; _i2caddr = addr;
Wire.begin(); Wire.begin();

} }


/**************************************************************************/ /**************************************************************************/
Expand All @@ -62,25 +66,61 @@ void Adafruit_MCP4725::begin(uint8_t addr) {
after power-down or reset. after power-down or reset.
*/ */
/**************************************************************************/ /**************************************************************************/
void Adafruit_MCP4725::setVoltage( uint16_t output, bool writeEEPROM ) void Adafruit_MCP4725::setVoltage(uint16_t output, bool writeEEPROM) {
{ uint8_t controlBits = writeEEPROM ? MCP4726_CMD_WRITEDACEEPROM : MCP4726_CMD_WRITEDAC;
writeI2cPacket(controlBits, output);
}

void Adafruit_MCP4725::setAddressPin(bool enable) {
if(_addressPin != MCP4725_ADDRESS_PIN_DISABLED) {
digitalWrite(_addressPin, enable);
}
}

void Adafruit_MCP4725::writeI2cPacket(uint8_t controlBits, uint16_t dataBits) {
setAddressPin(true);

#ifdef TWBR #ifdef TWBR
uint8_t twbrback = TWBR; uint8_t twbrback = TWBR;
TWBR = ((F_CPU / 400000L) - 16) / 2; // Set I2C frequency to 400kHz TWBR = ((F_CPU / 400000L) - 16) / 2; // Set I2C frequency to 400kHz
#endif #endif
Wire.beginTransmission(_i2caddr); Wire.beginTransmission(_i2caddr);
if (writeEEPROM) Wire.write(controlBits);
{ Wire.write(dataBits / 16); // Upper data bits (D11.D10.D9.D8.D7.D6.D5.D4)
Wire.write(MCP4726_CMD_WRITEDACEEPROM); Wire.write((dataBits % 16) << 4); // Lower data bits (D3.D2.D1.D0.x.x.x.x)
}
else
{
Wire.write(MCP4726_CMD_WRITEDAC);
}
Wire.write(output / 16); // Upper data bits (D11.D10.D9.D8.D7.D6.D5.D4)
Wire.write((output % 16) << 4); // Lower data bits (D3.D2.D1.D0.x.x.x.x)
Wire.endTransmission(); Wire.endTransmission();
#ifdef TWBR #ifdef TWBR
TWBR = twbrback; TWBR = twbrback;
#endif #endif

setAddressPin(false);
}

float Adafruit_MCP4725::setNearestActualVoltage(uint16_t desiredOutputMilliVolts, uint16_t vrefMilliVolts, bool writeEEPROM) {
float dacStepsPerMillivolt = 4095.0 / vrefMilliVolts;
uint16_t nearestDacInputCodeForVoltage = round(dacStepsPerMillivolt * desiredOutputMilliVolts);

float nearestVoltage = (vrefMilliVolts / 4095.0) * nearestDacInputCodeForVoltage;

setVoltage(nearestDacInputCodeForVoltage, writeEEPROM);
return nearestVoltage;
}

void Adafruit_MCP4725::powerDown(uint8_t loadResistance, bool writeEEPROM) {
uint8_t controlBits = writeEEPROM ? MCP4726_CMD_WRITEDACEEPROM : MCP4726_CMD_WRITEDAC;

switch (loadResistance) {
case MCP4725_OUTPUT_LOAD_RESISTANCE_1K:
controlBits |= 0x2;
break;
case MCP4725_OUTPUT_LOAD_RESISTANCE_100K:
controlBits |= 0x4;
break;
case MCP4725_OUTPUT_LOAD_RESISTANCE_500K:
default:
controlBits |= 0x6;
break;
}

writeI2cPacket(controlBits, 0x0);
} }
23 changes: 19 additions & 4 deletions Adafruit_MCP4725.h
Original file line number Original file line Diff line number Diff line change
@@ -1,3 +1,6 @@
#ifndef adafruit_mcp4725_h
#define adafruit_mcp4725_h

/**************************************************************************/ /**************************************************************************/
/*! /*!
@file Adafruit_MCP4725.h @file Adafruit_MCP4725.h
Expand Down Expand Up @@ -25,15 +28,27 @@


#include <Wire.h> #include <Wire.h>


#define MCP4726_CMD_WRITEDAC (0x40) // Writes data to the DAC #define MCP4726_CMD_WRITEDAC 0x40 // Writes data to the DAC
#define MCP4726_CMD_WRITEDACEEPROM (0x60) // Writes data to the DAC and the EEPROM (persisting the assigned value after reset) #define MCP4726_CMD_WRITEDACEEPROM 0x60 // Writes data to the DAC and the EEPROM (persisting the assigned value after reset)
#define MCP4725_OUTPUT_LOAD_RESISTANCE_1K 0
#define MCP4725_OUTPUT_LOAD_RESISTANCE_100K 1
#define MCP4725_OUTPUT_LOAD_RESISTANCE_500K 2
#define MCP4725_ADDRESS_PIN_DISABLED 255


class Adafruit_MCP4725{ class Adafruit_MCP4725{
public: public:
Adafruit_MCP4725(); Adafruit_MCP4725(uint8_t addressPin = MCP4725_ADDRESS_PIN_DISABLED);
void begin(uint8_t a); void begin(uint8_t a);
void setVoltage( uint16_t output, bool writeEEPROM ); void setVoltage(uint16_t output, bool writeEEPROM);
float setNearestActualVoltage(uint16_t desiredOutputMilliVolts, uint16_t vrefMilliVolts, bool writeEEPROM);
void powerDown(uint8_t loadResistance, bool writeEEPROM);


private: private:
uint8_t _i2caddr; uint8_t _i2caddr;
uint8_t _addressPin;

void writeI2cPacket(uint8_t controlBits, uint16_t data);
void setAddressPin(bool enable);
}; };

#endif
58 changes: 58 additions & 0 deletions examples/multiaddressing/multiaddressing.ino
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,58 @@
/**************************************************************************/
/*!
@file multiaddressing.ino
@author Alex Mitchell (MitchellSoft Technology Ltd.)
@license BSD (see license.txt)

This example shows how to address multiple MCP4725s on the same I2C bus.

One Arduino pin is required per MCP4725, which is used like a chip-select
pin. For this reason, it only makes sense to address MCP4725s in this
way if you need more than two DACs in your project and they all have the
same address. Otherwise, you will be using up Arduino pins needlessly.

This is an example sketch for the Adafruit MCP4725 breakout board
----> http://www.adafruit.com/products/935

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
*/
/**************************************************************************/
#include <Wire.h>
#include <Adafruit_MCP4725.h>

Adafruit_MCP4725 dac1(2); // ADDR pin of MCP4725 connected to Arduino pin 2
Adafruit_MCP4725 dac2(3); // ADDR pin of MCP4725 connected to Arduino pin 3
Adafruit_MCP4725 dac3(4); // ADDR pin of MCP4725 connected to Arduino pin 4

void setup(void) {
Serial.begin(9600);
Serial.println("Hello!");

// The begin method must be called with the address of the MCP4725 when ADDR pin is tied to VCC
// For Adafruit MCP4725A1 this is 0x63
// For MCP4725A0 this is 0x61
// For MCP4725A2 this is 0x65
dac1.begin(0x63);
dac2.begin(0x63);
dac3.begin(0x63);

Serial.println("Example sketch demonstrating addressing multiple MCP4725s");
}

void loop(void) {
Serial.println("Setting 3 different lower voltage outputs");
dac1.setVoltage(100, false);
dac2.setVoltage(200, false);
dac3.setVoltage(300, false);

delay(5000);

Serial.println("Setting 3 different higer voltage outputs");
dac1.setVoltage(1000, false);
dac2.setVoltage(2000, false);
dac3.setVoltage(3000, false);

delay(5000);
}
59 changes: 59 additions & 0 deletions examples/powerdown/powerdown.ino
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,59 @@
/**************************************************************************/
/*!
@file powerdown.ino
@author Alex Mitchell (MitchellSoft Technology Ltd.)
@license BSD (see license.txt)

This example shows how to put the MCP4725 into power-down mode.
During power-down mode, the device draws about 60 nA, compared
against 200 µA (typical) when running in normal mode.

When in power-down mode, the output pin is connected to ground via
a configurable pull-down resistance of either 1K, 100K, or 500K Ohms.

To bring the device out of power-down mode, simply call setVoltage
(it will also wake up if an I2C General Call Wake-Up Command is sent
on the I2C bus).

This is an example sketch for the Adafruit MCP4725 breakout board
----> http://www.adafruit.com/products/935

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
*/
/**************************************************************************/
#include <Wire.h>
#include <Adafruit_MCP4725.h>

Adafruit_MCP4725 dac;

void setup(void) {
Serial.begin(9600);
Serial.println("Hello!");

// For Adafruit MCP4725A1 the address is 0x62 (default) or 0x63 (ADDR pin tied to VCC)
// For MCP4725A0 the address is 0x60 or 0x61
// For MCP4725A2 the address is 0x64 or 0x65
dac.begin(0x62);

Serial.println("Example sketch demonstrating the MCP4725 power-down mode");
}

void loop(void) {
Serial.println("Putting MCP4725 to sleep. Output pin connected to ground via 1K Ohm resistance.");
dac.powerDown(MCP4725_OUTPUT_LOAD_RESISTANCE_1K, false);
delay(5000);

Serial.println("Switching sleep mode. Output pin now connected ot ground via 100K Ohm resistance.");
dac.powerDown(MCP4725_OUTPUT_LOAD_RESISTANCE_100K, false);
delay(5000);

Serial.println("Waking device up by setting an output voltage.");
dac.setVoltage(1000, false);
delay(5000);

Serial.println("Putting MCP4725 to sleep again. Output pin connected to ground via 500K Ohm resistance.");
dac.powerDown(MCP4725_OUTPUT_LOAD_RESISTANCE_500K, false);
delay(5000);
}
67 changes: 67 additions & 0 deletions examples/setactualvoltage/setactualvoltage.ino
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,67 @@
/**************************************************************************/
/*!
@file setactualvoltage.ino
@author Alex Mitchell (MitchellSoft Technology Ltd.)
@license BSD (see license.txt)

This example shows how to set a voltage on the MCP4725 by specifying
the output voltage in millivolts, rather than calculating the raw output
value required by the MCP4725.

The MCP4725 has a resolution of 12 bits (4096 steps, from 0 to 4095), so
it can get close, but not always output exactly the voltage requested.
In case this matters in your application, setNearestActualVoltage() returns
the value of the nearest voltage that could be generated by the MCP4725
so that your code can handle any discrepancies.

The reference voltage must be known and set for this to work. The
reference voltage will often be 5V (5000mV), but especially when
running from USB power, it may be slightly off 5V.
Any difference between the reference voltage and the value specified
will create an inaccuracy in the voltage that the MCP4725 outputs.

This is an example sketch for the Adafruit MCP4725 breakout board
----> http://www.adafruit.com/products/935

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
*/
/**************************************************************************/
#include <Wire.h>
#include <Adafruit_MCP4725.h>

static const int REFERENCE_VOLTAGE_mV = 5000;
static const bool WRITE_EEPROM = false;

Adafruit_MCP4725 dac;

void setup(void) {
Serial.begin(9600);
Serial.println("Hello!");

// For Adafruit MCP4725A1 the address is 0x62 (default) or 0x63 (ADDR pin tied to VCC)
// For MCP4725A0 the address is 0x60 or 0x61
// For MCP4725A2 the address is 0x64 or 0x65
dac.begin(0x62);

Serial.println("Example sketch demonstrating how to set a voltage with the MCP4725");
}

void loop(void) {
Serial.println("Outputting 0V");
dac.setNearestActualVoltage(0, REFERENCE_VOLTAGE_mV, WRITE_EEPROM);
delay(5000);

Serial.println("Requesting 2500mV (2.5V)");
float nearestMillivoltsPossible = dac.setNearestActualVoltage(2500, REFERENCE_VOLTAGE_mV, WRITE_EEPROM);
Serial.print("Nearest value to 2500mV that the MCP4725 could output is: ");
Serial.print(nearestMillivoltsPossible);
Serial.println("mV");
delay(5000);

Serial.println("Outputting 5000mV (5V)");
dac.setNearestActualVoltage(5000, REFERENCE_VOLTAGE_mV, WRITE_EEPROM);
delay(5000);
Serial.println("******");
}
2 changes: 1 addition & 1 deletion examples/sinewave/sinewave.ino
Original file line number Original file line Diff line number Diff line change
@@ -1,6 +1,6 @@
/**************************************************************************/ /**************************************************************************/
/*! /*!
@file sinewave.pde @file sinewave.ino
@author Adafruit Industries @author Adafruit Industries
@license BSD (see license.txt) @license BSD (see license.txt)


Expand Down
2 changes: 1 addition & 1 deletion examples/trianglewave/trianglewave.ino
Original file line number Original file line Diff line number Diff line change
@@ -1,6 +1,6 @@
/**************************************************************************/ /**************************************************************************/
/*! /*!
@file trianglewave.pde @file trianglewave.ino
@author Adafruit Industries @author Adafruit Industries
@license BSD (see license.txt) @license BSD (see license.txt)


Expand Down