AnsweredAssumed Answered

AD7175 register read glitch

Question asked by alincp on Jul 13, 2018

I've been experimenting with an AD7175-8 and I've encountered a problem regarding register writting/reading. 
I'm setting up a register with a certain HEX value, yet when reading it back (to verify that the writing was successful) the ADC responds with that HEX value + 1. Why so?

 

Console output:

 

Succesfully connected to ADC
ID=3CDE

ADCMODE Register READ ERROR!
ADCMODE = 8001
Expected 8000

SETUPCON0 Register READ ERROR!
SETUPCON0 = 1321
Expected 1320

FILTCON0 Register READ ERROR!
FILTCON0 = 505
Expected 504

SETUP complete


Waveform capture from a Saleae logic level analyzer:
You can find it attached bellow.

The code that's running on the main uC:

#include <SPI.h>
#include <AD8555.h>

#define ENABLE_OP_AMP_SETUP 0
#define ENABLE_VERBOSE_OUTPUT 1
//op-amp related
int outputpin = 23;    //op-amp data in pin
int inputpin = 15;  //op-amp data out pin
byte opAmpData;     //stores op-amp register values

//intialize op-amp handle
AD8555 opamp(outputpin, inputpin);

//ADC hook-up lines
//ARDUINO
/*
  #define SCK   13
  #define MOSI  11
  #define MISO  12
  #define CS    10
*/


//ESP32

#define SCK   26
#define MOSI  14
#define MISO  27
#define CS    25


//SPI bus settings
#define SPISPEED 4000000

byte received[3];
int i = 0;

//ADC commands
#define READ_REG        0B01000000
#define WRITE_REG       0B00000000

//ADC Register Adressess
#define IDREG           0B00000111
#define ADCMODE         0B00000001
#define FILTCON0        0B00101000
#define IFMODE          0B00000010
#define SETUPCON0       0B00100000

//sample rates
#define SPS5            0B00010100
#define SPS10           0B00010011
#define SPS100          0B00001110
#define SPS1000         0B00001010
#define SPS5000         0B00001000
#define SPS10000        0B00000111
#define SPS31250        0B00000100
#define SPS50000        0B00000011
#define SPS250000       0B00000000

uint16_t id;
uint16_t register16 = 0;
uint16_t dataRegister;

unsigned long raw;
byte adcData[3];
bool ok = false;

void setup() {
  Serial.begin(2000000);

  if (ENABLE_OP_AMP_SETUP) {
    pinMode(outputpin, OUTPUT);
    pinMode(inputpin, INPUT);
    opAmpSetup();
  }

  //SPI pins
  pinMode(MISO, INPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(SCK, OUTPUT);
  pinMode(CS, OUTPUT);

  digitalWrite(CS, HIGH);

  SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus
  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE3));

  //terminate CONTINUOUS READ MODE
  exitContinuous();

  //read device ID
  id = readID();
  checkID(id);

  dataRegister = 0B1000000000000000;
  writeRegister16(ADCMODE, dataRegister);
  register16 = readRegister16(ADCMODE);
  checkRegisterData(register16, dataRegister, "ADCMODE");


  //configure SETUPCON0 register
  //set unipolar mode
  dataRegister = 0B0001001100100000;
  writeRegister16(SETUPCON0, dataRegister);
  register16 = readRegister16(SETUPCON0);
  checkRegisterData(register16, dataRegister, "SETUPCON0");

  //configure FILTCON0 register
  /*
     FILTCON SYNC5 + SYNC 1 FILTER
  */


  dataRegister = 0B0000010100000000;
  //chose SPS
  dataRegister |= SPS31250;
  writeRegister16(FILTCON0, dataRegister);
  register16 = readRegister16(FILTCON0);
  checkRegisterData(register16, dataRegister, "FILTCON0");


  //configure IFMODE register
  //enable continious read by setting CONTREAD to 1
  //ONCE CONTREAD is set any other command is ignored!!!
  dataRegister = 0B0000100010000000;
  writeRegister16(IFMODE, dataRegister);

  //setup complete
  if (ENABLE_VERBOSE_OUTPUT)
    Serial.println("SETUP complete");

  digitalWrite(CS, LOW);
  digitalWrite(MOSI, LOW);
  //attachInterrupt(digitalPinToInterrupt(12), readADC, FALLING);
}
void loop () {


  digitalWrite(CS, LOW);
  digitalWrite(MOSI, LOW);

  //read analog input
  if (Serial.available() > 0) {
    byte pcFlag = Serial.read();

    if (pcFlag == 115) {
      ok = true;
      delay(2000);
    }
  }

  while (1 && ok) {
    while (digitalRead(MISO)) {}


    raw = SPI.transfer(0);
    raw <<= 8;
    raw |= SPI.transfer(0);
    raw <<= 8;
    raw |= SPI.transfer(0);
    Serial.println(raw);


    //adcData[0] = SPI.transfer(0);
    //adcData[1] = SPI.transfer(0);
    //adcData[2] = SPI.transfer(0);


    //Serial.print(adcData[0], BIN);
    //Serial.print(" ");
    //Serial.print(adcData[1], BIN);
    //Serial.print(" ");
    //Serial.println(adcData[2], BIN);


    //Serial.write(adcData, sizeof(adcData));

    while (!digitalRead(MISO)) {}
  }

}

uint16_t readID() {
  uint16_t id;

  //read JEDEC ID
  digitalWrite(CS, LOW);
  SPI.transfer(READ_REG | IDREG);
  id = SPI.transfer(0);
  id <<= 8;
  id |= SPI.transfer(0);
  digitalWrite(CS, HIGH);

  return id;
}

void checkID(unsigned long id) {
  if (ENABLE_VERBOSE_OUTPUT) {
    if (id == 0x3CDE )  {
      Serial.print("\nSuccesfully connected to ADC");
      Serial.print("\nID=");
      Serial.println(id, HEX);
    }
    else
      Serial.println("ADC not responding");
  }
}

void checkRegisterData(uint16_t received, uint16_t expected, char* registerName) {
  if (ENABLE_VERBOSE_OUTPUT) {
    if (received == expected) {
      Serial.print("\n");
      Serial.print(registerName);
      Serial.print(" succesfully set to: ");
      Serial.println(received, HEX);
    }
    else {
      Serial.print("\n");
      Serial.print(registerName);
      Serial.println(" Register READ ERROR!");
      Serial.print(registerName);
      Serial.print(" = ");
      Serial.println(received, HEX);
      Serial.print("Expected ");
      Serial.println(expected);
    }
  }
}

uint16_t readRegister16(byte regAddress) {
  uint16_t register_value = 0;

  digitalWrite(CS, LOW);
  SPI.transfer(READ_REG | regAddress);
  register_value = SPI.transfer16(0);
  digitalWrite(CS, HIGH);

  return register_value;
}
void writeRegister16(byte regAddress, uint16_t userData) {
  digitalWrite(CS, LOW);
  SPI.transfer(WRITE_REG | regAddress);
  SPI.transfer16(userData);
  digitalWrite(CS, HIGH);
}
void exitContinuous() {
  while (digitalRead(MISO)) {};
  digitalWrite(CS, LOW);
  SPI.transfer16(0x44);
  digitalWrite(CS, HIGH);
}

void opAmpSetup() {
  //op-amp setup sequence
  //Start----------------Op-Amp setup--------------------

  // get Second Stage Gain code
  Serial.println("Input Second Stage Gain code (0..7)");
  // wait for user to enter value
  while (!Serial.available());
  // set Second Stage Gain
  if (!opamp.setSecondStageGain(Serial.parseInt())) {
    // opamp will return false if code is out of range
    Serial.println("Invalid Second Stage Gain code. Valid range is 0..7");
    return;
  }



  //get First Stage Gain code
  Serial.println("Input First Stage Gain code (0..127)");
  while (!Serial.available());
  //set First Stage Gain
  if (!opamp.setFirstStageGain(Serial.parseInt())) {
    Serial.println("Invalid First Stage Gain code. Valid range is 0..127");
    return;
  }


  // get offset code
  Serial.println("Input Offset code (0..255)");
  while (!Serial.available());
  //set op-amp offset
  if (!opamp.setOffset(Serial.parseInt())) {
    Serial.println("Invalid Offset code. Valid range is 0..255");
    return;
  }


  // Chose between programming/simulation mode
  // !!! Once the op-amp gets programmed (programming has been chosen) you cannot revrse the settings! It's permanent!
  Serial.println("Choose programming mode: Enter \"0\" for simulation, \"1\" for permanent programming");
  while (!Serial.available());
  int mode = Serial.parseInt();
  if (mode == 0) {
    // simulation mode
    opamp.simulate();
    Serial.println("Done!");
  } else if (mode == 1) {
    // permanent programming mode
    Serial.println("Make sure to meet programming requirements described in AD8555 datasheet:");
    Serial.println("- A 5.5 V supply is required");
    Serial.println("- The power supply must be able to deliver 250 mA of current");
    Serial.println("- At least 0.1 uF of decoupling capacitance is needed across the power pins of the device");
    Serial.println("\nWARNING: This operation can not be undone, all programming values are permanent");
    Serial.println("Continue? [y/N]");
    while (!Serial.available());
    if (Serial.read() == 'y') {
      opamp.program();
      Serial.println("Programming... done");
    } else {
      Serial.println("Operation canceled");
    }
  }
  //opAmpData = opamp.readData(PAR_SSG_CODE);
  //Serial.println("Op-Amp offset code= ");
  //Serial.println(opAmpData, BIN);
  //Finish----------------Op-Amp setup--------------------

}


Attachments

Outcomes