Using MCP49xx DACs with Arduino Due

I'm doing a project where I need 4 additional 10bit analog outputs besides the built in ones on the Due.

I've bought some MCP4912 and want to connect two of them using SPI. I've got the circuit wired up, but I'm having a tough time getting the libraries to work on the Due as they seem to only work on the AVR boards.

I've tried several libraries but none seem to work. The one I tried last gives me this error when I try to compile it for the Due:

Using the example code from the DAC_MCP49xx library:

//
// Example for the MCP49x2 *dual* DACs
// For the single MCP49x1 series, see the other bundled example sketch.
//
#include <SPI.h>         // Remember this line!
#include <DAC_MCP49xx.h>

// The Arduino pin used for the slave select / chip select
#define SS_PIN 10

// The Arduino pin used for the LDAC (output synchronization) feature
#define LDAC_PIN 7

// Set up the DAC. 
// First argument: DAC model (MCP4902, MCP4912, MCP4922)
// Second argument: SS pin (10 is preferred)
// (The third argument, the LDAC pin, can be left out if not used)
DAC_MCP49xx dac(DAC_MCP49xx::MCP4922, SS_PIN, LDAC_PIN);

void setup() {
  // Set the SPI frequency to 1 MHz (on 16 MHz Arduinos), to be safe.
  // DIV2 = 8 MHz works for me, though, even on a breadboard.
  // This is not strictly required, as there is a default setting.
  dac.setSPIDivider(SPI_CLOCK_DIV16);
  
  // Use "port writes", see the manual page. In short, if you use pin 10 for
  // SS (and pin 7 for LDAC, if used), this is much faster.
  // Also not strictly required (no setup() code is needed at all).
  dac.setPortWrite(true);

  // Pull the LDAC pin low automatically, to synchronize output
  // This is true by default, however.
  dac.setAutomaticallyLatchDual(true);
}

// Output something slow enough that a multimeter can pick it up.
// For MCP4902, use values below (but including) 255.
// For MCP4912, use values below (but including) 1023.
// For MCP4922, use values below (but including) 4095.
void loop() {
  dac.output2(4095, 0);
  delay(2500);
  dac.output2(0, 4095);
  delay(2500);

  // Or, to update one channel at a time:
  // dac.outputA(1023);
  // dac.outputB(384);
  // dac.latch(); // To synchonize the two outputs
}
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp: In member function 'boolean DAC_MCP49xx::setSPIDivider(int)':
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:122:5: error: duplicate case value
     case SPI_CLOCK_DIV128:
     ^
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:121:5: error: previously used here
     case SPI_CLOCK_DIV64:
     ^
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp: In member function 'void DAC_MCP49xx::shutdown()':
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:137:5: error: 'PORTB' was not declared in this scope
     PORTB &= 0xfb; // Clear PORTB pin 2 = arduino pin 10
     ^
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:150:5: error: 'PORTB' was not declared in this scope
     PORTB |= (1 << 2); // set PORTB pin 2 = arduino pin 10
     ^
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp: In member function 'void DAC_MCP49xx::_output(short unsigned int, DAC_MCP49xx::Channel)':
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:168:5: error: 'PORTB' was not declared in this scope
     PORTB &= 0xfb; // Clear PORTB pin 2 = arduino pin 10
     ^
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:185:5: error: 'PORTB' was not declared in this scope
     PORTB |= (1 << 2); // set PORTB pin 2 = arduino pin 10
     ^
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp: In member function 'void DAC_MCP49xx::latch()':
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:242:5: error: 'PORTD' was not declared in this scope
     PORTD &= ~(1 << 7); // Uno: digital pin 7; Mega: digital pin 38
     ^
exit status 1
Error compiling for board Arduino Due (Programming Port).

Anything I can do to get this working on a Due or is there a compatible library available? I've looked of course, but I couldn't find one.

Remove the setSPIDivider() method from the library, it's completely unnecessary.

Hi pylon. Thank you for replying.

I have commented out everything related to "setSPI" in both the library and the example sketch, but I still get the following errors when trying to compile for Due:

/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp: In member function 'void DAC_MCP49xx::shutdown()':
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:138:5: error: 'PORTB' was not declared in this scope
     PORTB &= 0xfb; // Clear PORTB pin 2 = arduino pin 10
     ^
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:151:5: error: 'PORTB' was not declared in this scope
     PORTB |= (1 << 2); // set PORTB pin 2 = arduino pin 10
     ^
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp: In member function 'void DAC_MCP49xx::_output(short unsigned int, DAC_MCP49xx::Channel)':
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:169:5: error: 'PORTB' was not declared in this scope
     PORTB &= 0xfb; // Clear PORTB pin 2 = arduino pin 10
     ^
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:186:5: error: 'PORTB' was not declared in this scope
     PORTB |= (1 << 2); // set PORTB pin 2 = arduino pin 10
     ^
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp: In member function 'void DAC_MCP49xx::latch()':
/Users/konsolkongen/Documents/Arduino/libraries/DAC_MCP49xx/DAC_MCP49xx.cpp:243:5: error: 'PORTD' was not declared in this scope
     PORTD &= ~(1 << 7); // Uno: digital pin 7; Mega: digital pin 38
     ^
exit status 1
Error compiling for board Arduino Due (Programming Port).

Any further help or suggestions will be greatly appreciated :slight_smile:

This line:

PORTB &= 0xfb; // Clear PORTB pin 2 = arduino pin 10

is typically for an AVR and won't work for the ARM Sam3x of the DUE.

Search in the DUE sub forum for example sketches to drive digital pins with registers

Hi ard_newbie, thank you for the help.

Am I correct in thinking that I only need to change those lines to something equivalent for the Due and it should work? Or will I have to effectively rewrite the entire library? That would probably be much too complicated for me at this time :smiley:

Konsolkongen:
Am I correct in thinking that I only need to change those lines to something equivalent for the Due and it should work? Or will I have to effectively rewrite the entire library?

I don't know, try firstly to change these lines and see what you get.

Remove that line

  dac.setPortWrite(true);

It activates an AVR-only extension of the library. If you leave that option set to false the library uses the compatible function.