Rasp_grid/rasp_grid.py
2020-02-28 13:14:45 +01:00

669 lines
24 KiB
Python

from __future__ import print_function
import os
import sys
import glob
import datetime
from shutil import copyfile
try:
import RPi.GPIO as GPIO
except:
pass
import subprocess
import numpy as np
import threading
import multiprocessing as mp
from time import sleep, time
from IPython import embed
from uldaq import (get_daq_device_inventory, DaqDevice, AInScanFlag, ScanStatus,
ScanOption, create_float_buffer, InterfaceType, AiInputMode)
def GPIO_setup(LED1_pin, LED2_pin, LED_out_pin, Button1_pin, Button2_pin, power_controll_pin):
# LED output pins
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED1_pin, GPIO.OUT) # 1
GPIO.output(LED1_pin, GPIO.LOW)
GPIO.setup(LED2_pin, GPIO.OUT) # 2
GPIO.output(LED2_pin, GPIO.HIGH)
if LED_out_pin != None:
GPIO.setup(LED_out_pin, GPIO.OUT)
GPIO.output(LED_out_pin, GPIO.LOW)
LED_status = [False, True, False]
else:
LED_status = [False, True]
# switch controlled input
# GPIO.setup(Button1_pin, GPIO.IN)
GPIO.setup(power_controll_pin, GPIO.IN)
GPIO.setup(Button1_pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(Button2_pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
return LED_status
def read_cfg(cfg_file, now, init_read=False):
cfg_f = open(cfg_file, 'r+')
cfg = cfg_f.readlines()
### read cfg information ###
if init_read:
for line in cfg:
if "PathFormat" in line:
path_format = ':'.join(line.split(':')[1:]).strip().replace('"', '').replace("'", "")
cfg_f.close()
return path_format
else:
for line in cfg:
if 'Columns1' in line:
n_cols = int(line.split(':')[1].strip())
elif 'Rows1' in line:
n_rows = int(line.split(':')[1].strip())
elif 'Extra1' in line:
n_extra = int(line.split(':')[1].strip())
elif "AISampleRate" in line:
samplerate = int(float(line.split(':')[-1].strip().replace('kHz', '')) * 1000)
elif "AIMaxVolt" in line:
max_v = float(line.split(':')[1].strip().replace('mV', ''))
elif 'Gain' in line:
gain = int(line.split(':')[1].strip())
gain = int(line.split(':')[1].strip())
channels = n_rows * n_cols + n_extra
### alter information and re-write ###
for enu, line in enumerate(cfg):
if "StartDate" in line:
cfg[enu] = (' StartDate : %s\n' % now.strftime('%Y-%m-%d'))
elif "StartTime" in line:
cfg[enu] = (' StartTime : %s\n' % (now.strftime('%H:%M:%S') + now.strftime(".%f")[:4]))
cfg_f.close()
cfg_f = open(cfg_file, 'w+')
for line in cfg:
cfg_f.write(line)
cfg_f.close()
return channels, samplerate, n_cols, n_rows, max_v, gain
# for line in cfg:
# if 'Columns1' in line:
# self.Grid.columns_val = int(line.split(':')[1].strip())
# elif 'Rows1' in line:
# self.Grid.rows_val = int(line.split(':')[1].strip())
# elif "ColumnDistance1" in line:
# self.Grid.col_dist_val = float(line.split(':')[-1].strip().replace('cm', ''))
# elif "RowDistance1" in line:
# self.Grid.row_dist_val = float(line.split(':')[-1].strip().replace('cm', ''))
# elif "ChannelOffset1" in line:
# self.Grid.channel_offset_val = int(line.split(':')[-1].strip())
# elif "ElectrodeType1" in line:
# self.Grid.elec_type_val = line.split(':')[-1].strip()
# elif "RefElectrodeType1" in line:
# self.Grid.ref_elec_type_val = line.split(":")[-1].strip()
# elif "RefElectrodePosX1" in line:
# self.Grid.ref_elec_posx_val = float(line.split(':')[-1].strip().replace('m', ''))
# elif 'RefElectrodePosY1' in line:
# self.Grid.ref_elec_posy_val = float(line.split(':')[-1].strip().replace('m', ''))
# elif 'WaterDepth1' in line:
# self.Grid.water_depth_val = float(line.split(':')[-1].strip().replace('m', ''))
#
# elif "AISampleRate" in line:
# self.HardWare.ai_sr_val = float(line.split(':')[-1].strip().replace('kHz', ''))
# elif "AIMaxVolt" in line:
# self.HardWare.ai_max_vol_val = float(line.split(':')[-1].strip().replace('mV', ''))
# elif "AmplName" in line:
# self.HardWare.amp_name_val = line.split(':')[-1].strip()
# elif "AmplModel" in line:
# self.HardWare.amp_model_val = line.split(':')[-1].strip()
# elif ' Type ' in line:
# self.HardWare.amp_type_val = line.split(':')[-1].strip()
# elif 'Gain' in line:
# self.HardWare.gain_val = line.split(':')[-1].strip()
# elif "HighpassCutoff" in line:
# self.HardWare.highpass_cutoff_val = int(line.split(':')[-1].strip().replace('Hz', ''))
# elif 'LowpassCutoff' in line:
# self.HardWare.lowpass_cutoff_val = float(line.split(':')[-1].strip().replace('kHz', ''))
#
# elif "Experiment.Name" in line:
# self.Recording.experiment_name_val = line.split(':')[-1].strip()
# elif "StartDate" in line:
# self.Recording.startdate_val = line.split(':')[-1].strip()
# elif "StartTime" in line:
# self.Recording.starttime_val = ':'.join(line.split(':')[1:]).strip()
# elif "Location" in line:
# self.Recording.location_val = line.split(':')[-1].strip()
# elif "Position" in line:
# self.Recording.position_val = line.split(':')[-1].strip()
# elif "WaterTemperature" in line:
# self.Recording.water_temp_val = float(line.split(':')[-1].strip().replace('C', ''))
# elif "WaterConductivity" in line:
# self.Recording.water_cond_val = float(line.split(':')[-1].strip().replace('uS/cm', ''))
# elif 'WaterpH' in line:
# self.Recording.water_ph_val = float(line.split(':')[-1].strip().replace('pH', ''))
# elif "WaterOxygen" in line:
# self.Recording.water_oxy_val = float(line.split(':')[-1].strip().replace('mg/l', ''))
# elif "Comment" in line:
# self.Recording.comment_val = ':'.join(line.split(':')[1:]).strip()
# elif "Experimenter" in line:
# self.Recording.experimenter_val = ':'.join(line.split(':')[1:]).strip()
# elif "DataTime" in line:
# self.Recording.datatime_val = int(line.split(':')[-1].strip().replace('ms', ''))
# elif "DataInterval" in line:
# self.Recording.datainterval_val = int(line.split(':')[-1].strip().replace('ms', ''))
# elif "BufferTime" in line:
# self.Recording.buffertime_val = int(line.split(':')[-1].strip().replace('s', ''))
# else:
# continue
# def led_controll(pin, t0, dt, stop_flag, save_f=None):
# next = t0
#
# while True:
# if stop_flag():
# break
# if time() > next:
# save_t = next + time() - next
# GPIO.output(pin, GPIO.HIGH)
# sleep(0.1)
# GPIO.output(pin, GPIO.LOW)
#
# if save_f != None:
# save_f.write('%.4f' % (save_t))
# save_f.flush()
# next += dt
#
#
#
# def temp_rec(w1_bus_path, temp_f, t0, dt, stop_flag):
# next = t0
# while True:
# if stop_flag():
# break
# if time() > next:
# w1_f = open(w1_bus_path, 'r')
# w1_file = w1_f.readlines()
# for line in w1_file:
# if 't=' in line:
# temp = float((line.split('=')[-1].strip())) / 1000
# temp_f.write('%6.0f; %7.3f\n' % (next, temp))
# temp_f.flush()
# break
# w1_f.close()
# next += dt
#
# def clock_controll(end_clock, run_led_pin, sync_led_pin, w1_bus_path, temp_f, led_f, stop_flag):
# t0 = time()
# sub_stop_flag = False
#
# run_led_interval = 2
# run_thread = threading.Thread(target=led_controll, args=(run_led_pin, t0, run_led_interval, lambda: sub_stop_flag, None))
#
# sync_led_interval = 1
# sync_thread = threading.Thread(target=led_controll, args=(sync_led_pin, t0, sync_led_interval, lambda: sub_stop_flag, led_f))
#
# temp_interval = 300
# temp_thread = threading.Thread(target=temp_rec, args=(w1_bus_path, temp_f, t0, temp_interval, lambda: sub_stop_flag))
#
# run_thread.start()
# sync_thread.start()
# temp_thread.start()
#
# while True:
# if stop_flag():
# sub_stop_flag = True
# sync_thread.join()
# run_thread.join()
# break
# if datetime.datetime.now().hour == end_clock[0] and datetime.datetime.now().minute == end_clock[1]:
# break
def clock_process(end_clock, run_led_pin, sync_led_pin, w1_bus_path, temp_f, led_f):
t0 = time()
run_led_interval = 2
sync_led_interval = 1
temp_interval = 300
next_t_t = 0
next_l_t = 0
print("\nDatetime: %.0f:%0f o'clock" % (datetime.datetime.now().hour, datetime.datetime.now().minute))
print("Terminate: %.0f:%0f o'clock" % (end_clock[0], end_clock[1]))
while True:
if datetime.datetime.now().hour >= end_clock[0] and datetime.datetime.now().minute >= end_clock[1]:
print('\nEnd time reached ...')
break
if (time() - t0) % temp_interval <= 0.1:
GPIO.output(run_led_pin, GPIO.HIGH)
GPIO.output(sync_led_pin, GPIO.HIGH)
sleep(0.1)
GPIO.output(run_led_pin, GPIO.LOW)
GPIO.output(sync_led_pin, GPIO.LOW)
w1_f = open(w1_bus_path, 'r')
w1_file = w1_f.readlines()
for line in w1_file:
if 't=' in line:
temp = float((line.split('=')[-1].strip())) / 1000
temp_f.write('%6.0f; %7.3f\n' % (next_t_t, temp))
temp_f.flush()
break
w1_f.close()
next_t_t += temp_interval
elif (time() - t0) % run_led_interval <= 0.1:
GPIO.output(run_led_pin, GPIO.HIGH)
GPIO.output(sync_led_pin, GPIO.HIGH)
sleep(0.1)
GPIO.output(run_led_pin, GPIO.LOW)
GPIO.output(sync_led_pin, GPIO.LOW)
elif (time() - t0) % sync_led_interval <= 0.1:
GPIO.output(sync_led_pin, GPIO.HIGH)
sleep(0.1)
GPIO.output(sync_led_pin, GPIO.LOW)
if led_f != None:
led_f.write('%.4f' % (next_l_t))
led_f.flush()
next_l_t += sync_led_interval
else:
pass
def save_process(q, f, gain):
while True:
if q.empty():
pass
elif q.full():
print('\n!!! Queue full !!!')
else:
Cdata = q.get()
# print(Cdata[:10])
Cdata.tofile(f)
f.flush()
# def duration_control(end_clock, stop_flag):
# while True:
# if stop_flag():
# break
#
# if datetime.datetime.now().hour == end_clock[0] and datetime.datetime.now().minute == end_clock[1]:
# break
#
# def led_controll_box(LED_t, LED1_pin, LED_out_pin, led_f, stop_flag):
# LED_t_interval = 2
# out_LED_interval = 1
#
# led_on_times = []
#
# status0 = False
# status1 = False
# while True:
# if stop_flag():
# GPIO.output(LED1_pin, GPIO.LOW)
# GPIO.output(LED_out_pin, GPIO.LOW)
# break
#
# if (time() - LED_t) % LED_t_interval < .1:
# status0 = True
# GPIO.output(LED1_pin, GPIO.HIGH)
# elif (time() - LED_t) % LED_t_interval >= .1 and status0 == True:
# status0 = False
# GPIO.output(LED1_pin, GPIO.LOW)
# else:
# pass
#
# if (time() - LED_t) % out_LED_interval < .1:
# status1 = True
# GPIO.output(LED_out_pin, GPIO.HIGH)
#
# led_on_times.append(time() - LED_t)
# led_f.write('%.4f' % (time() - LED_t))
# led_f.flush()
# elif (time() - LED_t) % out_LED_interval >= .1 and status1 == True:
# GPIO.output(LED_out_pin, GPIO.LOW)
# status1 = False
# else:
# pass
# def record_temperature(temp_t0, w1_bus_path, temp_f, stop_flag):
# next_temp_t = 0
# temp_interval = 300
#
# while True:
# if stop_flag():
# break
#
# if time() - temp_t0 > next_temp_t:
# w1_f = open(w1_bus_path, 'r')
# w1_file = w1_f.readlines()
# for line in w1_file:
# if 't=' in line:
# temp = float((line.split('=')[-1].strip())) / 1000
# temp_f.write('%6.0f; %7.3f\n' % (next_temp_t, temp))
# temp_f.flush()
# break
#
# w1_f.close()
# next_temp_t += temp_interval
def main():
LED1_pin = 11
LED2_pin = 13
LED_out_pin = 35
Button1_pin = 16
Button2_pin = 18
power_controll_pin = 37
LED_status = GPIO_setup(LED1_pin, LED2_pin, LED_out_pin, Button1_pin, Button2_pin, power_controll_pin)
# switch LEDs off
GPIO.output(LED1_pin, GPIO.LOW)
LED_status[0] = False
GPIO.output(LED2_pin, GPIO.LOW)
LED_status[1] = False
last_button_2_t = time()
now = datetime.datetime.now()
# defined start and end time
valid = False
if len(sys.argv) == 3:
if len(sys.argv[1]) == 4 and len(sys.argv[2]) == 4:
start_clock = [int(sys.argv[1][:2]), int(sys.argv[1][2:])]
end_clock = [int(sys.argv[2][:2]), int(sys.argv[2][2:])]
valid = True
if not valid:
start_clock = [10, 00]
end_clock = [16, 00]
# get init cfg
if os.path.exists('/media/pi/data1'):
init_path = '/media/pi/data1'
else:
init_path = '/home/raab/data/rasp_test'
init_cfgfile = os.path.join(init_path, 'fishgrid.cfg')
if os.path.exists(init_cfgfile):
path_format = read_cfg(init_cfgfile, now, init_read = True)
else:
print('cfg file missing !!!')
quit()
# create save folder and copy cfg file
path = os.path.join(init_path, now.strftime(path_format))
os.makedirs(path)
copyfile(os.path.join(os.path.split(path)[0], 'fishgrid.cfg'), os.path.join(path, 'fishgrid.cfg'))
cfgfile = os.path.join(path, 'fishgrid.cfg')
# read and edit config file
channels, rate, n_cols, n_rows, max_v, gain = read_cfg(cfgfile, now)
file = os.path.join(path, 'traces-grid1.raw')
temp_file = os.path.join(path, 'temperatures.csv')
led_file = os.path.join(path, 'led_times.csv')
# find w1bus for temp
record_temp = False
temp_f = None
w1_bus_path = glob.glob('/sys/bus/w1/devices/28*/w1_slave')
if len(w1_bus_path) > 0:
w1_bus_path = w1_bus_path[0]
record_temp = True
temp_f = open(temp_file, 'w')
temp_f.write('%-6s; %-7s\n' % ('time/s', 'T/C'))
f = open(file, 'wb')
led_f = open(led_file, 'w')
# f.close()
# DAQ setup
if True:
status = ScanStatus.IDLE
descriptor_index = 0 # ToDo: ????
range_index = 0 # ToDo: ????
interface_type = InterfaceType.USB
low_channel = 0
high_channel = channels - 1
buffer_sec = 20
samples_per_channel = rate * buffer_sec # * channels = Buffer size
buffer_size = samples_per_channel * channels
print('\nChannels: %.0f' % channels)
# rate = 20000
scan_options = ScanOption.CONTINUOUS
flags = AInScanFlag.DEFAULT
# Get descriptors for all of the available DAQ devices.
devices = get_daq_device_inventory(interface_type)
number_of_devices = len(devices)
if number_of_devices == 0:
raise Exception('Error: No DAQ devices found')
print('Found', number_of_devices, 'DAQ device(s):')
for i in range(number_of_devices):
print(' ', devices[i].product_name, ' (', devices[i].unique_id, ')', sep='')
# Create the DAQ device object associated with the specified descriptor index.
daq_device = None
daq_device = DaqDevice(devices[descriptor_index])
# Get the AiDevice object and verify that it is valid.
ai_device = None
ai_device = daq_device.get_ai_device()
if ai_device is None:
raise Exception('Error: The DAQ device does not support analog input')
# Verify that the specified device supports hardware pacing for analog input.
ai_info = ai_device.get_info()
if not ai_info.has_pacer():
raise Exception('\nError: The specified DAQ device does not support hardware paced analog input')
# Establish a connection to the DAQ device.
descriptor = daq_device.get_descriptor()
print('\nConnecting to', descriptor.dev_string, '- please wait...')
daq_device.connect()
# The default input mode is SINGLE_ENDED.
input_mode = AiInputMode.SINGLE_ENDED
# If SINGLE_ENDED input mode is not supported, set to DIFFERENTIAL.
if ai_info.get_num_chans_by_mode(AiInputMode.SINGLE_ENDED) <= 0:
input_mode = AiInputMode.DIFFERENTIAL
# Get the number of channels and validate the high channel number.
number_of_channels = ai_info.get_num_chans_by_mode(input_mode)
if high_channel >= number_of_channels:
high_channel = number_of_channels - 1
channel_count = high_channel - low_channel + 1
# Get a list of supported ranges and validate the range index.
ranges = ai_info.get_ranges(input_mode)
int_ranges = []
for r in ranges:
int_ranges.append(int(r.name.replace('BIP', '').replace('VOLTS', '')))
for idx in np.argsort(int_ranges):
if max_v * gain / 1000 <= int_ranges[idx]:
range_index = idx
break
print(ranges[range_index])
GPIO.output(LED1_pin, GPIO.HIGH)
LED_status[0] = True
GPIO.output(LED2_pin, GPIO.HIGH)
LED_status[0] = True
sleep(.5)
GPIO.output(LED1_pin, GPIO.LOW)
LED_status[0] = False
GPIO.output(LED2_pin, GPIO.LOW)
LED_status[0] = False
sleep(.5)
GPIO.output(LED1_pin, GPIO.HIGH)
LED_status[0] = True
GPIO.output(LED2_pin, GPIO.HIGH)
LED_status[0] = True
sleep(.5)
GPIO.output(LED1_pin, GPIO.LOW)
LED_status[0] = False
disp_eth_power = True
stop_flag = False
while True:
if datetime.datetime.now().hour == start_clock[0] and datetime.datetime.now().minute == start_clock[1]:
break
elif datetime.datetime.now().hour > start_clock[0] or datetime.datetime.now().minute > start_clock[1]:
h = datetime.datetime.now().hour
m = datetime.datetime.now().minute
start_clock = [h, m]
end_clock = [h + 6, m]
#clock_thread = threading.Thread(target=clock_controll, args=(end_clock, LED1_pin, LED_out_pin, w1_bus_path, temp_f, led_f, lambda: stop_flag))
#clock_thread.start()
clock_thread = mp.Process(target=clock_process, args=(end_clock, LED1_pin, LED_out_pin, w1_bus_path, temp_f, led_f))
clock_thread.start()
q = mp.Queue()
save_thread = mp.Process(target=save_process, args=(q, f, gain))
save_thread.start()
print('\nRecording started.')
data = create_float_buffer(channel_count, samples_per_channel)
print('----')
print('Buffer size: %.0fn; %.0fsec' % (len(data), buffer_sec))
print('Channels: %.0f' % channel_count)
print('Samples per channel: %.0f' % samples_per_channel)
print('----')
rate = ai_device.a_in_scan(low_channel, high_channel, input_mode, ranges[range_index], samples_per_channel,
rate, scan_options, flags, data)
status, transfer_status = ai_device.get_scan_status()
save_ranges = np.array([[int(buffer_size / 2), len(data)], [0, int(buffer_size / 2)]])
save_range = save_ranges[0]
cont_t = time()
while GPIO.input(Button1_pin) == GPIO.LOW and clock_thread.is_alive():
if GPIO.input(Button2_pin) == GPIO.HIGH:
if (time() - last_button_2_t) > 5:
if disp_eth_power == True:
subprocess.run(['tvservice', '-o'])
subprocess.run(['vcgencmd', 'display_power', '0'])#
subprocess.run(['sudo', 'ip', 'link', 'set', 'eth0', 'down'])
GPIO.output(LED2_pin, GPIO.LOW)
disp_eth_power = False
last_button_2_t = time()
elif disp_eth_power == False:
subprocess.run(['tvservice', '-p'])
subprocess.run(['vcgencmd', 'display_power', '1'])
subprocess.run(['sudo', '/bin/chvt', '6'])
subprocess.run(['sudo', '/bin/chvt', '7'])#
subprocess.run(['sudo', 'ip', 'link', 'set', 'eth0', 'up'])
GPIO.output(LED2_pin, GPIO.HIGH)
disp_eth_power = True
last_button_2_t = time()
# Get the status of the background operation
status, transfer_status = ai_device.get_scan_status()
index = transfer_status.current_index
# print(index)
if index >= save_range[0] and index < save_range[1]:
GPIO.output(LED2_pin, GPIO.HIGH)
dt = time() - cont_t
cont_t = time()
print("dt = %.3f sec" % (dt))
print('samples = %.0f' % (len(data[save_range[0]:save_range[1]]) / 15))
print('rate = %.2f Hz\n' % (len(data[save_range[0]:save_range[1]]) / 15 /dt))
# (np.array(data[save_range[0]:save_range[1]], dtype=np.float32) / gain).tofile(f)
# f.flush()
Cdata = np.copy(np.array(data[save_range[0]:save_range[1]], dtype=np.float32) / gain)
q.put(Cdata)
save_ranges = np.roll(save_ranges, 1, axis=0)
save_range = save_ranges[0]
GPIO.output(LED2_pin, GPIO.LOW)
# if index < 0 or index == last_idx:
# continue
#
# if index > last_idx:
#
# if index-last_idx > buffer_size / 5:
# (np.array(data[last_idx:index], dtype=np.float32) / gain).tofile(f)
# last_idx = index
# print('save')
# else:
# buffer_size = samples_per_channel * channels
# if buffer_size - last_idx + index > buffer_size / 5:
# (np.array(data[last_idx:], dtype=np.float32) / gain).tofile(f)
# (np.array(data[:index], dtype=np.float32) / gain).tofile(f)
# f.flush()
# print('save n flush')
# last_idx = index
#stop_flag = True
#clock_thread.join()
print('\nEmpty Queue')
while not q.empty():
sleep(0.01)
clock_thread.terminate()
save_thread.terminate()
print('\nDone!')
f.close()
temp_f.close()
led_f.close()
GPIO.output(LED1_pin, GPIO.HIGH)
GPIO.output(LED2_pin, GPIO.HIGH)
sleep(2)
GPIO.output(LED1_pin, GPIO.LOW)
GPIO.output(LED2_pin, GPIO.LOW)
if daq_device:
# Stop the acquisition if it is still running.
if status == ScanStatus.RUNNING:
ai_device.scan_stop()
if daq_device.is_connected():
daq_device.disconnect()
daq_device.release()
if disp_eth_power == False:
subprocess.run(['tvservice', '-p'])
subprocess.run(['vcgencmd', 'display_power', '1'])
subprocess.run(['sudo', '/bin/chvt', '6'])
subprocess.run(['sudo', '/bin/chvt', '7'])
# subprocess.run(['sudo', 'ip', 'link', 'set', 'eth0', 'up'])
GPIO.cleanup()
if __name__ == '__main__':
main()