I am trying to interface the ads124s08 with teensy 3.6 to read data from some batteries. The code is written to configure the ADC for using an unipolar external reference of 5V, Gain set to 1, 4000 SPS and using an external clock from microcontroller. I a using arduino IDE for the purpose.
I am attaching the image of the logic analyser output which is showing the output of ADC as all zero during SPI comunication /resized-image/__size/320x240/__key/communityserver-discussions-components-files/73/WhatsApp-Image-2022_2D00_01_2D00_18-at-12.12.06-AM.jpeg
I have also attached the code that I am using for the purpose
#include<SPI.h> //#include <TimerOne.h> int CS_PIN = 10; int START_PIN = 5; int RESET_PIN = 6; int CKEN_PIN = 13; int DRDY_PIN = 14; int lastSample; int mosi = 11; int miso = 12; SPISettings mySPISettings(4000000, MSBFIRST, SPI_MODE1); #define NUM_REGISTERS 18 //rgeister map #define ID_ADDR_MASK 0x00 #define STATUS_ADDR_MASK 0x01 #define INPMUX_ADDR_MASK 0x02 #define PGA_ADDR_MASK 0x03 #define DATARATE_ADDR_MASK 0x04 #define REF_ADDR_MASK 0x05 #define IDACMAG_ADDR_MASK 0x06 #define IDACMUX_ADDR_MASK 0x07 #define VBIAS_ADDR_MASK 0x08 #define SYS_ADDR_MASK 0x09 #define OFCAL0_ADDR_MASK 0x0A #define OFCAL1_ADDR_MASK 0x0B #define OFCAL2_ADDR_MASK 0x0C #define FSCAL0_ADDR_MASK 0x0D #define FSCAL1_ADDR_MASK 0x0E #define FSCAL2_ADDR_MASK 0x0F #define GPIODAT_ADDR_MASK 0x10 #define GPIOCON_ADDR_MASK 0x11 /* Opcode masks (or "Commands" if you will...) */ #define NOP_OPCODE_MASK 0x00 #define WAKE_OPCODE_MASK 0x02 #define SLEEP_OPCODE_MASK 0x04 #define RESET_OPCODE_MASK 0x06 #define START_OPCODE_MASK 0x08 #define STOP_OPCODE_MASK 0x0A #define SFOCAL_OPCODE_MASK 0x19 #define SYOCAL_OPCODE_MASK 0x16 #define SYGCAL_OPCODE_MASK 0x17 #define RDATA_OPCODE_MASK 0x12 #define REGRD_OPCODE_MASK 0x20 #define REGWR_OPCODE_MASK 0x40 /* Define the ADC positive input channels (MUXP) */ #define ADS_P_AIN0 0x00 #define ADS_P_AIN1 0x10 #define ADS_P_AIN2 0x20 #define ADS_P_AIN3 0x30 #define ADS_P_AIN4 0x40 #define ADS_P_AIN5 0x50 #define ADS_P_AIN6 0x60 #define ADS_P_AIN7 0x70 #define ADS_P_AIN8 0x80 #define ADS_P_AIN9 0x90 #define ADS_P_AIN10 0xA0 #define ADS_P_AIN11 0xB0 #define ADS_P_AINCOM 0xC0 /* Define the ADC negative input channels (MUXN)*/ #define ADS_N_AIN0 0x00 #define ADS_N_AIN1 0x01 #define ADS_N_AIN2 0x02 #define ADS_N_AIN3 0x03 #define ADS_N_AIN4 0x04 #define ADS_N_AIN5 0x05 #define ADS_N_AIN6 0x06 #define ADS_N_AIN7 0x07 #define ADS_N_AIN8 0x08 #define ADS_N_AIN9 0x09 #define ADS_N_AIN10 0x0A #define ADS_N_AIN11 0x0B #define ADS_N_AINCOM 0x0C /* Define PGA control */ #define ADS_PGA_BYPASS 0x00 #define ADS_PGA_ENABLED 0x08 /* Define Gain */ #define ADS_GAIN_1 0x00 #define ADS_GAIN_2 0x01 #define ADS_GAIN_4 0x02 #define ADS_GAIN_8 0x03 #define ADS_GAIN_16 0x04 #define ADS_GAIN_32 0x05 #define ADS_GAIN_64 0x06 #define ADS_GAIN_128 0x07 /System Control register/ #define ADS_SENDSTATUS_DISABLE 0x00 #define ADS_SENDSTATUS_ENABLE 0x01 /Reference Control register/ #define ADS_FLAG_REF_DISABLE 0x00 #define ADS_FLAG_REF_EN_L0 0x40 #define ADS_FLAG_REF_EN_BOTH 0x80 #define ADS_FLAG_REF_EN_10M 0xC0 #define ADS_REFP_BYP_DISABLE 0x20 #define ADS_REFP_BYP_ENABLE 0x00 #define ADS_REFN_BYP_DISABLE 0x10 #define ADS_REFN_BYP_ENABLE 0x00 #define ADS_REFSEL_P0 0x00 #define ADS_REFSEL_P1 0x04 #define ADS_REFSEL_INT 0x08 #define ADS_REFINT_OFF 0x00 #define ADS_REFINT_ON_PDWN 0x01 #define ADS_REFINT_ON_ALWAYS 0x02 /* Flag to signal that we are in the process of collecting data */ #define DATA_MODE_NORMAL 0x00 #define DATA_MODE_STATUS 0x01 #define DATA_MODE_CRC 0x02 class ADS124S08 { // Device command prototypes public: ADS124S08(void); void begin(); char regRead(unsigned int regnum); void readRegs(unsigned int regnum, unsigned int count, uint8_t *data); void regWrite(unsigned int regnum, unsigned char data); void writeRegs(unsigned int regnum, unsigned int howmuch, unsigned char *data); void reStart(void); void sendCommand(uint8_t op_code); int rData(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC); int dataRead(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC); void selectDeviceCSLow(void); void releaseChipSelect(void); void assertStart(void); void deassertStart(void); void assertClock(void); void deassertClock(void); bool converting; uint8_t registers[NUM_REGISTERS]; private: bool fStart; void DRDY_int(void); uint8_t _drdy_pin; uint8_t _start_pin; uint8_t _reset_pin; }adc; ADS124S08::ADS124S08(void) // pin config and reg map { pinMode( CS_PIN, OUTPUT ); pinMode( START_PIN, OUTPUT ); pinMode( RESET_PIN, OUTPUT ); pinMode( CKEN_PIN, OUTPUT ); pinMode( DRDY_PIN, INPUT ); pinMode( mosi, OUTPUT ); pinMode( miso, INPUT ); digitalWrite( START_PIN, LOW ); digitalWrite( RESET_PIN, HIGH ); digitalWrite( CKEN_PIN, LOW ); /* Default register settings */ registers[ID_ADDR_MASK] = 0x08; registers[STATUS_ADDR_MASK] = 0x80; registers[INPMUX_ADDR_MASK] = 0x01; registers[PGA_ADDR_MASK] = 0x00; registers[DATARATE_ADDR_MASK] = 0x14; registers[REF_ADDR_MASK] = 0x10; registers[IDACMAG_ADDR_MASK] = 0x00; registers[IDACMUX_ADDR_MASK] = 0xFF; registers[VBIAS_ADDR_MASK] = 0x00; registers[SYS_ADDR_MASK] = 0x10; registers[OFCAL0_ADDR_MASK] = 0x00; registers[OFCAL1_ADDR_MASK] = 0x00; registers[OFCAL2_ADDR_MASK] = 0x00; registers[FSCAL0_ADDR_MASK] = 0x00; registers[FSCAL1_ADDR_MASK] = 0x00; registers[FSCAL2_ADDR_MASK] = 0x40; registers[GPIODAT_ADDR_MASK] = 0x00; registers[GPIOCON_ADDR_MASK] = 0x00; fStart = false; releaseChipSelect(); deassertStart(); } void ADS124S08::begin() //start transaction { SPI.begin( ); SPI.setBitOrder(MSBFIRST); SPI.setDataMode( SPI_MODE1 ); SPI.setClockDivider(21); //the system clock can be divided by values from 1 to 255. The default value is 21, which sets the clock to 4 MHz like other Arduino boards. #if defined (SPI_HAS_TRANSACTION) mySPISettings = SPISettings(4000000, MSBFIRST, SPI_MODE1); #endif } char ADS124S08::regRead(unsigned int regnum) { int i; uint8_t ulDataTx[3]; uint8_t ulDataRx[3]; ulDataTx[0] = REGRD_OPCODE_MASK + (regnum & 0x1f); ulDataTx[1] = 0x00; ulDataTx[2] = 0x00; selectDeviceCSLow(); #if defined (SPI_HAS_TRANSACTION) SPI.beginTransaction(mySPISettings); #endif for(i = 0; i < 3; i++) ulDataRx[i] = SPI.transfer(ulDataTx[i]); if(regnum < NUM_REGISTERS) registers[regnum] = ulDataRx[2]; #if defined (SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif releaseChipSelect(); //Serial.println("regRead tx: %02x %02x %02x",ulDataTx[0],ulDataTx[1],ulDataTx[2]); //Serial.println("regRead rx: %02x %02x %02x",ulDataRx[0],ulDataRx[1],ulDataRx[2]); return ulDataRx[2]; } void ADS124S08::readRegs(unsigned int regnum, unsigned int count, uint8_t *data) { int i; uint8_t ulDataTx[2]; ulDataTx[0] = REGRD_OPCODE_MASK + (regnum & 0x1f); ulDataTx[1] = count-1; selectDeviceCSLow(); SPI.transfer(ulDataTx[0]); SPI.transfer(ulDataTx[1]); for(i = 0; i < count; i++) { data[i] = SPI.transfer(0); if(regnum+i < NUM_REGISTERS) registers[regnum+i] = data[i]; } releaseChipSelect(); } void ADS124S08::regWrite(unsigned int regnum, unsigned char data) { uint8_t ulDataTx[3]; ulDataTx[0] = REGWR_OPCODE_MASK + (regnum & 0x1f); ulDataTx[1] = 0x00; ulDataTx[2] = data; selectDeviceCSLow(); SPI.transfer(ulDataTx[0]); SPI.transfer(ulDataTx[1]); SPI.transfer(ulDataTx[2]); releaseChipSelect(); //Serial.println("regWrite tx: %02x %02x %02x",ulDataTx[0],ulDataTx[1],ulDataTx[2]); return; } void ADS124S08::writeRegs(unsigned int regnum, unsigned int howmuch, unsigned char *data) { unsigned int i; uint8_t ulDataTx[2]; ulDataTx[0] = REGWR_OPCODE_MASK + (regnum & 0x1f); ulDataTx[1] = howmuch-1; selectDeviceCSLow(); SPI.transfer(ulDataTx[0]); SPI.transfer(ulDataTx[1]); for(i=0; i < howmuch; i++) { SPI.transfer( data[i] ); if(regnum+i < NUM_REGISTERS) registers[regnum+i] = data[i]; } releaseChipSelect(); return; } void ADS124S08::reStart(void) { sendCommand(STOP_OPCODE_MASK); sendCommand(START_OPCODE_MASK); return; } void ADS124S08::sendCommand(uint8_t op_code) { selectDeviceCSLow(); SPI.transfer(op_code); releaseChipSelect(); return; } int ADS124S08::rData(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC) { int result = -1; selectDeviceCSLow(); // according to datasheet chapter 9.5.4.2 Read Data by RDATA Command sendCommand(RDATA_OPCODE_MASK); // if the Status byte is set - grab it uint8_t shouldWeReceiveTheStatusByte = (registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS; if( shouldWeReceiveTheStatusByte ) { dStatus[0] = SPI.transfer(0x00); //Serial.print("status: "); //Serial.print(dStatus[0]); } // get the conversion data (3 bytes) uint8_t data[3]; data[0] = SPI.transfer(0x00); data[1] = SPI.transfer(0x00); data[2] = SPI.transfer(0x00); result = data[0]; result = (result<<8) + data[1]; result = (result<<8) + data[2]; //Serial.println(" 1: %02x 2: %02x, 3: %02x = %d", data[0], data[1], data[2], result); // is CRC enabled? uint8_t isCrcEnabled = (registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC; if( isCrcEnabled ) { dCRC[0] = SPI.transfer(0x00); } releaseChipSelect(); return result; } int ADS124S08::dataRead(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC) { uint8_t xcrc; uint8_t xstatus; int iData; selectDeviceCSLow(); if((registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS) { xstatus = SPI.transfer(0x00); Serial.print("0:"); Serial.print(xstatus); dStatus[0] = (uint8_t)xstatus; } // get the conversion data (3 bytes) uint8_t data[3]; data[0] = SPI.transfer(0x00); data[1] = SPI.transfer(0x00); data[2] = SPI.transfer(0x00); Serial.print(" 1:"); Serial.print(data[0]); Serial.print(" 2:"); Serial.print(data[1]); Serial.print(" 3:"); Serial.println(data[2]); iData = data[0]; iData = (iData<<8) + data[1]; iData = (iData<<8) + data[2]; if((registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC) { xcrc = SPI.transfer(0x00); dCRC[0] = (uint8_t)xcrc; } releaseChipSelect(); return iData ; } void ADS124S08::selectDeviceCSLow(void){ digitalWrite( CS_PIN, LOW ); } void ADS124S08::releaseChipSelect(void){ digitalWrite( CS_PIN, HIGH ); } void ADS124S08::assertStart() { fStart = true; digitalWrite(START_PIN ,HIGH); } void ADS124S08::deassertStart() { fStart = false; digitalWrite(START_PIN, LOW); } void ADS124S08::assertClock() { digitalWrite(CKEN_PIN, 1); } void ADS124S08::deassertClock() { digitalWrite(CKEN_PIN, LOW); } void setup() { Serial.begin(9600); delay(100); adc.begin(); delay(100); adc.sendCommand(RESET_OPCODE_MASK); delay(100); regMap(); configureAdc(); Serial.println("After config"); regMap(); } void loop() { long now = millis(); //uint8_t status; // Check if it's X seconds since last conversion if( now - lastSample > 25 ){ //delay between two conversions taken as 25ms //Serial.print(sampleNumber); //Serial.print(" "); lastSample = now; readData(); } } void configureAdc() { // Make sure the device is awake adc.sendCommand( WAKE_OPCODE_MASK ); // use channel 1 as positive and channel 2 as negative input adc.regWrite( INPMUX_ADDR_MASK, ADS_P_AIN0 + ADS_N_AIN1 ); // mux selection reg: AIN0 - +ve and AIN1 - -ve (default) // set PGA to 1x adc.regWrite( PGA_ADDR_MASK, ADS_PGA_BYPASS + ADS_GAIN_1 ); //Gain setting reg: PGA bypassed(default), gain set to 1 // The IDAC will only work if we enable the internal reference (ref Datasheet 9.3.7) //adc.regWrite( REF_ADDR_MASK, ADS_REFINT_ON_ALWAYS + ADS_REFSEL_P0 ); // use channel 3 as IDAC 1 (excitation current source) //adc.regWrite( IDACMUX_ADDR_MASK, ADS_IDAC1_A2 + ADS_IDAC2_OFF ); //We are not using internal reference // set IDAC 1 to output 500uA //adc.regWrite( IDACMAG_ADDR_MASK, ADS_IDACMAG_500 ); // Turn on status for debugging adc.regWrite( SYS_ADDR_MASK, ADS_SENDSTATUS_ENABLE ); //Status bit while reading data: pg no. 70 in datasheet //Configuring external register adc.regWrite( REF_ADDR_MASK, ADS_FLAG_REF_DISABLE + ADS_REFP_BYP_ENABLE + ADS_REFN_BYP_DISABLE + ADS_REFSEL_P0); //REFP0 and REFN0 as external reference //Configuring the data rate register adc.regWrite( DATARATE_ADDR_MASK, ADS_CLKSEL_EXT + ADS_FILTERTYPE_LL + ADS_DR_4000); adc.reStart(); delay(10); //regMap2(); } void readData() { uint8_t dStatus = 0; uint8_t dData; uint8_t dCRC = 0; int data = 0; /* Read out the results */ data = adc.dataRead(&dStatus, &dData, &dCRC); //call to dataRead() - the 24 bit data stored in iData will be stored in data /* * Need to determine if Status and/or CRC is enabled to transmit as desired */ /*if((adc.registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS) //Not yet completely understood these nested if loops { if((adc.registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC) { Serial.println("Conversion Data 0x%06x with Status 0x%02x and CRC 0x%02x.", data, dStatus, dCRC); } else { //sSerial.println("Conversion Data 0x%06x with Status 0x%02x. DEC %02d", data, dStatus,data); } } else if((adc.registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC) { Serial.println("Conversion Data 0x%06x with CRC 0x%02x.", data, dCRC); } else*/ //{ Serial.println(data,DEC); //This is where the raw conversion result should be available //} /* Set ADC back to the previous configuration */ //adc.sendCommand(STOP_OPCODE_MASK); //adc.sendCommand(SLEEP_OPCODE_MASK); //return dStatus; } void regMap(void) { unsigned int index; char cTemp; Serial.println("Register Contents"); Serial.println("---------------------"); for(index=0; index < 18 ; index++) { cTemp = adc.regRead(index); Serial.println(index, cTemp); } }