Tutorial.SPIDigitalPot History

Show minor edits - Show changes to markup

November 04, 2013, at 09:07 AM by Scott Fitzgerald -
Changed lines 45-46 from:
to:
November 16, 2011, at 04:38 AM by Scott Fitzgerald -
Changed lines 60-61 from:
to:
September 22, 2011, at 02:54 PM by Tom Igoe -
Changed lines 69-70 from:

'''original tutorial by Heather Dewey-Hagborg, update by Tom Igoe and Christian Cerrito'''

to:

original tutorial by Heather Dewey-Hagborg, update by Tom Igoe and Christian Cerrito

September 22, 2011, at 02:54 PM by Tom Igoe -
Changed lines 69-70 from:

''original tutorial by Heather Dewey-Hagborg, update by Tom Igoe and Christian Cerrito''

to:

'''original tutorial by Heather Dewey-Hagborg, update by Tom Igoe and Christian Cerrito'''

September 22, 2011, at 02:54 PM by Tom Igoe -
Deleted line 68:
September 23, 2010, at 10:58 PM by Christian Cerrito -
Changed lines 66-69 from:
to:
September 23, 2010, at 10:57 PM by Christian Cerrito -
Added lines 3-4:

Examples > SPI LIbrary

September 23, 2010, at 10:52 PM by Christian Cerrito -
Deleted line 0:
Changed lines 5-7 from:

explanation of SPI see the

SPI EEPROM tutorial.

to:

explanation of SPI see the SPI EEPROM tutorial.

September 23, 2010, at 10:51 PM by Christian Cerrito -
Changed lines 1-3 from:

Controlling a Digital Potentiometer Using SPI

to:

Controlling a Digital Potentiometer Using SPI

Added line 7:
Added line 16:
September 16, 2010, at 11:29 PM by Tom Igoe -
Changed lines 56-58 from:

(:source http://arduino.cc/en/pub/code/master/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.pde lang=arduino tabwidth=4:)

to:
September 16, 2010, at 11:28 PM by Tom Igoe -
Changed line 43 from:

[-image developed using Fritzing. For

to:

image developed using Fritzing. For

Changed line 45 from:

Fritzing project page-]

to:

Fritzing project page

September 16, 2010, at 11:28 PM by Tom Igoe -
Changed line 45 from:

Fritzing project page -]

to:

Fritzing project page-]

September 16, 2010, at 11:27 PM by Tom Igoe -
Added line 42:
September 16, 2010, at 11:26 PM by Tom Igoe -
Changed lines 46-47 from:

Schematic

to:

Schematic

September 16, 2010, at 11:25 PM by Tom Igoe -
Changed line 46 from:

Schematic

to:

Schematic

September 16, 2010, at 11:25 PM by Tom Igoe -
Changed lines 23-24 from:

[[http://datasheet.octopart.com/AD5206BRU10-Analog-Devices-datasheet-8405.pdf | Click for for the AD5206's datasheet.]]

to:

Click for for the AD5206's datasheet.

September 16, 2010, at 11:25 PM by Tom Igoe -
Added line 54:
Added line 57:
September 16, 2010, at 11:24 PM by Tom Igoe -
Changed line 55 from:

border=0:)

to:

lang=arduino tabwidth=4:)

August 15, 2010, at 02:49 PM by Tom Igoe -
Changed lines 1-4 from:

Controlling a Digital Potentiometer Using SPI

In this tutorial you will learn how to control the AD5206 digital potentiometer using Serial Peripheral Interface (SPI). For an explanation of SPI see the SPI EEPROM tutorial. Digital potentiometers are useful when you need to vary the resistance in a circuit electronically rather than by hand. Example applications include LED dimming, audio signal conditioning and tone generation. In this example we will use a six channel digital potentiometer to control the brightness of six LEDs. The steps we will cover for implementing SPI communication can be modified for use with most other SPI devices.

to:

Controlling a Digital Potentiometer Using SPI

In this tutorial you will learn how to control the AD5206 digital potentiometer using Serial Peripheral Interface (SPI). For an explanation of SPI see the SPI EEPROM tutorial. Digital potentiometers are useful when you need to vary the resistance in a circuit electronically rather than by hand. Example applications include LED dimming, audio signal conditioning and tone generation. In this example we will use a six channel digital potentiometer to control the brightness of six LEDs. The steps we will cover for implementing SPI communication can be modified for use with most other SPI devices.

Deleted line 19:
Deleted line 21:
Changed lines 23-24 from:

Click for for the AD5206's datasheet.

to:

[[http://datasheet.octopart.com/AD5206BRU10-Analog-Devices-datasheet-8405.pdf | Click for for the AD5206's datasheet.]]

Deleted line 25:
Changed lines 27-34 from:

The AD5206 is a 6 channel digital potentiometer. This means it has six variable resistors (potentiometers) built in for individual electronic control. There are three pins on the chip for each of the six internal variable resistors, and they can be interfaced with just as you would use a mechanical potentiometer. The individual variable resistor pins are labeled Ax, Bx and Wx, ie. A1, B1 and W1.

For example, in this tutorial we will be using each variable resistor as a voltage divider by pulling one side pin (pin B) high, pulling another side pin (pin A) low and taking the variable voltage output of the center pin (Wiper).

In this case, the AD5206 provides a maximum resistance of 10K ohms, delivered in 255 steps (255 being the max, 0 being the least).

to:

The AD5206 is a 6 channel digital potentiometer. This means it has six variable resistors (potentiometers) built in for individual electronic control. There are three pins on the chip for each of the six internal variable resistors, and they can be interfaced with just as you would use a mechanical potentiometer. The individual variable resistor pins are labeled Ax, Bx and Wx, ie. A1, B1 and W1. For example, in this tutorial we will be using each variable resistor as a voltage divider by pulling one side pin (pin B) high, pulling another side pin (pin A) low and taking the variable voltage output of the center pin (Wiper). In this case, the AD5206 provides a maximum resistance of 10K ohms, delivered in 255 steps (255 being the max, 0 being the least).

Deleted line 41:
Changed lines 43-45 from:

image developed using Fritzing. For more circuit examples, see the Fritzing project page

to:

[-image developed using Fritzing. For more circuit examples, see the Fritzing project page -]

Deleted line 46:
Deleted line 50:
Changed line 52 from:
to:
Changed lines 54-55 from:
to:

(:source http://arduino.cc/en/pub/code/master/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.pde border=0:)

Deleted line 57:
Changed lines 61-62 from:

original tutorial by Heather Dewey-Hagborg, update by Tom Igoe and Christian Cerrito

to:

''original tutorial by Heather Dewey-Hagborg, update by Tom Igoe and Christian Cerrito''

August 15, 2010, at 07:39 AM by Christian Cerrito -
Changed lines 27-29 from:
to:

In this case, the AD5206 provides a maximum resistance of 10K ohms, delivered in 255 steps (255 being the max, 0 being the least).

August 15, 2010, at 07:32 AM by Christian Cerrito -
Changed lines 17-18 from:
to:

Click for for the AD5206's datasheet.

August 15, 2010, at 07:29 AM by Christian Cerrito -
Changed lines 1-2 from:

Controlling a Digital Potentiometer Using SPI

to:

Controlling a Digital Potentiometer Using SPI

Deleted line 6:
Changed lines 16-17 from:

Introduction to the AD5206 Digital Potentiometer

to:

Introduction to the AD5206 Digital Potentiometer

August 15, 2010, at 07:27 AM by Christian Cerrito -
Changed lines 1-2 from:

Controlling a Digital Potentiometer Using SPI

to:

Controlling a Digital Potentiometer Using SPI

August 14, 2010, at 12:44 AM by Christian Cerrito -
August 14, 2010, at 12:08 AM by Christian Cerrito -
Changed line 42 from:

""Code""

to:

Code

August 14, 2010, at 12:08 AM by Christian Cerrito -
Changed line 42 from:

Describe what's going on here

to:

""Code""

August 13, 2010, at 11:59 PM by Christian Cerrito -
Changed line 53 from:

original tutorial by Heather Dewey-Hagborg, update by Tom Igoe and Cristian Cerrito

to:

original tutorial by Heather Dewey-Hagborg, update by Tom Igoe and Christian Cerrito

August 13, 2010, at 11:52 PM by Christian Cerrito -
Added line 11:
  • 6 220 ohm resistors
August 13, 2010, at 11:47 PM by Christian Cerrito -
Changed lines 3-4 from:

In this tutorial you will learn how to control the AD5206 digital potentiometer using Serial Peripheral Interface (SPI). For an explanation of SPI see the SPI EEPROM tutorial. Digital potentiometers are useful when you need to vary the resistance in a ciruit electronically rather than by hand. Example applications include LED dimming, audio signal conditioning and tone generation. In this example we will use a six channel digital potentiometer to control the brightness of six LEDs. The steps we will cover for implementing SPI communication can be modified for use with most other SPI devices.

to:

In this tutorial you will learn how to control the AD5206 digital potentiometer using Serial Peripheral Interface (SPI). For an explanation of SPI see the SPI EEPROM tutorial. Digital potentiometers are useful when you need to vary the resistance in a circuit electronically rather than by hand. Example applications include LED dimming, audio signal conditioning and tone generation. In this example we will use a six channel digital potentiometer to control the brightness of six LEDs. The steps we will cover for implementing SPI communication can be modified for use with most other SPI devices.

August 10, 2010, at 11:40 PM by Tom Igoe -
Changed line 44 from:
to:
August 10, 2010, at 11:38 PM by Tom Igoe -
Changed lines 5-6 from:

Materials Needed:

to:
Added lines 13-15:
Changed lines 26-210 from:

The AD5206 is digitally controlled using SPI. The device is enabled by pulling the Chip Select (CS) pin low. Instructions are sent as 11 bit operational codes (opcodes) with the three most significant bits (11-9) defining the address of which potentiometer to adjust and the eight least significant bits (8-1) defining what value to set that potentiometer to from 0-255. Data is shifted in Most Significant Bit (MSB) first on the rising edge of the data clock. The data clock is idle when low, and the interface runs much faster than the Arduino, so we don't need to worry about pre-scaling to slow down the transmission.

Prepare the Breadboard

Insert the AD5206 chip into the breadboard. Connect 5V power and ground from the breadboard to 5V power and ground from the microcontroller. Connect AD5206 pins 3, 6, 10, 13, 16, 21 and 24 to 5v and pins 1, 4, 9, 12, 15, 18, 19, and 22 to ground. We are connecting all the A pins to ground and all of the B pins to 5v to create 6 voltage dividers.

Connect AD5206 pin 5 to Arduino pin 10 (Slave Select - SS), AD5206 pin 7 to Arduino pin 11 (Master Out Slave In - MOSI), and AD5206 pin 8 to Arduino pin 13 (Serial Clock - SCK).

Finally, connect an LED between each Wiper pin (AD5206 pins 2, 11, 14, 17, 20 and 23) and ground so that the long pin of the LED connects to the wiper and the short pin, or flat side of the LED connects to ground.

Program the Arduino

Now we will write the code to enable SPI control of the AD5206. This program will sequentially pulse each LED on and then fade it out gradually. This is accomplished in the main loop of the program by individually changing the resistance of each potentiometer from full off to full on over its full range of 255 steps.

We will walk through the code in small sections.

We define the pins we will be using for our SPI connection, DATAOUT, DATAIN, SPICLOCK and SLAVESELECT. Although we are not reading any data back out of the AD5206 in this program, pin 12 is attached to the builtin SPI so it is best not to use it for other programming functions to avoid any possible errors:

#define DATAOUT 11//MOSI
#define DATAIN 12//MISO - not used, but part of builtin SPI
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

Next we allocate variables to store resistance values and address values for the potentiometers:

byte pot=0;
byte resistance=0;

First we set our input and output pin modes and set the SLAVESELECT line high to start. This deselects the device and avoids any false transmission messages due to line noise:

void setup()
{
  byte clr;
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device

Now we set the SPI Control register (SPCR) to the binary value 01010000. In the control register each bit sets a different functionality. The eighth bit disables the SPI interrupt, the seventh bit enables the SPI, the sixth bit chooses transmission with the most significant bit going first, the fifth bit puts the Arduino in Master mode, the fourth bit sets the data clock idle when it is low, the third bit sets the SPI to sample data on the rising edge of the data clock, and the second and first bits set the speed of the SPI to system speed / 4 (the fastest). After setting our control register up we read the SPI status register (SPSR) and data register (SPDR) in to the junk clr variable to clear out any spurious data from past runs:

  SPCR = (1<<SPE)|(1<<MSTR);
  clr=SPSR;
  clr=SPDR;
  delay(10);

We conclude the setup function by setting all the potentiometers to full on resistance states thereby turning the LEDs off:

  for (i=0;i<6;i++)
  {
    write_pot(i,255);
  }
}

In our main loop we iterate through each resistance value (0-255) for each potentiometer address (0-5). We pause for 10 milliseconds each iteration to make the steps visible. This causes the LEDs to sequentially flash on brightly and then fade out slowly:

void loop()
{
     write_pot(pot,resistance);
     delay(10);
     resistance++;
     if (resistance==255)
     {
       pot++;
     }
     if (pot==6)
     {
       pot=0;
     }
}

The spi_transfer function loads the output data into the data transmission register, thus starting the SPI transmission. It polls a bit to the SPI Status register (SPSR) to detect when the transmission is complete using a bit mask, SPIF. An explanation of bit masks can be found here. It then returns any data that has been shifted in to the data register by the EEPROM:

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

The write_pot function allows us to control the individual potentiometers. We set the SLAVESELECT line low to enable the device. Then we transfer the address byte followed by the resistance value byte. Finally, we set the SLAVSELECT line high again to release the chip and signal the end of our data transfer.

byte write_pot(int address, int value)
{
  digitalWrite(SLAVESELECT,LOW);
  //2 byte opcode
  spi_transfer(address);
  spi_transfer(value);
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
}

LED video

For easy copy and pasting the full program text of this tutorial is below:

#define DATAOUT 11//MOSI
#define DATAIN 12//MISO - not used, but part of builtin SPI
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

byte pot=0;
byte resistance=0;

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

void setup()
{
  byte i;
  byte clr;
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
  // SPCR = 01010000
  //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
  //sample on leading edge of clk,system clock/4 (fastest)
  SPCR = (1<<SPE)|(1<<MSTR);
  clr=SPSR;
  clr=SPDR;
  delay(10);
  for (i=0;i<6;i++)
  {
    write_pot(i,255);
  }
}

byte write_pot(int address, int value)
{
  digitalWrite(SLAVESELECT,LOW);
  //2 byte opcode
  spi_transfer(address);
  spi_transfer(value);
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
}

void loop()
{
     write_pot(pot,resistance);
     delay(10);
     resistance++;
     if (resistance==255)
     {
       pot++;
     }
     if (pot==6)
     {
       pot=0;
     }
}

code, tutorial and photos by Heather Dewey-Hagborg

to:
September 06, 2006, at 11:02 PM by Heather Dewey-Hagborg -
Changed lines 137-138 from:

VIDEO ? LEDs

to:

LED video

September 06, 2006, at 10:55 PM by Heather Dewey-Hagborg -
Changed lines 204-206 from:

@]

to:

@]

code, tutorial and photos by Heather Dewey-Hagborg

September 06, 2006, at 10:49 PM by Heather Dewey-Hagborg -
Changed lines 28-29 from:

PICTURE power

to:
Changed lines 32-33 from:

PICTURE datacom

to:
Changed lines 36-37 from:

PICTURE leds

to:
September 06, 2006, at 10:38 PM by Heather Dewey-Hagborg -
Added lines 5-11:

Materials Needed:

  • AD5206 Digital Potentiometer
  • Arduino Microcontroller Module
  • 6 Light Emitting Diodes (LEDs)
  • Hookup Wire
September 06, 2006, at 05:03 PM by Heather Dewey-Hagborg -
September 06, 2006, at 04:22 PM by Heather Dewey-Hagborg -
Changed lines 7-10 from:

PICTURE pins

PICTURE pin functions

to:

September 05, 2006, at 10:11 PM by Heather Dewey-Hagborg -
Added lines 130-131:

VIDEO ? LEDs

September 05, 2006, at 10:07 PM by Heather Dewey-Hagborg -
September 05, 2006, at 10:03 PM by Heather Dewey-Hagborg -
Changed lines 117-118 from:

The write_pot function allows us to control the individual potentiometers. First we shift the potentiometer address 8 bits to the left to put it in the most significant bit position of the 11 bit data byte. This makes room to add the resistance value which occupies the least significant eight bits of the data byte. When we sum the two together we get our 11 bit opcode to transmit:

to:

The write_pot function allows us to control the individual potentiometers. We set the SLAVESELECT line low to enable the device. Then we transfer the address byte followed by the resistance value byte. Finally, we set the SLAVSELECT line high again to release the chip and signal the end of our data transfer.

Deleted lines 121-128:
  int opcode=0;
  address<<=8; //shift pot address 8 left, ie. 101 = 10100000000
  opcode = address+value; //10111111111

@]

We set the SLAVESELECT line low to enable the device. Then we transfer the 11 bit opcode in two bytes sending the eight most significant bits first and sending the three least significant bits last. We set the SLAVSELECT line high again to release the chip and signal the end of our data transfer.

[@

Changed lines 124-125 from:
  spi_transfer((char)(opcode>>8));   //send MSByte address first a0a1a2d0d1d2d3d4
  spi_transfer((char)(opcode));      //send LSByte address, d5d6d700000
to:
  spi_transfer(address);
  spi_transfer(value);
Deleted lines 173-175:
  int opcode=0;
  address<<=8; //shift pot address 8 left, ie. 101 = 10100000000
  opcode = address+value; //10111111111
Changed lines 176-177 from:
  spi_transfer((char)(opcode>>8));   //send MSByte address first a0a1a2d0d1d2d3d4
  spi_transfer((char)(opcode));      //send LSByte address, d5d6d700000
to:
  spi_transfer(address);
  spi_transfer(value);
September 05, 2006, at 09:42 PM by Heather Dewey-Hagborg -
Changed lines 11-12 from:

The AD5206 is a 6 channel digital potentiometer. This means it has six variable resistors built in for individual electronic control. There are three pins on the chip for each of the six internal variable resistors, and they can be interfaced with just as you would use a mechanical potentiometer. The individual variable resistor pins are labeled Ax, Bx and Wx, ie. A1, B1 and W1.

to:

The AD5206 is a 6 channel digital potentiometer. This means it has six variable resistors (potentiometers) built in for individual electronic control. There are three pins on the chip for each of the six internal variable resistors, and they can be interfaced with just as you would use a mechanical potentiometer. The individual variable resistor pins are labeled Ax, Bx and Wx, ie. A1, B1 and W1.

Changed lines 85-86 from:

The spi_transfer function loads the output data into the data transmission register, thus starting the SPI transmission. It polls a bit to the SPI Status register (SPSR) to detect when the transmission is complete using a bit mask, SPIF. An explanation of bit masks can be found here?. It then returns any data that has been shifted in to the data register by the EEPROM:

to:

In our main loop we iterate through each resistance value (0-255) for each potentiometer address (0-5). We pause for 10 milliseconds each iteration to make the steps visible. This causes the LEDs to sequentially flash on brightly and then fade out slowly:

Changed line 88 from:

char spi_transfer(volatile char data)

to:

void loop()

Changed lines 90-94 from:
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
to:
     write_pot(pot,resistance);
     delay(10);
     resistance++;
     if (resistance==255)
     {
       pot++;
     }
     if (pot==6)
     {
       pot=0;
     }
Added lines 102-205:

@]

The spi_transfer function loads the output data into the data transmission register, thus starting the SPI transmission. It polls a bit to the SPI Status register (SPSR) to detect when the transmission is complete using a bit mask, SPIF. An explanation of bit masks can be found here. It then returns any data that has been shifted in to the data register by the EEPROM:

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

The write_pot function allows us to control the individual potentiometers. First we shift the potentiometer address 8 bits to the left to put it in the most significant bit position of the 11 bit data byte. This makes room to add the resistance value which occupies the least significant eight bits of the data byte. When we sum the two together we get our 11 bit opcode to transmit:

byte write_pot(int address, int value)
{
  int opcode=0;
  address<<=8; //shift pot address 8 left, ie. 101 = 10100000000
  opcode = address+value; //10111111111

We set the SLAVESELECT line low to enable the device. Then we transfer the 11 bit opcode in two bytes sending the eight most significant bits first and sending the three least significant bits last. We set the SLAVSELECT line high again to release the chip and signal the end of our data transfer.

  digitalWrite(SLAVESELECT,LOW);
  //2 byte opcode
  spi_transfer((char)(opcode>>8));   //send MSByte address first a0a1a2d0d1d2d3d4
  spi_transfer((char)(opcode));      //send LSByte address, d5d6d700000
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
}

For easy copy and pasting the full program text of this tutorial is below:

[@

  1. define DATAOUT 11//MOSI
  2. define DATAIN 12//MISO - not used, but part of builtin SPI
  3. define SPICLOCK 13//sck
  4. define SLAVESELECT 10//ss

byte pot=0; byte resistance=0;

char spi_transfer(volatile char data) {

  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte

}

void setup() {

  byte i;
  byte clr;
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
  // SPCR = 01010000
  //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
  //sample on leading edge of clk,system clock/4 (fastest)
  SPCR = (1<<SPE)|(1<<MSTR);
  clr=SPSR;
  clr=SPDR;
  delay(10);
  for (i=0;i<6;i++)
  {
    write_pot(i,255);
  }

}

byte write_pot(int address, int value) {

  int opcode=0;
  address<<=8; //shift pot address 8 left, ie. 101 = 10100000000
  opcode = address+value; //10111111111
  digitalWrite(SLAVESELECT,LOW);
  //2 byte opcode
  spi_transfer((char)(opcode>>8));   //send MSByte address first a0a1a2d0d1d2d3d4
  spi_transfer((char)(opcode));      //send LSByte address, d5d6d700000
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer

}

void loop() {

     write_pot(pot,resistance);
     delay(10);
     resistance++;
     if (resistance==255)
     {
       pot++;
     }
     if (pot==6)
     {
       pot=0;
     }

}

September 05, 2006, at 09:25 PM by Heather Dewey-Hagborg -
Added lines 53-96:

First we set our input and output pin modes and set the SLAVESELECT line high to start. This deselects the device and avoids any false transmission messages due to line noise:

void setup()
{
  byte clr;
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device

Now we set the SPI Control register (SPCR) to the binary value 01010000. In the control register each bit sets a different functionality. The eighth bit disables the SPI interrupt, the seventh bit enables the SPI, the sixth bit chooses transmission with the most significant bit going first, the fifth bit puts the Arduino in Master mode, the fourth bit sets the data clock idle when it is low, the third bit sets the SPI to sample data on the rising edge of the data clock, and the second and first bits set the speed of the SPI to system speed / 4 (the fastest). After setting our control register up we read the SPI status register (SPSR) and data register (SPDR) in to the junk clr variable to clear out any spurious data from past runs:

  SPCR = (1<<SPE)|(1<<MSTR);
  clr=SPSR;
  clr=SPDR;
  delay(10);

We conclude the setup function by setting all the potentiometers to full on resistance states thereby turning the LEDs off:

  for (i=0;i<6;i++)
  {
    write_pot(i,255);
  }
}

The spi_transfer function loads the output data into the data transmission register, thus starting the SPI transmission. It polls a bit to the SPI Status register (SPSR) to detect when the transmission is complete using a bit mask, SPIF. An explanation of bit masks can be found here?. It then returns any data that has been shifted in to the data register by the EEPROM:

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

September 05, 2006, at 09:14 PM by Heather Dewey-Hagborg -
Changed lines 15-16 from:

The AD5206 is digitally controlled using SPI. The device is enabled by pulling the Chip Select (CS) pin low. Instructions are sent as 11 bit operational codes (opcodes) and are shifted in Most Significant Bit (MSB) first on the rising edge of the data clock. The data clock is idle when low, and the interface runs much faster than the Arduino, so we don't need to worry about pre-scaling to slow down the transmission.

to:

The AD5206 is digitally controlled using SPI. The device is enabled by pulling the Chip Select (CS) pin low. Instructions are sent as 11 bit operational codes (opcodes) with the three most significant bits (11-9) defining the address of which potentiometer to adjust and the eight least significant bits (8-1) defining what value to set that potentiometer to from 0-255. Data is shifted in Most Significant Bit (MSB) first on the rising edge of the data clock. The data clock is idle when low, and the interface runs much faster than the Arduino, so we don't need to worry about pre-scaling to slow down the transmission.

Added lines 26-52:

Finally, connect an LED between each Wiper pin (AD5206 pins 2, 11, 14, 17, 20 and 23) and ground so that the long pin of the LED connects to the wiper and the short pin, or flat side of the LED connects to ground.

PICTURE leds

Program the Arduino

Now we will write the code to enable SPI control of the AD5206. This program will sequentially pulse each LED on and then fade it out gradually. This is accomplished in the main loop of the program by individually changing the resistance of each potentiometer from full off to full on over its full range of 255 steps.

We will walk through the code in small sections.

We define the pins we will be using for our SPI connection, DATAOUT, DATAIN, SPICLOCK and SLAVESELECT. Although we are not reading any data back out of the AD5206 in this program, pin 12 is attached to the builtin SPI so it is best not to use it for other programming functions to avoid any possible errors:

#define DATAOUT 11//MOSI
#define DATAIN 12//MISO - not used, but part of builtin SPI
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

Next we allocate variables to store resistance values and address values for the potentiometers:

byte pot=0;
byte resistance=0;

September 05, 2006, at 08:59 PM by Heather Dewey-Hagborg -
Changed lines 11-12 from:

The AD5206 is a 6 channel digital potentiometer. This means it has six variable resistors built in for individual electronic control. There are three pins on the chip for each of the six internal variable resistors, and they can be interfaced with just as you would use a mechanical potentiometer.

to:

The AD5206 is a 6 channel digital potentiometer. This means it has six variable resistors built in for individual electronic control. There are three pins on the chip for each of the six internal variable resistors, and they can be interfaced with just as you would use a mechanical potentiometer. The individual variable resistor pins are labeled Ax, Bx and Wx, ie. A1, B1 and W1.

Changed lines 15-25 from:

The AD5206 is digitally controlled using standard SPI. The device is enabled by pulling the Chip Select (CS) pin low. Instructions are sent as 11 bit operational codes (opcodes) and are shifted in Most Significant Bit (MSB) first on the rising edge of the data clock. The data clock is idle when low, and the interface runs much faster than the Arduino, so we don't need to worry about pre-scaling to slow down the transmission.

to:

The AD5206 is digitally controlled using SPI. The device is enabled by pulling the Chip Select (CS) pin low. Instructions are sent as 11 bit operational codes (opcodes) and are shifted in Most Significant Bit (MSB) first on the rising edge of the data clock. The data clock is idle when low, and the interface runs much faster than the Arduino, so we don't need to worry about pre-scaling to slow down the transmission.

Prepare the Breadboard

Insert the AD5206 chip into the breadboard. Connect 5V power and ground from the breadboard to 5V power and ground from the microcontroller. Connect AD5206 pins 3, 6, 10, 13, 16, 21 and 24 to 5v and pins 1, 4, 9, 12, 15, 18, 19, and 22 to ground. We are connecting all the A pins to ground and all of the B pins to 5v to create 6 voltage dividers.

PICTURE power

Connect AD5206 pin 5 to Arduino pin 10 (Slave Select - SS), AD5206 pin 7 to Arduino pin 11 (Master Out Slave In - MOSI), and AD5206 pin 8 to Arduino pin 13 (Serial Clock - SCK).

PICTURE datacom

September 05, 2006, at 08:34 PM by Heather Dewey-Hagborg -
Changed line 15 from:

The AD5206 is digitally controlled using standard SPI. The device is enabled by pulling the Chip Select (CS) pin low. Instructions are sent as 11 bit operational codes (opcodes) and are shifted in Most Significant Bit (MSB) first on the rising edge of the data clock. The data clock is idle when low, and the interface runs up to speeds of 100Mhz.

to:

The AD5206 is digitally controlled using standard SPI. The device is enabled by pulling the Chip Select (CS) pin low. Instructions are sent as 11 bit operational codes (opcodes) and are shifted in Most Significant Bit (MSB) first on the rising edge of the data clock. The data clock is idle when low, and the interface runs much faster than the Arduino, so we don't need to worry about pre-scaling to slow down the transmission.

September 05, 2006, at 08:30 PM by Heather Dewey-Hagborg -
Changed line 15 from:

The AD5206is controlled using standard SPI. The device is enabled by pulling the Chip Select (CS) pin low. Instructions are sent as 8 bit operational codes (opcodes) and are shifted in on the rising edge of the data clock.

to:

The AD5206 is digitally controlled using standard SPI. The device is enabled by pulling the Chip Select (CS) pin low. Instructions are sent as 11 bit operational codes (opcodes) and are shifted in Most Significant Bit (MSB) first on the rising edge of the data clock. The data clock is idle when low, and the interface runs up to speeds of 100Mhz.

September 05, 2006, at 08:23 PM by Heather Dewey-Hagborg -
Added lines 1-15:

Controlling a Digital Potentiometer Using SPI

In this tutorial you will learn how to control the AD5206 digital potentiometer using Serial Peripheral Interface (SPI). For an explanation of SPI see the SPI EEPROM tutorial. Digital potentiometers are useful when you need to vary the resistance in a ciruit electronically rather than by hand. Example applications include LED dimming, audio signal conditioning and tone generation. In this example we will use a six channel digital potentiometer to control the brightness of six LEDs. The steps we will cover for implementing SPI communication can be modified for use with most other SPI devices.

Introduction to the AD5206 Digital Potentiometer

PICTURE pins

PICTURE pin functions

The AD5206 is a 6 channel digital potentiometer. This means it has six variable resistors built in for individual electronic control. There are three pins on the chip for each of the six internal variable resistors, and they can be interfaced with just as you would use a mechanical potentiometer.

For example, in this tutorial we will be using each variable resistor as a voltage divider by pulling one side pin (pin B) high, pulling another side pin (pin A) low and taking the variable voltage output of the center pin (Wiper).

The AD5206is controlled using standard SPI. The device is enabled by pulling the Chip Select (CS) pin low. Instructions are sent as 8 bit operational codes (opcodes) and are shifted in on the rising edge of the data clock.

Share