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.

ADS122C04: ADC reading photodiode Constant Output. Interacing ADC with raspberry pi 4 using I2C.Review Circuit and code.

Part Number: ADS122C04

Hii,

I am trying to read photodiode value using ADS122C04 using raspberry pi4 with i2c.But i am getting constant output as change in input(Photodiode value).

Please correct me if any change in circuit i am using following circuit..

The following is the library for ADS122C04 i am using 

import RPi.GPIO as GPIO
from time import sleep
from smbus2 import SMBus, i2c_msg

class ADS122C04:
    CMD_RESET               = 0x06
    CMD_START_SYNC          = 0x08
    CMD_POWERDOWN           = 0x02
    CMD_RDATA               = 0x10
    CMD_RREG                = 0x20
    CMD_WREG                = 0x40

    MUX_MASK                = 0x1F
    MUX_DIF_0_1             = 0x00
    MUX_DIF_0_2             = 0x10
    MUX_DIF_0_3             = 0x20
    MUX_DIF_1_0             = 0x30
    MUX_DIF_1_2             = 0x40
    MUX_DIF_1_3             = 0x50
    MUX_DIF_2_3             = 0x60
    MUX_DIF_3_2             = 0x70
    MUX_SINGLE_0            = 0x80
    MUX_SINGLE_1            = 0x90
    MUX_SINGLE_2            = 0xa0
    MUX_SINGLE_3            = 0xb0
    MUX_REFPmREFN           = 0xc0
    MUX_AVDDmAVSS           = 0xd0
    MUX_SHORTED             = 0xe0

    GAIN_MASK               = 0xF3
    GAIN_1                  = 0x00
    GAIN_2                  = 0x10
    GAIN_4                  = 0x20
    GAIN_8                  = 0x30
    GAIN_16                 = 0x40
    GAIN_32                 = 0x50
    GAIN_64                 = 0x60
    GAIN_128                = 0x70

    PGA_DISABLED            = 0x1
    PGA_ENABLED             = 0x0

    DATA_RATE_MASK          = 0xF3
    DATA_RATE_20SPS         = 0x00
    DATA_RATE_45SPS         = 0x10
    DATA_RATE_90SPS         = 0x20
    DATA_RATE_175SPS        = 0x30
    DATA_RATE_330SPS        = 0x40
    DATA_RATE_600SPS        = 0x50
    DATA_RATE_1000SPS       = 0x60

    OP_MODE_NORMAL          = 0x00
    OP_MODE_TURBO           = 0x10

    MODE_MASK               = 0xFD
    MODE_SINGLESHOT         = 0x00
    MODE_CONTINUOUS         = 0x02

    VREF_INTERNAL           = 0x00
    VREF_EXTERNAL           = 0x10
    VREF_AVDD               = 0x20

    ### TEMP SENSOR MODE
    TEMP_SENSOR_OFF         = 0x00
    TEMP_SENSOR_ON          = 0x10
    
    #### --- Configuration Register 2
    ### DATA COUNTER ENABLE
    DCNT_DISABLE            = 0x00
    DCNT_ENABLE             = 0x10

    ### DATA INTEGRITY CHECK
    CRC_DISABLED            = 0x00
    CRC_INVERTED            = 0x10
    CRC_CRC16_ENABLED       = 0x20

    ### BURNOUT CURRENT SOURCE
    BURN_OUT_CURRENT_OFF    = 0x00
    BURN_OUT_CURRENT_ON     = 0x10

    ### IDAC CURRENT SETTING
    IDAC_CURRENT_OFF        = 0x00
    IDAC_CURRENT_10_UA      = 0x10
    IDAC_CURRENT_50_UA      = 0x20
    IDAC_CURRENT_100_UA     = 0x30
    IDAC_CURRENT_250_UA     = 0x40
    IDAC_CURRENT_500_UA     = 0x50
    IDAC_CURRENT_1000_UA    = 0x60
    IDAC_CURRENT_1500_UA    = 0x70

    #### --- Configuration Register 3
    ### IDAC1 ROUTING CONFIGURATION
    IDAC1_DISABLED          = 0x00
    IDAC1_AIN0              = 0x10
    IDAC1_AIN1              = 0x20
    IDAC1_AIN2              = 0x30
    IDAC1_AIN3              = 0x40
    IDAC1_REFP              = 0x50
    IDAC1_REFN              = 0x60

    ### IDAC2 ROUTING CONFIGURATION
    IDAC2_DISABLED          = 0x00
    IDAC2_AIN0              = 0x10
    IDAC2_AIN1              = 0x20
    IDAC2_AIN2              = 0x30
    IDAC2_AIN3              = 0x40
    IDAC2_REFP              = 0x50
    IDAC2_REFN              = 0x60


    def write_command(self, reg, cmd):
        write_command = 0x40 | (reg << 2)
        self.bus.write_byte(self.i2c_adr, write_command, cmd)

    def send_command(self, cmd):
        self.bus.write_byte(self.i2c_adr, cmd)

    def read_registers(self, reg, size):
        write = i2c_msg.write(self.i2c_adr, [reg])
        read = i2c_msg.read(self.i2c_adr, size)
        self.bus.i2c_rdwr(write, read)
        return list(read)

    def send_command(self, cmd):
        self.bus.write_byte(self.i2c_adr, cmd)

    def start(self):
        self.send_command(0x08)

    def reset(self):
        self.send_command(0x06)

    def powerdown(self):
        self.write_command(self.CMD_POWERDOWN)

    def config(self, mux=MUX_SINGLE_2, gain=GAIN_1, datarate=DATA_RATE_90SPS, mode=MODE_CONTINUOUS, ref=VREF_EXTERNAL, pga=PGA_DISABLED, op_mode=OP_MODE_NORMAL, temp=TEMP_SENSOR_OFF, dcount=DCNT_DISABLE, crc=CRC_DISABLED, bcurrent=BURN_OUT_CURRENT_OFF, idac=IDAC_CURRENT_OFF, idac1=IDAC1_DISABLED, idac2=IDAC2_DISABLED): 
        value = mux | gain | datarate | mode | ref | pga | op_mode | temp | dcount | crc | bcurrent | idac | idac1 | idac2
        self.bus.write_byte_data(self.i2c_adr, self.CMD_WREG, value)

    def ready(self):
        buffer = self.read_registers(self.CMD_RREG | 4, 1)
        return buffer[0] & 0x80

    def waitForResult(self):
        if self.rdyPin > 0:
            GPIO.wait_for_edge(self.rdyPin, GPIO.FALLING)
        else:
            while not self.ready():
                sleep(0.0005)

    def result(self):
        buffer = self.read_registers(self.CMD_RDATA, 3)
        value = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2])
        if value >= 0x800000:
            value = value - 0x1000000
        return value

    def callback(self, callbackFunction):
        GPIO.add_event_detect(self.rdyPin, GPIO.FALLING, callback=lambda _: callbackFunction())

    def __init__(self, port=1, address=0x45, rdyPin=0):
        # print("_INIT_")
        self.i2c_adr = address  # 0x40
        self.bus = SMBus(port, True)
        self.rdyPin = rdyPin
        if rdyPin > 0:
            GPIO.setmode(GPIO.BCM)
            GPIO.setup(rdyPin, GPIO.IN)

    def __enter__(self):
        # print("_ENTER_")
        return self

    def __del__(self):
        # print("_DEL_")
        self.bus.close()

    def __exit__(self, exc_type, exc_value, traceback):
        # print("_EXIT_")
        self.bus.close()

This is code i am using

from time import sleep
from ADS122C04_lib import ADS122C04

ads=ADS122C04( rdyPin=4 )

ads.reset()
ads.config(ads.MUX_SINGLE_2, ads.GAIN_1, ads.DATA_RATE_90SPS, ads.MODE_CONTINUOUS, ads.VREF_EXTERNAL, ads.PGA_DISABLED, ads.OP_MODE_NORMAL, ads.TEMP_SENSOR_OFF, ads.DCNT_DISABLE, ads.CRC_DISABLED, ads.BURN_OUT_CURRENT_OFF, ads.IDAC_CURRENT_OFF, ads.IDAC1_DISABLED, ads.IDAC2_DISABLED)	
ads.start()
try:
    while True:
        result = ads.result()
        print(result)
        sleep(1)  # Adjust the sleep duration as needed
except KeyboardInterrupt:
     pass

Please Help

Thanks,

  • Hi Sayali,

    We have example C code for the ADS122C04 available here: https://www.ti.com/tool/download/SBAC299 

    Are you verifying you are setting the device properly and cycling through the right MUX settings for reading your values? 

    Have you used a logic analyzer or oscilloscope to verify that your I2C communications to the device are working properly and match the data sheet's specifications?

    Also have you tried probing the input pins with a digital multimeter or oscilloscope to see what voltage present at the input pins looks like?

    Best Regards,

    Angel

  • yes i check i am getting proper voltage at input and i2c communication also working fine. but i am getting some random output as well but no change with change in input getting constant value.

    I check everythig but something i am missing that's why i am not getting proper output but i am no getting.So please review my code and circuit and please help me to find out what exactly i am missing.

    Here again i am sharing  my code and circuit 

    This is library file

    import RPi.GPIO as GPIO
    from time import sleep
    from smbus2 import SMBus, i2c_msg
    
    class ADS122C04:
        CMD_RESET               = 0x06
        CMD_START_SYNC          = 0x08
        CMD_POWERDOWN           = 0x02
        CMD_RDATA               = 0x10
        CMD_RREG                = 0x20
        CMD_WREG                = 0x40
    
        #MUX_MASK                = 0x1F
        MUX_DIF_0_1             = 0x0
        MUX_DIF_0_2             = 0x1
        MUX_DIF_0_3             = 0x2
        MUX_DIF_1_0             = 0x3
        MUX_DIF_1_2             = 0x4
        MUX_DIF_1_3             = 0x5
        MUX_DIF_2_3             = 0x6
        MUX_DIF_3_2             = 0x7
        MUX_SINGLE_0            = 0x8
        MUX_SINGLE_1            = 0x9
        MUX_SINGLE_2            = 0xa
        MUX_SINGLE_3            = 0xb
        MUX_REFPmREFN           = 0xc
        MUX_AVDDmAVSS           = 0xd
        MUX_SHORTED             = 0xe
    
        #GAIN_MASK               = 0xF3
        GAIN_1                  = 0x0
        GAIN_2                  = 0x1
        GAIN_4                  = 0x2
        GAIN_8                  = 0x3
        GAIN_16                 = 0x4
        GAIN_32                 = 0x5
        GAIN_64                 = 0x6
        GAIN_128                = 0x7
    
        PGA_DISABLED            = 0x1
        PGA_ENABLED             = 0x0
    
        #DATA_RATE_MASK          = 0xF3
        DATA_RATE_20SPS         = 0x0
        DATA_RATE_45SPS         = 0x1
        DATA_RATE_90SPS         = 0x2
        DATA_RATE_175SPS        = 0x3
        DATA_RATE_330SPS        = 0x4
        DATA_RATE_600SPS        = 0x5
        DATA_RATE_1000SPS       = 0x6
    
        OP_MODE_NORMAL          = 0x0
        OP_MODE_TURBO           = 0x1
    
        #MODE_MASK               = 0xFD
        MODE_SINGLESHOT         = 0x0
        MODE_CONTINUOUS         = 0x1
    
        VREF_INTERNAL           = 0x0
        VREF_EXTERNAL           = 0x1
        VREF_AVDD               = 0x2
    
        ### TEMP SENSOR MOD
        TEMP_SENSOR_OFF         = 0x0
        TEMP_SENSOR_ON          = 0x1
        
        #### --- Configuration Register 2
        ### DATA COUNTER ENABLE
        DCNT_DISABLE            = 0x0
        DCNT_ENABLE             = 0x1
    
        ### DATA INTEGRITY CHECK
        CRC_DISABLED            = 0x0
        CRC_INVERTED            = 0x1
        CRC_CRC16_ENABLED       = 0x2
    
        ### BURNOUT CURRENT SOURCE
        BURN_OUT_CURRENT_OFF    = 0x0
        BURN_OUT_CURRENT_ON     = 0x1
    
        ### IDAC CURRENT SETTING
        IDAC_CURRENT_OFF        = 0x0
        IDAC_CURRENT_10_UA      = 0x1
        IDAC_CURRENT_50_UA      = 0x2
        IDAC_CURRENT_100_UA     = 0x3
        IDAC_CURRENT_250_UA     = 0x4
        IDAC_CURRENT_500_UA     = 0x5
        IDAC_CURRENT_1000_UA    = 0x6
        IDAC_CURRENT_1500_UA    = 0x7
    
        #### --- Configuration Register 3
        ### IDAC1 ROUTING CONFIGURATION
        IDAC1_DISABLED          = 0x0
        IDAC1_AIN0              = 0x1
        IDAC1_AIN1              = 0x2
        IDAC1_AIN2              = 0x3
        IDAC1_AIN3              = 0x4
        IDAC1_REFP              = 0x5
        IDAC1_REFN              = 0x6
        ### IDAC2 ROUTING CONFIGURATION
        IDAC2_DISABLED          = 0x0
        IDAC2_AIN0              = 0x1
        IDAC2_AIN1              = 0x2
        IDAC2_AIN2              = 0x3
        IDAC2_AIN3              = 0x4
        IDAC2_REFP              = 0x5
        IDAC2_REFN              = 0x6
    
        def write_command(self, cmd):
            self.bus.write_byte(self.i2c_adr, cmd)
    
        
        def read_registers(self, reg, size):
            write_msg = i2c_msg.write(self.i2c_adr, [reg])
            read_msg = i2c_msg.read(self.i2c_adr, size)
            self.bus.i2c_rdwr(write_msg, read_msg)
            return list(read_msg)
    
        
        def start(self):
            self.write_command(self.CMD_START_SYNC)
    
        def reset(self):
            self.write_command(self.CMD_RESET)
    
        def powerdown(self):
            self.write_command(self.CMD_POWERDOWN)
    
        def config(self, mux=MUX_SINGLE_2, gain=GAIN_1, datarate=DATA_RATE_20SPS, mode=MODE_CONTINUOUS, ref=VREF_EXTERNAL, pga=PGA_DISABLED, op_mode=OP_MODE_NORMAL, temp=TEMP_SENSOR_OFF, dcount=DCNT_DISABLE, crc=CRC_DISABLED, bcurrent=BURN_OUT_CURRENT_OFF, idac=IDAC_CURRENT_OFF, idac1=IDAC1_DISABLED, idac2=IDAC2_DISABLED): 
            value = mux | gain | datarate | mode | ref | pga | op_mode | temp | dcount | crc | bcurrent | idac | idac1 | idac2
            self.bus.write_byte_data(self.i2c_adr, self.CMD_WREG, value)
    
        def ready(self):
            buffer = self.read_registers(self.CMD_RREG | 4, 1)
            return buffer[0] & 0x80
    
        def waitForResult(self):
            if self.rdyPin > 0:
                GPIO.wait_for_edge(self.rdyPin, GPIO.FALLING)
            else:
                while not self.ready():
                    sleep(0.0001)
    
        def result(self):
            buffer = self.read_registers(self.CMD_RDATA, 3)
            value = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2])
            if value >= 0x800000:
                value = value - 0x1000000
            return value
    
    
        def callback(self, callbackFunction):
            GPIO.add_event_detect(self.rdyPin, GPIO.FALLING, callback=lambda _: callbackFunction())
    
        def __init__(self, port=1, address=0x40, rdyPin=0):
            # print("_INIT_")
            self.i2c_adr = address  # 0x40
            self.bus = SMBus(port, True)
            self.rdyPin = rdyPin
            if rdyPin > 0:
                GPIO.setmode(GPIO.BCM)
                GPIO.setup(rdyPin, GPIO.IN)
    
        def __enter__(self):
            # print("_ENTER_")
            return self
    
        def __del__(self):
            # print("_DEL_")
            self.bus.close()
    
        def __exit__(self, exc_type, exc_value, traceback):
            # print("_EXIT_")
            self.bus.close()
    

    This is main code i am using

    from time import sleep
    from ADS122C04_lib import ADS122C04
    
    ads=ADS122C04()
    
    ads.reset()
    ads.config(ads.MUX_SINGLE_2, ads.GAIN_1, ads.DATA_RATE_20SPS, ads.MODE_CONTINUOUS, ads.VREF_EXTERNAL, ads.PGA_DISABLED, ads.OP_MODE_NORMAL, ads.TEMP_SENSOR_OFF, ads.DCNT_DISABLE, ads.CRC_DISABLED, ads.BURN_OUT_CURRENT_OFF, ads.IDAC_CURRENT_OFF, ads.IDAC1_DISABLED, ads.IDAC2_DISABLED)	
    ads.start()
    try:
        while True:
            result = ads.result()
            print(result)
            sleep(1)  # Adjust the sleep duration as needed
    except KeyboardInterrupt:
         pass

    And Here the output i am getting

    Please help me to find the correct configuration for ADS122C04.

  • Hi Sayali,

    The problem with this setup is that there is no bias on your photodiode circuitry. 

    When you operate a photodiode without any bias voltage, shining light on it generates a very small voltage across its terminals.

    The most common way to read photodiode values is to use a transimpedance amplifier circuit and use the voltage output of this circuit as the input to the ADC. 

    The following resources help explain this concept and how to implement this circuit configuration:

    Photodiode amplifier circuit | Video | TI.com

    Using Photodiode Amplifiers for Ambient Light Sensing in Automotive Displays (Rev. A)

    Alternatively, you could try the following approach with the photodiode in reverse bias mode:

    Photodiodes are usually used in this mode, where a voltage is applied and the input to the ADC would be between the resistor and diode as shown in the picture.

    Best Regards,

    Angel

  • Hello,

    Thanks for your quick response.It helps me alot.

    I use photodiode in reverse bias mode.with multimeter i check voltage it is coming correctly without light fall on photodiode i am getting voltage between the resistor and diode is 0.07V and with light fall on photodiode i am getting voltage between the resistor and diode is max. 3.48V.

    I applied that voltage between the resistor and diode as input to ADC channel AIN2, But still i am getting constant output



    Please suggest me my code is ok or any change in that python library and code for ADS122C04.Any other changes in circuit.

    Please help me to resolve this issu. 

  • Hello,
         i made connection as follow
    A0 and A1 connected to ground
    RESET connected to 3.3V
    DGND and AVSS connected to ground
    REFN connected to ground
    REFP connected to 3.3V in between o.1uf capacitor with ground
    AVDD connected to 3.3V in between o.1uf capacitor with ground
    DVDD connected to 3.3V in between o.1uf capacitor with ground
    DRDY connected to 2.2K pull up resistor
    SDA connected to 2.2K pull up resistor
    SDL connected to 2.2K pull up resistor

    Now please help me to figure out at code side or circuit side is having issue.

  • Hi Sayali

    From your descriptions and schematic, the circuit should be okay.

    i am getting voltage between the resistor and diode is 0.07V and with light fall on photodiode i am getting voltage between the resistor and diode is max. 3.48V.

    Keep in mind that if your supply and VREF is 3.3V, the ADC can't read input voltages higher than this, so take this into consideration if the analog input voltage goes all the way up to 3.48V. You might have to modify either your supply voltage, or your photodiode circuitry to be within the appropriate range. 

    You likely have a problem with your software if you aren't able to get proper ADC readings but verified the voltages with a multimeter. 

    I would recommend probing your digital communication lines with a logic analyzer or a scope to verify that the digital communications seen, match what you intent to do with your code, and comply with the data sheet specifications for communicating with the device.

    Best Regards,

    Angel