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()