Skip to content
Josh Levine edited this page Jul 19, 2021 · 23 revisions

Welcome to the dac_shield wiki!

This is a work in progress. If you have a specific question which isn't answered here, please leave a comment and we'll add it in!

Hardware Overview

Rev4.5 Rev4 Rev3

Changelog

Rev 4.5

  • C2 - 47u, ceramic
  • Pluggable headers for power input and output connections

Rev4

  • Adjustment potentiometer - The direction of the adjustment pot has changed. In Rev 4, turning the pot clockwise increases gain and turning counter-clockwise decreases gain. The pot has also been labeled with a "+" and "-" in Rev 4
  • Minor routing changes, improved silkscreen size and clarity

Rev3

  • C2 - 22u, Tantalum
  • R7, R8, R9 - 2.2k

Connecting and Testing the Power DAC Shield

Equipment Needed:

  • Power DAC Shield
  • Dual-output power supply or two batteries
  • Arduino Uno, Duemilanove, Mega, or compatible board
  • Oscilloscope

Battery Wiring

The easiest way to get a dual output power supply is to connect two 9 or 12v batteries in series where the middle junction is ground.

Voltage drop across PTC fuse

The PTC fuse adds a non-trivial resistance in the output signal path. This causes voltage drop at the output that is equal to (the current being delivered) * (the resistance of the fuse). The typical resistance of the PTC seems to be about 8ohms, meaning that the voltage at the output will be about 0.8 volts lower than expected when the output is sourcing 100mA.

To fix this...

  1. If you have a purely resistive load, it it possible to compensate for this extra drop by increasing the value sent to the DAC.
  2. You can connect the feedback trace to the output side of the fuse rather than the opamp side.
  3. You can short out the fuse.

Basic Split Rail/Voltage Power Supply

The most common split rail power supply uses a 12V center tapped transformer, bridge rectifier and large filtering capacitors.

Connection to dual-output power supply

If you don't have a dual-output power supply, two single-output, isolated power supplies can be used TODO: Add notes about connecting the shield to two bench supplies

Connection Diagram

Programming

The heart of this shield is the MCP4921 (Datasheet). This DAC uses the SPI protocol and can be written to either using the hard SPI on the Uno or bit-banged on Mega. The first step is to write a method that can send a unsigned 16 integer to the DAC. Since this is a 12bit DAC, the max voltage will be 4095, zero volts is between 2047 and 2048, and the minimum (most negative) voltage is 0. The DAC is triggered one one of the 4 slave select pins (10,9,8,7) depending on the jumper. There are two ways these ping can be written, the first is to use the Arduino Digital Write.

//Method to write to the DAC
void writeMCP492x(uint16_t data,uint8_t slave_select) {
  // Take the top 4 bits of config and the top 4 valid bits (data is actually a 12 bit number) 
  //and OR them together
  uint8_t config = 0x30; 
  uint8_t top_msg = (config & 0xF0) | (0x0F & (data >> 8));
  
  // Take the bottom octet of data
  uint8_t lower_msg = (data & 0x00FF);
   
  // Select our DAC, Active LOW
  digitalWrite(slave_select, LOW);
 
  // Send first 8 bits
  SPI.transfer(top_msg);
  // Send second 8 bits
  SPI.transfer(lower_msg);
  
  //Deselect DAC
  digitalWrite(slave_select, HIGH);
}

While this is very straight forward, the digitalWrite method is fairly slow and can impact the ability to produce high frequency waves. An alternative is to write directly using the PORT. A good article explaining this can be found here.
For the Uno we can define Slave Select pins the following way:

#define SS0 (1 << 2) //Slave Select 0 PORTB
#define SS0PORT PORTB   

#define SS1 (1 << 1) //Slave Select 1 PORTB
#define SS1PORT PORTB

#define SS2 (1 << 0) //Slave Select 2 PORTB
#define SS2PORT PORTB

#define SS3 (1 << 7) //Slave Select 2 PORTD
#define SS3PORT PORTD

For the Mega the Slave Selects are defined the as the following.

#define SS0 (1 << 4) //Slave Select 0 PORTB
#define SS0PORT PORTB   

#define SS1 (1 << 6) //Slave Select 1 PORTH
#define SS1PORT PORTH

#define SS2 (1 << 5) //Slave Select 2 PORTH
#define SS2PORT PORTH

#define SS3 (1 << 4) //Slave Select 2 PORTH
#define SS3PORT PORTH

The WriteMCP Method will now be modified:

//Method to write to the DAC
void writeMCP492x(uint16_t data,uint8_t ss,volatile uint8_t* slave_port) {
  // Take the top 4 bits of config and the top 4 valid bits (data is actually a 12 bit number) 
  //and OR them together
  uint8_t config = 0x30; 
  uint8_t top_msg = (config & 0xF0) | (0x0F & (data >> 8));
  
  // Take the bottom octet of data
  uint8_t lower_msg = (data & 0x00FF);
   
  // Select our DAC, Active LOW
  *slave_port &= ~ss;
 
  // Send first 8 bits
  SPI.transfer(top_msg);
  // Send second 8 bits
  SPI.transfer(lower_msg);
  
  //Deselect DAC
  *slave_port |= ss;
}

Here are is of is an example of generating a square wave using the digital Digitalwrite version

while(1) {
  writeMCP492x(4097,10); //Write max voltage to shield 0 (SS pin 10)
  writeMCP492x(0,10); //Write min voltage to shield 0 (SS pin 10)
}

The same example using the direct port

while(1) {
  writeMCP492x(4097,10,SS0,SS0PORT); //Write max voltage to shield 0
  writeMCP492x(0,10,SS0,SS0PORT); //Write min voltage to shield 0
}

SAY what the frequency difference is