Tutorial.SPIDigitalPot History

Hide minor edits - Show changes to output

November 04, 2013, at 09:07 AM by Scott Fitzgerald -
Changed lines 45-46 from:
%height=300px%[[Attach:AD5206_arduino_bb.png | Attach:AD5206_arduino_bb.png]]
to:
%height=300px%[[Attach:AD5206_arduino_bb2.png | Attach:AD5206_arduino_bb2.png]]
November 16, 2011, at 04:38 AM by Scott Fitzgerald -
Changed lines 60-61 from:
(:source http://arduino.cc/en/pub/code/master/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.pde lang=arduino tabwidth=4:)
to:
(:source http://arduino.cc/en/pub/code/master/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino lang=arduino tabwidth=4:)
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:
* [[Reference/SPI | Arduino SPI LIbrary]]
* [[Tutorial/BarometricPressureSensor]]

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

[[http://www.arduino.cc/en/Tutorial/SPIEEPROM | SPI EEPROM tutorial]].
to:
explanation of SPI see the [[http://www.arduino.cc/en/Tutorial/SPIEEPROM | 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:
(:source http://arduino.cc/en/pub/code/master/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.pde lang=arduino tabwidth=4:)
September 16, 2010, at 11:28 PM by Tom Igoe -
Changed line 43 from:
[-image developed using [[http://www.fritzing.org |Fritzing]]. For
to:
image developed using [[http://www.fritzing.org |Fritzing]]. For
Changed line 45 from:
[[http://fritzing.org/projects/|Fritzing project page]]-]
to:
[[http://fritzing.org/projects/|Fritzing project page]]
September 16, 2010, at 11:28 PM by Tom Igoe -
Changed line 45 from:
[[http://fritzing.org/projects/|Fritzing project page]] -]
to:
[[http://fritzing.org/projects/|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:
[[http://datasheet.octopart.com/AD5206BRU10-Analog-Devices-datasheet-8405.pdf | 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 [[http://www.arduino.cc/en/Tutorial/SPIEEPROM | 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
[[http://www.arduino.cc/en/Tutorial/SPIEEPROM | 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:
[[http://datasheet.octopart.com/AD5206BRU10-Analog-Devices-datasheet-8405.pdf | 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 [[http://www.fritzing.org |Fritzing]]. For more circuit examples, see the [[http://fritzing.org/projects/|Fritzing project page]] -]
to:
[-image developed using [[http://www.fritzing.org |Fritzing]]. For
more circuit examples, see the
[[http://fritzing.org/projects/|Fritzing project page]] -]
Deleted line 46:
Deleted line 50:
Changed line 52 from:
to:
Changed lines 54-55 from:
(:source http://arduino.cc/en/pub/code/master/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.pde lang=arduino tabwidth=4:)
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:
[[http://datasheet.octopart.com/AD5206BRU10-Analog-Devices-datasheet-8405.pdf | 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 [[http://www.arduino.cc/en/Tutorial/SPIEEPROM | 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 [[http://www.arduino.cc/en/Tutorial/SPIEEPROM | 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:
(:source http://arduino.cc/en/pub/code/master/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.pde lang=arduino tabwidth=4:)
to:
(:source http://arduino.cc/en/pub/code/master/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.pde lang=arduino tabwidth=4:)
August 10, 2010, at 11:38 PM by Tom Igoe -
Changed lines 5-6 from:
Materials Needed:
to:
(:div class=BOM :)
!!!Hardware Required
Added lines 13-15:
(:divend:)

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.

Attach:AD5206_pwr.jpg

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).

Attach:AD5206_data.jpg

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.

Attach:AD5206_leds.jpg

!!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 [[http://www.arduino.cc/en/Tutorial/BitMask | 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:

!!!Circuit
(:div class=circuit :)

%height=300px%[[Attach:AD5206_arduino_bb.png | Attach:AD5206_arduino_bb.png]]

[-image developed using [[http://www.fritzing.org |Fritzing]]. For more circuit examples, see the [[http://fritzing.org/projects/|Fritzing project page]] -]

(:divend:)

!!!Schematic
(:div class=circuit :)
%height=300px%[[Attach:AD5206_arduino_sch.png | Attach:AD5206_arduino_sch.png]]
(:divend:)

Describe what's going on here

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


!!!See Also:



''original tutorial by Heather Dewey-Hagborg, update by Tom Igoe and Cristian Cerrito''
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:
Attach:AD5206_pwr.jpg
Changed lines 32-33 from:
PICTURE datacom
to:
Attach:AD5206_data.jpg
Changed lines 36-37 from:
PICTURE leds
to:
Attach:AD5206_leds.jpg
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:
Attach:AD5206_pins.jpg

Attach:AD5206_pinsDescript.jpg
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 [[Tutorials\bitMask | 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 [[http://www.arduino.cc/en/Tutorial/BitMask | 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:

[@
#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)
{
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 [[Tutorials\bitMask | 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 [[http://www.arduino.cc/en/Tutorial/SPIEEPROM | 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