Exemple #1
0
def do_measurement():
    ### STEP 1: Initialise ADC object:
    ads = ADS1256(conf)
    n_loop = 1000

    ### STEP 2: Gain and offset self-calibration:
    ads.cal_self()

    timestamp1 = time.time()
    for a in range(1, n_loop):
        ### STEP 3: Get data:
        raw_channels = ads.read_continue(CH_SEQUENCE)
#        raw_channels = ads.read_sequence(CH_SEQUENCE)

    timestamp2 = time.time()

    voltages     = [i * ads.v_per_digit for i in raw_channels]
    nice_output(raw_channels, voltages)

    # Timing info
    print("\n"*9)
    delta = timestamp2 - timestamp1
    print("Delta seconds: {}".format(delta))
    per_sample = 1.0E6*delta/(n_loop*len(CH_SEQUENCE))
    print("Per sample microseconds: {}".format(per_sample))
    overhead = per_sample - 1.0e6/n_loop
    print("Overhead per sample microseconds: {}".format(overhead))
Exemple #2
0
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__(input_dev,
                                          testing=testing,
                                          name=__name__)

        # Initialize custom options
        self.adc_calibration = None
        # Set custom options
        self.setup_custom_options(INPUT_INFORMATION['custom_options'],
                                  input_dev)

        if not testing:
            from ADS1256_definitions import POS_AIN0
            from ADS1256_definitions import POS_AIN1
            from ADS1256_definitions import POS_AIN2
            from ADS1256_definitions import POS_AIN3
            from ADS1256_definitions import POS_AIN4
            from ADS1256_definitions import POS_AIN5
            from ADS1256_definitions import POS_AIN6
            from ADS1256_definitions import POS_AIN7
            from ADS1256_definitions import NEG_AINCOM
            from pipyadc_py3 import ADS1256
            import glob

            # Input pin for the potentiometer on the Waveshare Precision ADC board
            POTI = POS_AIN0 | NEG_AINCOM

            # Light dependant resistor
            LDR = POS_AIN1 | NEG_AINCOM

            # The other external input screw terminals of the Waveshare board
            EXT2, EXT3, EXT4 = POS_AIN2 | NEG_AINCOM, POS_AIN3 | NEG_AINCOM, POS_AIN4 | NEG_AINCOM
            EXT5, EXT6, EXT7 = POS_AIN5 | NEG_AINCOM, POS_AIN6 | NEG_AINCOM, POS_AIN7 | NEG_AINCOM

            self.CH_SEQUENCE = (POTI, LDR, EXT2, EXT3, EXT4, EXT5, EXT6, EXT7)

            self.adc_gain = input_dev.adc_gain
            self.adc_sample_speed = input_dev.adc_sample_speed

            if glob.glob('/dev/spi*'):
                self.ads = ADS1256()

                # Perform selected calibration
                if self.adc_calibration == 'SELFOCAL':
                    self.ads.cal_self_offset()
                elif self.adc_calibration == 'SELFGCAL':
                    self.ads.cal_self_gain()
                elif self.adc_calibration == 'SELFCAL':
                    self.ads.cal_self()
                elif self.adc_calibration == 'SYSOCAL':
                    self.ads.cal_system_offset()
                elif self.adc_calibration == 'SYSGCAL':
                    self.ads.cal_system_gain()

            else:
                raise Exception(
                    "SPI device /dev/spi* not found. Ensure SPI is enabled "
                    "and the device is recognized/setup by linux.")
Exemple #3
0
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__(input_dev, testing=testing, name=__name__)

        if not testing:
            from ADS1256_definitions import POS_AIN0
            from ADS1256_definitions import POS_AIN1
            from ADS1256_definitions import POS_AIN2
            from ADS1256_definitions import POS_AIN3
            from ADS1256_definitions import POS_AIN4
            from ADS1256_definitions import POS_AIN5
            from ADS1256_definitions import POS_AIN6
            from ADS1256_definitions import POS_AIN7
            from ADS1256_definitions import NEG_AINCOM
            from pipyadc_py3 import ADS1256
            import glob

            # Input pin for the potentiometer on the Waveshare Precision ADC board
            POTI = POS_AIN0 | NEG_AINCOM
            # Light dependant resistor
            LDR = POS_AIN1 | NEG_AINCOM
            EXT2, EXT3, EXT4 = POS_AIN2 | NEG_AINCOM, POS_AIN3 | NEG_AINCOM, POS_AIN4 | NEG_AINCOM
            EXT5, EXT6, EXT7 = POS_AIN5 | NEG_AINCOM, POS_AIN6 | NEG_AINCOM, POS_AIN7 | NEG_AINCOM
            self.CH_SEQUENCE = (POTI, LDR, EXT2, EXT3, EXT4, EXT5, EXT6, EXT7)

            self.adc_calibration = None
            self.adc_gain = input_dev.adc_gain
            self.adc_sample_speed = input_dev.adc_sample_speed

            if input_dev.custom_options:
                for each_option in input_dev.custom_options.split(';'):
                    option = each_option.split(',')[0]
                    value = each_option.split(',')[1]
                    if option == 'adc_calibration':
                        self.adc_calibration = value

            if glob.glob('/dev/spi*'):
                self.ads = ADS1256()

                # Perform selected calibration
                if self.adc_calibration == 'SELFOCAL':
                    self.ads.cal_self_offset()
                elif self.adc_calibration == 'SELFGCAL':
                    self.ads.cal_self_gain()
                elif self.adc_calibration == 'SELFCAL':
                    self.ads.cal_self()
                elif self.adc_calibration == 'SYSOCAL':
                    self.ads.cal_system_offset()
                elif self.adc_calibration == 'SYSGCAL':
                    self.ads.cal_system_gain()

            else:
                raise Exception(
                    "SPI device /dev/spi* not found. Ensure SPI is enabled "
                    "and the device is recognized/setup by linux.")
Exemple #4
0
def do_measurement():
    ### STEP 1: Initialise ADC object using default configuration:
    # (Note1: See ADS1256_default_config.py, see ADS1256 datasheet)
    # (Note2: Input buffer on means limited voltage range 0V...3V for 5V supply)
    ads = ADS1256()

    ### STEP 2: Gain and offset self-calibration:
    ads.cal_self()

    while True:
        ### STEP 3: Get data:
        raw_channels = ads.read_sequence(CH_SEQUENCE)
        voltages = [i * ads.v_per_digit for i in raw_channels]

        ### STEP 4: DONE. Have fun!
        nice_output(raw_channels, voltages)
Exemple #5
0
    def initialize_input(self):
        from ADS1256_definitions import POS_AIN0
        from ADS1256_definitions import POS_AIN1
        from ADS1256_definitions import POS_AIN2
        from ADS1256_definitions import POS_AIN3
        from ADS1256_definitions import POS_AIN4
        from ADS1256_definitions import POS_AIN5
        from ADS1256_definitions import POS_AIN6
        from ADS1256_definitions import POS_AIN7
        from ADS1256_definitions import NEG_AINCOM
        from pipyadc_py3 import ADS1256
        import glob

        # Input pin for the potentiometer on the Waveshare Precision ADC board
        POTI = POS_AIN0 | NEG_AINCOM

        # Light dependant resistor
        LDR = POS_AIN1 | NEG_AINCOM

        # The other external input screw terminals of the Waveshare board
        EXT2, EXT3, EXT4 = POS_AIN2 | NEG_AINCOM, POS_AIN3 | NEG_AINCOM, POS_AIN4 | NEG_AINCOM
        EXT5, EXT6, EXT7 = POS_AIN5 | NEG_AINCOM, POS_AIN6 | NEG_AINCOM, POS_AIN7 | NEG_AINCOM

        self.CH_SEQUENCE = (POTI, LDR, EXT2, EXT3, EXT4, EXT5, EXT6, EXT7)

        self.adc_gain = self.input_dev.adc_gain
        self.adc_sample_speed = self.input_dev.adc_sample_speed

        if glob.glob('/dev/spi*'):
            self.sensor = ADS1256()

            # Perform selected calibration
            if self.adc_calibration == 'SELFOCAL':
                self.sensor.cal_self_offset()
            elif self.adc_calibration == 'SELFGCAL':
                self.sensor.cal_self_gain()
            elif self.adc_calibration == 'SELFCAL':
                self.sensor.cal_self()
            elif self.adc_calibration == 'SYSOCAL':
                self.sensor.cal_system_offset()
            elif self.adc_calibration == 'SYSGCAL':
                self.sensor.cal_system_gain()

        else:
            raise Exception(
                "SPI device /dev/spi* not found. Ensure SPI is enabled and the device is recognized/setup by linux."
            )
Exemple #6
0
def adcInitialSetUp():
    #Precompute scaling constant to speed up refinedNumber calculation
    global scaling
    scaling = 5 / 8388607

    #Create ADS module (instance of class used to interface with analog input library)
    global ads
    ads = ADS1256()

    #Reset all registers so we start from clean slate
    ads.reset()

    #Set the gain (0-5 input voltage * gain of 1 = 0-5 output voltage?)
    ads.pga_gain = 1
    '''
    Set configuration options hidden inside status register
    This register stores info in binary form where each bit is a flag
    We are...
        DISABLING Buffer (0x02, 2nd bit in register)
        ...we don't need any buffering, we will be busy waiting on each new sample as it comes
        DISABLING Autocal (0x04, 3rd bit in register)
        ...don't need auto calibration
        PRESERVING LSB (0x08, 4th bit in register)
        ...LSB (least significant bit) is responsible for handling endianness, don't touch it!
    '''
    #In effect turn off everything but keep LSB as it was
    if ads._status & ORDER_LSB:
        ads.status = ORDER_LSB  #LSB was on, so turn off everything but LSB
    else:
        ads.status = 0  #LSB was off, so just turn off everything

    #Set the rate at which sampling occurs by the library in SPS (samples per second)
    ads.drate = DRATE_1000

    #Set the analog pin we will use for input
    ads.mux = POS_AIN0 | NEG_AINCOM

    #Perform calibration
    ads.cal_self()
Exemple #7
0
    def __init__(self, input_dev, testing=False):
        self.logger = logging.getLogger('mycodo.ads1256')
        self.acquiring_measurement = False
        self._voltage = None

        self.adc_gain = input_dev.adc_gain
        self.adc_sample_speed = input_dev.adc_sample_speed
        self.adc_channel = input_dev.adc_channel

        if not testing:
            from ADS1256_definitions import POS_AIN0
            from ADS1256_definitions import POS_AIN1
            from ADS1256_definitions import POS_AIN2
            from ADS1256_definitions import POS_AIN3
            from ADS1256_definitions import POS_AIN4
            from ADS1256_definitions import POS_AIN5
            from ADS1256_definitions import POS_AIN6
            from ADS1256_definitions import POS_AIN7
            from ADS1256_definitions import POS_AINCOM
            from ADS1256_definitions import NEG_AINCOM
            from ADS1256_definitions import NEG_AIN0

            from pipyadc_py3 import ADS1256
            import glob

            ################################################################################
            ###  STEP 0: CONFIGURE CHANNELS AND USE DEFAULT OPTIONS FROM CONFIG FILE: ###
            #
            # For channel code values (bitmask) definitions, see ADS1256_definitions.py.
            # The values representing the negative and positive input pins connected to
            # the ADS1256 hardware multiplexer must be bitwise OR-ed to form eight-bit
            # values, which will later be sent to the ADS1256 MUX register. The register
            # can be explicitly read and set via ADS1256.mux property, but here we define
            # a list of differential channels to be input to the ADS1256.read_sequence()
            # method which reads all of them one after another.
            #
            # ==> Each channel in this context represents a differential pair of physical
            # input pins of the ADS1256 input multiplexer.
            #
            # ==> For single-ended measurements, simply select AINCOM as the negative input.
            #
            # AINCOM does not have to be connected to AGND (0V), but it is if the jumper
            # on the Waveshare board is set.
            #
            # Input pin for the potentiometer on the Waveshare Precision ADC board:
            POTI = POS_AIN0 | NEG_AINCOM
            # Light dependant resistor of the same board:
            LDR = POS_AIN1 | NEG_AINCOM
            # The other external input screw terminals of the Waveshare board:
            EXT2, EXT3, EXT4 = POS_AIN2 | NEG_AINCOM, POS_AIN3 | NEG_AINCOM, POS_AIN4 | NEG_AINCOM
            EXT5, EXT6, EXT7 = POS_AIN5 | NEG_AINCOM, POS_AIN6 | NEG_AINCOM, POS_AIN7 | NEG_AINCOM

            # You can connect any pin as well to the positive as to the negative ADC input.
            # The following reads the voltage of the potentiometer with negative polarity.
            # The ADC reading should be identical to that of the POTI channel, but negative.
            POTI_INVERTED = POS_AINCOM | NEG_AIN0

            # For fun, connect both ADC inputs to the same physical input pin.
            # The ADC should always read a value close to zero for this.
            SHORT_CIRCUIT = POS_AIN0 | NEG_AIN0

            # Specify here an arbitrary length list (tuple) of arbitrary input channel pair
            # eight-bit code values to scan sequentially from index 0 to last.
            # Eight channels fit on the screen nicely for this example..
            self.CH_SEQUENCE = (POTI, LDR, EXT2, EXT3, EXT4, EXT5, EXT6, EXT7)
            ################################################################################

            self.logger = logging.getLogger(
                'mycodo.ads1256_{id}'.format(id=input_dev.unique_id.split('-')[0]))

            self.adc_calibration = None

            if input_dev.custom_options:
                for each_option in input_dev.custom_options.split(';'):
                    option = each_option.split(',')[0]
                    value = each_option.split(',')[1]
                    if option == 'adc_calibration':
                        self.adc_calibration = value

            if glob.glob('/dev/spi*'):
                self.ads = ADS1256()

                # Perform selected calibration
                if self.adc_calibration == 'SELFOCAL':
                    self.ads.cal_self_offset()
                elif self.adc_calibration == 'SELFGCAL':
                    self.ads.cal_self_gain()
                elif self.adc_calibration == 'SELFCAL':
                    self.ads.cal_self()
                elif self.adc_calibration == 'SYSOCAL':
                    self.ads.cal_system_offset()
                elif self.adc_calibration == 'SYSGCAL':
                    self.ads.cal_system_gain()

                self.running = True
            else:
                raise Exception(
                    "SPI device /dev/spi* not found. Ensure SPI is enabled "
                    "and the device is recognized/setup by linux.")
Exemple #8
0
    def __init__(self, input_dev, testing=False, run_main=True):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger('mycodo.ads1256')
        self.run_main = run_main

        if not testing:
            from ADS1256_definitions import POS_AIN0
            from ADS1256_definitions import POS_AIN1
            from ADS1256_definitions import POS_AIN2
            from ADS1256_definitions import POS_AIN3
            from ADS1256_definitions import POS_AIN4
            from ADS1256_definitions import POS_AIN5
            from ADS1256_definitions import POS_AIN6
            from ADS1256_definitions import POS_AIN7
            from ADS1256_definitions import NEG_AINCOM
            from pipyadc_py3 import ADS1256
            import glob

            # Input pin for the potentiometer on the Waveshare Precision ADC board
            POTI = POS_AIN0 | NEG_AINCOM
            # Light dependant resistor
            LDR = POS_AIN1 | NEG_AINCOM
            EXT2, EXT3, EXT4 = POS_AIN2 | NEG_AINCOM, POS_AIN3 | NEG_AINCOM, POS_AIN4 | NEG_AINCOM
            EXT5, EXT6, EXT7 = POS_AIN5 | NEG_AINCOM, POS_AIN6 | NEG_AINCOM, POS_AIN7 | NEG_AINCOM
            self.CH_SEQUENCE = (POTI, LDR, EXT2, EXT3, EXT4, EXT5, EXT6, EXT7)

            self.logger = logging.getLogger('mycodo.ads1256_{id}'.format(
                id=input_dev.unique_id.split('-')[0]))

            self.adc_calibration = None

            self.device_measurements = db_retrieve_table_daemon(
                DeviceMeasurements).filter(
                    DeviceMeasurements.device_id == input_dev.unique_id)

            self.adc_gain = input_dev.adc_gain
            self.adc_sample_speed = input_dev.adc_sample_speed

            if input_dev.custom_options:
                for each_option in input_dev.custom_options.split(';'):
                    option = each_option.split(',')[0]
                    value = each_option.split(',')[1]
                    if option == 'adc_calibration':
                        self.adc_calibration = value

            if glob.glob('/dev/spi*'):
                self.ads = ADS1256()

                # Perform selected calibration
                if self.adc_calibration == 'SELFOCAL':
                    self.ads.cal_self_offset()
                elif self.adc_calibration == 'SELFGCAL':
                    self.ads.cal_self_gain()
                elif self.adc_calibration == 'SELFCAL':
                    self.ads.cal_self()
                elif self.adc_calibration == 'SYSOCAL':
                    self.ads.cal_system_offset()
                elif self.adc_calibration == 'SYSGCAL':
                    self.ads.cal_system_gain()

                self.running = True
            else:
                raise Exception(
                    "SPI device /dev/spi* not found. Ensure SPI is enabled "
                    "and the device is recognized/setup by linux.")
import os
from ADS1256_definitions import *
from pipyadc_py3 import ADS1256

if not os.path.exists("/dev/spidev0.1"):
    raise IOError("Error: No SPI device. Check settings in /boot/config.txt")

#Analog input channel for eyeblink amplitude
EYEBLINK = POS_AIN0 | NEG_AINCOM

#Sequence of all analog input channels (we only have eyeblink channel)
CH_SEQUENCE = ([EYEBLINK])

#Create ADS module and self-calibrate it
ads = ADS1256()
ads.cal_self()

#I believe calling read_sequence only draws from a buffer the library maintains and this buffer...
#is udpdated at the rate defined by here. It seems like the library might actually be performing...
#some averaging of the most recent samples to smooth it out and minimize the occurance of outlying values.
ads.drate = DRATE_1000  #In SPS (samples per second)

#Refer to PiPyADC's ADS1256_definitions.py for list of valid DRATE's


#Return a single numerical value of the "current" (most recent read from A/D library) eyeblink amplitude
def getEyeblinkAmplitude():
    #Read in the data from PiPyADC
    raw_channels = ads.read_sequence(CH_SEQUENCE)
Exemple #10
0
    def initialize(self):
        import glob
        from pipyadc_py3 import ADS1256
        from pipyadc_py3.ADS1256_definitions import POS_AIN0
        from pipyadc_py3.ADS1256_definitions import POS_AIN1
        from pipyadc_py3.ADS1256_definitions import POS_AIN2
        from pipyadc_py3.ADS1256_definitions import POS_AIN3
        from pipyadc_py3.ADS1256_definitions import POS_AIN4
        from pipyadc_py3.ADS1256_definitions import POS_AIN5
        from pipyadc_py3.ADS1256_definitions import POS_AIN6
        from pipyadc_py3.ADS1256_definitions import POS_AIN7
        from pipyadc_py3.ADS1256_definitions import NEG_AINCOM

        # Input pin for the potentiometer on the Waveshare Precision ADC board
        POTI = POS_AIN0 | NEG_AINCOM

        # Light dependant resistor
        LDR = POS_AIN1 | NEG_AINCOM

        # The other external input screw terminals of the Waveshare board
        EXT2, EXT3, EXT4 = POS_AIN2 | NEG_AINCOM, POS_AIN3 | NEG_AINCOM, POS_AIN4 | NEG_AINCOM
        EXT5, EXT6, EXT7 = POS_AIN5 | NEG_AINCOM, POS_AIN6 | NEG_AINCOM, POS_AIN7 | NEG_AINCOM

        channels = {
            0: POTI,
            1: LDR,
            2: EXT2,
            3: EXT3,
            4: EXT4,
            5: EXT5,
            6: EXT6,
            7: EXT7
        }

        # Generate the channel sequence for enabled channels
        self.CH_SEQUENCE = []
        for channel in self.channels_measurement:
            if self.is_enabled(channel):
                self.CH_SEQUENCE.append(channels[channel])
        self.CH_SEQUENCE = tuple(self.CH_SEQUENCE)

        self.adc_gain = self.input_dev.adc_gain
        self.adc_sample_speed = self.input_dev.adc_sample_speed

        if glob.glob('/dev/spi*'):
            self.sensor = ADS1256()

            # Perform selected calibration
            if self.adc_calibration == 'SELFOCAL':
                self.sensor.cal_self_offset()
            elif self.adc_calibration == 'SELFGCAL':
                self.sensor.cal_self_gain()
            elif self.adc_calibration == 'SELFCAL':
                self.sensor.cal_self()
            elif self.adc_calibration == 'SYSOCAL':
                self.sensor.cal_system_offset()
            elif self.adc_calibration == 'SYSGCAL':
                self.sensor.cal_system_gain()

        else:
            raise Exception(
                "SPI device /dev/spi* not found. Ensure SPI is enabled and the device is recognized/setup by linux."
            )
Exemple #11
0
def do_measurement():
    ### STEP 1: Initialise ADC objects for two chips connected to the SPI bus.
    # In this example, we pretend myconfig_2 was a different configuration file
    # named "myconfig_2.py" for a second ADS1256 chip connected to the SPI bus.
    # This file must be imported, see top of the this file.
    # Omitting the first chip here, as this is only an example.

    #ads1 = ADS1256(myconfig_1)
    # (Note1: See ADS1256_default_config.py, see ADS1256 datasheet)
    # (Note2: Input buffer on means limited voltage range 0V...3V for 5V supply)
    ads2 = ADS1256(myconfig_2)

    # Just as an example: Change the default sample rate of the ADS1256:
    # This shows how to acces ADS1256 registers via instance property
    ads2.drate = DRATE_100

    ### STEP 2: Gain and offset self-calibration:
    ads2.cal_self()

    ### Get ADC chip ID and check if chip is connected correctly.
    chip_ID = ads2.chip_ID
    print("\nADC No. 2 reported a numeric ID value of: {}.".format(chip_ID))
    # When the value is not correct, user code should exit here.
    if chip_ID != 3:
        print(
            "\nRead incorrect chip ID for ADS1256. Is the hardware connected?")
    # Passing that step because this is an example:
    #    sys.exit(1)

    # Channel gain must be multiplied by LSB weight in volts per digit to
    # display each channels input voltage. The result is a np.array again here:
    CH_GAIN = ads2.v_per_digit * GAIN_CAL

    # Numpy 2D array as buffer for raw input samples. Each row is one complete
    # sequence of samples for eight input channel pin pairs. Each column stores
    # the number of FILTER_SIZE samples for each channel.
    rows, columns = FILTER_SIZE, len(CH_SEQUENCE)
    filter_buffer = np.zeros((rows, columns), dtype=np.int)

    # Fill the buffer first once before displaying continuously updated results
    print("Channels configured: {}\n"
          "Initializing filter (this can take a minute)...".format(
              len(CH_SEQUENCE)))
    for row_number, data_row in enumerate(filter_buffer):
        # Do the data acquisition of eight multiplexed input channels.
        # The ADS1256 read_sequence() method automatically fills into
        # the buffer specified as the second argument:
        ads2.read_sequence(CH_SEQUENCE, data_row)
        # Depending on aquisition speed and filter lenth, this can take long...
        sys.stdout.write("\rProgress: {:3d}%".format(
            int(100 * (row_number + 1) / FILTER_SIZE)))
        sys.stdout.flush()

    # From now, update filter_buffer cyclically with new ADC samples and
    # calculate results with averaged results.
    print(
        "\n\nOutput values averaged over {} ADC samples:".format(FILTER_SIZE))
    # The following is an endless loop!
    timestamp = time.time()  # Limit output data rate to fixed time interval
    for data_row in itertools.cycle(filter_buffer):
        #
        # Do the data acquisition of eight multiplexed input channels
        #
        # The result channel values are directy read into the array specified
        # as the second argument, which must be a mutable type.
        ads2.read_sequence(CH_SEQUENCE, data_row)

        elapsed = time.time() - timestamp
        if elapsed > 1:
            timestamp += 1

            # Calculate moving average of input samples, subtract offset
            ch_unscaled = np.average(filter_buffer, axis=0) - CH_OFFSET
            ch_volts = ch_unscaled * CH_GAIN

            nice_output([int(i) for i in ch_unscaled], ch_volts)