Here's my situation: I have four FDC1004 devices that I want to have connected to an array of 64 electrodes through four ADG1206 16:1 multiplexers. Each device is slaved to a pi4 using separate I2C buses, each set to 400 kHz. This is done due to the devices having the same address. This is the general scheme of my data acquisition process:
- Initiate repeat mode for each FDC1004 device at 400 Hz
- Wait until each device's 0x0C register "ready" bit is 1 (they do not have an interrupt pin)
- Read off the 24 bit measurement from each device
- Convert 24 bit measurements to floats and store measurements in array
- Set each device into standby mode
- Switch to next set of 4 electrodes using the ADG1206s
- Repeat until all 64 data points have been collected
Trying to do this with loops and device polling has resulting in a linear increase in data acquisition time with the number of devices i.e. 1 device=45ms, 2 = 90ms, etc. I would like to see if multiprocessing speeds up the data acquisition but I am unsure how to implement it in this case. Here is my non-optimized python script set for 2 FDC devices:
from smbus2 import SMBus, i2c_msg
import RPi.GPIO as GPIO
import time
#ADG1206 binary addresses
addresses = [
[0, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0], [1, 1, 0, 0],
[0, 0, 1, 0], [1, 0, 1, 0], [0, 1, 1, 0], [1, 1, 1, 0],
[0, 0, 0, 1], [1, 0, 0, 1], [0, 1, 0, 1], [1, 1, 0, 1],
[0, 0, 1, 1], [1, 0, 1, 1], [0, 1, 1, 1], [1, 1, 1, 1]
]
GPIO_pins = [10,9,11,25,8]
GPIO.setmode(GPIO.BCM)
for pin in GPIO_pins:
GPIO.setup(pin,GPIO.OUT)
def switch_elec(elec):
GPIO.output(GPIO_pins[0],GPIO.HIGH)
for i in range(4):
GPIO.output(GPIO_pins[i+1],addresses[elec][i])
class FDC1004(object):
def __init__(self, bus, address):
self.bus = bus
self.address = address
def write_register(self, reg, data):
# Function to write a 16-bit value to a register
msg = i2c_msg.write(self.address, [reg, data >> 8, data & 0xFF])
self.bus.i2c_rdwr(msg)
def read_register_16_bit(self, reg):
# Function to read a 16-bit value from a register
msg_write = i2c_msg.write(self.address, [reg])
msg_read = i2c_msg.read(self.address, 2)
self.bus.i2c_rdwr(msg_write, msg_read)
value = int.from_bytes(msg_read, byteorder='big', signed=False)
return value
def read_measurement_registers(self):
# Function to read the MSB and LSB measurement registers and combine into a 24-bit value
msb = self.read_register_16_bit(0x00)
lsb = self.read_register_16_bit(0x01)
return (msb << 8) | lsb
def convert_to_float(self, rawdata):
# Function to convert the 24-bit rawdata into a float value (capacitance in pF)
capacitance = rawdata / 524288.0 # 2^19 = 524288.0 (scaling factor)
return capacitance
if __name__ == "__main__":
bus_nums=[3,4]
num_dev=2
addr=0x50
num_elec=16
dev_count=0
fdc_data=[[0.0 for _ in range(num_elec)] for _ in range(num_dev)]
fdcs = [FDC1004(SMBus(fdc), addr) for fdc in bus_nums]
#Reset FDC devices
for fdc in fdcs:
fdc.write_register(0x0C, 0x800)
while not (fdc.read_register_16_bit(0x0C) & 0x0800)==0x0800:
print ("ready")
#Set measurement channel and set to standy mode
fdc.write_register(0x0C,0xD00)
fdc.write_register(0x08,0x1C00)
start_time=time.perf_counter()
#loop through 16x4 electrodes
for i in range(num_elec):
#set FDCs in standby mode before switching electrode
if i>0:
for fdc in fdcs:
fdc.write_register(0x0C,0xD00)
#switch ADG1206 multiplexer to next electrode
switch_elec(i)
#set devices to repeat mode at 400 Hz
for fdc in fdcs:
fdc.write_register(0x0C,0xD80)
#Wait until each device is ready before storing measurement in array
while dev_count<num_dev:
for j, fdc in enumerate(fdcs):
if fdc.read_register_16_bit(0x0C) ^ 0xD88==0:
raw_measurement_data = fdc.read_measurement_registers()
converted_data = fdc.convert_to_float(raw_measurement_data)
fdc_data[j][i]=converted_data
dev_count+=1
dev_count=0
#print out values
if i==num_elec-1:
for j in range(num_dev):
for k in range(num_elec):
print (fdc_data[j][k])
print (time.perf_counter()-start_time,"seconds")
I am not sure which parts, if any would be faster using multiprocessing. I am also not sure if Python is too slow compared to C/C++ for multiprocessing to make a noticeable difference. I chose Python because it's what I know, but if C or C++ would be much faster than I will just try that. If multiprocessing would significantly speed up the data acquisition, what would that look like? -Not asking for someone to write the code, but just places to start or directions to take with it.