Post Go back to editing

AD4695 Conversion Mode

Category: Hardware
Product Number: AD4695

Hello,

It is my first time working with an IC that ha this Conversion Mode. And I am having problems making it work. I can write and read the registers without problem, but moving to conversion mode has been problematic.

I only get a saturated output: FFFFFFFF

Here is my  schematic:

and my code (I am using a arduino nano ble as my mcu):

#include <SPI.h>
#include <ArduinoBLE.h>

// Define pins and constants
const int CS_PIN = D7; // Chip Select pin for SPI
//const int SCK_PIN = D8;
const int MOSI_PIN = D10;
const int MISO_PIN = D9;
SPISettings MP_settings(1000000, MSBFIRST, SPI_MODE3);  // Adjust speed as necessary

// AD4695 register addresses
const uint16_t SPI_CONFIG_A = 0x0000;
const uint16_t SPI_CONFIG_B = 0x0001;
const uint16_t DEVICE_TYPE = 0x0003;
const uint16_t SPI_CONFIG_C = 0x0010;
const uint16_t SCRATCH_PAD = 0x000A;
const uint16_t VENDOR_L = 0x000C; //should give back 56 if working well
const uint16_t VENDOR_H = 0x000D;
const uint16_t SETUP = 0x0020;
const uint16_t REF_CTRL = 0x0021;
const uint16_t SEQ_CTRL = 0x0022;
const uint16_t AC_CTRL = 0x0023;
const uint8_t STD_SEQ_CTRL_1 = 0x0024;
const uint8_t STD_SEQ_CTRL_2 = 0x0025;
const uint8_t TEMP_CTRL = 0x0029;
const uint8_t CONFIG_IN15 = 0x003F;
const uint8_t AS_SLOT15 = 0x010F;
const uint8_t UPPER_IN0 = 0x0040;
const uint8_t LOWER_IN0 = 0x0060;

BLEService DeviceInformation("180A");
BLEService DataService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service

// create switch characteristic and allow remote device to read and write
BLEByteCharacteristic DataCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLECharacteristic ManufacturerChar("2A29", BLERead, "Bioelectronics Lab, U of Cambridge");
BLEByteCharacteristic VendorChar("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead);

const int bufferSize = 16;
uint16_t valueBuffer[bufferSize];
int bufferIndex = 0;

void setup() {
  Serial.begin(115200);
  SPI.begin();
  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH); // CS idle high

  if (!BLE.begin()) {
    Serial.println("starting Bluetooth® Low Energy module failed!");
    while (1);
  }
  // set the local name peripheral advertises
  BLE.setLocalName("Bioelectronics EEG 16");
  // set the UUID for the service this peripheral advertises:
  BLE.setAdvertisedService(DeviceInformation);
  BLE.setAdvertisedService(DataService);
  // add the characteristics to the service
  DataService.addCharacteristic(DataCharacteristic);
  DeviceInformation.addCharacteristic(ManufacturerChar);
  DataService.addCharacteristic(VendorChar);
  // add the service
  BLE.addService(DeviceInformation);
  BLE.addService(DataService);
  DataCharacteristic.writeValue(0);
  // start advertising
  BLE.advertise();
  Serial.println("Bluetooth® device active, waiting for connections...");

  // Configure AD4695
  Serial.println("Setting up Multiplexer...");
  configureAD4695();
}

void loop() {
  // poll for Bluetooth® Low Energy events
  BLE.poll();
  BLEDevice central = BLE.central();

  uint32_t pri;
  pri = readData();
  Serial.println(pri, HEX);


  delay(100);
}

void configureAD4695() {
  // Software Reset
  writeRegister(SPI_CONFIG_A, 0x91); //write 1 to both MSB and LSB to reset
  delay(310);
  // Configuring Address length and mode
  writeRegister(SPI_CONFIG_B, 0x80); //write 1 to MSB enables single intruction mode
  delay(1);
  // Configuring CRC
  writeRegister(SPI_CONFIG_C, 0x23); //write 00000011 to disable CRC and enable multibyte register together
  delay(1);
  // Configuring Reference Control
  writeRegister(REF_CTRL, 0x02); //write 00000010
  delay(1);
  // Configuring sequencer
  writeRegister(SEQ_CTRL, 0x80); //write 10000000 to turn on standard sequencer, 00001111 for 16 slots in advanced
  delay(1);
  // Configuring AC
  writeRegister(AC_CTRL, 0x00); //write 00000001 to turn on AC
  delay(1);
  // Configuring channels
  writeRegister(STD_SEQ_CTRL_1, 0xFF); //enable all channels
  delay(1);
  writeRegister(STD_SEQ_CTRL_2, 0xFF); //enable all channels
  delay(1);
  // Configuring temperature sensor
  writeRegister(TEMP_CTRL, 0x00); //
  delay(1);
  // Configuring input 0, to go forward as std seq is on
  writeRegister(CONFIG_IN15, 0x18); //write 00001000
  for (int i=0; i<15; i++) { // apply same settings to all 15 other channels
    SPI.transfer(0x18); // refer channel to "COM", unipolar mode, high input Z, OSR of 1
  }
  delay(1);
  writeRegister(AS_SLOT15, 0x0F); //write 00001000
  for (int i=14; i==0; i--) { // apply same settings to all 15 other channels
    SPI.transfer(i); //
  }
  delay(1);
 
  uint8_t vendor_value = readRegister(VENDOR_L);
  VendorChar.writeValue(vendor_value);

  // Configuring Internal LDO
  writeRegister(SETUP, 0x04); //write LDO_EN 0 to disable it. KEEP IN MIND SPI_MODE  0x04 to start conversion
  delay(1);
   // change CS (CNV) pin to LOW to change into acquisition phase
  // Trigger conversion
  //conservation_mode();

}

void conversionPhase()
{
  digitalWrite(CS_PIN,LOW);
  delayMicroseconds(1); // apply t_SCKCNV delay (technically 80ns) to ensure there is a sufficient delay between the final SCK edge and the next CNV rising edge
  digitalWrite(CS_PIN,HIGH); // change CS (CNV) pin to HIGH to initiate conversion phase
  delayMicroseconds(2); // apply t_CONVERSION (technically 415ns) to ensure completion of the conversion phase before the digital host provides the first SCK falling edge.
  digitalWrite(CS_PIN,LOW); // change CS (CNV) pin to LOW to change into acquisition phase
}

uint32_t readData()
{
  conversionPhase();
  uint32_t data;
  SPI.beginTransaction(MP_settings); // begin SPI transaction with the appropriate parameters
  //digitalWrite(CS_PIN,LOW);
  data |= SPI.transfer16(0x0000) << 16;
  data |= SPI.transfer16(0x0000); // send NOOP and read in new set of 16-bit data. THe advanced sequencer has been programmed to follow the channel order
  //digitalWrite(CS_PIN,HIGH);
  SPI.endTransaction(); // conclude SPI transaction until new conversion phase is initiated
  return data;
}

void writeRegister(uint16_t reg_addr, uint8_t reg_data) {
  digitalWrite(CS_PIN, LOW);
  SPI.beginTransaction(MP_settings);
    //Serial.print("Write Address: ");
    //Serial.print((reg_addr >> 8) & 0x7F, HEX);
    //Serial.print(0xFF & reg_addr, HEX);
  SPI.transfer((reg_addr >> 8) & 0x7F); // Write address MSB first
  SPI.transfer(0xFF & reg_addr);
    //Serial.print(", write value: ");
    //Serial.println(reg_data, HEX);
  SPI.transfer(reg_data); // Write value
  SPI.endTransaction();
  digitalWrite(CS_PIN, HIGH);
  delayMicroseconds(10);
}

uint8_t readRegister(uint16_t reg_addr) {
  digitalWrite(CS_PIN, LOW);
  SPI.beginTransaction(MP_settings);
    //Serial.print("Read Address: ");
    //Serial.print((1 << 7) | ((reg_addr >> 8) & 0x7F), HEX);
    //Serial.print(0xFF & reg_addr, HEX);
  SPI.transfer((1 << 7) | ((reg_addr >> 8) & 0x7F)); // Write address MSB first, with a 1 on MSB
  SPI.transfer(0xFF & reg_addr);
  uint8_t result = SPI.transfer(0xFF); // read result
    //Serial.print(", Read Result: ");
    //Serial.println(result, HEX);
  SPI.endTransaction();
  digitalWrite(CS_PIN, HIGH);
  delayMicroseconds(10);
  return result;
}