I wrote a test sketch to learn how to write to the Dallas Semiconductor DS1882 Dual Digital Potentiometer. Datasheet directly from the manufacturer website is here.
There are a couple of libraries for this chip already on Github, but one depends on a library that's broken, and the other one isn't documented or commented well. I also wanted to figure out how to talk to this chip on my own, and to be successful I need to understand the code better than just snipping bits from other libraries and sketches
The sketch writes to both pots, increasing the wiper setting/attenuation (thus reducing the volume) with each loop, pauses on the highest setting (position 63 from the datasheet) for 2 seconds, then starts over again from the lowest wiper setting (0).
It mostly works, except when I started it would not get all the way down to the mute setting. When I experimented with the variable check at the end, I found if I step all the way up to 255, I get the desired behavior, with the chip reducing the volume all the way to mute.
But...the datasheet specifies 0-63 wiper positions. You'll see where I increase the wiper setting at the very bottom of the loop.
I suspect something is askew in my bitmath, but haven't been able to wrap my head around it.
Here's the sketch--I made some notes on the chip communication specs at the beginning of it:
[code]
/*
DS1882 Test Sketch
---------------------------------
DS1882 I2C Command Byte Structure
---------------------------------
SLAVE ADDRESS BYTE
Base A2 A1 A0 ... R/W (LSB=1 for Read request)
Bin 0 1 0 1 0 0 0 ... 0
Bitval 64 32 16 8 4 2 1
Hex 0x28 (<-----This is the slave address base)
Dec 40
COMMAND BYTE
Bin 0 0 0 0 0 0 0 0
POT0 0 0 0 POT0WiperPos <---BIT6 toggles POT0 or POT1
POT1 0 1 0 POT1WiperPos <┘
CONFIG 1 0 X X X 0 0 0 <---BIT7 flags CONFIG register
| | |
| | POTConfig(BIT0): 0(0x0)=63 positions & mute, 1(0x1)=33 positions & mute(default)
| POTZeroCrossing(BIT1): 0=disabled, 1=enabled(default)
POTNVM Volatile/Nonvolatile(BIT2): 0=nonvolatile, 1=volatile(default, potentiometer powers up in mute pos.)
Read Protocol: Start SLAVEADDR POT0BYTE POT1BYTE CONFIG Stop
Write Protocol: Start SLAVEADDR (POT0BYTE, POT1BYTE, CONFIG can be sent in any order after SLAVEADDR) Stop
*/
#include <Wire.h>
byte CONFIG = B10000010; //set configuration byte
byte POT0 = 00; //flag for pot 0
byte POT1 = 01; //flag for pot 1
int POT0SET = 1; //initialize pot 0 wiper set (63 = mute, 0 = no attenuation)
int POT1SET = 1; //initialize pot 1 wiper set
byte POT0CMD; //initialize pot 0 command byte
byte POT1CMD; //initialize pot 1 command byte
byte POT0RD; //initialize pot 0 read byte
byte POT1RD; //initialize pot 1 read byte
byte CONFIGRD; //initialize configuration byte read
int POT0GET; //initialize pot 0 wiper position reading
int POT1GET; //initialize pot 1 wiper position reading
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600);
}
void loop()
{
POT0SET++; // increase attenuation
POT1SET++;
POT0CMD = ((POT0 << 6) | (POT0SET >> 2)); //assemble pot 0 command byte
POT1CMD = ((POT1 << 6) | (POT1SET >> 2)); //assemble pot 1 command byte
Wire.beginTransmission(40); // transmit to device #40 (0x28)
Wire.write(POT0CMD); // sends pot 0 command byte
Wire.write(POT1CMD); // sends pot 1 command byte
Wire.write(CONFIG); // sends configuration byte
Wire.endTransmission(); // stop transmitting
Serial.print("Pot0 WiperSetValue = ");
Serial.println(POT0SET);
Serial.print("Pot1 WiperSetValue = ");
Serial.println(POT1SET);
/* Not working yet - returns "255" on every POT#GET print
Wire.requestFrom(40, 3); //request 3 bytes from device #40
POT0RD = Wire.read(); //read pot0 byte
POT1RD = Wire.read(); //read pot1 byte
CONFIGRD = Wire.read(); //read configuration register byte
POT0GET = POT0RD & B00111111; //mask pot0 flag and extract wiper value
POT1GET = POT1RD & B00111111; //mask pot1 flag and extract wiper value
Serial.print("Pot0 Position = ");
Serial.println(POT0RD);
Serial.print("Pot1 Position = ");
Serial.println(POT1RD);
Serial.println();
*/
if(POT0SET == 255) // if reached position 63(???!) (mute)
{
delay(2000); // hold mute for 2 seconds
POT0SET = 0; // start over from full volume
POT1SET = 0;
}
delay(100);
}
[/code]