class ScaleThread(QThread): def __init__(self, portName): QThread.__init__(self) self.portName = portName self.txq = queue.queue() self.running = True def ser_out(self, s): self.txq.put(s) def ser_in(self, s): display(s) def run(self): try: self.scalePort = MettlerToledoDevice(port=self.portName) except: self.scalePort = None if not self.scalePort: print("Serial Port troubs") self.running = False while (self.running): s = self.scalePort.get_weight() if s: num = s[0] numstr = int.Parse(num) self.ser_in(numstr) if not self.txq.empty(): txd = str(self.txq.get()) self.ser_out(txd) if self.scalePort: self.scalePort.close() self.scalePort = None
class Connection: def __init__(self, address, device_id): self.address = address self.device_id = device_id self.dev = MettlerToledoDevice(port=self.address) def get_weight(self): weight = self.dev.get_weight() return { 'value': weight[0], 'unit': weight[1], 'stable': True if weight[2] is 'S' else False } def get_info(self): data = self.dev.get_balance_data() sn = self.dev.get_serial_number() sw = self.dev.get_software_version() if len(data) > 3: info = { 'model': data[0], 'model-type': data[1], 'sn': sn, 'sw-version': sw[0], 'sw-type': sw[1], 'capacity': data[1], 'unit': data[2] } else: info = { 'model': data[0], 'sn': sn, 'sw-version': sw[0], 'sw-type': sw[1], 'capacity': data[1], 'unit': data[2] } return info def get_address(self): return self.dev.get_port() def close(self): self.dev.close()
from mettler_toledo_device import MettlerToledoDevice dev = MettlerToledoDevice() # Might automatically find device if one available # if it is not found automatically, specify port directly #dev = MettlerToledoDevice(port='/dev/ttyUSB0') # Linux specific port dev = MettlerToledoDevice(port='/dev/ttyACM0') # Linux specific port for abstract control model dev = MettlerToledoDevice(port='/dev/tty.usbmodem262471') # Mac OS X specific port #dev = MettlerToledoDevice(port='COM3') # Windows specific port dev.get_serial_number() #1126493049 dev.get_balance_data() #['XS204', 'Excellence', '220.0090', 'g'] dev.get_weight_stable() #[-0.0082, 'g'] #if weight is stable #None #if weight is dynamic dev.get_weight() #[-0.6800, 'g', 'S'] #if weight is stable #[-0.6800, 'g', 'D'] #if weight is dynamic dev.zero_stable() #True #zeros if weight is stable #False #does not zero if weight is not stable dev.zero() #'S' #zeros if weight is stable #'D' #zeros if weight is dynamic
class Worker(QObject): ''' Worker thread Inherits from QRunnable to handler worker thread setup, signals and wrap-up. :param callback: The function callback to run on this worker thread. Supplied args and kwargs will be passed through to the runner. :type callback: function :param args: Arguments to pass to the callback function :param kwargs: Keywords to pass to the callback function ''' def __init__(self, name, max, **kwargs): super(Worker, self).__init__() # Store constructor arguments (re-used for processing) self.name = name self.max = max self.kwargs = kwargs self.signals = WorkerSignals() self.running = True self.isPaused = False self.scalePort = MettlerToledoDevice(port=self.name) # Add the callback to our kwargs def stop(self): self.event @Slot() def pause(self): self.isPaused = True @Slot() def resume(self): self.isPaused = False def cancel(self): self.scalePort.close() self.running = False def factor_conversion(self): if 0 < self.maxed < 5001: factor = 0.9 elif 5001 <= self.max < 20001: factor = 0.99 elif 20001 <= self.max: factor = 0.999 return factor @Slot() def run(self): resultcounter = 0 resultarray = npy.array([]) deltaarray = npy.array([]) changecounter = 0 while (self.running): while self.isPaused() == True: time.wait(0) try: s = self.scalePort.get_weight() if s: resultcounter += 1 num = s[0] inum = int(num) result = str(num) if resultcounter >= 5: resultarray.append(result) resultcounter = 0 changecounter += 1 p if changecounter >= 5: deltaarray.append(resultarray[len(resultarray) - 1] - resultarray[-1]) changecounter = 0 if deltaarray[len(deltaarray) - 1] - deltaarray[-1] <= 50: self.cancel() if len(resultarray) > 10: if len(resultarray) < 25: if sum(resultarray) / len(resultarray) <= 100: self.cancel() self.signals.result.emit(result) self.signals.progress.emit( 100 * inum / int(0.9 * self.factor_conversion())) if (inum > int(self.factor_conversion())): self.cancel() break if self.scalePort is None: self.cancel() break except: self.cancel() break # Return the result of the processin # Done if (self.running == False): self.signals.finished.emit()
class Worker(QRunnable): ''' Worker thread Inherits from QRunnable to handler worker thread setup, signals and wrap-up. :param callback: The function callback to run on this worker thread. Supplied args and kwargs will be passed through to the runner. :type callback: function :param args: Arguments to pass to the callback function :param kwargs: Keywords to pass to the callback function ''' def __init__(self, name, pumpname, max, isSerial, **kwargs): super(Worker, self).__init__() # Store constructor arguments (re-used for processing) self.name = name self.max = max self.isPaused = False self.pumpname = pumpname self.resultsvector = [] self.changevector = [] self.isSerial = isSerial self.kwargs = kwargs self.signals = WorkerSignals() self.running = True if (self.isSerial == True): try: self.pumpPort = serial.Serial(port=self.pumpname, baudrate=4800, bytesize=serial.SEVENBITS, parity=serial.PARITY_ODD, timeout=1) except: self.pumpPort.close() self.pumpPort = serial.Serial(port=self.pumpname, baudrate=4800, bytesize=serial.SEVENBITS, parity=serial.PARITY_ODD, timeout=1) self.scalePort = MettlerToledoDevice(port=self.name) # Add the callback to our kwargs def stop(self): self.event def pause(self): self.isPaused = True def resume(self): self.isPaused = False def cancel(self): if (self.isSerial == True): try: self.scalePort.close() self.running = False self.resultsvector = [] self.changevector = [] self.pumpPort.close() except: self.scalePort = None self.pumpPort = None else: #self.signals.pumpStop.emit() self.scalePort.close() self.running = False def factor_conversion(self): if 0 < self.max < 5001: factor = 0.9 elif 5001 <= self.max < 20001: factor = 0.99 elif 20001 <= self.max: factor = 0.999 return factor def convertToVoltage(self, rpm): volt = self.rpm * 0.016 @Slot() def run(self): if (self.isSerial == True): if (self.pumpPort): self.pumpPort.close() while (self.running): while self.isPaused: time.sleep(0) try: s = self.scalePort.get_weight() if s: num = s[0] inum = int(num) result = str(num) changes = [] self.resultsvector.append(int(inum)) self.signals.result.emit(result) self.signals.progress.emit(100 * inum / int(0.97 * self.max)) if (len(self.resultsvector) > 5): if (self.resultsvector[-1] != self.resultsvector[-2]): change = float(self.resultsvector[-1]) - float( self.resultsvector[-2]) self.changevector.append(float(change)) if (len(self.changevector) > 5): avg = sum(self.changevector) / len( self.changevector) if ((self.changevector[-1]) / avg < 0.1): self.signals.result.emit( "Air in the line or still clamped") self.signals.error.emit((str( self.changevector[-1] ), "Rate of change has fallen to low, check line" )) self.cancel() break if (inum > int(0.999 * self.max)): self.cancel() break if self.scalePort is None: self.cancel() break except: self.cancel() break # Return the result of the processin # Done if (self.running == False): self.signals.finished.emit()
from mettler_toledo_device import MettlerToledoDevice dev = MettlerToledoDevice() # Might automatically find device if one available # if it is not found automatically, specify port directly dev = MettlerToledoDevice(port='/dev/ttyACM0') # Linux specific port filename = dt.datetime.now().strftime('%Y-%m-%d hr%H_min%M_s%S') filename += '.csv' saveFile = open(filename, 'w') #saveFile = open('timedata.csv', 'aw') writer = csv.writer(saveFile) # Main # # get current weight print('program started') weight, units, stability = dev.get_weight() currWeight = weight # start picamera camera = picamera.PiCamera() stream = picamera.PiCameraCircularIO(camera, seconds=10) camera.start_recording(stream, format='h264') try: while True: print('waiting') # # Annotate camera timestamp = dt.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') camera.annotate_background = picamera.Color('black') camera.annotate_text = timestamp # Write File writer.writerow([timestamp, weight]) camera.wait_recording(0.2)
class Worker(QRunnable): ''' Worker thread Inherits from QRunnable to handler worker thread setup, signals and wrap-up. :param callback: The function callback to run on this worker thread. Supplied args and kwargs will be passed through to the runner. :type callback: function :param args: Arguments to pass to the callback function :param kwargs: Keywords to pass to the callback function ''' def __init__(self, name, pumpname, max, **kwargs): super(Worker, self).__init__() # Store constructor arguments (re-used for processing) self.name = name self.max = max self.pumpname = pumpname self.kwargs = kwargs self.signals = WorkerSignals() self.running = True self.resultsvector = [] self.changevector = [] self.txq = queue.Queue() self.scalePort = MettlerToledoDevice(port=self.name) try: self.pumpPort = serial.Serial(port=self.pumpname, baudrate=4800, bytesize=serial.SEVENBITS, parity=serial.PARITY_ODD, timeout=1) except: self.pumpPort.close() self.pumpPort = serial.Serial(port=self.pumpname, baudrate=4800, bytesize=serial.SEVENBITS, parity=serial.PARITY_ODD, timeout=1) # Add the callba ck to our kwargs def stop(self): self.event def cancel(self): try: self.scalePort.close() self.running = False self.pumpPort.close() self.resultsvector = [] self.changevector = [] except: self.scalePort = None self.pumpPort = None @Slot() def run(self): if (self.pumpPort): self.pumpPort.close() while (self.running): try: s = self.scalePort.get_weight() if s: num = s[0] inum = int(num) result = str(num) changes = [] self.resultsvector.append(int(inum)) self.signals.result.emit(result) self.signals.progress.emit(100 * inum / int(0.97 * self.max)) if (len(self.resultsvector) > 2): if (self.resultsvector[-1] != self.resultsvector[-2]): change = float(self.resultsvector[-1]) - float( self.resultsvector[-2]) self.changevector.append(float(change)) if (len(self.changevector) > 5): avg = sum(self.changevector) / len(self.changevector) if (avg > 0 and (self.changevector[-1]) / avg < 0.1): self.signals.result.emit( "Air in the line or still clamped") self.signals.error.emit( (str(self.changevector[-1]), "Rate of change has fallen to low, check line" )) self.cancel() break elif (avg == 0 and len(self.changevector) < 2): self.signals.result.emit( "Air in the line or still clamped") self.signals.error.emit( (str(self.changevector[-1]), "Rate of change has fallen to low, check line" )) self.cancel() break if (inum > int(0.99 * self.max)): self.cancel() break if self.scalePort is None: self.cancel() break except: traceback.print_exc() exctype, value = sys.exc_info()[:2] self.signals.error.emit( (exctype, value, traceback.format_exc())) self.cancel() break # Return the result of the processin # Done if (self.running == False): self.signals.finished.emit()
from mettler_toledo_device import MettlerToledoDevice dev = MettlerToledoDevice() # Might automatically find device if one available # if it is not found automatically, specify port directly #dev = MettlerToledoDevice(port='/dev/ttyUSB0') # Linux specific port dev = MettlerToledoDevice( port='/dev/ttyACM0') # Linux specific port for abstract control model dev = MettlerToledoDevice( port='/dev/tty.usbmodem262471') # Mac OS X specific port #dev = MettlerToledoDevice(port='COM3') # Windows specific port dev.get_serial_number() #1126493049 dev.get_balance_data() #['XS204', 'Excellence', '220.0090', 'g'] dev.get_weight_stable() #[-0.0082, 'g'] #if weight is stable #None #if weight is dynamic dev.get_weight() #[-0.6800, 'g', 'S'] #if weight is stable #[-0.6800, 'g', 'D'] #if weight is dynamic dev.zero_stable() #True #zeros if weight is stable #False #does not zero if weight is not stable dev.zero() #'S' #zeros if weight is stable #'D' #zeros if weight is dynamic
import serial from time import gmtime, strftime import picamera import datetime as dt import csv from mettler_toledo_device import MettlerToledoDevice dev = MettlerToledoDevice() # Might automatically find device if one available # if it is not found automatically, specify port directly dev = MettlerToledoDevice(port='/dev/ttyACM0') # Linux specific port #ser = serial.Serial('/dev/ttyACM0',9600) #weightdata = ser.readline() weightdata = dev.get_weight() timedata = strftime("%Y-%m-%d %H:%M:%S", gmtime()) file = open('timedata.csv','aw') writer = csv.writer(file) # with picamera.PiCamera() as camera: # camera.resolution = (640, 480) #weightdata = ser.readline() weightdata = dev.get_weight() timedata = strftime("%Y-%m-%d %H:%M:%S", gmtime()) print(weightdata,timedata) camera = picamera.PiCamera(resolution=(1280, 720), framerate=24) camera.start_preview() camera.annotate_background = picamera.Color('black')
class Hybridizer(object): ''' This Python package (hybridizer) creates a class named Hybridizer to communcate with and control the Janelia Hybridizer. The hybridizer uses two hardware control devices, the mixed_signal_controller modular_device, and the bioshake_device. The mixed_signal_controller both switches the valves and reads the analog signals from the cylinder hall effect sensors. The bioshake_device controls the heater/shaker. Example Usage: hyb = Hybridizer('example_config.yaml') hyb.run_protocol() ''' # def __init__(self, # config_file_path, # *args,**kwargs): def __init__(self, config_file_path, calibration_file_path, *args,**kwargs): if 'debug' in kwargs: self._debug = kwargs['debug'] else: kwargs.update({'debug': DEBUG}) self._debug = DEBUG with open(config_file_path,'r') as config_stream: self._config = yaml.load(config_stream) with open(calibration_file_path,'r') as calibration_stream: self._calibration = yaml.load(calibration_stream) self._valves = self._config['head'] self._valves.update(self._config['manifold']) ports = find_serial_device_ports(debug=self._debug) self._debug_print('Found serial devices on ports ' + str(ports)) self._debug_print('Identifying connected devices (may take some time)...') self._balance = MettlerToledoDevice() ports.remove(self._balance.get_port()) # try: # self._bsc = BioshakeDevice() # except RuntimeError: # # try one more time # self._bsc = BioshakeDevice() # self._debug_print('Found bioshake device on port ' + str(self._bsc.get_port())) # ports.remove(self._bsc.get_port()) # self._SHAKE_SPEED_MIN = self._bsc.get_shake_speed_min() # self._SHAKE_SPEED_MAX = self._bsc.get_shake_speed_max() # self._SHAKE_DURATION_MIN = 10 # self._SHAKE_ATTEMPTS = 2 # self._POST_SHAKE_OFF_DURATION = 5 modular_devices = ModularDevices(try_ports=ports) try: msc_dict = modular_devices['mixed_signal_controller'] except KeyError: raise HybridizerError('Could not find mixed_signal_controller. Check connections and permissions.') if len(msc_dict) > 1: raise HybridizerError('More than one mixed_signal_controller found. Only one should be connected.') self._msc = msc_dict[msc_dict.keys()[0]] self._debug_print('Found mixed_signal_controller on port ' + str(self._msc.get_port())) # self._adc_values_min = None # self._adc_values_max = None self._adc_sample_count = 21 self._fill_duration_all_cylinders = 250 self._fill_duration_one_cylinder = 100 self._volume_crossover = 6 self._volume_threshold_initial = 1.0 def prime_system(self): self._setup() self._debug_print('priming system...') manifold = self._config['manifold'] chemicals = manifold.keys() try: chemicals.remove('aspirate') except ValueError: pass try: chemicals.remove('separate') except ValueError: pass self._set_valves_on(['separate','aspirate']) for chemical in chemicals: self._prime_chemical(chemical,self._config['system_prime_count']) self._set_all_valves_off() self._debug_print('priming finished!') def run_protocol(self): self._setup() self.protocol_start_time = time.time() self._debug_print('running protocol...') self._set_valves_on(['separate','aspirate']) for chemical_info in self._config['protocol']: chemical = chemical_info['chemical'] try: prime_count = chemical_info['prime_count'] except KeyError: prime_count = 1 try: dispense_count = chemical_info['dispense_count'] except KeyError: dispense_count = 1 try: shake_speed = chemical_info['shake_speed'] except KeyError: shake_speed = None try: shake_duration = chemical_info['shake_duration'] except KeyError: shake_duration = None try: post_shake_duration = chemical_info['post_shake_duration'] except KeyError: post_shake_duration = 0 try: separate = chemical_info['separate'] except KeyError: separate = False try: aspirate = chemical_info['aspirate'] except KeyError: aspirate = True try: temperature = chemical_info['temperature'] except KeyError: temperature = None try: repeat = chemical_info['repeat'] except KeyError: repeat = 0 self._run_chemical(chemical, prime_count, dispense_count, shake_speed, shake_duration, post_shake_duration, separate, aspirate, temperature, repeat) self._set_all_valves_off() self.protocol_end_time = time.time() protocol_run_time = self.protocol_end_time - self.protocol_start_time self._debug_print('protocol finished! it took ' + str(round(protocol_run_time/60)) + ' mins to run.') def _setup(self): # self._bsc.reset_device() self._msc.remove_all_set_fors() self._set_all_valves_off() self._set_valves_on(['primer','quad1','quad2','quad3','quad4','quad5','quad6']) self._debug_print('setting up for ' + str(self._config['setup_duration']) + 's...') time.sleep(self._config['setup_duration']) self._set_all_valves_off() self._debug_print('setup finished!') def _prime_chemical(self,chemical,prime_count): if prime_count > 0: self._set_valve_on(chemical) for i in range(prime_count): self._set_valves_on(['primer','system']) self._debug_print('priming ' + chemical + ' for ' + str(self._config['prime_duration']) + 's ' + str(i+1) + '/' + str(prime_count) + '...') time.sleep(self._config['prime_duration']) self._set_valves_off(['system']) self._debug_print('emptying ' + chemical + ' for ' + str(self._config['prime_aspirate_duration']) + 's ' + str(i+1) + '/' + str(prime_count) + '...') time.sleep(self._config['prime_aspirate_duration']) self._set_valve_off('primer') if prime_count > 0: self._set_valve_off(chemical) def _run_chemical(self, chemical, prime_count=1, dispense_count=1, shake_speed=None, shake_duration=None, post_shake_duration=0, separate=False, aspirate=True, temp_target=None, repeat=0): if (chemical not in self._valves): raise HybridizerError(chemical + ' is not listed as part of the manifold in the config file!') if repeat < 0: repeat = 0 run_count = repeat + 1 if temp_target is not None: self._debug_print('turning on temperature control for ' + chemical + '...') self._bsc.temp_on(temp_target) temp_actual = self._bsc.get_temp_actual() self._debug_print('actual temperature: ' + str(temp_actual) + ',target temperature: ' + str(temp_target)) while abs(temp_target - temp_actual) > 0.5: time.sleep(1) temp_actual = self._bsc.get_temp_actual() self._debug_print('actual temperature: ' + str(temp_actual) + ',target temperature: ' + str(temp_target)) self._debug_print() self._prime_chemical(chemical,prime_count) for run in range(run_count): self._debug_print('running ' + chemical + ' ' + str(run+1) + '/' + str(run_count) + '...') self._set_valve_on(chemical) self._set_valves_on(['quad1','quad2','quad3','quad4','quad5','quad6','aspirate']) for i in range(dispense_count): if i > 0: dispense_shake_duration = self._config['inter_dispense_shake_duration'] if dispense_shake_duration < self._SHAKE_DURATION_MIN: dispense_shake_duration = self._SHAKE_DURATION_MIN dispense_shake_speed = self._shake_on(self._config['inter_dispense_shake_speed']) self._debug_print('shaking at ' + str(dispense_shake_speed) + 'rpm for ' + str(dispense_shake_duration) + 's...') time.sleep(dispense_shake_duration) self._shake_off(dispense_shake_speed) self._set_valve_on('system') self._debug_print('loading ' + chemical + ' into syringes for ' + str(self._config['load_duration']) + 's ' + str(i+1) + '/' + str(dispense_count) + '...') time.sleep(self._config['load_duration']) self._set_valve_off('system') self._debug_print('dispensing ' + chemical + ' into microplate for ' + str(self._config['dispense_duration']) + 's ' + str(i+1) + '/' + str(dispense_count) + '...') time.sleep(self._config['dispense_duration']) self._set_valves_off(['quad1','quad2','quad3','quad4','quad5','quad6']) if not ((shake_duration is None) or (shake_duration <= 0)): actual_shake_duration = shake_duration if shake_duration < self._SHAKE_DURATION_MIN: actual_shake_duration = self._SHAKE_DURATION_MIN actual_shake_speed = self._shake_on(shake_speed) self._debug_print('shaking at ' + str(actual_shake_speed) + 'rpm for ' + str(actual_shake_duration) + 's...') time.sleep(actual_shake_duration) self._shake_off(actual_shake_speed) if (post_shake_duration > 0): self._debug_print('waiting post shake for ' + str(post_shake_duration) + 's...') time.sleep(post_shake_duration) if separate: separate_shake_speed = self._shake_on(self._config['separate_shake_speed']) self._set_valve_off('separate') self._debug_print('separating ' + chemical + ' for ' + str(self._config['chemical_separate_duration']) + 's...') time.sleep(self._config['chemical_separate_duration']) self._set_valve_on('separate') self._shake_off(separate_shake_speed) if aspirate: aspirate_shake_speed = self._shake_on(self._config['aspirate_shake_speed']) self._set_valve_off('aspirate') self._debug_print('aspirating ' + chemical + ' from microplate for ' + str(self._config['chemical_aspirate_duration']) + 's...') time.sleep(self._config['chemical_aspirate_duration']) self._set_valve_on('aspirate') self._shake_off(aspirate_shake_speed) self._set_valve_off(chemical) self._debug_print(chemical + ' finished!') self._debug_print() if temp_target is not None: self._debug_print('turning off temperature control for ' + chemical + '...') try: self._bsc.temp_off() except BioshakeError: pass self._debug_print() def _shake_on(self,shake_speed): if (shake_speed is None) or (shake_speed < self._SHAKE_SPEED_MIN): shake_speed = 0 elif shake_speed > self._SHAKE_SPEED_MAX: shake_speed = self._SHAKE_SPEED_MAX if shake_speed != 0: shook = False shake_try = 0 while (not shook) and (shake_try < self._SHAKE_ATTEMPTS): shake_try += 1 try: self._bsc.shake_on(shake_speed) shook = True except BioshakeError: self._debug_print('bioshake_device.get_error_list(): ' + str(self._bsc.get_error_list())) self._debug_print('BioshakeError! Resetting for ' + str(self._config['setup_duration']) + 's and trying again...') self._bsc.reset_device() time.sleep(self._config['setup_duration']) return shake_speed def _shake_off(self,shake_speed): if shake_speed != 0: shook = False shake_try = 0 while (not shook) and (shake_try < self._SHAKE_ATTEMPTS): shake_try += 1 try: self._bsc.shake_off() shook = True except BioshakeError: self._debug_print('bioshake_device.get_error_list(): ' + str(self._bsc.get_error_list())) self._debug_print('BioshakeError! Resetting for ' + str(self._config['setup_duration']) + 's and trying again...') self._bsc.reset_device() time.sleep(self._config['setup_duration']) time.sleep(self._POST_SHAKE_OFF_DURATION) def _debug_print(self,*args): if self._debug: print(*args) def _set_valve_on(self,valve_key): try: valve = self._valves[valve_key] channels = [valve['channel']] self._msc.set_channels_on(channels) except KeyError: raise HybridizerError('Unknown valve: ' + str(valve_key) + '. Check yaml config file for errors.') def _set_valves_on(self,valve_keys): try: channels = [self._valves[valve_key]['channel'] for valve_key in valve_keys] self._msc.set_channels_on(channels) except KeyError: raise HybridizerError('Unknown valve: ' + str(valve_key) + '. Check yaml config file for errors.') def _set_valve_off(self,valve_key): try: valve = self._valves[valve_key] channels = [valve['channel']] self._msc.set_channels_off(channels) except KeyError: raise HybridizerError('Unknown valve: ' + str(valve_key) + '. Check yaml config file for errors.') def _set_valves_off(self,valve_keys): try: channels = [self._valves[valve_key]['channel'] for valve_key in valve_keys] self._msc.set_channels_off(channels) except KeyError: raise HybridizerError('Unknown valve: ' + str(valve_key) + '. Check yaml config file for errors.') def _set_all_valves_off(self): valve_keys = self._get_valves() self._set_valves_off(valve_keys) def _get_valves(self): valve_keys = self._valves.keys() valve_keys.sort() return valve_keys def _get_adc_values_filtered(self): adc_values = None for sample_n in range(self._adc_sample_count): sample_values = self._msc.get_analog_inputs_filtered() if adc_values is None: adc_values = numpy.array([sample_values],int) else: adc_values = numpy.append(adc_values,[sample_values],axis=0) time.sleep(0.1) adc_values_filtered = numpy.median(adc_values,axis=0) adc_values_filtered = adc_values_filtered.astype(int) return adc_values_filtered # def _store_adc_values_min(self): # self._adc_values_min = {} # adc_values_filtered = self._get_adc_values_filtered() # head_valves = self._config['head'] # for head_valve in head_valves: # try: # ain = self._config['head'][head_valve]['analog_inputs']['low'] # adc_value = adc_values_filtered[ain] # self._adc_values_min[head_valve] = adc_value # except KeyError: # continue # self._debug_print(self._adc_values_min) # def _set_valves_on_until(self,valve_keys,volume): # for valve_key in valve_keys: # valve = self._valves[valve_key] # channels = [valve['channel']] # adc_value_goal,ain = self._volume_to_adc_and_ain(valve_key,volume) # set_until_index = self._msc.set_channels_on_until(channels,ain,adc_value_goal) # while not self._msc.are_all_set_untils_complete(): # self._debug_print('Waiting...') # time.sleep(1) # self._msc.remove_all_set_untils() # for valve_key in valve_keys: # valve = self._valves[valve_key] # adc_value_goal,ain = self._volume_to_adc_and_ain(valve_key,volume) # adc_value = self._msc.get_analog_input(ain) # volume = self._adc_to_volume_low(valve_key,adc_value) def _set_valves_on_until(self,valve_keys,volume): channels = [] adc_value_goals = [] ains = [] jumps = {} valve_keys_copy = copy.copy(valve_keys) for valve_key in valve_keys: valve = self._valves[valve_key] channels.append(valve['channel']) adc_value_goal,ain = self._volume_to_adc_and_ain(valve_key,volume) adc_value_goals.append(adc_value_goal) ains.append(ain) jumps[valve_key] = 0 volume_goal_initial = volume - self._volume_threshold_initial fill_duration_initial_max = 0 fill_durations_initial = [] if volume_goal_initial >= self._volume_threshold_initial/2: for valve_key in valve_keys: fill_duration_initial = self._volume_to_fill_duration(valve_key,volume_goal_initial) fill_durations_initial.append(fill_duration_initial) fill_duration_initial_min = min(fill_durations_initial) self._msc.set_channels_on_for(channels,fill_duration_initial_min) while not self._msc.are_all_set_fors_complete(): self._debug_print('Waiting...') time.sleep(0.5 + fill_duration_initial_min/1000) self._msc.remove_all_set_fors() fill_duration_base = self._fill_duration_one_cylinder fill_duration_per_cylinder = (self._fill_duration_all_cylinders - self._fill_duration_one_cylinder)//(len(channels)-1) while len(channels) > 0: fill_duration = fill_duration_base + fill_duration_per_cylinder*(len(channels)-1) self._debug_print("Setting {0} valves on for {1}ms".format(valve_keys_copy,fill_duration)) self._msc.set_channels_on_for(channels,fill_duration) while not self._msc.are_all_set_fors_complete(): self._debug_print('Waiting...') time.sleep(fill_duration/1000) self._msc.remove_all_set_fors() adc_values_filtered = self._get_adc_values_filtered() ains_copy = copy.copy(ains) for ain in ains_copy: index = ains.index(ain) valve_key_copy = valve_keys_copy[index] jumps[valve_key_copy] += 1 if adc_values_filtered[ain] >= adc_value_goals[index]: channels.pop(index) adc_value_goals.pop(index) ains.pop(index) valve_keys_copy.pop(index) adc_values_filtered = self._get_adc_values_filtered() final_adc_values = [] jumps_list = [] for valve_key in valve_keys: adc_value_goal,ain = self._volume_to_adc_and_ain(valve_key,volume) adc_value = adc_values_filtered[ain] final_adc_values.append(adc_value) jumps_list.append(jumps[valve_key]) # volume = self._adc_to_volume_low(valve_key,adc_value) return final_adc_values,jumps_list # def _volume_to_adc_and_ain(self,valve_key,volume): # valve = self._valves[valve_key] # if volume <= self._config['volume_crossover']: # ain = valve['analog_inputs']['low'] # else: # ain = valve['analog_inputs']['low'] # if volume > self._config['volume_max']: # raise HybridizerError('Asking for volume greater than the max volume of {0}!'.format(self._config['volume_max'])) # if volume <= self._config['volume_crossover']: # poly = Polynomial(self._config['poly_coefficients']['volume_to_adc_low']) # adc_value = int(round(poly(volume))) # adc_value += self._adc_values_min[valve_key] # self._debug_print("valve: {0}, adc_value: {1}, ain: {2}".format(valve_key,adc_value,ain)) # return adc_value,ain # else: # return 400,ain def _volume_to_adc_and_ain(self,valve_key,volume): valve = self._valves[valve_key] if volume <= self._volume_crossover: ain = valve['analog_inputs']['low'] else: ain = valve['analog_inputs']['high'] if volume > self._config['volume_max']: raise HybridizerError('Asking for volume greater than the max volume of {0}!'.format(self._config['volume_max'])) if volume <= self._volume_crossover: poly = Polynomial(self._calibration[valve_key]['volume_to_adc_low']) adc_value = int(round(poly(volume))) self._debug_print("valve: {0}, adc_value: {1}, ain: {2}".format(valve_key,adc_value,ain)) return adc_value,ain else: poly = Polynomial(self._calibration[valve_key]['volume_to_adc_high']) adc_value = int(round(poly(volume))) self._debug_print("valve: {0}, adc_value: {1}, ain: {2}".format(valve_key,adc_value,ain)) return adc_value,ain def _volume_to_fill_duration(self,valve_key,volume): poly = Polynomial(self._calibration[valve_key]['volume_to_fill_duration']) fill_duration = int(round(poly(volume))) return fill_duration # def _adc_to_volume_low(self,valve_key,adc_value): # valve = self._valves[valve_key] # adc_value -= self._adc_values_min[valve_key] # poly = Polynomial(self._config['poly_coefficients']['adc_to_volume_low']) # volume = poly(adc_value) # self._debug_print("valve: {0}, adc_value: {1}, volume: {2}".format(valve_key,adc_value,volume)) # return volume def run_dispense_tests(self): self._debug_print('pre setup sequence...') valves = ['quad1','quad2','quad3','quad4','quad5','quad6'] self._set_valve_on('aspirate') self._set_valve_on('system') self._set_valves_on(valves) time.sleep(10) self._set_valve_off('system') time.sleep(10) self._set_valve_off('aspirate') time.sleep(20) self._setup() self._set_valve_on('aspirate') time.sleep(10) # self._debug_print('zeroing hall effect sensors...') # self._store_adc_values_min() self._debug_print('zeroing balance...') self._balance.zero() self._debug_print('running dispense tests...') timestr = time.strftime("%Y%m%d-%H%M%S") data_file = open(timestr+'.csv','w') data_writer = csv.writer(data_file) header = ['dispense_goal','initial_weight'] valve_adc = [valve+'_adc' for valve in valves] header.extend(valve_adc) valve_jumps = [valve+'_jumps' for valve in valves] header.extend(valve_jumps) header.extend(valves) data_writer.writerow(header) # dispense_goals = [5,4,3,2,1] # dispense_goals = [1,0.75,0.5,0.25] dispense_goals = [5,1,0.5] # dispense_goals = [2,1] # run_count = 10 run_count = 1 # dispense_goals = [1] # run_count = 2 for dispense_goal in dispense_goals: for run in range(run_count): self._set_valve_on('aspirate') time.sleep(2) self._debug_print('dispense_goal: {0}, run: {1} out of {2}'.format(dispense_goal,run+1,run_count)) row_data = [] row_data.append(dispense_goal) initial_weight = self._balance.get_weight()[0] self._debug_print('initial_weight: {0}'.format(initial_weight)) row_data.append(initial_weight) self._set_valve_on('system') time.sleep(2) final_adc_values,jumps = self._set_valves_on_until(valves,dispense_goal) row_data.extend(final_adc_values) row_data.extend(jumps) self._set_valve_off('system') time.sleep(4) weight_prev = initial_weight for valve in valves: self._debug_print('Dispensing {0}'.format(valve)) self._set_valve_on(valve) time.sleep(4) self._set_valve_off(valve) time.sleep(2) weight_total = self._balance.get_weight()[0] weight = weight_total - weight_prev self._debug_print('{0} measured {1}'.format(valve,weight)) row_data.append(weight) weight_prev = weight_total self._set_valve_off('aspirate') self._debug_print('aspirating...') time.sleep(20) self._set_all_valves_off() data_writer.writerow(row_data) data_file.close() def run_calibration(self): self._debug_print('pre setup sequence...') valves = ['quad1','quad2','quad3','quad4','quad5','quad6'] self._set_valve_on('aspirate') self._set_valve_on('system') self._set_valves_on(valves) time.sleep(10) self._set_valve_off('system') time.sleep(10) self._set_valve_off('aspirate') time.sleep(20) self._setup() self._set_valve_on('aspirate') time.sleep(10) # self._debug_print('zeroing hall effect sensors...') # self._store_adc_values_min() self._debug_print('zeroing balance...') self._balance.zero() self._debug_print('running calibration...') timestr = time.strftime("%Y%m%d-%H%M%S") data_file = open(timestr+'.csv','w') data_writer = csv.writer(data_file) header = ['fill_duration','initial_weight'] valve_adc_low = [valve+'_adc_low' for valve in valves] header.extend(valve_adc_low) valve_adc_high = [valve+'_adc_high' for valve in valves] header.extend(valve_adc_high) header.extend(valves) data_writer.writerow(header) duration_inc = 250 duration_max = 10000 fill_durations = range(duration_inc,duration_max+duration_inc,duration_inc) run_count = 3 for run in range(run_count): for fill_duration in fill_durations: self._set_valve_on('aspirate') time.sleep(2) self._debug_print('fill_duration: {0}, run: {1} out of {2}'.format(fill_duration,run+1,run_count)) row_data = [] row_data.append(fill_duration) initial_weight = self._balance.get_weight()[0] self._debug_print('initial_weight: {0}'.format(initial_weight)) row_data.append(initial_weight) self._set_valve_on('system') time.sleep(2) channels = [] adc_low_ain = [] adc_high_ain = [] for valve_key in valves: valve = self._valves[valve_key] channels.append(valve['channel']) adc_low_ain.append(valve['analog_inputs']['low']) adc_high_ain.append(valve['analog_inputs']['high']) self._msc.set_channels_on_for(channels,fill_duration) while not self._msc.are_all_set_fors_complete(): self._debug_print('Waiting...') time.sleep(fill_duration/1000) self._msc.remove_all_set_fors() adc_values_filtered = self._get_adc_values_filtered() adc_low_values = [adc_values_filtered[ain] for ain in adc_low_ain] adc_high_values = [adc_values_filtered[ain] for ain in adc_high_ain] row_data.extend(adc_low_values) row_data.extend(adc_high_values) self._set_valve_off('system') time.sleep(4) weight_prev = initial_weight for valve in valves: self._debug_print('Dispensing {0}'.format(valve)) self._set_valve_on(valve) time.sleep(4) self._set_valve_off(valve) time.sleep(2) weight_total = self._balance.get_weight()[0] weight = weight_total - weight_prev self._debug_print('{0} measured {1}'.format(valve,weight)) row_data.append(weight) weight_prev = weight_total self._set_valve_off('aspirate') self._debug_print('aspirating...') time.sleep(20) self._set_all_valves_off() data_writer.writerow(row_data) data_file.close()
import csv from mettler_toledo_device import MettlerToledoDevice dev = MettlerToledoDevice() # Might automatically find device if one available # if it is not found automatically, specify port directly dev = MettlerToledoDevice(port='/dev/ttyACM0') # Linux specific port filename = dt.datetime.now().strftime('%Y-%m-%d hr%H_min%M_s%S') filename += '.csv' saveFile = open(filename, 'w') #saveFile = open('timedata.csv', 'aw') writer = csv.writer(saveFile) # Main # # get current weight print('program started') weight, units, stability = dev.get_weight() currWeight = weight # start picamera camera = picamera.PiCamera() stream = picamera.PiCameraCircularIO(camera, seconds=10) camera.start_recording(stream, format='h264') try: while True: print('waiting') # # Annotate camera timestamp = dt.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') camera.annotate_background = picamera.Color('black') camera.annotate_text = timestamp # Write File writer.writerow([timestamp, weight]) camera.wait_recording(0.2)