Pregunta

I'm having trouble controlling an AD5270 10-bit Digital Potentiometer. It seems that no matter what I write to the register the actual value of resistance between the terminal A and the wiper does not change. I'm assuming I'm running into a problem with the "Falling Edge Synchronization Signal" Specifically, from page 10 of the data sheet:

SYNC: Falling Edge Synchronization Signal. This is the frame synchronization signal for the input data. When SYNC goes low, it enables the shift register and data is transferred in on the falling edges of the subsequent clocks. The selected register is updated on the rising edge of SYNC following the 16th clock cycle. If SYNC is taken high before the 16th clock cycle, the rising edge of SYNC acts as an interrupt, and the write sequence is ignored by the RDAC.

I have been treating this pin much like a SS pin. So far, this is what I have as far as code goes:

#include <SPI.h> 

 const int csPinCWF = 10; 

 const byte enableUpdateMSB = 0x1C; //B00011100
 const byte enableUpdateLSB = 0x02; //B00000010
 const byte command = 0x04; //B00000100

 void setup() {
  Serial.begin(9600);
  Serial.println("Ready");

  SPI.begin();
  Serial.println("SPI Begin");
  SPI.setBitOrder(MSBFIRST); //We know this from the Data Sheet
  SPI.setDataMode(SPI_MODE1); //Pg.7:Fig.3 states CPOL=0, CPHA=1 --> MODE1

  pinMode(csPinCWF,OUTPUT);
  Serial.println("Output Set");

  digitalWrite(csPinCWF, HIGH);
  Serial.println("Set pin to HIGH");
}

 void loop() {
 for(int i=0; i<1023; i++) { 
   Serial.println(i);
   enablePotWrite(csPinCWF);
   digitalPotWrite(csPinCWF, i);
   delay(5000);
  } 
}

 void digitalPotWrite(int csPin, int value) {
  Serial.println("In digitalPotWrite Now");
  digitalWrite(csPin, LOW); //select slave
  Serial.println("Set csPin to LOW");

  Serial.print("Command Byte is: ");
  Serial.println(command, BIN);

  byte shfitedValue = (value >> 8);
  Serial.print("Shifted bit value is: ");
  Serial.println(shfitedValue, BIN);

  byte byte1 = (command | shfitedValue);
  Serial.print("Byte1 is: "); 
  Serial.println(byte1, BIN);

  byte byte0 = (value & 0xFF); //0xFF = B11111111 trunicates value to 8 bits
  Serial.print("Byte0 is: ");
  Serial.println(byte0, BIN);

  //Write to the RDAC Register to move the wiper
  SPI.transfer(byte1);
  SPI.transfer(byte0);

  Serial.print("Transfered: ");
  Serial.print(byte1, BIN);
  Serial.print("    ");
  Serial.println(byte0, BIN);

  digitalWrite(csPin, HIGH); //de-select slave
  Serial.println("Set csPin back to HIGH, end of digitalPotWrite");
}

 void enablePotWrite(int csPin) { //Enable Update of the Wiper position through the digital interface
   digitalWrite(csPin, LOW); //select slave

   Serial.print("Enable byte is: ");
   Serial.print(enableUpdateMSB, BIN);
   Serial.print("    ");
   Serial.println(enableUpdateLSB, BIN);

   SPI.transfer(enableUpdateMSB); 
   SPI.transfer(enableUpdateLSB);

   digitalWrite(csPin, HIGH); //de-select slave
}

I've gone over it many times and it seems like the math is correct and it is transferring the correct bytes but I'm not getting any change between terminal A and the wiper. Page 19:Table 11 of the data sheet shows the format of the 16-bit word that I should be transferring. Can anyone shed some light on what I'm may be missing here? Any help would be greatly appreciated, thanks!

Edit: Changed my code to reflect mpflaga's suggestions but still no dice unfortunately.

Edit2: SPI mode is indeed SPI_MODE1. Pg. 7:Fig 3 of the data sheet states CPOL=0, CPHA=1. Edited the code above to reflect the change. Thanks again to @mpflaga.

¿Fue útil?

Solución

Several issues:

First -

Per the data sheet, page 18:

To enable programming of the RDAC register, the write protect bit (Bit C1), of the control register must first be programmed by loading the serial data input register with Command 7

per the data sheet page 20 table 14, shows that by default C1 is 0,

0 = wiper position frozen to value in 50-TP memory (default) , or midscale if not previously programed.

See table 12's example sequences to get things moving, by initially sending 0x1C03. I believe you could substitute with 0x1C02, if you do not want to enable programming and just want to update on the fly.


Second -

Also looks like from the data sheet the Din is sampled on the falling edge of the clock. you need the following in the setup

SPI.setDataMode(SPI_MODE1);

Where often this may appear to work in MODE0(Default) with slower data rates.

Otros consejos

I just happened to be working with the AD5271 (same thing but 8-bit) and I finally got it working on the Arduino Duemilanove.

Here's a working copy of the test code I wrote:

#include <SPI.h>

const int SS_PIN = 10;
const int MOSI_PIN = 11;
const int MISO_PIN = 12;
const int CLK_PIN = 13;

// Writes to the control register enabling the RDAC register write access.
void initRheostat() {
    Serial.println("Writing Control Reg");
    byte upper = 0x1C;
    byte lower = 0x02;
    digitalWrite(SS_PIN, LOW);
    SPI.transfer(upper);
    SPI.transfer(lower);
    digitalWrite(SS_PIN, HIGH);
}

// Writes the value to the RDAC register.
void writeRheostat(byte val) {
    Serial.print("Writing to Rheostat... ");
    Serial.println(val);
    byte command = 0x01;
    byte upper = (command << 2) | (val >> 6);
    byte lower = val << 2;
    digitalWrite(SS_PIN, LOW);
    SPI.transfer(upper);
    SPI.transfer(lower);
    digitalWrite(SS_PIN, HIGH);
}

// Readsd the value in the RDAC register.
void readRheostat() {
    Serial.println("Reading rheostat...");
    digitalWrite(SS_PIN, LOW);
    byte upper = 0x80;
    byte response = SPI.transfer(upper);
    // Print the raw byte response.
    Serial.println(response, HEX);
    digitalWrite(SS_PIN, HIGH);
    digitalWrite(SS_PIN, LOW);
    byte lower = 0x00;
    // Print the raw byte response.
    byte secondResponse = SPI.transfer(lower);
    Serial.println(secondResponse, HEX);
    // Calculate the actual value and print it out.
    int value = ((response & 0x03) << 6) | (secondResponse >> 2);
    Serial.print("Actual Value: " );
    Serial.println(value);
    digitalWrite(SS_PIN, HIGH);
}

void setup() {
    Serial.begin(9600);
    // Initialize SPI
    pinMode(SS_PIN, OUTPUT);
    SPI.begin();
    // SPI_MODE1 (CPOL = 0, CPHA = 1) - From the datasheet
    SPI.setDataMode(SPI_MODE1);
    // MSBFIRST - From the data sheet
    SPI.setBitOrder(MSBFIRST);
    // Call to init and enable RDAC register write access.
    initRheostat();
}

void loop() {
    // Serial listener that sets the wiper to the specified value.
    while (Serial.available() > 0) {
        char inChar = Serial.read();
        writeRheostat(inChar);
        readRheostat();
    }
}

Also make sure that your circuit wiring is correct. You'll have to make some changes to the bit shifts in the writeRheostat function for the 10-bit.

  • The EXT_CAP should have a 1uF capacitor connected to VSS
  • VDD needs to be decoupled with a 10uF capacitor and 0.1uF capacitor
  • SDO needs to have a pull-up resistor.

Hope that helps.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top