Add output tasks for NiDaq
add possibility to cycle a potential or hold a potemtial with the NIDaq card. Required to control a potentiostat
The program should measure the applied voltage as well as the actual voltage.
ts = TimeSeries()
class Daq():
def __init__(self, device, chanin, chanout):
self.device = device
self.channelin = chanin
self.channelout = chanout
self.measurement = None # reserved for the asyncio task
self.U = []
self.E = []
self.t = []
self.I = []
self.taskA = nidaqmx.Task()
self.taskB = nidaqmx.Task()
self.Rbalance = 10000
if chanin == 'ai0':
#self.taskA.ai_channels.add_ai_voltage_chan(f"{self.device}/ai0")
#with self.taskA() as task:
ai_channel = self.taskA.ai_channels.add_ai_voltage_chan(f"{self.device}/ai0", terminal_config = TerminalConfiguration.RSE)
elif chanin == 'ai1':
self.taskA.ai_channels.add_ai_voltage_chan(f"{self.device}/ai1")
elif chanin == 'ai2':
self.taskA.ai_channels.add_ai_voltage_chan(f"{self.device}/ai2")
elif chanin == 'ai3':
self.taskA.ai_channels.add_ai_voltage_chan(f"{self.device}/ai3")
else:
self.taskA.ai_channels.add_ai_voltage_chan(f"{self.device}/ai0")
if chanout == 'ao0':
self.taskB.ao_channels.add_ao_voltage_chan('Dev1/ao0','mychannel',0,5)
elif chanout == 'ai1':
self.taskB.ao_channels.add_ao_voltage_chan('Dev1/ao1','mychannel',0,5)
else:
self.taskB.ao_channels.add_ao_voltage_chan('Dev1/ao0','mychannel',0,5)
def start_hold(self, voltage = 5, resistance = 22000):
print('start measurement')
self.output(self.channelout, voltage)
self.measurement = asyncio.create_task(self.measure_hold(voltage = voltage, resistance = resistance)) # create an asyncio task and tell him which function it should execute
#self.measurement = asyncio.create_task(self.measure_vanilla())
print('measurement initiated')
self.t_init = time.time()
def start_cycle(self, U_i = 0.95, LPL = 0.05, UPL = 1.5, scanspeed = 50, resistance = 22000):
print('start measurement')
self.taskB.start()
self.measurement = asyncio.create_task(self.measure_cycle(U_i, LPL, UPL, scanspeed, resistance)) # create an asyncio task and tell him which function it should execute
#self.measurement = asyncio.create_task(self.measure_vanilla())
print('measurement initiated')
self.t_init = time.time()
def output(self, chan, voltage):
self.taskB.start()
self.taskB.write(voltage)
async def measure_hold(self, voltage, resistance):
while True:
t = time.time() - self.t_init
U = self.taskA.read()
self.U.append(U)
self.E.append(voltage)
self.t.append(t)
I = U/resistance
self.I.append(I)
ts.push(t, I)
await asyncio.sleep(1/20)
async def measure_cycle(self, U_i, LPL, UPL, scanspeed, resistance):
U_appl = U_i
direction = -1
dt = 0.05
dU = scanspeed * dt / 1000
while True:
U_appl = U_appl + direction * dU
if (U_appl < LPL) or (U_appl > UPL):
direction = -1 * direction
self.taskB.write(U_appl)
await asyncio.sleep(dt)
t = time.time() - self.t_init
U = self.taskA.read()
self.U.append(U)
self.E.append(U_appl)
self.t.append(t)
I = U/resistance
self.I.append(I)
ts.push(t, I)
def stop(self):
self.measurement.cancel()
self.taskA.stop()
print('Measurement stopped')
def close(self):
self.taskA.close()
self.taskB.close()
daq = Daq(device='Dev1', chanin = 'ai0', chanout = 'ao0') #specify device accordingly
ts
daq = Daq(device='Dev1', chanin = 'ai0', chanout = 'ao0') #specify device accordingly
ts
mode = 'hold'
#mode = 'cycle'
if mode == 'hold':
daq.start_hold(voltage = 1.2, resistance = 20000)
elif mode == 'cycle':
daq.start_cycle(U_i = 0.95, LPL = 0.05, UPL = 1.4, scanspeed = 100, resistance = 20000)
relevat for saving data
if mode == 'hold':
data = {'time':daq.t, 'voltage':daq.U, 'current':daq.I} # for holding
elif mode == 'cycle':
data = {'time':daq.t, 'potential':daq.E, 'voltage':daq.U, 'current':daq.I} # for cycling
df = pd.DataFrame(data = data)