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.

ADS131M08: ADS131M08 HELP!! Configuration Issues - RASPBERRY PI 4b

Part Number: ADS131M08
Other Parts Discussed in Thread: , ADS131M04

Hello, some time ago I purchased an ADS131M08EVM to conduct tests, but now I need to step out of my comfort zone and start implementing it with the board using a Raspberry Pi 4b. I want to use a Raspberry Pi 4b to control the ADS131M08 via SPI by programming in the Python language. My goal is to start by reading the registers, using the default values provided in the datasheet as a foundation.

 

I'm not sure if my code is well structured

CODE:

import spidev
import RPi.GPIO as GPIO
import time

class ads131m08():
# ADS131M08 commands
commands = {
'CMD_NULL': [0b00000000, 0b00000000], # Request ads samples
'CMD_RESET_DEVICE': [0b00000000, 0b00010001], # Reset the device
'CMD_STANDBY': [0b00000000, 0b00100010],
'CMD_WAKEUP': [0b00000000, 0b00110011],
'CMD_LOCK': [0b00000000, 0b10101010],
'CMD_UNLOCK': [0b00000000, 0b11001010],
'CMD_RREG': [0b10100000, 0b00000000], # Read register
'CMD_WREG': [0b01100000, 0b00000000], # Write register
}

def __init__(self, SyncResetGpio, DrdyGpio, DeviseSpi, cs, sclk=12000000):

# SPI configuration
self.spi = spidev.SpiDev()
self.spi.open(DeviseSpi, cs)
self.spi.max_speed_hz = sclk
self.spi.mode = 1
self.spi.lsbfirst = False # default

# ADS131M08 operates in mode 1
self.ChEnable = 8
# GPIO configuration
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(DrdyGpio, GPIO.IN) # To read the pin --> DrdyState = GPIO.input(DrdyGpio)
GPIO.setup(SyncResetGpio, GPIO.OUT) # To write the pin HIGH = Deactivate, LOW = Activate --> GPIO.output(SyncResetGpio, GPIO.LOW)
# GPIO.output(SyncResetGpio, GPIO.HIGH)
GPIO.setup(self.ChEnable, GPIO.OUT)

GPIO.output(SyncResetGpio, GPIO.LOW)
time.sleep(1)
GPIO.output(SyncResetGpio, GPIO.HIGH)

def id(self):
GPIO.output(self.ChEnable, GPIO.LOW)
respons = self.spi.xfer2([0xA0, 0x01, 0x00]) # Sending the read command with address 0x01 (status)
GPIO.output(self.ChEnable, GPIO.HIGH)
print("STATUS: ", respons)
time.sleep(1)

def close(self):
self.spi.close()

def invert(self):
print("Inverts the bits to use mode 3 as mode 1")

ads = ads131m08(22, 24, 0, 0, 1000000)
try:
while True:
ads.id()

except KeyboardInterrupt:
ads.close()
GPIO.cleanup()


RESULTS:

STATUS: [255, 40, 0]

STATUS: [224, 1, 0]

STATUS: [5, 255, 0]

STATUS: [224, 1, 0]

STATUS: [5, 255, 0]

STATUS: [224, 1, 0]

STATUS: [5, 255, 0]

STATUS: [224, 1, 0]

STATUS: [5, 255, 0]

STATUS: [224, 1, 0]

For the same command, I'm receiving various responses and none are as expected --> 0x0500h.

For --> respons = self.spi.xfer2([0xA0, 0x00, 0x00])

RESULTS: STATUS: [255, 40, 0]

STATUS: [40, 1, 0]

STATUS: [40, 1, 0]

STATUS: [40, 1, 0]

STATUS: [40, 1, 0]

STATUS: [40, 1, 0]

STATUS: [40, 1, 0]

STATUS: [40, 1, 0]

STATUS: [40, 1, 0]

STATUS: [40, 1, 0]

For the same command, I'm receiving various responses and none are as expected ID --> 0x28XXh.

For --> respons = self.spi.xfer2([0xA0, 0x03, 0x00])

RESULTS:

STATUS: [255, 40, 0]

STATUS: [224, 3, 0]

STATUS: [5, 255, 0]

STATUS: [224, 3, 0]

STATUS: [5, 255, 0]

STATUS: [224, 3, 0]

STATUS: [5, 255, 0]

STATUS: [224, 3, 0]

STATUS: [5, 255, 0]

For the same command, I'm receiving various responses and none are as expected --> 0xFF0Eh.







  • Hi ,

    Can you please provide the following information?

    1. Timing plots for SCLK, /CS, DIN, DOUT and /DRDY? for each register reading, the timing of two frames will be good because the register data will be shifted out in the 2nd frame.
    2. Signal connections to your Raspberry Pi 4b.
    3. Power supply connections.
    4. Jumper configurations on the EVM.

    The datasheet has a code example on page 93-94 that could be a reference for you.

    Best regards,

    Dale

  • Hello, good evening. I thank you for responding. I'm attaching my signals after the first capture. The enable signal is correct; I was only able to plot 4 signals, so I didn't include the enable signal in the graph, but I confirm that it's correct

    Detail from +90us to +40us:

    I'm only transmitting, and the responses are from the ADS. But after sending the data, I read the number of bytes I sent (described in detail from +2us to +5us)

    Detail from +2us to +5us:

    This is my current code; I implemented interrupts as in the example on pages 93-94 of the datasheet

    CODE:

    import spidev
    import RPi.GPIO as GPIO
    import time

    class ads131m08():
    # ADS131M08 commands
    commands = {
    'CMD_NULL': [0b00000000, 0b00000000], # Request ads samples
    'CMD_RESET_DEVICE': [0b00000000, 0b00010001], # Reset the device
    'CMD_STANDBY': [0b00000000, 0b00100010],
    'CMD_WAKEUP': [0b00000000, 0b00110011],
    'CMD_LOCK': [0b00000000, 0b10101010],
    'CMD_UNLOCK': [0b00000000, 0b11001010],
    'CMD_RREG': [0b10100000, 0b00000000], # Read register
    'CMD_WREG': [0b01100000, 0b00000000], # Write register
    }

    def __init__(self, SyncResetGpio, DrdyGpio, DeviseSpi, cs, sclk=12000000):

    # SPI configuration
    self.spi = spidev.SpiDev()
    self.spi.open(DeviseSpi, cs)
    self.spi.max_speed_hz = sclk
    self.spi.mode = 1
    self.spi.lsbfirst = False # default

    # ADS131M08 operates in mode 1
    self.ChEnable = 8
    self.DrdyGpio_init = DrdyGpio
    # GPIO configuration
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(9, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # pull down to eliminate noise issues

    GPIO.setup(self.DrdyGpio_init, GPIO.IN) # To read the pin --> DrdyState = GPIO.input(DrdyGpio)

    GPIO.setup(SyncResetGpio, GPIO.OUT) # To write the pin HIGH = Deactivate, LOW = Activate --> GPIO.output(SyncResetGpio, GPIO.LOW)
    # GPIO.output(SyncResetGpio, GPIO.HIGH)
    GPIO.setup(self.ChEnable, GPIO.OUT)

    GPIO.output(SyncResetGpio, GPIO.LOW)

    time.sleep(0.000125)

    GPIO.output(SyncResetGpio, GPIO.HIGH)

    def DrdyInterrup(self, channel):
    """if GPIO.input(self.DrdyGpio_init) == GPIO.LOW:"""
    self.id()

    def init_interrup(self):
    # Initialize interrupt

    GPIO.add_event_detect(self.DrdyGpio_init, GPIO.FALLING)
    GPIO.add_event_callback(self.DrdyGpio_init, self.DrdyInterrup)

    def cali(self):
    tx_data = [0x00, 0x00, 0x00] # Data you want to send
    self.spi.writebytes(tx_data)
    tx_data = [0x00, 0x00, 0x00] # Data you want to send
    self.spi.writebytes(tx_data)
    tx_data = [0x00, 0x00, 0x00] # Data you want to send
    self.spi.writebytes(tx_data)

    def id(self):
    # GPIO.output(self.ChEnable, GPIO.LOW)

    # Adapt the signal.
    adrress = 0x01 # ID, make this a parameter for a general read function.

    tx_data = [0xA0, adrress, 0x00] # Data you want to send
    self.spi.writebytes(tx_data)
    self.spi.writebytes(tx_data)
    self.spi.writebytes(tx_data)

    rx_data = self.spi.readbytes(len(3 * tx_data)) # Read the same amount of bytes as you sent
    # print("Received response:", rx_data)
    # GPIO.output(self.ChEnable, GPIO.HIGH)

    def close(self):
    self.spi.close()

    def invert(self):
    pass
    # print("Inverts the bits to use mode 3 as mode 1")

    try:
    ads = ads131m08(22, 24, 0, 0, 12000000)
    ads.cali()
    ads.init_interrup()
    while True:
    pass

    except KeyboardInterrupt:
    ads.close()
    GPIO.cleanup()

    CONNECTIONS:

    Observing the schematic, I took the power input from 3v3_lp and connected it to the 3v3 power pin on the Raspberry Pi (pin 1). I connected GND to a ground pin on the Raspberry Pi (pin 39).

    The following connections were made:

    • SYNC/RESET to GPIO22
    • DIN to GPIO10 - PIN 19
    • DIGITAL.CLK - not connected
    • CS to GPIO8 - PIN 24
    • SCLK to GPIO11 - PIN 23
    • DRDY to GPIO24 - PIN 18
    • DOUT to GPIO9 - PIN 21
    • GND - PIN 39
    • VCC - PIN 1

    To start, I didn't modify the ads131m08evm board. The default clock is 8192MHz. My initial goal is to read the registers correctly, following the datasheet to verify the data is accurate. Thank you very much for your assistance in advance. Regards

  • Hi ,

    It is not easy to check your timing. Below is a timing example captured on ADS131M04 for reading CFG register(0x06 address) which was already written 0x0700 to enable Global-chop mode with a default delay in the previous step. As you can see, the register data (0x0700) was successfully shifted out on DOUT line in the 2nd frame without checking and waiting for /DRDY signal.

    Could you please show me your timing like this so that I can easily read the data? 

    When you connect 3v3_lp on the EVM to the 3v3 power pin on your Raspberry Pi , dii you have a jumper on JP12 to short pin 1 and 2 of JP12? Also, did you provide any power to DVDD of the ADC on the EVM?

    Regards,

    Dale

  • Good afternoon! I'll detail the updates I've made. I modified my code to use only pigpio on my Raspberry Pi 4B in order to achieve a better clock and timing precision. I configured the SPI frequency to 2 MHz; I'm not certain if this frequency is correct. The datasheet specifies a maximum SPI clock frequency of 25 MHz, but it doesn't mention the minimum frequency. What is the known minimum frequency at which the ads131m08 can operate?

    I'm using a simple 8-channel 25Ms/s logic analyzer. Due to this, I'm using a frequency of 2 MHz and I want to confirm if it's correct.

    I edited my code to read the ID and STATUS registers, as well as to read all channels of the ads, implementing the timing described in this link: ADS131M08: DRDY not going low - Data converters forum - Data converters - TI E2E support forums

    ADS131M08EVM Power Supply: I made the external power supply connection based on this note from the datasheet:


         



    CÓDIGO: 

    import pigpio
    import time

    class ads131m08():

    # address registers ads131
    registers = {
    'id': 0x00,
    'status': 0x01,
    'mode': 0x02,
    'clock': 0x03,
    'gain1': 0x04,
    'gain2': 0x05,
    'cfg': 0x06,
    'thrshld_msb': 0x07,
    'thrshld_lsb': 0x08,
    'ch0_cfg': 0x09,
    'ch0_ocal_msb': 0x0A,
    'ch0_ocal_lsb': 0x0B,
    'ch0_gcal_msb': 0x0C,
    'ch0_gcal_lsb': 0x0D,
    'ch1_cfg': 0x0E,
    'ch1_ocal_msb': 0x0F,
    'ch1_ocal_lsb': 0x10,
    'ch1_gcal_msb': 0x11,
    'ch1_gcal_lsb': 0x12,
    'ch2_cfg': 0x13,
    'ch2_ocal_msb': 0x14,
    'ch2_ocal_lsb': 0x15,
    'ch2_gcal_msb': 0x16,
    'ch2_gcal_lsb': 0x17,
    'ch3_cfg': 0x18,
    'ch3_ocal_msb': 0x19,
    'ch3_ocal_lsb': 0x1A,
    'ch3_gcal_msb': 0x1B,
    'ch3_gcal_lsb': 0x1C,
    'ch4_cfg': 0x1D,
    'ch4_ocal_msb': 0x1E,
    'ch4_ocal_lsb': 0x1F,
    'ch4_gcal_msb': 0x20,
    'ch4_gcal_lsb': 0x21,
    'ch5_cfg': 0x22,
    'ch5_ocal_msb': 0x23,
    'ch5_ocal_lsb': 0x24,
    'ch5_gcal_msb': 0x25,
    'ch5_gcal_lsb': 0x26,
    'ch6_cfg': 0x27,
    'ch6_ocal_msb': 0x28,
    'ch6_ocal_lsb': 0x29,
    'ch6_gcal_msb': 0x2A,
    'ch6_gcal_lsb': 0x2B,
    'ch7_cfg': 0x2C,
    'ch7_ocal_msb': 0x2D,
    'ch7_ocal_lsb': 0x2E,
    'ch7_gcal_msb': 0x2F,
    'ch7_gcal_lsb': 0x30,
    'regmap_crc': 0x3E,
    'reserved': 0x3F
    }
    def __init__(self, SyncResetGpio, DrdyGpio, DeviseSpi, cs, sclk=12000000):
    self.pi = pigpio.pi() # Iniciar PIGPIO
    # SPI configuration
    self.spi = self.pi.spi_open(cs, sclk, 1)

    self.DrdyGpio_init = DrdyGpio
    # Configurar pines
    self.pi.set_mode(SyncResetGpio, pigpio.OUTPUT)
    self.pi.set_mode(self.DrdyGpio_init, pigpio.INPUT)

    self.pi.write(SyncResetGpio, 0)
    time.sleep(0.000125)
    self.pi.write(SyncResetGpio, 1)

    def cmd_reset(self):
    self.pi.wait_for_edge(self.DrdyGpio_init,pigpio.FALLING_EDGE,0)
    tx_data = [0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] # Datos que deseas enviar
    rx_data = self.pi.spi_xfer(self.spi, tx_data) # read output
    print("reset: ", rx_data)

    def cmd_read_reg(self, key):
    reg = self.registers.get(key)

    #self.pi.wait_for_edge(self.DrdyGpio_init, pigpio.FALLING_EDGE, 0)
    antes = time.time_ns()
    while self.pi.read(self.DrdyGpio_init):
    if time.time_ns() - antes >= 10:
    break

    tx_data = [0xA0, reg, 0x00, 0x00, 0x00, 0x00] # frame 24bits default.
    rx_data = self.pi.spi_xfer(self.spi, tx_data)
    print("registro leido: ",rx_data)

    def cmd_write_reg(self, key, data):
    reg = self.registers.get(key)

    def cmd_read_ads_all_channel(self):

    #self.pi.wait_for_edge(self.DrdyGpio_init, pigpio.FALLING_EDGE, 0)
    antes = time.time_ns()
    while self.pi.read(self.DrdyGpio_init):
    if time.time_ns() - antes >= 10:
    break

    tx_data = [0x00] * 27 # read status register + channel 1 + channel2 + channel3... channel 8
    rx_data = self.pi.spi_xfer(self.spi, tx_data) # read output
    print("canales leidos: ", rx_data)

    def close(self):
    self.pi.spi_close(self.spi)
    self.pi.stop()

    try:
    ads = ads131m08(22, 24, 0, 0, 2000000)
    pepe = 1
    while pepe:
    #ads.cmd_reset()
    time.sleep(1)
    ads.cmd_read_reg('id')
    ads.cmd_read_reg('status')
    ads.cmd_read_ads_all_channel()
    pepe = 0


    except KeyboardInterrupt:
    ads.close()




    Attached are the temporal graphs you requested.

    Temporal Timeline Graph - Reading ID Register




    SECOND SAMPLE:

    Temporal Timeline Graph - Reading STATUS Register

    SECOND SAMPLE:


    Temporal Graph Reading All ADC Channels

    SECOND SAMPLE:

  • Hi CELESTE GONZALEZ CANTERO,

    When your SCLK frequency is 2MHz, one clock period is 0.5us. If you want to read the data of all channels and your data size is 24 bits, one cycle has one STATUS word+8 channel data + CRC word, the minimum time for one cycle is (1+8+1)*24*0.5us=120us, so your data rate should be limited to 1/120us=8.3ksps (other delays are ignored).

    It's very hard to see your timings except the 1st timing. Your command to read ID register is correct, your should be able to get the data of ID register in the 2nd frame, see my timings below that were just captured on the M08EVM. 0x2801 in the following 2nd frame is the data of ID register from M08 ADC.

    1st frame to read ID register:

    2nd frame to read ID register:

    I could not clearly see your timing to read the STATUS register which has an address 01h, however it seems that your were sending 0xA001 command to the ADC, this is incorrect, the correct command is 0xA080. Please double check your command.

    By the way, if the input CRC is disabled (default), you only need to send 24 SCLKs to read a register from the ADC instead of 48 SCLKs and also you only need to send NULL (all zeros) in the second sample/frame. See my timing in my previous post.

    I could not see the details in your timing to read data of all channels, so I could not check it.

    Best regards,

    Dale