# ADS1220 Support # # Copyright (C) 2024 Gareth Farrington # # This file may be distributed under the terms of the GNU GPLv3 license. import logging from . import bulk_sensor, bus # # Constants # BYTES_PER_SAMPLE = 4 # samples are 4 byte wide unsigned integers MAX_SAMPLES_PER_MESSAGE = bulk_sensor.MAX_BULK_MSG_SIZE // BYTES_PER_SAMPLE UPDATE_INTERVAL = 0.10 RESET_CMD = 0x06 START_SYNC_CMD = 0x08 RREG_CMD = 0x20 WREG_CMD = 0x40 NOOP_CMD = 0x0 RESET_STATE = bytearray([0x0, 0x0, 0x0, 0x0]) # turn bytearrays into pretty hex strings: [0xff, 0x1] def hexify(byte_array): return "[%s]" % (", ".join([hex(b) for b in byte_array])) class ADS1220: def __init__(self, config): self.printer = printer = config.get_printer() self.name = config.get_name().split()[-1] self.last_error_count = 0 self.consecutive_fails = 0 # Chip options # Gain self.gain_options = { "1": 0x0, "2": 0x1, "4": 0x2, "8": 0x3, "16": 0x4, "32": 0x5, "64": 0x6, "128": 0x7, } self.gain = config.getchoice("gain", self.gain_options, default="128") # Sample rate self.sps_normal = { "20": 20, "45": 45, "90": 90, "175": 175, "330": 330, "600": 600, "1000": 1000, } self.sps_turbo = { "40": 40, "90": 90, "180": 180, "350": 350, "660": 660, "1200": 1200, "2000": 2000, } self.sps_options = self.sps_normal.copy() self.sps_options.update(self.sps_turbo) self.sps = config.getchoice("sample_rate", self.sps_options, default="660") self.is_turbo = str(self.sps) in self.sps_turbo # Input multiplexer: AINP and AINN mux_options = { "AIN0_AIN1": 0b0000, "AIN0_AIN2": 0b0001, "AIN0_AIN3": 0b0010, "AIN1_AIN2": 0b0011, "AIN1_AIN3": 0b0100, "AIN2_AIN3": 0b0101, "AIN1_AIN0": 0b0110, "AIN3_AIN2": 0b0111, "AIN0_AVSS": 0b1000, "AIN1_AVSS": 0b1001, "AIN2_AVSS": 0b1010, "AIN3_AVSS": 0b1011, } self.mux = config.getchoice("input_mux", mux_options, default="AIN0_AIN1") # PGA Bypass self.pga_bypass = config.getboolean("pga_bypass", default=False) # bypass PGA when AVSS is the negative input force_pga_bypass = self.mux >= 0b1000 self.pga_bypass = force_pga_bypass or self.pga_bypass # Voltage Reference self.vref_options = { "internal": 0b0, "REF0": 0b01, "REF1": 0b10, "analog_supply": 0b11, } self.vref = config.getchoice("vref", self.vref_options, default="internal") # check for conflict between REF1 and AIN0/AIN3 mux_conflict = [ 0b0000, 0b0001, 0b0010, 0b0100, 0b0101, 0b0110, 0b0111, 0b1000, 0b1011, ] if self.vref == 0b10 and self.mux in mux_conflict: raise config.error( "ADS1220 config error: AIN0/REFP1 and AIN3/REFN1" " cant be used as a voltage reference and" " an input at the same time" ) # SPI Setup spi_speed = 512000 if self.is_turbo else 256000 self.spi = bus.MCU_SPI_from_config(config, 1, default_speed=spi_speed) self.mcu = mcu = self.spi.get_mcu() self.oid = mcu.create_oid() # Data Ready (DRDY) Pin drdy_pin = config.get("data_ready_pin") ppins = printer.lookup_object("pins") drdy_ppin = ppins.lookup_pin(drdy_pin) self.data_ready_pin = drdy_ppin["pin"] drdy_pin_mcu = drdy_ppin["chip"] if drdy_pin_mcu != self.mcu: raise config.error( "ADS1220 config error: SPI communication and" " data_ready_pin must be on the same MCU" ) # Bulk Sensor Setup self.bulk_queue = bulk_sensor.BulkDataQueue(self.mcu, oid=self.oid) # Clock tracking chip_smooth = self.sps * UPDATE_INTERVAL * 2 # Measurement conversion self.ffreader = bulk_sensor.FixedFreqReader(mcu, chip_smooth, "