Agata
Posts: 1
Joined: Wed Jun 16, 2021 8:01 am

High-Precision AD/DA Board: problem with high sample rates

Wed Jun 16, 2021 10:13 am

I'm using a raspberry PI 3 model B combined with a High-Precision AD/DA Board with ADS1256, programming in Python.
I have to acquire three different signals, in three separate moments.
Everything goes well with the first two signals, which are acquired respectively at 50 SPS and 500 SPS.
The problem is that I should acquire the third one with an high sample frequency (15KHz), but I cannot reach such a speed.
Using Spike, I tried to visualize DRDY and the distance between two falling edges is too large and it is not constant.

To write this code I started from example given by Waveshare: https://github.com/waveshare/High-Preci ... 56/python3.
I slightly modified ADS1256 code, while I left unchanged config.py.

This is the code regarding the acquisition of the third signal (15kHz):

Code: Select all

import numpy as np
import matplotlib.pyplot as plt
import time
import os
import ADS1256new
import RPi.GPIO as GPIO
import config

def read_data():
   	 ADC.ADS1256_WaitDRDY() 
   	 buf = config.spi_readbytes(3)

    	read = (buf[0]<<16) & 0xff0000
    	read |= (buf[1]<<8) & 0xff00
    	read |= (buf[2]) & 0xff
   
    	if (read & 0x800000): 
       		read = -(0xffffff - read + 0x000001)

    	return (read * 5.0 / 0x7fffff)
    	
    
 ####### MAIN CODE ##########
    
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(16, GPIO.OUT)  # imposta numero pin output
GPIO.setup(26, GPIO.OUT)
GPIO.setup(18, GPIO.OUT)
  
 ACD = ADS1256_new.ADS1256()
 fs = 15000 #15KHz
 signal =[]
  
  ADC.ADS1256_reset()
  gain = ADS1256new.ADS1256_GAIN_E['ADS1256_GAIN_1']
  drate = ADS1256new.ADS1256_DRATE_E['ADS1256_15000SPS']
  channel = 2
   ADC.ADS1256_init(gain,drate,channel)  # inizializzazione
   ADC.ADS1256_WriteCmd(ADS1256new.CMD['CMD_SYNC'])
   ADC.ADS1256_WriteCmd(ADS1256new.CMD['CMD_WAKEUP'])
   ADC.ADS1256_WaitDRDY() 
    
    config.digital_write(config.CS_PIN, GPIO.LOW)  # CS 0
    config.spi_writebyte([ADS1256new.CMD['CMD_RDATAC']])
    config.digital_write(config.CS_PIN, GPIO.HIGH)  # CS 1
    time.sleep(7/10000) 
    
    config.digital_write(config.CS_PIN, GPIO.LOW)  # cs  0
    start_time = time.time()
     
     while len(signal)<=15000*fs:
        	signal.append(read_data())
      
      print("Acquisition time: ", time.time()-start_time)  

And this is ADS1256new code:

Code: Select all

import config
import RPi.GPIO as GPIO

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
                 }


ADS1256_DRATE_E = {'ADS1256_30000SPS' : 0xF0, #1111 0000 
                   'ADS1256_15000SPS' : 0xE0, #1110 0000
                   'ADS1256_7500SPS' : 0xD0,  #1101 0000
                   'ADS1256_3750SPS' : 0xC0,  #1100 0000
                   'ADS1256_2000SPS' : 0xB0,  #1011 0000
                   'ADS1256_1000SPS' : 0xA1,  #1010 0001 
                   'ADS1256_500SPS' : 0x92,   #1001 0010
                   'ADS1256_100SPS' : 0x82,   #1000 0010
                   'ADS1256_60SPS' : 0x72,    #0111 0010
                   'ADS1256_50SPS' : 0x63,    #0110 0011
                   'ADS1256_30SPS' : 0x53,    #0101 0011
                   'ADS1256_25SPS' : 0x43,    #0100 0011
                   'ADS1256_15SPS' : 0x33,    #0011 0011
                   'ADS1256_10SPS' : 0x23,    #0010 0011 NB nella libreria on line era 0x20, cambito a 23 per rispettare il datasheet
                   'ADS1256_5SPS' : 0x13,     #0001 0011
                   'ADS1256_2d5SPS' : 0x03    #0000 0011
                  }


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
        }


 
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
        config.spi_writebyte([reg])
        config.digital_write(self.cs_pin, GPIO.HIGH)#cs 1
    
    def ADS1256_WriteReg(self, reg, data):
        config.digital_write(self.cs_pin, GPIO.LOW)#cs  0
        config.spi_writebyte([CMD['CMD_WREG'] | reg, 0x00, data])
        config.digital_write(self.cs_pin, GPIO.HIGH)#cs 1

    def ADS1256_Read_data(self, reg):
        config.digital_write(self.cs_pin, GPIO.LOW)#cs  0
        config.spi_writebyte([CMD['CMD_RREG'] | reg, 0x00])
        data = config.spi_readbytes(1)
        config.digital_write(self.cs_pin, GPIO.HIGH)#cs 1

        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_init(self,gain,drate,ch):
            
        if(config.module_init() != 0):
            return -1
        
        self.ADS1256_reset()

        #ID checking
        id = self.ADS1256_ReadChipID()
        if id == 3 :
            print("ID Read success  ")
        else:
            print("ID Read failed   ")
            return -1
       
       #ADC configuration
        self.ADS1256_WaitDRDY()
        buf = [0,0,0,0]
        buf[0] = 0x04 			#self calibration on
        buf[1] = (ch<<4)|0x08 		#channel selection
        buf[2] = 0x01<<5 | gain	#clock = f(CLKIN), sensor detector OFF, set gain
        buf[3] = drate			#set data rate 
               
        config.digital_write(self.cs_pin, GPIO.LOW)#cs  0
        config.spi_writebyte([CMD['CMD_WREG'] | 0x00, 0x03])
        config.digital_write(self.cs_pin, GPIO.HIGH)#cs 1
        config.delay_ms(1)

        return 0
    
    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

#### END OF FILE ####


While setting data rate up to 3750sps everything goes well. At higher frequencies the signal is sampled more slowly (about 4s to acquire 15 000 signal samples, setting the rate to 15Ksps).

Has anyone else experienced this problem?

I know there is the possibility of implementing DMA protocol, to reach better ADC performances. As it would be a very time spending activity, I would like to understand if the problem is somewhere else before doing it. Mainly because the observation of DRDY pin waveform makes me doubts about the correct functionalities of the ADC itself.

Thanks to those who will answer.

Agata

[moderator enabled code tags]

Return to “HATs and other add-ons”