[SOLVED] MAX1416 SPI interface with Arduino

Hi!
I'm loosing my days with this ADC... I can't get it work!
I found few threads in other forums but nothing that really works!
From datasheet i learned:

  • SPI mode is 3. Clock base value is HIGH and data are sampled at rising edge.
  • CS(SS) i have to set SS LOW before communicate with ADC in both directions,then set it to HIGH.

My circuit is the following ( ADC on the left, Arduino on the right):

1 SCLK - SCK D13
2 CLKIN - GND
3 CLKOUT - NC
4 !CS - D8
5 !RESET - 5V
6 AIN2+ - NC
7 AIN1+ - Analog sensor pin +
8 AIN1- Analog sensor pin -
9 REF+ - 5V
10 REF- - GND
11 AIN2- - NC
12 !DRDY - D9
13 DOUT - MISO D12
14 DIN - MOSI D11
15 Vdd - 5V
16 GND - GND

and here is the code :

#include "SPI.h"

#define DRDY 9
#define SPICLOCK 13

int ss=8;
unsigned int adcValue;

 
void setup()
{
  pinMode(ss, OUTPUT);
  digitalWrite(SPICLOCK,HIGH);
  digitalWrite(ss,HIGH);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);
  //SPI.setClockDivider(SPI_CLOCK_DIV16);
   
  Serial.begin(9600);
  
  delay(300);
}
 
void MAX1416_Config()//You can modify it for handle channels
{
  //series of commandbit    
  digitalWrite(ss,LOW); // Enable ADC SPI
  
  //Write OP
  SPI.transfer(0x20);//command for comm reg to select ch1 and write to clock register 
  SPI.transfer(0xA5);//command for clock reg to set 2,4576Mhz                                  
  //End Write OP
  
  //Write OP
  SPI.transfer(0x10);//command for comm reg to write setup register                          
  SPI.transfer(0x44);//command for setup reg to self calibration,unipolar,unbuffered,     
  //End Write OP

  digitalWrite(ss,HIGH); // Disable ADC SPI
}
 
void MAX1416_WaitForData_Soft() 
{
      char DataNotReady = 0x80;
      
      digitalWrite(ss,LOW); // Enable ADC SPI
      
      while(DataNotReady) // wait for end of conversion 
      {
          // Read OP
          SPI.transfer(0x08);//command for comm reg to read  (dec   8)
          DataNotReady =SPI.transfer(0x00); // Read comm register
          // End Read OP
          
          DataNotReady &= 0x80;
      }
      
      digitalWrite(ss,HIGH); // Disable ADC SPI
}

void MAX1416_WaitForData_Hard() 
{
      char DataNotReady = 1;
      char value;

      while(DataNotReady) // wait for end of conversion 
      {
          // Read OP
          value = digitalRead(DRDY); // Read comm register
           if (value == LOW)
             DataNotReady = 0;
          // End Read OP
          Serial.println("NOT READY");
      }
}

byte MAX1416_ReadSetupReg() //You can modify it to read other channels
{

      byte myByte;
      
      digitalWrite(ss,LOW); // Enable ADC SPI
      
      // READ Data OPERATION
      SPI.transfer(0x18);//command for the comm to read register register 00011000
      //read 8bit of data
      myByte = SPI.transfer(0x00);
      // End Read Data
      Serial.println(myByte,BIN);
      delay(2000);
      digitalWrite(ss,HIGH); // Disable ADC SPI
    
      
      return myByte;
}

 
unsigned int MAX1416_ReadCH0Data() //You can modify it to read other channels
{
      unsigned int uiData;
      byte highByte;
      byte lowByte;
      
      digitalWrite(ss,LOW); // Enable ADC SPI
      
      // READ Data OPERATION
      SPI.transfer(0x38);//command for the comm to read data register for channel 1 (dec  56)
      //read 16bit of data ADC
      highByte = SPI.transfer(0x00);
      lowByte = SPI.transfer(0x00);
      // End Read Data
      
      digitalWrite(ss,HIGH); // Disable ADC SPI
    
      
      uiData = highByte << 8;
      uiData |= lowByte;
      
      return uiData;
}
 
void loop()
{
  //digitalWrite(ss,LOW); // Enable ADC SPI
  delay(100); 
  MAX1416_Config();
  delay(100);
  while(1)
  {
      MAX1416_ReadSetupReg();
      //MAX1416_WaitForData_Soft() ;
      //MAX1416_WaitForData_Hard() ;
      delay(10);
      adcValue = MAX1416_ReadCH0Data();
      Serial.print("analog value =");
      Serial.println(adcValue, DEC );
      Serial.print('\n');
      
  }
  //digitalWrite(ss,HIGH); // Enable ADC SPI

}

Some considerations:

  • If i disable DRDY hardware polling, i always read 0. If i enable it i can't read from ADC cause data isn't ready.
  • If i read from Setup register i get 0...and that is not valid.
  • With DRDY software pooling, data is ready but the value is always 0.
  • With DRDY software pooling, data is ready but the value is always 0.

Datasheet is available at: Mixed-signal and digital signal processing ICs | Analog Devices

Any help is appreciated!
Thanks,
Protoinfy

SPI.transfer(0xA5);//command for clock reg to set 2,4576Mhz

From the datasheet I'd say this should be 0x22. The first two bits (6 and 7, MSB) are ignored, so they can be 0, you want the internal clock enabled, so bit 5 is set. Bit 4 is 0 as clock should be enabled. Clock divider is used only for external clock sources (so bit 3 is 0) and Clock Select must be one to enable internal 2.4576MHz clock (bit 2 = 1). Filter Select is used only for external clock sources so both bits (0 and 1) can be 0.

I'd change this line

uiData = highByte << 8;

to

uiData = highByte;
uiData <<= 8;

because a left shift of 8 bits within a byte does not make that much sense.

Except these little changes I cannot find an error in your code.

Do you get 0 for the setup register too or just for the analog read value? Can you post the actual output you get on the serial?

Thanks pylon for your reply!
Good news! After few changes I manage to get max1416 work!
Command to SETUP register was right and also the bit shift code was working , but i'll use yours, cleaner than mine.
I really don't see relevant differences with code in first post, but something in code and/or circuit changed and now it's working!

This is my code, someone could find this useful:

#include "SPI.h"

#define DRDY 9
#define ADCRST 2
#define SPICLOCK 13

int ss=8;
unsigned int adcValue;

 
void setup()
{
  delay(100);
  pinMode(ss, OUTPUT);
  pinMode(DRDY, INPUT);
  pinMode(ADCRST, OUTPUT);
  
  digitalWrite(ss,HIGH);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  digitalWrite(SPICLOCK,HIGH);
  digitalWrite(ADCRST,HIGH);
  delay(1000);
  digitalWrite(ADCRST,LOW);
  delay(1000);
  digitalWrite(ADCRST,HIGH);
  delay(1000);
  
  Serial.begin(9600);
  
  delay(300);
}

void MAX1416_SerialInit()//You can modify it for handle channels
{
  //series of commandbit    
  digitalWrite(ss,LOW); // Enable ADC SPI
  
  SPI.transfer(0xFF);
  SPI.transfer(0xFF);  
  SPI.transfer(0xFF); 
  SPI.transfer(0xFF);

  digitalWrite(ss,HIGH); // Disable ADC SPI
}
 
void MAX1416_Config()//You can modify it for handle channels
{
  //series of commandbit    
  digitalWrite(ss,LOW); // Enable ADC SPI
  
  //Write OP
  SPI.transfer(0x20);//command for comm reg to select ch1 and write to clock register 
  delay(100);
  SPI.transfer(0xA7);//command for clock reg to set 2,4576Mhz                                  
  //End Write OP
  delay(100);
  //Write OP
  SPI.transfer(0x10);//command for comm reg to write setup register 
  delay(100);
  SPI.transfer(0x44);//command for setup reg to self calibration,unipolar,unbuffered,     
  //End Write OP

  digitalWrite(ss,HIGH); // Disable ADC SPI
}
 
void MAX1416_WaitForData_Soft() 
{
      char DataNotReady = 0x80;
      
      digitalWrite(ss,LOW); // Enable ADC SPI
      
      while(DataNotReady) // wait for end of conversion 
      {
          // Read OP
          SPI.transfer(0x08);//command for comm reg to read  (dec   8)
          DataNotReady =SPI.transfer(0x00); // Read comm register
          // End Read OP
          Serial.println(DataNotReady,BIN);
          DataNotReady &= 0x80;
      }
      
      digitalWrite(ss,HIGH); // Disable ADC SPI
}

void MAX1416_WaitForData_Hard() 
{
      char DataNotReady = 1;
      char value;

      while(DataNotReady) // wait for end of conversion 
      {
          // Read OP
          value = digitalRead(DRDY); // Read comm register
           if (value == LOW)
             DataNotReady = 0;
           else
             DataNotReady = 1;
          // End Read OP
          //Serial.println("NOT READY");
      }
}

byte MAX1416_ReadSetupReg() //You can modify it to read other channels
{

      byte myByte;
      
      digitalWrite(ss,LOW); // Enable ADC SPI
      
      // READ Data OPERATION
      SPI.transfer(0x18);//command for the comm to read register register 00011000
      //read 8bit of data
      myByte = SPI.transfer(0x00);
      // End Read Data
      Serial.print(myByte,BIN);
      //delay(2000);
      digitalWrite(ss,HIGH); // Disable ADC SPI
    
      
      return myByte;
}

 
unsigned int MAX1416_ReadCH0Data() //You can modify it to read other channels
{
      unsigned int uiData;
      byte highByte;
      byte lowByte;
      
      digitalWrite(ss,LOW); // Enable ADC SPI
      
      // READ Data OPERATION
      SPI.transfer(0x38);//command for the comm to read data register for channel 1 (dec  56)
      //read 16bit of data ADC
      highByte = SPI.transfer(0x00);
      lowByte = SPI.transfer(0x00);
      // End Read Data
      
      digitalWrite(ss,HIGH); // Disable ADC SPI
    
      
      uiData = highByte;
      uiData <<= 8;
      uiData |= lowByte;
      
      return uiData;
}
 
void loop()
{
  //digitalWrite(ss,LOW); // Enable ADC SPI
  delay(100); 
  MAX1416_Config();
  delay(100);
  double volt;
  MAX1416_ReadSetupReg();
  while(1)
  {
      
      //MAX1416_WaitForData_Soft() ;
      MAX1416_WaitForData_Hard() ;
      delay(10);
      adcValue = MAX1416_ReadCH0Data();
      Serial.print("analog value =");
      Serial.print(adcValue);
      volt=double(adcValue)*5/65535;
      Serial.print(" volt =");
      Serial.println(volt,4);
      
  }
  digitalWrite(ss,HIGH); // Enable ADC SPI

}