This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS1256: ads1256

Part Number: ADS1256

hello sir, actually i am trying to read the adc of ads1256 in differential mode. So now i have read the adc data from AIN0-AIN1 that is channel 0 output, but similarly i cant able to read the adc data from channel 1 ,channel 2 and channel 3. i don't know its hardware connection problem or software side problem please help me to come out from this.

  • Hi Sagar,

    Can you explain what happens when you try to read data from the other channels? What do you receive on DOUT?

    Have you tried reading back the registers to make sure they are set as you intended? If yes, please send me the readback so I can see how the ADC is configured.

    -Bryan

  • hello, yes i have set my registers to read for all channels. when i connect on board potentiometer and LDR to AIN0-AIN1 i can able to read the data but similarly when i get connected to AIN2-AIN7 i got zero's So don't know what is happening here, i think i need your support.

    import config
    import RPi.GPIO as GPIO
    
    
    ScanMode = 0
    
    
    # gain channel
    ADS1256_GAIN_E = {'ADS1256_GAIN_1' : 0, # GAIN   1
                      'ADS1256_GAIN_2' : 1,	# GAIN   2
                      'ADS1256_GAIN_4' : 2,	# GAIN   4
                      'ADS1256_GAIN_8' : 3,	# GAIN   8
                      'ADS1256_GAIN_16' : 4,# GAIN  16
                      'ADS1256_GAIN_32' : 5,# GAIN  32
                      'ADS1256_GAIN_64' : 6,# GAIN  64
                     }
    
    # data rate
    ADS1256_DRATE_E = {'ADS1256_30000SPS' : 0xF0, # reset the default values
                       'ADS1256_15000SPS' : 0xE0,
                       'ADS1256_7500SPS' : 0xD0,
                       'ADS1256_3750SPS' : 0xC0,
                       'ADS1256_2000SPS' : 0xB0,
                       'ADS1256_1000SPS' : 0xA1,
                       'ADS1256_500SPS' : 0x92,
                       'ADS1256_100SPS' : 0x82,
                       'ADS1256_60SPS' : 0x72,
                       'ADS1256_50SPS' : 0x63,
                       'ADS1256_30SPS' : 0x53,
                       'ADS1256_25SPS' : 0x43,
                       'ADS1256_15SPS' : 0x33,
                       'ADS1256_10SPS' : 0x20,
                       'ADS1256_5SPS' : 0x13,
                       'ADS1256_2d5SPS' : 0x03
                      }
    
    # registration definition
    REG_E = {'REG_STATUS' : 0,  # x1H
             'REG_MUX'    : 1,  # 01H
             'REG_ADCON'  : 2,  # 20H
             'REG_DRATE'  : 3,  # F0H
             'REG_IO'     : 4,  # E0H
             'REG_OFC0'   : 5,  # xxH
             'REG_OFC1'   : 6,  # xxH
             'REG_OFC2'   : 7,  # xxH
             'REG_FSC0'   : 8,  # xxH
             'REG_FSC1'   : 9,  # xxH
             'REG_FSC2'   : 10, # xxH
            }
    
    # command definition
    CMD = {'CMD_WAKEUP' : 0x00,     # Completes SYNC and Exits Standby Mode 0000  0000 (00h)
           'CMD_RDATA' : 0x01,      # Read Data 0000  0001 (01h)
           'CMD_RDATAC' : 0x03,     # Read Data Continuously 0000   0011 (03h)
           'CMD_SDATAC' : 0x0F,     # Stop Read Data Continuously 0000   1111 (0Fh)
           'CMD_RREG' : 0x10,       # Read from REG rrr 0001 rrrr (1xh)
           'CMD_WREG' : 0x50,       # Write to REG rrr 0101 rrrr (5xh)
           'CMD_SELFCAL' : 0xF0,    # Offset and Gain Self-Calibration 1111    0000 (F0h)
           'CMD_SELFOCAL' : 0xF1,   # Offset Self-Calibration 1111    0001 (F1h)
           'CMD_SELFGCAL' : 0xF2,   # Gain Self-Calibration 1111    0010 (F2h)
           'CMD_SYSOCAL' : 0xF3,    # System Offset Calibration 1111   0011 (F3h)
           'CMD_SYSGCAL' : 0xF4,    # System Gain Calibration 1111    0100 (F4h)
           'CMD_SYNC' : 0xFC,       # Synchronize the A/D Conversion 1111   1100 (FCh)
           'CMD_STANDBY' : 0xFD,    # Begin Standby Mode 1111   1101 (FDh)
           'CMD_RESET' : 0xFE,      # Reset to Power-Up Values 1111   1110 (FEh)
          }
    
    class ADS1256:
        def __init__(self):
            self.rst_pin = config.RST_PIN
            self.cs_pin = config.CS_PIN
            self.drdy_pin = config.DRDY_PIN
    
        # Hardware reset
        def ADS1256_reset(self):
            config.digital_write(self.rst_pin, GPIO.HIGH)
            config.delay_ms(200)
            config.digital_write(self.rst_pin, GPIO.LOW)
            config.delay_ms(200)
            config.digital_write(self.rst_pin, GPIO.HIGH)
        
        def ADS1256_WriteCmd(self, reg):
            config.digital_write(self.cs_pin, GPIO.LOW)#cs  0     ////low means enables the CS0 
            config.spi_writebyte([reg])
            config.digital_write(self.cs_pin, GPIO.HIGH)#cs 1    ////high means disables the CS1 
        
        def ADS1256_WriteReg(self, reg, data):
            config.digital_write(self.cs_pin, GPIO.LOW)#cs  0           ////low means enables the CS0 
            config.spi_writebyte([CMD['CMD_WREG'] | reg, 0x00, data])
            config.digital_write(self.cs_pin, GPIO.HIGH)#cs 1           ////low means disables the CS1
            
        def ADS1256_Read_data(self, reg):
            config.digital_write(self.cs_pin, GPIO.LOW)#cs  0       ////low means enables the CS0 
            config.spi_writebyte([CMD['CMD_RREG'] | reg, 0x00])
            data = config.spi_readbytes(1)
            config.digital_write(self.cs_pin, GPIO.HIGH)#cs 1      ////low means disables the CS1
    
            return data
            
        def ADS1256_WaitDRDY(self):
            for i in range(0,400000,1):
                if(config.digital_read(self.drdy_pin) == 0):
                    
                    break
            if(i >= 400000):
                print ("Time Out ...\r\n")
            
            
        def ADS1256_ReadChipID(self):
            self.ADS1256_WaitDRDY()
            id = self.ADS1256_Read_data(REG_E['REG_STATUS'])
            id = id[0] >> 4
            # print 'ID',id
            return id
            
        #The configuration parameters of ADC, gain and data rate
        def ADS1256_ConfigADC(self, gain, drate):
            self.ADS1256_WaitDRDY()
            buf = [0,0,0,0,0,0,0,0]
            buf[0] = (0<<3) | (1<<2) | (0<<1)
            buf[1] = 0x08
            buf[2] = (0<<5) | (0<<3) | (gain<<0)
            buf[3] = drate
            
            config.digital_write(self.cs_pin, GPIO.LOW)#cs  0
            config.spi_writebyte([CMD['CMD_WREG'] | 0, 0x03])
            config.spi_writebyte(buf)
            
            config.digital_write(self.cs_pin, GPIO.HIGH)#cs 1
            config.delay_ms(1) 
    
    
    
        def ADS1256_SetChannal(self, Channal):
            if Channal > 7:
                return 0
            self.ADS1256_WriteReg(REG_E['REG_MUX'], (Channal<<4) | (1<<3))
    
        def ADS1256_SetDiffChannal(self, Channal):
            if Channal == 0:
                self.ADS1256_WriteReg(REG_E['REG_MUX'], (0 << 4) | 1) 	#DiffChannal  AIN0-AIN1
            elif Channal == 1:
                self.ADS1256_WriteReg(REG_E['REG_MUX'], (2 << 4) | 3) 	#DiffChannal   AIN2-AIN3
            elif Channal == 2:
                self.ADS1256_WriteReg(REG_E['REG_MUX'], (4 << 4) | 5) 	#DiffChannal    AIN4-AIN5
            elif Channal == 3:
                self.ADS1256_WriteReg(REG_E['REG_MUX'], (6 << 4) | 7) 	#DiffChannal   AIN6-AIN7
    
        def ADS1256_SetMode(self, Mode):
            ScanMode = Mode
    
        def ADS1256_init(self):
            if (config.module_init() != 0):
                return -1
            self.ADS1256_reset()
            id = self.ADS1256_ReadChipID()
            if id == 3 :
                print("ID Read success  ")
            else:
                print("ID Read failed   ")
                return -1
            self.ADS1256_ConfigADC(ADS1256_GAIN_E['ADS1256_GAIN_1'], ADS1256_DRATE_E['ADS1256_30000SPS'])
            return 0
            
        def ADS1256_Read_ADC_Data(self):
            self.ADS1256_WaitDRDY()
            config.digital_write(self.cs_pin, GPIO.LOW)#cs  0
            config.spi_writebyte([CMD['CMD_RDATA']])
            # config.delay_ms(10)
    
            buf = config.spi_readbytes(3)
            config.digital_write(self.cs_pin, GPIO.HIGH)#cs 1
            read = (buf[0]<<16) & 0xff0000
            read |= (buf[1]<<8) & 0xff00
            read |= (buf[2]) & 0xff
            if (read & 0x800000):
                read &= 0xF000000
            return read
     
        def ADS1256_GetChannalValue(self, Channel):
            if(ScanMode == 0):# 0  Single-ended input  8 channel1 Differential input  4 channe 
                if(Channel>=8):
                    return 0
                self.ADS1256_SetChannal(Channel)
                self.ADS1256_WriteCmd(CMD['CMD_SYNC'])
                # config.delay_ms(10)
                self.ADS1256_WriteCmd(CMD['CMD_WAKEUP'])
                # config.delay_ms(200)
                Value = self.ADS1256_Read_ADC_Data()
            else:
                if(Channel>=4):
                    return 0
                self.ADS1256_SetDiffChannal(Channel)
                self.ADS1256_WriteCmd(CMD['CMD_SYNC'])
                # config.delay_ms(10) 
                self.ADS1256_WriteCmd(CMD['CMD_WAKEUP'])
                # config.delay_ms(10) 
                Value = self.ADS1256_Read_ADC_Data()
            return Value
            
        def ADS1256_GetAll(self):
            ADC_Value = [0,0,0,0,0,0,0,0]
            for i in range(0,8,1):
                ADC_Value[i] = self.ADS1256_GetChannalValue(i)
            return ADC_Value
    ### END OF FILE ###
    
    ##this is ADS1256 file/ADS1256.py
    *****************************************************************************
    ## this is config file/config.py
    import spidev
    import RPi.GPIO as GPIO
    import time
    
    # Pin definition
    RST_PIN         = 18
    CS_PIN       = 22
    DRDY_PIN        = 17
    
    # SPI device, bus = 0, device = 0
    SPI = spidev.SpiDev(0, 0)
    
    def digital_write(pin, value):
        GPIO.output(pin, value)
    
    def digital_read(pin):
        return GPIO.input(DRDY_PIN)
    
    def delay_ms(delaytime):
        time.sleep(delaytime // 1000.0)
    
    def spi_writebyte(data):
        SPI.writebytes(data)
        
    def spi_readbytes(reg):
        return SPI.readbytes(reg)
        
    
    def module_init():
        GPIO.setmode(GPIO.BCM)
        GPIO.setwarnings(False)
        GPIO.setup(RST_PIN, GPIO.OUT)
        GPIO.setup(CS_PIN, GPIO.OUT)
        #GPIO.setup(DRDY_PIN, GPIO.IN)
        GPIO.setup(DRDY_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        SPI.max_speed_hz = 20000
        SPI.mode = 0b01
        return 0;
    
    ### END OF FILE ###
    ********************************************************************************
    ##this is my main.file/main.py
    import time
    import ADS1256
    import RPi.GPIO as GPIO
    
    
    try:
        ADC = ADS1256.ADS1256()
        ADC.ADS1256_init()
    
        while(1):
            ADC_Value = ADC.ADS1256_GetAll()
            print ("0 ADC = %lf"%(ADC_Value[0]*5.0/0x7fffff))
            print ("1 ADC = %lf"%(ADC_Value[1]*5.0/0x7fffff))
            print ("2 ADC = %lf"%(ADC_Value[2]*5.0/0x7fffff))
            print ("3 ADC = %lf"%(ADC_Value[3]*5.0/0x7fffff))
            print ("4 ADC = %lf"%(ADC_Value[4]*5.0/0x7fffff))
            print ("5 ADC = %lf"%(ADC_Value[5]*5.0/0x7fffff))
            print ("6 ADC = %lf"%(ADC_Value[6]*5.0/0x7fffff))
            print ("7 ADC = %lf"%(ADC_Value[7]*5.0/0x7fffff))
            print ("\33[9A")
    
            
    except :
        GPIO.cleanup()
        print ("\r\nProgram end     ")
        exit()
    *******************************************************************************
    
     

  • attached file is my raspberry pi CM4 code 

  • Hi Sagar,

    When you perform the register readback after sending the commands to switch channels, do the registers read the correct data? In other words, do you see that the input mux values have changed to reflect the new channel selections e.g. MUXP = AIN2 and MUXN = AIN3? Or are they stuck at AIN0 and AIN1? You might also try just connecting a 1V signal from a bench source to the input to eliminate any possible errors coming from the sensor.

    Do you have a logic analyzer so we can see how you are communicating to the ADC and how the ADC responds? This will also verify that the timing is correct, which is something that you cannot confirm by looking at the code.

    -Bryan

  • hello, actually i have connected my AC supply 0.46 mv which converted from 230v(AC) , to AIN0,AIN2,AIN4,AIN6 and AIN1,AIN3,AIN5,AIN7 to AGND for differential mode so for respective inputs i should get a 4 channel outputs like channel 0,channel 1,channel 2 & channel 3. But i can only able to read a data from channel 0 the output is in 25 to 27 mv for positive half cycle and -16 to -18 mv for negative half cycle. 

    what you have mentioned above like the MUX register has changed for different channels i agree that and in my shared code for differential mode i wrote a code i hope which make sense. that is for each channels out of 4 i have write a data to MUX register that leads to switch for different channels .

    and one more thing that i don't have any logic analyzer so for remaining channels like channel 1, channel 2, channel 3 i got only 0v only for Vref=2.5v. I hope that you will help me to resolve this problem. 

    the differential channel code of mine is attached below i respect you to please check it out.

        
    //**********************************************************************//
        
        def ADS1256_SetDiffChannal(self, Channal):
            if Channal == 0:
                self.ADS1256_WriteReg(REG_E['REG_MUX'], (0 << 4) | 1) 	#DiffChannal  AIN0-AIN1
            elif Channal == 1:
                self.ADS1256_WriteReg(REG_E['REG_MUX'], (2 << 4) | 3) 	#DiffChannal   AIN2-AIN3
            elif Channal == 2:
                self.ADS1256_WriteReg(REG_E['REG_MUX'], (4 << 4) | 5) 	#DiffChannal    AIN4-AIN5
            elif Channal == 3:
                self.ADS1256_WriteReg(REG_E['REG_MUX'], (6 << 4) | 7) 	#DiffChannal   AIN6-AIN7
    
    
    ///********************************************************************//

  • sorry that is not 0.46 mv its 0.46 v(AC)

  • Hi Sagar,

    The default configuration on the ADS1256 is measuring between AIN0 and AIN1. Since this configuration works correctly, it seems like somehow the ADC is not recognizing the WREG commands you are sending to the change the registers to AIN2/AIN3, AIN4/AIN5, etc.

    Have you tried reading back the registers to see if they actually change?

    Can you try changing other registers e.g. gain or data rate, and seeing if the ADC output changes? If you change the gain from 1 to 2, does the ADC output code double? If you change the data rate to something much slower, does data come out of the ADC at that same rate?

    If the registers don't change then somewhere you have a communication issue. And unfortunately, you might have good code but the timing might be off, which you really can only determine with a logic analyzer or oscilloscope. You could also have set the SPI mode incorrectly in the MCU, which again is easily seen in a scope shot but not always easy to determine from the code, as some MCU SPI peripherals don't have the same conventions for the different SPI modes.

    In other words, I don't think just looking at the code will solve this issue. You will need additional tools to help track down the source of this error.

    -Bryan

  • hello, actually i have changed data rate from 2.5 SPS to 2000 SPS and i have seen the changes in output data rate for channel 0 but i haven't change the gain value only i have used  gain=1. After listening to you now i  am getting doubts on my hardware connection of ADS1256 with my RPI CM4 but the ADS1256 wave share  what they have mentioned a hardware connection i followed that only .So ok i will check with oscilloscope and i will update to you.

    thanks for your reply

  • Hi Sagar,

    Make sure there is a solid ground connection between multiple boards. This can lead to communication issues.

    Also, a quick test would be to read back the registers after writing to them, to make sure the changes took place. If the ADC is switching to the correct channels e.g. AIN2 and AIN3, then something else is wrong.

    -Bryan

  • hello ,yes i got output from three channels channel 0,channel 1,channel 2 there is problem with ground connection between multiple boards, thank you so much Bryan.

    but now one more thing that i need to know how to make sure that we are getting correct output.  

  • Hi Sagar,

    I thought you had already determined that you were getting the correct output from AIN0/AIN1? Can you not just use the same procedure for determining the correct output from the other channels?

    If not, please let me know what you are doing to translate the ADC output code to a voltage?

    -Bryan

  • hello, at first i have given a input to AIN0-AIN1 with on board potentiometer and LDR so final output value can be get by doing a calculation to reading ADC value that is , final output =ADCValue*5.0/0x7fffff so this is how i have done calculation and final output will be within 5V .But now i have given 0.46V AC which is converted from 230V AC with some resistor circuit  so now i got 26-28 mv as  a output with respect to calculation  output=ADCValue*230/0x7fffff. So is that i should get output voltage peak to peak  is 26-28 mv or i should get voltage peak to peak  is 230 V /??.  

  • Hi Sagar,

    If you are trying to measure an AC signal, then you would need to convert the ADC codes to voltage and then plot them to see how faithfully they recreate the original sinewave.

    To convert an ADC code to voltage, first convert the hex/binary values to decimal. Keep in mind that since the ADS1256 output codes are given in binary 2's complement, any ADC code whose most significant bit (MSB) is a 1 is a negative decimal value while codes whose MSB is 0 are positive decimal values.

    Next,  determine the value of one least significant bit (LSB). For the ADS1256, the code range extends from -2*VREF/GAIN to +2*VREF/GAIN, for a full-scale range (FSR) of 4*VREF/GAIN. If VREF = 2.5V and Gain = 8 for example, then the FSR = 4*2.5/8 = 1.25V (you can adjust these values based on your specific system settings). To find the value of one LSB, divide the FSR by the total number of codes, which in this case is 2^24. So 1x LSB = FSR / 2^24 for the ADS1256.

    Now all you need to do is multiply 1 LSB by the decimal value of the ADC code, resulting in the corresponding voltage. You can now plot these values to see if they accurately recreate the sinewave you applied to the ADC.

    Also, remember that the ADS1256 is not really intended to convert negative voltages (with respect to AGND). So if your AC signal is not offset to / centered at some higher voltage (e.g. 1V), you may be violating the input range requirements on the ADS1256.

    -Bryan

  • hi Bryan,

    yes what you have said, the same thing i have done before in my code i mean to convert ADC into voltage but the value i got finally is in range almost zero like 0.0XXX so for this i thought i should multiply with 230 *Vref / 0x7fffff  so then only i got 26-28 mv still i am not sure about this output that's why  i have raised query. So now tell me that if i do conversion with this FSR  that is 2*Vref /0x7fffff the output will be almost zero may be its in mv or micro volts since how to convert this into my input AC voltage and how can i identify the max value, min value and how to find the peak to peak voltage??    

  • Hi Sagar,

    I would always suggest starting with a "simple" signal, like a 1V DC input, to test and make sure everything is working properly. If you have a precision source you can use different values to test different gain settings, etc., to be sure all of your channels are working properly (and are not very noisy). Then you can move on to more "complex" signals, like a sinewave. But right now it is hard to determine if the error you are seeing is coming from the signal source, the signal chain, or even the computations in the code. When you put a 1V signal in you know you should get a 1V signal out - with the signals you have right now, it does not seem like it is even clear what the output should be, so I would start much simpler.

    Once you have your data, would you not just run an algorithm that pulls out the min and max value, as well as calculates the PP voltage? I am not really sure I understand the last request, as this is just math you perform on the final dataset. It doesn't really have anything to do with the ADC.

    -Bryan

  • hi Bryan,

    yes i have check with the 1v first and i got output 0.999v that's cool and now i have connect with  0.46 V(AC) which is converted from 230 V(AC) and i have used FSR like 2*Vref /2^23 here Vref=2.5V. So after creating 1 LSB byte, i just multiplied  with ADC raw data and i got 0.5 V as output , now tell me that how i can covert the data into actual input voltage . yes i can do some trial and error calculation to convert the output data into actual input voltage but i need a scientific exact calculation to convert it into input voltage even i have seen datasheet  and lot of forums but i didn't get any idea from that.

    -Sagar

  • Hi Sagar,

    It sounds like the ADC is working appropriately on all channels then, which is the desired result.

    how i can covert the data into actual input voltage

    I am a bit confused by this question. If you put 0.46V in, and got 0.5V out, that is pretty close (though there must be some noise/error in your system, unless the input signal is not exactly 0.46V). But importantly this confirms that the ADC is converting this signal correctly, and your code-to-voltage conversion is also correct.

    So, what do you need from us? There is not much we can tell you about your input signal - that is really for you to determine.

    -Bryan

  • hello Bryan,

    from code to voltage conversion is ok but i need to convert this 0.5 V into 230 V. So for that calculation part i need your help ,Because i need to recreate the sine wave at the output side. 

    -Sagar

  • Hi Sagar,

    Would you not just convert the ADC code to voltage then multiply that voltage by the attenuation factor from the resistor divider circuit?

    So if your divider 230V results in a 0.46V output, then your attenuation factor is 230/0.46 = 500. So whatever voltage value you receive from the ADC you would just multiple by 500 to get the actual voltage.

    I would also expect that you would plot the voltage values from the ADC to make sure you are getting a clean sinewave. Then you would perform a lookup function on this dataset to determine the min and max values.

    -Bryan

  • hello Bryan,

    yes i got it. thank you so much BryanSmiley

  • You are welcome, Sagar!