Hello, I’m trying to control a digital potentiometer MCP4261 (Datasheet). I tried three approaches below, none of which is working. Wiring is at the end.
Since I can’t just measure the resistance with a multimeter when it’s powered, I’m instead measuring the current through the multimeter: wiper (pin 6) to 150ohm Resistor to multimeter (current) to ground. Since I’m feeding +5V, I was expecting that this would vary from about 1 mA to 34 mA, but I can’t get it to budge from 2mA (which matches the default wiper-to-Ground resistance of about 2.6 kOhm) with any of these codes.
(1) Using the MCP4261 Library from https://playground.arduino.cc/Code/Mcp4261 and its example code.
I can run the code fine, but the pot resistance doesn’t change.
I added some serial debugging lines, and I’m finding that the code stops executing or hangs as soon as it tries to write the wiper resistance, i.e., in my setup function I have:
Serial.println("Setup\n");
Mcp4261.wiper0_pos(0);
Serial.println("write to Wiper0");
Mcp4261.wiper1_pos(0);
Serial.println("write to Wiper1");
And the serial just reads:
Setup
If I comment the Mcp4261.wiperx_pos(x) lines, the serial prints as expected until I get to the next write-to-wiper command:
Setup
write to Wiper0
write to Wiper1Scale to 100%
(2) I also tried modifying the DigitalPotControl example that comes with the SPI library. This is for an AD5206, so I think maybe I didn’t properly switch the addressing? But I’m learning as I go here so I’m not sure.
/*
Digital Pot Control
This example controls an Analog Devices AD5206 digital potentiometer.
The AD5206 has 6 potentiometer channels. Each channel's pins are labeled
A - connect this to voltage
W - this is the pot's wiper, which changes when you set it
B - connect this to ground.
The AD5206 is SPI-compatible,and to command it, you send two bytes,
one with the channel number (0 - 5) and one with the resistance value for the
channel (0 - 255).
The circuit:
* All A pins of AD5206 connected to +5V
* All B pins of AD5206 connected to ground
* An LED and a 220-ohm resisor in series connected from each W pin to ground
* CS - to digital pin 10 (SS pin)
* SDI - to digital pin 11 (MOSI pin)
* CLK - to digital pin 13 (SCK pin)
created 10 Aug 2010
by Tom Igoe
Thanks to Heather Dewey-Hagborg for the original tutorial, 2005
*/
// inslude the SPI library:
#include <SPI.h>
// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;
void setup() {
// set the slaveSelectPin as an output:
pinMode(slaveSelectPin, OUTPUT);
// initialize SPI:
SPI.begin();
}
void loop() {
// go through the six channels of the digital pot:
for (int channel = 0; channel < 6; channel++) {
// change the resistance on this channel from min to max:
for (int level = 0; level < 255; level++) {
digitalPotWrite(channel, level);
delay(10);
}
// wait a second at the top:
delay(100);
// change the resistance on this channel from max to min:
for (int level = 0; level < 255; level++) {
digitalPotWrite(channel, 255 - level);
delay(10);
}
}
}
void digitalPotWrite(int address, int value) {
// take the SS pin low to select the chip:
digitalWrite(slaveSelectPin, LOW);
// send in the address and value via SPI:
SPI.transfer(address);
SPI.transfer(value);
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin, HIGH);
}
(3) Finally I tried writing a simple SPI control from what I’d read in the documentation and a few other examples including this one for a MCP4251, and ended up with the code below.
In table 7-2 in the documenation it says that the SPI string for “write data to volatile wiper 1” is
‘0001 00nn nnnn nnnn’
But I got an error when I tried to write a 16-bit command:
‘B0001010000000000’ was not declared in this scope
So I tried splitting it into two bytes like I’d seen in the other examples:
SPI.transfer(B00010100); //the command byte
SPI.transfer(B00000000); // The data byte
which compiled fine but didn’t seem to change the wiper value.
#include <SPI.h> // include the SPI library
const int slaveSelectPin = 10;
void setup() {
pinMode (slaveSelectPin, OUTPUT); // slaveSelectPin is an output
SPI.begin(); // initialize SPI:
}
void loop() {
// take the SS pin low to select the chip:
digitalWrite(slaveSelectPin,LOW);
SPI.transfer(B00010100); //the command byte
SPI.transfer(B00000000); // The data byte
digitalWrite(slaveSelectPin,HIGH);
delay(10);
}
Wiring setup of MCP4261 pins:
- 1 CS to Arduino 10
- 2 SCK to Arduino 13
- 3 SDI to Arduion 11
- 4 Vss to Ground
- 5 P1B to Ground
- 6 P1W to 150ohm Resistor to multimeter (current) to ground
- 7 P1A to +5V
- 8 P0A to +5V
- 9 P0W unconnected
- 10 P0B to Ground
- 11 WP to +5V
- 12 SHDN to +5V (or in Method 2, to digital pin 7 and a 4.7k pull down resistor)
- 13 SDO to Arduino 12
- 14 Vdd to +5V
Thanks for any help getting this working. I’m really feeling stuck on this.
MCP4261_Method1.ino (3.53 KB)
MCP4261_Method2.ino (727 Bytes)
MCP4261_Method3.ino (485 Bytes)