def create_stimuli(self, banner): """ Creates all stimuli that is to be drawn by the Trial class and stores them as attributes and into lists for easy drawing. Params: None Returns: None """ banner_text = visual.TextStim(self.win, text=banner, pos=[0, 500], height=40, wrapWidth=Constants.WINDOW_SIZE[0]) next_box_text = visual.TextStim(self.win, text="Show next box", pos=[0, -300]) choice_text0 = visual.TextStim( self.win, text='Press the circle if you believe it is the dominant colour:', pos=[-600, -300]) choice_text1 = visual.TextStim( self.win, text='Press the circle if you believe it is the dominant colour:', pos=[600, -300]) self.button0 = visual.Circle(self.win, radius=50, pos=[-600, -400], fillColor=self.colours[0]) self.button1 = visual.Circle(self.win, radius=50, pos=[600, -400], fillColor=self.colours[1]) self.continue_box = visual.Rect(self.win, pos=[0, -300], width=Constants.SQUARE_SIZE, height=Constants.SQUARE_SIZE / 2, fillColor="black") rating_text0 = visual.TextStim(self.win, text=f"More \n{self.colours[2]}", pos=[-800, -400], color=self.colours[0]) rating_text1 = visual.TextStim(self.win, text=f"More \n{self.colours[3]}", pos=[800, -400], color=self.colours[1]) self.rating_scale = Scale(self.win, self.colours) self.rating_stims = [rating_text0, rating_text1, banner_text ] + self.grid self.drawables = [self.continue_box, next_box_text, banner_text ] + self.grid self.choice_stims = [ self.button0, self.button1, choice_text0, choice_text1 ] self.boxes_revealed = 0
def main(): base = 528.00 mode_builder = ModeBuilder(base) # Unpure Octave mode_builder.build_scale_from_octave_adjustment() #Pure Octave mode_builder.build_scale_from_pythag_class() pythag_series = PythagSeries(base) scale = Scale(base) scale.scale_intervals = pythag_series.scale_intervals ModeBuilderTests.test_natural_scale(pythag_series) ModeBuilderTests.test_octave_scale(scale)
def InicializarCeldasTR(self): #Inicializa las celdas de carga del concentrado self.ahxC1 = Scale(self.alsensorC1[0], self.alsensorC1[1], 1, 80) #Celda de carga Concentrado C2 self.ahxC2 = Scale(self.alsensorC2[0], self.alsensorC2[1], 1, 80) #Celda de carga Concentrado C3 self.ahxC3 = Scale(self.alsensorC3[0], self.alsensorC3[1], 1, 80) #Celda de carga Concentrado C4 self.ahxC4 = Scale(self.alsensorC4[0], self.alsensorC4[1], 1, 80)
def inicializarCeldas(self): #Inciar celdas de carga print("\n________________\nIniciando celdas de carga\n________________\n") #Formato tupla: self.alsensorA = (dt,sck) #Celda de carga Concentrado C1 self.ahxC1 = Scale(self.alsensorC1[0], self.alsensorC1[1], 1, 80) #Celda de carga Concentrado C2 self.ahxC2 = Scale(self.alsensorC2[0], self.alsensorC2[1], 1, 80) #Celda de carga Concentrado C3 self.ahxC3 = Scale(self.alsensorC3[0], self.alsensorC3[1], 1, 80) #Celda de carga Concentrado C4 self.ahxC4 = Scale(self.alsensorC4[0], self.alsensorC4[1], 1, 80) #Celda de carga Levadura Mineral self.ahxML = Scale(self.alsensorML[0], self.alsensorML[1], 1, 80) self.resetearCeldas()
def __init__(self, filename, Cport, Tport, Sport): self.filename=filename self.Cport = Cport self.Tport = Tport self.Sport = Sport self.con = ConductivityProbe(Cport, 115200) self.con.openC() self.T = TemperatureProbes(Tport, 115200) self.T.openC() self.S = Scale(Sport, 19200) self.S.openC() f = open(self.filename, "w+") f.write("Cond\tWeight\tHotIn\tHotOut\tColdIn\tColdOut\tMonth\tDay\tHour\tMinute\tSecond\n") f.close() print("Waiting for first second of minute...") time = t.localtime(None).tm_sec while(time != 0): time = t.localtime(None).tm_sec
def add_scales(self): for scale in Scale.all(): #if fingerprint exists, get current fingerprint to modify #print(scale.stamp) if self.fingerprint(scale.id): fingerprint = self.fingerprints[scale.id] fingerprint.add_scale(scale) #else create new fingerprint else: self.fingerprints[scale.id] = Fingerprint(scale.stamp) self.fingerprints[scale.id].add_scale(scale)
def build_scale_from_octave_adjustment(self): octave_scale = Scale(self.base_frequency) octave_scale.scale_intervals = self.initial_scale.scale_intervals octave_scale.scale_intervals = octave_scale.sort_by_final_frequency() for i in self.mode_names: print(i) self.play_scale(octave_scale.scale_intervals) octave_scale.get_next_mode()
def __init__(self): QMainWindow.__init__(self) # Setup the ui form self.ui = Ui_MainWindow() self.ui.setupUi(self) # Create a new QGraphicsScene and show it on the ui self.scene = QGraphicsScene(self) self.scene.setBackgroundBrush(QColor(120, 120, 120)) self.ui.graphicsView.setScene(self.scene) self.ui.graphicsView.show() # Setup tuning self.tuning = [('Standard Tuning', [ Note("E", 2), Note("A", 2), Note("D", 3), Note("G", 3), Note("B", 3), Note("E", 4) ]), ('Dropped D', [ Note("D", 2), Note("A", 2), Note("D", 3), Note("G", 3), Note("B", 3), Note("E", 4) ]), ('Dropped C', [ Note("C", 2), Note("G", 2), Note("C", 3), Note("F", 3), Note("A", 3), Note("D", 4) ])] t1 = QGraphicsTextItem() t2 = QGraphicsTextItem() t3 = QGraphicsTextItem() t4 = QGraphicsTextItem() t5 = QGraphicsTextItem() t6 = QGraphicsTextItem() self.tuning_list = [t1, t2, t3, t4, t5, t6] # Define fret number self.FRETS = 22 # Create a new Guitar object self.GibsonGuitar = Guitar(self.FRETS, self.tuning[0][1]) # Create a new Guitar Fretboard object and show it on the scene self.GibsonGuitar_Fretboard = GraphicsFretboard(self.FRETS) self.GibsonGuitar_Fretboard.setPos(0, 0) self.scene.addItem(self.GibsonGuitar_Fretboard) # Draw the tuning self.draw_tuning(self.tuning[0][1]) # Populate the notes pool self.notes = [ 'A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#' ] # Populate the scales pool self.scales = [ Scale("Pentatonic Major", [2, 2, 3, 2, 3], 'box_pattern'), Scale("Pentatonic Minor", [3, 2, 2, 3, 2], 'box_pattern'), Scale("Pentatonic Blues", [3, 2, 1, 1, 3, 2], 'box_pattern'), Scale("Major", [2, 2, 1, 2, 2, 2, 1], 'three_notes'), Scale("Ionian", [2, 2, 1, 2, 2, 2, 1], 'three_notes'), Scale("Dorian", [2, 1, 2, 2, 2, 1, 2], 'three_notes'), Scale("Phrygian", [1, 2, 2, 2, 1, 2, 2], 'three_notes'), Scale("Lydian", [2, 2, 2, 1, 2, 2, 1], 'three_notes'), Scale("Mixolydian", [2, 2, 1, 2, 2, 1, 2], 'three_notes'), Scale("Aeolian", [2, 1, 2, 2, 1, 2, 2], 'three_notes'), Scale("Locrian", [1, 2, 2, 1, 2, 2, 2], 'three_notes'), Scale("Minor", [2, 1, 2, 2, 1, 2, 2], 'three_notes'), Scale("Harmonic Minor", [2, 1, 2, 2, 1, 3, 1], 'three_notes'), Scale("Melodic Minor - Ascending", [2, 1, 2, 2, 2, 2, 1], 'three_notes'), Scale("Melodic Minor - Descending", [2, 1, 2, 2, 1, 2, 2], 'three_notes'), Scale("Chromatic", [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 'three_notes'), Scale("Whole Tone", [2, 2, 2, 2, 2, 2], 'three_notes'), Scale("Diminished", [2, 1, 2, 1, 2, 1, 2], 'four_notes') ] # Add notes and scales to the comboboxes for note in self.notes: self.ui.rootComboBox.addItem(note) for scale in self.scales: self.ui.scaleComboBox.addItem(scale.name) for item in self.tuning: self.ui.tuningComboBox.addItem(item[0]) # Set the init value to the first item self.ui.rootComboBox.setCurrentIndex = 0 self.ui.scaleComboBox.setCurrentIndex = 0 # Setup the root note and the current scale to be the first item from the combobox self.root_note = self.notes[self.ui.rootComboBox.currentIndex()] self.currentScale = self.scales[self.ui.scaleComboBox.currentIndex()] self.scale = self.currentScale.get_scale_notes(self.root_note) self.update_repr() # Signaling if combobox has changed self.ui.rootComboBox.currentIndexChanged.connect(self.update_ui) self.ui.scaleComboBox.currentIndexChanged.connect(self.update_ui) self.ui.tuningComboBox.currentIndexChanged.connect(self.update_tuning) # Set the initial position for the scale draw self.newPos = 0 # Set the initial string number for the one sting per scale representation self.sting_num = 0 # Length of the scale self.intervalLength = len(self.currentScale.intervals) # QTimer object for animation self.timer = QTimer() self.is_animation_active = False # Variable to store the actual scale on the guitar for drawing # It based on the Radio Button selection self.notes_to_draw = []
def main(): """ Read in settings from AMW_config.jsn. If we don't find the file, make it. Note that we save the file with new line as a separator, but can't load it with a non-standard separator, so we replace new lines with commas, he default separator character """ try: with open('AMW_config.jsn', 'r') as fp: data = fp.read() data = data.replace('\n', ',') configDict = json.loads(data) fp.close() # Constants for saving data # cage name, to tell data from different cages kCAGE_NAME = configDict.get('Cage Name') # path where data from each day will be saved kCAGE_PATH = configDict.get('Data Path') # rollover time, 0 to start the file for each day at 12 midnight. Could set to 7 to synch files to mouse day/night cycle kDAYSTARTHOUR = configDict.get('Day Start Hour') # size of array used for threaded reading from load cell amplifier kTHREADARRAYSIZE = configDict.get('Thread Array Size') # cuttoff weight where we stop the thread from reading when a mouse steps away kMINWEIGHT = configDict.get('Minimum Weight') # GPIO pin numbers and scaling for HX711, adjust as required for individual setup kDATA_PIN = configDict.get('GPIO Data Pin') kCLOCK_PIN = configDict.get('GPIO Clock Pin') kGRAMS_PER_UNIT = configDict.get('Grams Per Unit') # RFID Reader. Note that code as written only works with ID tag readers not RDM readers because of reliance on Tag-In-Range Pin kSERIAL_PORT = configDict.get('Serial Port') kTIR_PIN = configDict.get('GPIO Tag In Range Pin') #whether data is saved locally 1 or, not yet supported, sent to a server 2, or both, 3 kSAVE_DATA = configDict.get('Data Save Options') # a dictionary of ID Tags and cutoff weights, as when monitoring animal weights over time kHAS_CUTOFFS = configDict.get('Has Cutoffs') if kHAS_CUTOFFS: kCUT_OFF_DICT = configDict.get('Cutoff Dict') else: kCUT_OFF_DICT = None # can call get day weights code and email weights, needs extra options kEMAIL_WEIGHTS = configDict.get('Email Weights') if kEMAIL_WEIGHTS: kEMAIL_DICT = configDict.get('Email Dict') else: kEMAIL_DICT = None except (TypeError, IOError, ValueError) as e: #we will make a file if we didn't find it, or if it was incomplete print( 'Unable to load configuration data from AMW_config.jsn, let\'s make a new AMW_config.jsn.\n' ) jsonDict = {} kCAGE_NAME = input( 'Enter the cage name, used to distinguish data from different cages:' ) kCAGE_PATH = input( 'Enter the path where data from each day will be saved:') kDAYSTARTHOUR = int( input( 'Enter the rollover hour, in 24 hour format, when a new data file is started:' )) kTHREADARRAYSIZE = int( input( 'Enter size of array used for threaded reading from Load Cell:' )) kMINWEIGHT = float( input( 'Enter cutoff weight where we stop the thread from reading:')) kDATA_PIN = int( input( 'Enter number of GPIO pin connected to data pin on load cell:') ) kCLOCK_PIN = int( input( 'Enter number of GPIO pin connected to clock pin on load cell:' )) kGRAMS_PER_UNIT = float( input( 'Enter the scaling of the load cell, in grams per A/D unit:')) kSERIAL_PORT = input( 'Enter the name of serial port used for tag reader,e.g. serial0 or ttyAMA0:' ) kTIR_PIN = int( input( 'Enter number of the GPIO pin connected to the Tag-In-Range pin on the RFID reader:' )) kSAVE_DATA = int( input( 'To save data locally, enter 1; to send data to a server, not yet supported, enter 2:' )) tempInput = input('Track weights against existing cutoffs(Y or N):') kHAS_CUTOFFS = bool(tempInput[0] == 'y' or tempInput[0] == 'Y') if kHAS_CUTOFFS: kCUT_OFF_DICT = {} while True: tempInput = input( 'Enter a Tag ID and cuttoff weight, separated by a comma, or return to end entry:' ) if tempInput == "": break entryList = tempInput.split(',') try: kCUT_OFF_DICT.update({entryList[0]: float(entryList[1])}) except Exception as e: print('bad data entered', str(e)) else: kCUT_OFF_DICT = None jsonDict.update({ 'Has Cutoffs': kHAS_CUTOFFS, 'Cutoff Dict': kCUT_OFF_DICT }) tempInput = input('Email weights every day ? (Y or N):') kEMAIL_WEIGHTS = bool(tempInput[0] == 'y' or tempInput[0] == 'Y') if kEMAIL_WEIGHTS: kEMAIL_DICT = {} kFROMADDRESS = input( 'Enter the account used to send the email with weight data:') kPASSWORD = input( 'Enter the password for the email account used to send the mail:' ) kSERVER = input( 'Enter the name of the email server and port number, e.g., smtp.gmail.com:87, with separating colon:' ) kRECIPIENTS = tuple( input( 'Enter comma-separated list of email addresses to get the daily weight email:' ).split(',')) kEMAIL_DICT.update({ 'Email From Address': kFROMADDRESS, 'Email Recipients': kRECIPIENTS }) kEMAIL_DICT.update({ 'Email Password': kPASSWORD, 'Email Server': kSERVER }) else: kEMAIL_DICT = None jsonDict.update({ 'Email Weights': kEMAIL_WEIGHTS, 'Email Dict': kEMAIL_DICT }) # add info to a dictionay we will write to file jsonDict.update({ 'Cage Name': kCAGE_NAME, 'Data Path': kCAGE_PATH, 'Day Start Hour': kDAYSTARTHOUR, 'Thread Array Size': kTHREADARRAYSIZE }) jsonDict.update({ 'Minimum Weight': kMINWEIGHT, 'GPIO Data Pin': kDATA_PIN, 'GPIO Clock Pin': kCLOCK_PIN }) jsonDict.update({ 'GPIO Tag In Range Pin': kTIR_PIN, 'Grams Per Unit': kGRAMS_PER_UNIT, 'Serial Port': kSERIAL_PORT }) jsonDict.update({ 'Data Save Options': kSAVE_DATA, 'Email Weights': kEMAIL_WEIGHTS }) with open('AMW_config.jsn', 'w') as fp: fp.write( json.dumps(jsonDict, sort_keys=True, separators=('\r\n', ':'))) """ Initialize the scale from variables listed above and do an initial taring of the scale with 10 reads. Because pins are only accessed from C++, do not call Python GPIO.setup for the dataPin and the clockPin """ scale = Scale(kDATA_PIN, kCLOCK_PIN, kGRAMS_PER_UNIT, kTHREADARRAYSIZE) scale.weighOnce() scale.tare(10, True) """ Setup tag reader and GPIO for TIR pin, with tagReaderCallback installed as an event callback when pin changes either from low-to-high, or from high-to-low. """ tagReader = TagReader('/dev/' + kSERIAL_PORT, doChecksum=False, timeOutSecs=0.05, kind='ID') tagReader.installCallBack(kTIR_PIN) """ A new binary data file is opened for each day, with a name containing the current date, so open a file to start with """ now = datetime.fromtimestamp(int(time())) startDay = datetime(now.year, now.month, now.day, kDAYSTARTHOUR, 0, 0) if startDay > now: # it's still "yesterday" according to kDAYSTARTHOUR definition of when a day starts startDay = startDay - timedelta(hours=24) startSecs = startDay.timestamp( ) # used to report time of an entry through the weighing tube nextDay = startDay + timedelta(hours=24) filename = kCAGE_PATH + kCAGE_NAME + '_' + str( startDay.year) + '_' + '{:02}'.format( startDay.month) + '_' + '{:02}'.format(startDay.day) if kSAVE_DATA & kSAVE_DATA_LOCAL: print('opening file name = ' + filename) outFile = open(filename, 'ab') from OneDayWeights import get_day_weights """ Weight data is written to the file as grams, in 32 bit floating point format. Each run of data is prefaced by metadata from a 32 bit floating point metaData array of size 2. The first point contains the last 6 digits of the RFID code, as a negative value to make it easy for analysis code to find the start of each run. The second point contains the time in seconds since the start of the day. Both data items have been selected to fit into a 32 bit float. """ metaData = array('f', [0, 0]) while True: try: """ Loop with a brief sleep, waiting for a tag to be read or a new day to start, in which case a new data file is made """ while RFIDTagReader.globalTag == 0: if datetime.fromtimestamp(int(time())) > nextDay: if kSAVE_DATA & kSAVE_DATA_LOCAL: outFile.close() print('save data date =', startDay.year, startDay.month, startDay.day) try: get_day_weights(kCAGE_PATH, kCAGE_NAME, startDay.year, startDay.month, startDay.day, kCAGE_PATH, False, kEMAIL_DICT, kCUT_OFF_DICT) except Exception as e: print('Error getting weights for today:' + str(e)) startDay = nextDay nextDay = startDay + timedelta(hours=24) startSecs = startDay.timestamp() filename = kCAGE_PATH + kCAGE_NAME + '_' + str( startDay.year) + '_' + '{:02}'.format( startDay.month) + '_' + '{:02}'.format( startDay.day) if kSAVE_DATA & kSAVE_DATA_LOCAL: outFile = open(filename, 'ab') print('opening file name = ' + filename) else: sleep(kTIMEOUTSECS) """ A Tag has been read. Fill the metaData array and tell the C++ thread to start recording weights """ thisTag = RFIDTagReader.globalTag startTime = time() print('mouse = ', thisTag) #scale.turnOn() metaData[0] = -(thisTag % 1000000) metaData[1] = startTime - startSecs scale.threadStart(scale.arraySize) nReads = scale.threadCheck() lastRead = 0 """ Keep reading weights into the array until a new mouse is read by the RFID reader, or the last read weight drops below 2 grams, or the array is full, then stop the thread print the metaData array and the read weights from the thread array to the file """ while ((RFIDTagReader.globalTag == thisTag or (RFIDTagReader.globalTag == 0 and scale.threadArray[nReads - 1] > kMINWEIGHT)) and nReads < scale.arraySize): if nReads > lastRead: print(nReads, scale.threadArray[nReads - 1]) lastRead = nReads sleep(0.05) nReads = scale.threadCheck() nReads = scale.threadStop() if kSAVE_DATA & kSAVE_DATA_LOCAL: metaData.tofile(outFile) scale.threadArray[0:nReads - 1].tofile(outFile) if kSAVE_DATA & kSAVE_DATA_REMOTE: # modify to send : Time:UNIX time stamp, RFID:FULL RFID Tag, CageID: id, array: weight array response = requests.post( kSERVER_URL, data={ 'tag': thisTag, 'cagename': kCAGE_NAME, 'datetime': int(startTime), 'array': str((metaData + scale.threadArray[0:nReads - 1]).tobytes(), 'latin_1') }).text if response != '\nSuccess\n': print(reponse) #scale.turnOff() except KeyboardInterrupt: #scale.turnOn() event = scale.scaleRunner('10:\tQuit AutoMouseWeight program\n') if event == 10: if kSAVE_DATA & kSAVE_DATA_LOCAL: outFile.close() GPIO.cleanup() return except Exception as error: print("Closing file...") outFile.close() GPIO.cleanup() raise error
class Trial(): """ A class specifying a Trial and methods related to a trial. when a trial is created, it only needs to be drawn and checked for input. """ def __init__(self, win, colours, sequence, mouse, output_stream, clock, location_sequence, manager, override_text=None): """ Initializes a Trial object. Params: win: A window object the form should be drawn onto colours: A tuple of colour strings. (names, hex, or rgb) sequence: A sequence string containing only 0's and 1's mouse: A mouse object for checking against mouse input output_stream: A dictionary object containing lists for writing data into clock: A clock object to get the current time """ self.manager = manager self.clock = clock self.win = win self.mouse = mouse self.output = output_stream self.colours = colours self.sequence = sequence self.location_sequence = location_sequence self.place_boxes() info_text = Constants.TRIAL_BASE_INFO if override_text is not None: info_text = override_text else: if self.manager.failed_last == True: info_text += Constants.FAILED_TRIAL else: info_text += Constants.COMPLETED_TRIAL if len(sequence) != Constants.MATRIX[0] * Constants.MATRIX[1]: info_text += Constants.TIMED_TRIAL_INFO banner = Constants.BANNER_TIMED else: info_text += Constants.NOT_TIMED_INFO banner = Constants.BANNER_NOT_TIMED self.manager.scene = InfoScene(self.win, self, self.mouse, info_text) self.create_stimuli(banner) def to_trial(self): self.manager.scene = self def place_boxes(self): """ Places a centered grid of box stimuli and returns a list of the created grid. Params: None Returns: A python list containing all the boxes that was created for the grid """ boxes = [] y_offset = ( Constants.WINDOW_SIZE[1] / 2 ) - 2 * Constants.SQUARE_SIZE # The starting offset of the first square. (Upper-left) y_spacing = abs( y_offset * 2 / (Constants.MATRIX[1] - 1) ) #Has the value for the spacing between the squares. The formula calculates even distribution on all monitors #Places the squares in two-dimensional array structure for _ in range(Constants.MATRIX[1]): x_offset = (-Constants.WINDOW_SIZE[0] / 2) + 2 * Constants.SQUARE_SIZE x_spacing = abs(x_offset * 2 / (Constants.MATRIX[0] - 1)) for _ in range(Constants.MATRIX[0]): box = visual.Rect( self.win, width=Constants.SQUARE_SIZE, height=Constants.SQUARE_SIZE, pos=[ x_offset + Constants.CENTER_OFFSET[0], y_offset + Constants.CENTER_OFFSET[1] ], # Sets the position to the offset values in addition to adding a global offset to each box to control grid location fillColor="#BEBEBE") boxes.append(box) x_offset += x_spacing y_offset -= y_spacing self.grid = boxes """ Creates the confidence scales """ def create_stimuli(self, banner): """ Creates all stimuli that is to be drawn by the Trial class and stores them as attributes and into lists for easy drawing. Params: None Returns: None """ banner_text = visual.TextStim(self.win, text=banner, pos=[0, 500], height=40, wrapWidth=Constants.WINDOW_SIZE[0]) next_box_text = visual.TextStim(self.win, text="Show next box", pos=[0, -300]) choice_text0 = visual.TextStim( self.win, text='Press the circle if you believe it is the dominant colour:', pos=[-600, -300]) choice_text1 = visual.TextStim( self.win, text='Press the circle if you believe it is the dominant colour:', pos=[600, -300]) self.button0 = visual.Circle(self.win, radius=50, pos=[-600, -400], fillColor=self.colours[0]) self.button1 = visual.Circle(self.win, radius=50, pos=[600, -400], fillColor=self.colours[1]) self.continue_box = visual.Rect(self.win, pos=[0, -300], width=Constants.SQUARE_SIZE, height=Constants.SQUARE_SIZE / 2, fillColor="black") rating_text0 = visual.TextStim(self.win, text=f"More \n{self.colours[2]}", pos=[-800, -400], color=self.colours[0]) rating_text1 = visual.TextStim(self.win, text=f"More \n{self.colours[3]}", pos=[800, -400], color=self.colours[1]) self.rating_scale = Scale(self.win, self.colours) self.rating_stims = [rating_text0, rating_text1, banner_text ] + self.grid self.drawables = [self.continue_box, next_box_text, banner_text ] + self.grid self.choice_stims = [ self.button0, self.button1, choice_text0, choice_text1 ] self.boxes_revealed = 0 def check_input(self): """ Checks input for all components of the trial on screen except for the rating scale. It also writes to the output if a trial is failed. Params: None Returns: bool: indicating wether the Trial has ended. A true value indicates the trial has ended """ if (self.mouse.isPressedIn(self.button0, buttons=[0]) and self.button0 in self.drawables): [ self.output["Decision"].append(-1) for _ in range(len(self.output["Box_Num"]) - 1) ] self.output["Decision"].append(self.colours[2]) self.manager.completed_trial(False) return elif (self.mouse.isPressedIn(self.button1, buttons=[0]) and self.button0 in self.drawables): [ self.output["Decision"].append(-1) for _ in range(len(self.output["Box_Num"]) - 1) ] self.output["Decision"].append(self.colours[3]) self.manager.completed_trial(False) return elif (len(self.sequence) == 0 and self.mouse.isPressedIn(self.continue_box, buttons=[0])): self.output["Box_Num"].append(self.boxes_revealed + 1) self.output["Reaction_time"].append(-1) self.output["Probability_Estimates"].append(-1) [ self.output["Decision"].append(-1) for _ in self.output["Box_Num"] ] self.manager.completed_trial(True) return if 'escape' in event.getKeys(): core.quit() if self.mouse.isPressedIn(self.continue_box, buttons=[0]): self.next_box() box_seen = self.clock.getTime() self.get_rating() rating_given = self.clock.getTime() self.output["Reaction_time"].append(rating_given - box_seen) def next_box(self): """ Opens the next box. Reads the sequence data and gives the appropriate box its colour and writes data to the output. Params: None Returns: None """ if (self.boxes_revealed == 0): self.drawables += self.choice_stims location = self.location_sequence[0] box = self.grid[location - 1] if (self.sequence[0] == '0'): box.fillColor = self.colours[0] elif (self.sequence[0] == '1'): box.fillColor = self.colours[1] else: raise SyntaxError( "The given input does not match program specification for a sequence. Allowed values: 0 and 1" ) self.boxes_revealed += 1 self.output["Box_Num"].append(self.boxes_revealed) self.sequence = self.sequence[1:] self.location_sequence = self.location_sequence[1:] def get_rating(self): """ Draws the rating scale and waits for input. Once the input is given, it is written to the output and the method returns. Params: None Returns: None """ event.clearEvents() while (self.rating_scale.noResponse() == True): if 'escape' in event.getKeys(): core.quit() self.rating_scale.draw() [x.draw() for x in self.rating_stims] self.win.flip() self.output["Probability_Estimates"].append( self.rating_scale.getRating()) self.rating_scale.reset() event.clearEvents( ) #Event queue is cleared to prevent keypresses from rating period to be carried forward def save(self): return self.output def draw(self): """ Draws the Trial to a window. Params: None Returns: None """ for drawable in self.drawables: drawable.draw()
class Dosificadora: def __init__(self): #Crear el objeto de la clase dosificadora ##Convenciones: axxxx: a significa atributo #Con-> Concentrado #Min-> Mineral #Lev-> Levadura #Puertos de control para las valvulas self.avTolva = 2 self.avMineral = 16 self.avLevadura = 27 #Puertos de asignacion de las celdas de carga self.alsensorC1 = (11, 9) #Formato tupla: (dt,sck) self.alsensorC2 = (22, 10) self.alsensorC3 = (24, 23) self.alsensorC4 = (12, 6) self.alsensorML = (19, 13) #Puertos control de motores self.amCon = (7, 8) #Formato tupla: (Encendido, velocidad) self.amMin = (20, 21) #Formato tupla: (velocidad, sentido) self.amLev = (25, 26) #Sensibilidades celdas de carga self.asMin = 1030.3320 self.asLev = 2563.3821 self.asC1 = 1 self.asC2 = 1 self.asC3 = 1 self.asC4 = 1 self.asConc = 53.2201 #Valores de Tara para cada celda de carga self.asZeroMin = 0 self.asZeroLev = 0 self.asZeroC1 = 0 self.asZeroC2 = 0 self.asZeroC3 = 0 self.asZeroC4 = 0 #Masas objetivo self.aConObj = 1 self.aMinObj = 1 self.aLevObj = 1 self.aMasaObj = [self.aConObj, self.aMinObj, self.aLevObj] #Parametros del filtro tamizador y media movil self.aPeso_kbuffer = [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] #Formato lista [Con,Min,Lev] self.aSk = [0.0, 0.0, 0.0] #Formato listas [Con,Min,Lev] self.aContador = [0, 0, 0] self.aDato_k_1 = [0.0, 0.0, 0.0] self.aX_k_1 = [0.0, 0.0, 0.0] #Valores para algoritmo de control self.aMultiplo = [0.8, 0.8, 0.8] #Formato listas [Con,Min,Lev] self.aDeltaRef = [0.0, 0.0, 0.0] self.aInt = [0.0, 0.0, 0.0] self.aKp = [0.00051743, 0.0, 0.0] self.aKi = [0.0, 0.0, 0.0] self.aKd = [0.00080848, 0.0, 0.0] self.aN = [0.3704] self.aVk_1 = 0.0 self.aEk_1 = 0.0 self.aYk_1 = 0.0 self.aDk_1 = 0.0 self.aUk_1 = 0 self.aRk_1 = 0 self.aInt_Retardo = 0 self.aTcontador = 0 self.aDoCalcularKp = [True, True, True] self.aPWM = [0.0, 0.0, 0.0] self.aAceleracion = [300.0, 0.0, 0.0] #Otros atributos self.asText = "________________" #Separador de Textos self.minCon = 39.0 #Menor ciclo de PWM permitido para el concentrado self.maxCon = 99.0 #Mayor ciclo de PWM permitido para el concentrado self.razon = [ 60.0, 50.0, 10.0 ] #Mayor tasa de cambio permitida por el filtro tamizador #Formato lista [Con,Min,Lev] self.aConCrucero = 70.0 #Velocidad crucero motor Con self.aConMin = 60.0 #Minima velocidad para mover el motor def __del__(self): #Metodo destructor de objeto nombre = self.__class__.__name__ print(nombre, "Destruido") def inicializarPuertos(self): #Encargado de iniciar el estado de los puertos de RPi. print("\n________________\nIniciando puertos\n________________\n") #Configurar puertos #Valvulas GPIO.setup(self.avTolva, GPIO.OUT) GPIO.setup(self.avMineral, GPIO.OUT) GPIO.setup(self.avLevadura, GPIO.OUT) #Motores #Concentrado GPIO.setup(self.amCon[0], GPIO.OUT) GPIO.setup(self.amCon[1], GPIO.OUT) #Mineral GPIO.setup(self.amMin[0], GPIO.OUT) GPIO.setup(self.amLev[0], GPIO.OUT) #Levadura GPIO.setup(self.amMin[1], GPIO.OUT) GPIO.setup(self.amLev[1], GPIO.OUT) #Colocar todos los puertos en BAJO "LOW". GPIO.output(self.avTolva, 0) GPIO.output(self.avMineral, 0) GPIO.output(self.avLevadura, 0) GPIO.output(self.amCon[0], 0) GPIO.output(self.amCon[1], 0) GPIO.output(self.amMin[0], 0) GPIO.output(self.amMin[1], 0) GPIO.output(self.amLev[0], 0) GPIO.output(self.amLev[1], 0) def inicializarMotores(self): #Iniciar el estado de los motores #Frecuencia de PWM self.amMinPWM = GPIO.PWM(self.amMin[0], 300) #Formato tupla: (velocidad, sentido) self.amLevPWM = GPIO.PWM(self.amLev[0], 300) #Formato tupla: (velocidad, sentido) self.amConPWM = GPIO.PWM(self.amCon[1], 250) ##Iniciar PWM en valor 0 self.amMinPWM.start(0) self.amLevPWM.start(0) self.amConPWM.start(0) def inicializarCeldas(self): #Inciar celdas de carga print( "\n________________\nIniciando celdas de carga\n________________\n" ) #Formato tupla: self.alsensorA = (dt,sck) #Celda de carga Concentrado C1 self.ahxC1 = Scale(self.alsensorC1[0], self.alsensorC1[1], 1, 80) #Celda de carga Concentrado C2 self.ahxC2 = Scale(self.alsensorC2[0], self.alsensorC2[1], 1, 80) #Celda de carga Concentrado C3 self.ahxC3 = Scale(self.alsensorC3[0], self.alsensorC3[1], 1, 80) #Celda de carga Concentrado C4 self.ahxC4 = Scale(self.alsensorC4[0], self.alsensorC4[1], 1, 80) #Celda de carga Levadura Mineral self.ahxML = Scale(self.alsensorML[0], self.alsensorML[1], 1, 80) self.resetearCeldas() def encenderMotores(self, motor): #Metodo que activa los motores #Entrada: self-> Objeto propio de python # motor-> Selector del motor: # Con: Concentrado, Min: mineral Lev: levadura if (motor == 'Con'): if self.aConObj != 0: #Encendido motor Con velocidad = 99 #self.aConCrucero self.amConPWM.ChangeDutyCycle(velocidad) GPIO.output(self.amCon[0], 1) else: print("Masa es 0, concentrado no encendido") return if (motor == 'Min'): if self.aMinObj != 0: self.amMinPWM.ChangeFrequency(750) self.amMinPWM.ChangeDutyCycle(50) else: print("Masa igual a 0, mineral no encendido") return if (motor == 'Lev'): if self.aLevObj != 0: self.amLevPWM.ChangeFrequency(750) self.amLevPWM.ChangeDutyCycle(50) else: print("Masa igual a 0, levadura no encendido") return else: print("Motor no encontrado") def desacelerarMotores(self, motor): #Metodo que desacelera los motores if (motor == 'Con'): velocidad = self.aConMin self.amConPWM.ChangeDutyCycle(velocidad) return if (motor == 'Min'): self.amMinPWM.ChangeFrequency(200) self.amMinPWM.ChangeDutyCycle(50) return if (motor == 'Lev'): self.amLevPWM.ChangeFrequency(200) self.amLevPWM.ChangeDutyCycle(50) return else: print("Motor no encontrado") return def apagarMotores(self, motor, condicion): #Detener motores #Entradas: motor: Seleccion del motor deseado # Con -> Concentrado # Min -> Mineral # Lev -> Levadura # Condicion: Indica si el motor no fue apagado en la iteracion anterior if (motor == 'Con'): GPIO.output(self.amCon[0], 0) self.amConPWM.stop() if condicion: print("Concentrado apagado") return if (motor == 'Min'): self.amMinPWM.ChangeFrequency(50) self.amMinPWM.ChangeDutyCycle(0) if condicion: print("Mineral apagado") return if (motor == 'Lev'): self.amLevPWM.ChangeFrequency(50) self.amLevPWM.ChangeDutyCycle(0) if condicion: print("Levadura apagado") return else: print("Motor no encontrado") return def abrirCerrarValvulas(self, valvula, condicion): #Metodo de abrir y cerrar valvulas #Entradas: valvula: # Tolv -> Puerta de la tolva Romana # Min -> Compuerta del mineral # Lev -> Compuerta levadura # condicion: # 0 -> Valvula cerrada # 1 -> Valvula abierta if (valvula == 'Tolv'): GPIO.output(self.avTolva, condicion) return if (valvula == 'Min'): GPIO.output(self.avMineral, condicion) return if (valvula == 'Lev'): GPIO.output(self.avLevadura, condicion) return else: print("Valvula incorrecta") def cambiarSensibilidad(self, celda, sensibilidad): #Metodo para cambiar la sensibilidad de la celda de carga: (depuracion) #Formato de celda: 'Min','Lev','A','B' #Entradas: celda: A1, A2, B1, B2, Min, Lev print("Cambiando sensibilidad") if (celda == 'A1'): self.asA1 = sensibilidad self.axA.select_channel(channel='A') self.axA.set_scale_ratio(sensibilidad) return if (celda == 'A2'): self.asA2 = sensibilidad self.axA.select_channel(channel='B') self.axA.set_scale_ratio(sensibilidad) return if (celda == 'B1'): self.asB1 = sensibilidad self.axB.select_channel(channel='A') self.axB.set_scale_ratio(sensibilidad) return if (celda == 'B2'): self.asB2 = sensibilidad self.axB.select_channel(channel='B') self.axB.set_scale_ratio(sensibilidad) return if (celda == 'Min'): self.asMin = sensibilidad self.axML.select_channel(channel='A') self.axML.set_scale_ratio(sensibilidad) return if (celda == 'Lev'): self.asLev = sensibilidad self.axML.select_channel(channel='A') self.axML.set_scale_ratio(sensibilidad) return else: print("Celda no encontrada") def leerMineral(self, lecturas): #Leer el peso del mineral en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar #Mineral puerto A del sensor masaMin = -((self.ahxML.weighOnce()) - self.asZeroMin) / self.asMin return masaMin def leerLevadura(self, lecturas): #Leer el peso del mineral en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar masaLev = (self.ahxML.weighOnce() - self.asZeroLev) / self.asLev return masaLev def leerConcentrado(self, lecturas): #Leer el peso del concentrado en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar Conc1 = self.ahxC1.weighOnce() - self.asZeroC1 Conc2 = self.ahxC2.weighOnce() - self.asZeroC2 Conc3 = self.ahxC3.weighOnce() - self.asZeroC3 Conc4 = -(self.ahxC4.weighOnce() - self.asZeroC4) Conc = (Conc1 + Conc2 + Conc3 + Conc4) / (4 * self.asConc) #Nota: De momento se estan leyendo solo las celdas de los puertos A del concentrado # las celdas B presetan problemas de retardos en las lecturas return float(Conc) def cerrarSteppers(self): #Metodo para apagar puertos de velocidad de los motores self.amMinPWM.stop() self.amLevPWM.stop() self.amConPWM.stop() def leer4Concentrado(self): #Metodo para leer por separado cada celda de carga del concentrado (depuracion) Conc1 = self.ahxC1.weighOnce() - self.asZeroC1 Conc2 = self.ahxC2.weighOnce() - self.asZeroC2 Conc3 = self.ahxC3.weighOnce() - self.asZeroC3 Conc4 = -(self.ahxC4.weighOnce() - self.asZeroC4) print("%d\t%d\t%d\t%d" % (Conc1, Conc2, Conc3, Conc4)) def leer4ConcentradoRaw(self, lecturas): #Metodo para leer cada celda del concentrado sin restar tara (depuracion) Conc1 = self.ahxC1.weighOnce() Conc2 = self.ahxC2.weighOnce() Conc3 = self.ahxC3.weighOnce() Conc4 = self.ahxC4.weighOnce() print("%d\t%d\t%d\t%d" % (Conc1, Conc2, Conc3, Conc4)) def tararConcentrado(self, imprimir=False, lecturas=30): #Metodo para tarar los amplificadores del concentrado if imprimir: print("Tarando") self.asZeroC1 = self.ahxC1.weigh(80) self.asZeroC2 = self.ahxC2.weigh(80) self.asZeroC3 = self.ahxC3.weigh(80) self.asZeroC4 = self.ahxC4.weigh(80) if imprimir: print("Tara del concentrado\n%d\t%d\t%d\t%d\t" % (self.asZeroC1, self.asZeroC2, self.asZeroC3, self.asZeroC4)) def tararMineral(self, printVal=False, lecturas=30): #Metodo para tarar mineral self.asZeroMin = self.ahxML.tare(lecturas, False) if printVal: print("\tTara del mineral %d" % (self.asZeroMin)) def tararLevadura(self, printVal=False, lecturas=30): #Metodo para tarar levdura self.asZeroMin = self.ahxML.tare(lecturas, False) if printVal: print("\tTara de la levadura %d" % (self.asZeroMin)) def filtradorTamizador(self, dato, alimento): #Metodo para filtrar y tamizar los valores de las celdas de carga #Se aplica un filtro de media movil con tres periodos, #luego se eliminan las lecturas que presenten cambios abruptos respecto de los valores predecesores. if alimento == 'Con': #Tamizar if ((abs(dato - self.aDato_k_1[0])) > self.razon[0]): datoT = self.aX_k_1[0] #print("Tamizado") else: datoT = dato #Filtrar self.aSk[0] = self.aSk[0] - self.aPeso_kbuffer[0][ self.aContador[0]] + datoT concentrado = self.aSk[0] / 5 self.aPeso_kbuffer[0][self.aContador[0]] = datoT #Mover el contador y retrasar las muestras self.aContador[0] += 1 self.aDato_k_1[0] = dato self.aX_k_1[0] = datoT if self.aContador[0] == 5: self.aContador[0] = 0 return concentrado if alimento == 'Min': #Tamizar if ((abs(dato - self.peso_k_1[1])) > self.razon[1]): datoT = self.peso_k_1[1] print("Tamizado") else: datoT = dato #Filtrar self.aSk[1] = self.aSk[1] - self.aPeso_kbuffer[1][ self.aContador[1]] + datoT mineral = self.aSk[1] / 5 self.aPeso_kbuffer[1][self.aContador[1]] = datoT #Mover el contador y retrasar las muestras self.aContador[1] += 1 self.aDato_k_1[1] = dato self.aX_k_1[1] = datoT if self.aContador[1] == 5: self.aContador[1] = 0 return mineral if alimento == 'Lev': #Tamizar if ((abs(dato - self.aDato_k_1[2])) > self.razon[2]): datoT = self.aX_k_1[2] #print("Tamizado") else: datoT = dato #Filtrar self.aSk[2] = self.aSk[2] - self.aPeso_kbuffer[2][ self.aContador[2]] + datoT levadura = self.aSk[2] / 5 self.aPeso_kbuffer[2][self.aContador[2]] = datoT #Mover el contador y retrasar las muestras self.aContador[2] += 1 self.aDato_k_1[2] = dato self.aX_k_1[2] = datoT if self.aContador[2] == 5: self.aContador[2] = 0 return levadura else: print("Alimento no encontrado") def inRangeCoerce(self, dato, minimo=0.0, maximo=100.0): #Metodo que limita los valores de una variable if dato > maximo: return maximo if dato < minimo: return minimo else: return dato def normalizarVelocidadConcentrado(self, dato): #Metodo para normalizar los valores del concentrado #Debido a la electronica, el valor de PWM permitido es entre 39 y 99. #Fuera de esos valores comienza a presentarse comportamiento erratico. dato = self.inRangeCoerce(dato, 0, 100) dato = (self.maxCon - self.minCon) / 100 * dato + self.minCon return dato #Metodos para resumir bloques de la secuencia def tararCeldas(self): #Metodo para tarar todas las cedas de carga. Permite no hacerlo desde el main self.leerMineral(80) print("________________\nTarando Concentrado\n________________\n") self.tararConcentrado(80, True) print("Zero A1 ", self.asZeroC1) print("Zero A2 ", self.asZeroC2) print("Zero B1 ", self.asZeroC3) print("Zero B2 ", self.asZeroC4) print("________________\nTarando Mineral\n________________\n") self.tararMineral(80) print("________________\nTarando Levadura\n________________\n") self.tararLevadura(80) def resetearCeldas(self): print("Reseteando celdas de carga concentrado") #Celdas del concentrado self.ahxC1.turnOff() time.sleep(0.5) self.ahxC1.turnOn() time.sleep(0.5) self.ahxC1.turnOff() time.sleep(0.5) self.ahxC1.turnOn() time.sleep(0.5) self.ahxC2.turnOff() time.sleep(0.5) self.ahxC2.turnOn() time.sleep(0.5) self.ahxC3.turnOff() time.sleep(0.5) self.ahxC3.turnOn() time.sleep(0.5) self.ahxC4.turnOff() time.sleep(0.5) self.ahxC4.turnOn() time.sleep(0.5) print("Reseteando celdas de carga Mineral y Levadura") self.ahxML.turnOff() time.sleep(0.5) self.ahxML.turnOn() time.sleep(0.5) def filtroButterWorth(self, xk): self.yk = ( 0.7769 * self.xk_1 #- 0.007079*self.xk_2 + 0.2231 * self.yk_1) #- 0.000002 * self.yk_2) #Retrasar muestras #self.xk_4 = self.xk_3 #self.xk_3 = self.xk_2 self.xk_2 = self.xk_1 self.xk_1 = xk #self.yk_4 = self.yk_3 #self.yk_3 = self.yk_2 self.yk_2 = self.yk_1 self.yk_1 = self.yk return self.yk def controlPD(self, yk): #Comienza algoritmo de control #Estimacion de la velocidad #vk = yk-self.aYk_1+0.6703*self.aVk_1 #Estimacion del retardo #self.aInt_Retardo = self.inRangeCoerce(self.aInt_Retardo,0,10000) #Estimacion del error ek = (self.aMasaObj[0] - yk) #Estimacion del control PD pk = self.aKp[0] * (ek) dk = ((self.aKd[0] * self.aN[0]) * (ek - self.aEk_1) + self.aDk_1) / (1 + self.aN[0] * 0.05) pidk = pk + dk + 0.4 #Compensacion de componente no lineal pidk = 100 * self.inRangeCoerce(pidk, 0, 0.99) self.amConPWM.ChangeDutyCycle(pidk) #Termina algoritmo de control #Retrasa las muestras self.aYk_1 = yk self.aDk_1 = dk self.aEk_1 = ek self.aPWM[0] = pidk def generadorTrayectoria(self): print("Generando Trayectorias") a = self.aAceleracion[0] t2 = self.aMasaObj[0] / a - 2 tf = t2 + 4 k = 0 m1 = 0.5 * a m2 = a * t2 + m1 tiempo = np.arange(0.05, 30.05, 0.05) k = 0 mk = np.zeros(600) #Inicia la generacion de la trayectoria t = 0 while t < 30: t = tiempo[k] if t <= 1: mk[k] = (a / 2) * t * t if ((1 < t) and (t <= (t2 + 1))): mk[k] = a * (t - 1) + m1 if ((t2 + 1 < t) and (t <= tf)): mk[k] = -a / 6 * (t - t2 - 1) * (t - t2 - 1) + a * (t - t2 - 1) + m2 elif (t > tf): mk[k] = self.aMasaObj[0] k += 1 print("Trayectoria generada") self.aTrayectoriaCon = mk
@app.route('/favicon.ico') def favicon(): return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico', mimetype='image/vnd.microsoft.icon') @app.errorhandler(418) @app.route('/418') def error418(): return "I'm a tea pot", 418 def getStats(): return { 'grams': round(scale.readGrams(), 2), 'ounces': round(scale.readOunces(), 2), 'cups': round(scale.readOunces() / 8.0, 2), 'servings': round(scale.readOunces() / 4.5, 2), 'caffeine': str(round((scale.readOunces() / 8.5) * 49, 2)) + "mg" } if __name__ == "__main__": scale = Scale(VENDOR_ID, PRODUCT_ID) app.debug = False app.template_folder = "./" app.run(host='0.0.0.0', port=80)
class Testing: def __init__(self): #Atributos de las celdas de carga del concentrado self.alsensorC1 = (11, 9) #Formato tupla: (dt,sck) self.alsensorC2 = (22, 10) self.alsensorC3 = (24, 23) self.alsensorC4 = (12, 6) self.alsensorML = (19, 13) self.asZeroC1 = 0 self.asZeroC1 = 0 self.asZeroC1 = 0 self.asZeroC1 = 0 self.asZeroMin = 0 self.asZeroLev = 0 self.asConc = 53.2201 self.asMin = 1030.3320 self.asLev = 2563.3821 #Atributos del filtro self.aDato_k_1 = [0.0, 0.0, 0.0] self.razon = [60.0, 50.0, 10.0] self.aX_k_1 = [0.0, 0.0, 0.0] self.aSk = [0.0, 0.0, 0.0] self.aPeso_kbuffer = np.zeros((3, 20), dtype=np.float32) self.aContador = [0, 0, 0] #Otros atributos self.aEspacio = "_________________" def __del__(self): nombre = self.__class__.__name__ print(nombre, "Destruido") def InicializarCeldasTR(self): #Inicializa las celdas de carga del concentrado self.ahxC1 = Scale(self.alsensorC1[0], self.alsensorC1[1], 1, 80) #Celda de carga Concentrado C2 self.ahxC2 = Scale(self.alsensorC2[0], self.alsensorC2[1], 1, 80) #Celda de carga Concentrado C3 self.ahxC3 = Scale(self.alsensorC3[0], self.alsensorC3[1], 1, 80) #Celda de carga Concentrado C4 self.ahxC4 = Scale(self.alsensorC4[0], self.alsensorC4[1], 1, 80) def InicializarCeldasML(self): #Inicializa las celdas de carga del mineral Levadura self.ahxML = Scale(self.alsensorML[0], self.alsensorML[1], 1, 80) def ResetearCeldasTR(self): print("Reseteando celdas de carga concentrado") #Celdas del concentrado self.ahxC1.turnOff() time.sleep(0.5) self.ahxC1.turnOn() time.sleep(0.5) self.ahxC1.turnOff() time.sleep(0.5) self.ahxC1.turnOn() time.sleep(0.5) self.ahxC2.turnOff() time.sleep(0.5) self.ahxC2.turnOn() time.sleep(0.5) self.ahxC3.turnOff() time.sleep(0.5) self.ahxC3.turnOn() time.sleep(0.5) self.ahxC4.turnOff() time.sleep(0.5) self.ahxC4.turnOn() time.sleep(0.5) def ResetearCeldasML(self): print("Reseteando celdas de carga concentrado") #Celdas del concentrado self.ahxML.turnOff() time.sleep(0.5) self.ahxML.turnOn() def LeerConcentrado(self, lecturas): #Leer el peso del concentrado en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar concentrado = 0 for i in range(lecturas): Conc1 = self.ahxC1.weighOnce() - self.asZeroC1 Conc2 = self.ahxC2.weighOnce() - self.asZeroC2 Conc3 = self.ahxC3.weighOnce() - self.asZeroC3 Conc4 = -(self.ahxC4.weighOnce() - self.asZeroC4) Conc = (Conc1 + Conc2 + Conc3 + Conc4) / (4 * self.asConc) concentrado += Conc concentrado = concentrado / lecturas return float(concentrado) def LeerMineral(self, lecturas): #Leer el peso del mineral en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar #Mineral puerto A del sensor masaMin = -((self.ahxML.weighOnce()) - self.asZeroMin) / self.asMin return masaMin def FiltroMediaTamizador(self, dato, alimento, periodos=5): #Metodo para filtrar y tamizar los valores de las celdas de carga #Se aplica un filtro de media movil con n periodos, #luego se eliminan las lecturas que presenten cambios abruptos respecto de los valores predecesores. if alimento == 'Con': #Tamizar if ((abs(dato - self.aDato_k_1[0])) > self.razon[0]): datoT = self.aX_k_1[0] #print("Tamizado") else: datoT = dato #Filtrar self.aSk[0] = self.aSk[0] - self.aPeso_kbuffer[0][ self.aContador[0]] + datoT concentrado = self.aSk[0] / periodos self.aPeso_kbuffer[0][self.aContador[0]] = datoT #Calcular filtro de media movil en linea self.aContador[0] += 1 self.aDato_k_1[0] = dato self.aX_k_1[0] = datoT if self.aContador[0] == periodos: self.aContador[0] = 0 return concentrado if alimento == 'Min': #Tamizar if ((abs(dato - self.peso_k_1[1])) > self.razon[1]): datoT = self.peso_k_1[1] print("Tamizado") else: datoT = dato #Filtrar self.aSk[1] = self.aSk[1] - self.aPeso_kbuffer[1][ self.aContador[1]] + datoT mineral = self.aSk[1] / periodos self.aPeso_kbuffer[1][self.aContador[1]] = datoT #Mover el contador y retrasar las muestras self.aContador[1] += 1 self.aDato_k_1[1] = dato self.aX_k_1[1] = datoT if self.aContador[1] == periodos: self.aContador[1] = 0 return mineral if alimento == 'Lev': #Tamizar if ((abs(dato - self.aDato_k_1[2])) > self.razon[2]): datoT = self.aX_k_1[2] #print("Tamizado") else: datoT = dato #Filtrar self.aSk[2] = self.aSk[2] - self.aPeso_kbuffer[2][ self.aContador[2]] + datoT levadura = self.aSk[2] / periodos self.aPeso_kbuffer[2][self.aContador[2]] = datoT #Mover el contador y retrasar las muestras self.aContador[2] += 1 self.aDato_k_1[2] = dato self.aX_k_1[2] = datoT if self.aContador[2] == periodos: self.aContador[2] = 0 return levadura else: print("Alimento no encontrado") def TararConcentrado(self, imprimir=False, lecturas=30): #Metodo para tarar los amplificadores del concentrado if imprimir: print("Tarando") self.asZeroC1 = self.ahxC1.weigh(lecturas) self.asZeroC2 = self.ahxC2.weigh(lecturas) self.asZeroC3 = self.ahxC3.weigh(lecturas) self.asZeroC4 = self.ahxC4.weigh(lecturas) if imprimir: print("Tara del concentrado\n%d\t%d\t%d\t%d\t" % (self.asZeroC1, self.asZeroC2, self.asZeroC3, self.asZeroC4)) def ProbarCeldasTR(self, tiempo): #Obtiene muestras de la celda de carga por una cantidad determinada de tiempo print(self.aEspacio) print("Probando celdas de carga Tolva Romana") print(self.aEspacio) self.InicializarCeldasTR() self.ResetearCeldasTR() self.TararConcentrado(False, 80) print("Sin filtro\tCon Filtro") tic = time.time() while True: Con = self.LeerConcentrado(4) #Calcular filtro de media movil en linea ConF = self.FiltroMediaTamizador(Con, 'Con', 5) print("%f\t%f" % (Con, ConF)) toc = time.time() #Condicion de parada para el ciclo if ((toc - tic) >= tiempo): break def ProbarCeldasMinLev(self, tiempo): #Obtiene muestras de la celda de carga por una cantidad determinada de tiempo print(self.aEspacio) print("Probando celdas de carga Mineral-Levadura") print(self.aEspacio) self.InicializarCeldasML() self.ResetearCeldasML() self.TararMinLev(False, 80) print("Sin filtro\tCon Filtro") tic = time.time() while True: Min = self.LeerMineral(80) #Calcular filtro de media movil en linea ConF = self.FiltroMediaTamizador(Con, 'Con', 5) print("%f\t%f" % (Con, ConF)) toc = time.time() #Condicion de parada para el ciclo if ((toc - tic) >= tiempo): break
def testScale(self): for S, R in self.KnownScale: P = Scale(S).ToIntervalPattern() self.assertEqual(P, R) print(S, "to interval pattern yields", R)
class Player(Repeatable): # Set private values __vars = [] __init = False # These are used by FoxDot keywords = ('degree', 'oct', 'freq', 'dur', 'delay', 'buf', 'blur', 'amplify', 'scale', 'bpm', 'sample') # Base attributes base_attributes = ( 'sus', 'fmod', 'vib', 'slide', 'slidefrom', 'pan', 'rate', 'amp', 'room', 'bits', ) fx_attributes = FxList.kwargs() metro = None server = None # Tkinter Window widget = None default_scale = Scale.default() default_root = Root.default() def __init__(self): # Inherit Repeatable.__init__(self) # General setup self.synthdef = None self.id = None self.quantise = False self.stopping = False self.stop_point = 0 self.following = None self.queue_block = None self.playstring = "" self.char = PlayerKey("", parent=self) self.buf_delay = [] # Visual feedback information self.envelope = None self.line_number = None self.whitespace = None self.bang_kwargs = {} # Modifiers self.reversing = False self.degrading = False # Keeps track of which note to play etc self.event_index = 0 self.event_n = 0 self.notes_played = 0 self.event = {} # Used for checking clock updates self.old_dur = None self.old_pattern_dur = None self.isplaying = False self.isAlive = True # These dicts contain the attribute and modifier values that are sent to SuperCollider self.attr = {} self.modf = {} # Keyword arguments that are used internally self.scale = None self.offset = 0 self.following = None # List the internal variables we don't want to send to SuperCollider self.__vars = self.__dict__.keys() self.__init = True self.reset() # Class methods @classmethod def Attributes(cls): return cls.keywords + cls.base_attributes + cls.fx_attributes # Player Object Manipulation def __rshift__(self, other): """ The PlayerObject Method >> """ if isinstance(other, SynthDefProxy): self.update(other.name, other.degree, **other.kwargs) self + other.mod for method, arguments in other.methods.items(): args, kwargs = arguments getattr(self, method).__call__(*args, **kwargs) return self raise TypeError( "{} is an innapropriate argument type for PlayerObject".format( other)) return self def __setattr__(self, name, value): if self.__init: # Force the data into a Pattern if the attribute is used with SuperCollider if name not in self.__vars: value = asStream(value) if not isinstance(value, PlayerKey) else value # Update the attribute dict self.attr[name] = value # Update the current event # self.event[name] = modi(value, self.event_index) ## # Make sure the object's dict uses PlayerKey instances ## ## if name not in self.__dict__: ## ## self.__dict__[name] = PlayerKey(self.event[name], parent=self) ## ## elif not isinstance(self.__dict__[name], PlayerKey): ## ## self.__dict__[name] = PlayerKey(self.event[name], parent=self) ## ## else: ## ## self.__dict__[name].update(self.event[name]) return self.__dict__[name] = value return def __eq__(self, other): return self is other def __ne__(self, other): return not self is other # --- Startup methods def reset(self): # Add all keywords to the dict, then set non-zero defaults for key in Player.Attributes(): if key != "scale": self.attr[key] = asStream(0) if key not in self.__dict__: self.__dict__[key] = PlayerKey(0, parent=self) elif not isinstance(self.__dict__[key], PlayerKey): self.__dict__[key] = PlayerKey(0, parent=self) else: self.__dict__[key].update(0) # --- SuperCollider Keywords # Left-Right panning (-1,1) self.pan = 0 # Sustain self.sus = 1 # Amplitude self.amp = 1 # Rate - varies between SynthDef self.rate = 1 # Audio sample buffer number self.buf = 0 # Reverb self.verb = 0.25 self.room = 0.00 # Frequency modifier self.fmod = 0 # Buffer self.sample = 0 # Frequency / rate modifier self.slide = 0 self.slidefrom = 1 # Echo effect self.decay = 1 # Filters self.lpr = 1 self.hpr = 1 # --- FoxDot Keywords # Duration of notes self.dur = 0.5 if self.synthdef == SamplePlayer else 1 self.old_pattern_dur = self.old_dur = self.attr['dur'] self.delay = 0 # Degree of scale / Characters of samples self.degree = " " if self.synthdef is SamplePlayer else 0 # Octave of the note self.oct = 5 # Amplitude mod self.amplify = 1 # Legato self.blur = 1 # Tempo self.bpm = None # Frequency and modifier self.freq = 0 # Offbeat delay self.offset = 0 # Modifier dict self.modf = dict([(key, [0]) for key in self.attr]) return self # --- Update methods def __call__(self, **kwargs): # If stopping, kill the event if self.stopping and self.metro.now() >= self.stop_point: self.kill() return # If the duration has changed, work out where the internal markers should be if self.dur_updated() or kwargs.get("count", False) is True: try: # this is where self.reversing goes wrong self.event_n, self.event_index = self.count(self.event_index) except TypeError: print("TypeError: Innappropriate argument type for 'dur'") self.old_dur = self.attr['dur'] # Get the current state dur = 0 while True: self.get_event() # Set a 'None' to 0 if self.event['dur'] is None: dur = 0 # If there are more than one dur (happens sometimes because of threading), only use first # This is a temporary solution <-- TODO try: if len(self.event['dur']) > 0: self.event['dur'] = self.event['dur'][0] except TypeError: pass finally: if isinstance(self.event['dur'], TimeVar.var): dur = float(self.event['dur'].now(self.event_index)) else: dur = float(self.event['dur']) # Skip events with durations of 0 if dur == 0: self.event_n += 1 else: break # Play the note if self.metro.solo == self and kwargs.get( 'verbose', True) and type(self.event['dur']) != rest: self.send() # If using custom bpm if self.event['bpm'] is not None: try: tempo_shift = float(self.metro.bpm) / float(self.event['bpm']) except (AttributeError, TypeError): tempo_shift = 1 dur *= tempo_shift # Schedule the next event self.event_index = self.event_index + dur self.metro.schedule(self, self.event_index, kwargs={}) # Change internal marker self.event_n += 1 self.notes_played += 1 return def count(self, time=None, event_after=False): """ Counts the number of events that will have taken place between 0 and `time`. If `time` is not specified the function uses self.metro.now(). Setting `event_after` to `True` will find the next event *after* `time`""" n = 0 acc = 0 dur = 0 now = (time if time is not None else self.metro.now()) durations = self.rhythm() total_dur = float(sum(durations)) if total_dur == 0: WarningMsg("Player object has a total duration of 0. Set to 1") durations = [1] total_dur = 1 self.dur = 1 acc = now - (now % total_dur) try: n = int(len(durations) * (acc / total_dur)) except TypeError as e: WarningMsg(e) self.stop() return 0, 0 if acc != now: while True: dur = float(modi(durations, n)) if acc + dur == now: acc += dur n += 1 break elif acc + dur > now: if event_after: acc += dur n += 1 break else: acc += dur n += 1 # Store duration times self.old_dur = self.attr['dur'] # Returns value for self.event_n and self.event_index return n, acc def rhythm(self): # If a Pattern TimeVar if isinstance(self.attr['dur'], TimeVar.Pvar): r = asStream(self.attr['dur'].now().data) # If duration is a TimeVar elif isinstance(self.attr['dur'], TimeVar.var): r = asStream(self.attr['dur'].now()) else: r = asStream(self.attr['dur']) # TODO: Make sure degree is a string if self.synthdef is SamplePlayer: try: d = self.attr['degree'].now() except: d = self.attr['degree'] r = r * [(char.dur if hasattr(char, "dur") else 1) for char in d.flat()] return r def update(self, synthdef, degree, **kwargs): # SynthDef name self.synthdef = synthdef if self.isplaying is False: self.reset() # <-- # If there is a designated solo player when updating, add this at next bar if self.metro.solo.active() and self.metro.solo != self: self.metro.schedule( lambda *args, **kwargs: self.metro.solo.add(self), self.metro.next_bar()) # Update the attribute values special_cases = ["scale", "root", "dur"] # Set the degree if synthdef == SamplePlayer: if type(degree) == str: self.playstring = degree else: self.playstring = None if degree is not None: setattr(self, "degree", degree if len(degree) > 0 else " ") elif degree is not None: self.playstring = str(degree) setattr(self, "degree", degree) # Set special case attributes self.scale = kwargs.get("scale", self.__class__.default_scale) self.root = kwargs.get("root", self.__class__.default_root) # If only duration is specified, set sustain to that value also if "dur" in kwargs: self.dur = kwargs['dur'] if "sus" not in kwargs and synthdef != SamplePlayer: self.sus = self.attr['dur'] if synthdef is SamplePlayer: pass # self.old_pattern_dur # self.old_dur = self.attr['dur'] # Set any other attributes for name, value in kwargs.items(): if name not in special_cases: setattr(self, name, value) # Calculate new position if not already playing if self.isplaying is False: # Add to clock self.isplaying = True self.stopping = False next_bar = self.metro.next_bar() self.event_n = 0 self.event_n, self.event_index = self.count(next_bar, event_after=True) self.metro.schedule(self, self.event_index) return self def dur_updated(self): dur_updated = self.attr['dur'] != self.old_dur if self.synthdef == SamplePlayer: dur_updated = (self.pattern_rhythm_updated() or dur_updated) return dur_updated def step_duration(self): return 0.5 if self.synthdef is SamplePlayer else 1 def pattern_rhythm_updated(self): r = self.rhythm() if self.old_pattern_dur != r: self.old_pattern_dur = r return True return False def char(self, other=None): if other is not None: try: if type(other) == str and len(other) == 1: #char return Samples.bufnum(self.now('buf')) == other raise TypeError("Argument should be a one character string") except: return False else: try: return Samples.bufnum(self.now('buf')) except: return None def calculate_freq(self): """ Uses the scale, octave, and degree to calculate the frequency values to send to SuperCollider """ # If the scale is frequency only, just return the degree if self.scale == Scale.freq: try: return list(self.event['degree']) except: return [self.event['degree']] now = {attr: self.event[attr] for attr in ('degree', 'oct')} size = LCM(get_expanded_len(now['oct']), get_expanded_len(now['degree'])) f = [] for i in range(size): try: midinum = midi(self.scale, group_modi(now['oct'], i), group_modi(now['degree'], i), self.now('root')) except Exception as e: print e WarningMsg( "Invalid degree / octave arguments for frequency calculation, reset to default" ) print now['degree'], modi(now['degree'], i) raise f.append(miditofreq(midinum)) return f def f(self, *data): """ adds value to frequency modifier """ self.fmod = tuple(data) p = [] for val in self.attr['fmod']: try: pan = tuple((item / ((len(val) - 1) / 2.0)) - 1 for item in range(len(val))) except: pan = 0 p.append(pan) self.pan = p return self # Methods affecting other players - every n times, do a random thing? def stutter(self, n=2, **kwargs): """ Plays the current note n-1 times. You can specify some keywords, such as dur, sus, and rate. """ if self.metro.solo == self and n > 0: dur = float(kwargs.get("dur", self.dur)) / int(n) delay = 0 size = self.largest_attribute() for stutter in range(1, n): delay += dur # Use a custom attr dict and specify the first delay to play "immediately" sub = { kw: modi(val, stutter - 1) for kw, val in kwargs.items() + [("send_now", True)] } self.metro.schedule(func_delay(self.send, **sub), self.event_index + delay) return self # --- Misc. Standard Object methods def __int__(self): return int(self.now('degree')) def __float__(self): return float(self.now('degree')) def __add__(self, data): """ Change the degree modifier stream """ self.modf['degree'] = asStream(data) return self def __sub__(self, data): """ Change the degree modifier stream """ data = asStream(data) data = [d * -1 for d in data] self.modf['degree'] = data return self def __mul__(self, data): """ Multiplying an instrument player multiplies each amp value by the input, or circularly if the input is a list. The input is stored here and calculated at the update stage """ if type(data) in (int, float): data = [data] self.modf['amp'] = asStream(data) return self def __div__(self, data): if type(data) in (int, float): data = [data] self.modf['amp'] = [1.0 / d for d in data] return self # --- Data methods def __iter__(self): for _, value in self.event.items(): yield value def number_of_layers(self): """ Returns the deepest nested item in the event """ num = 1 for attr, value in self.event.items(): if isinstance(value, PGroup): l = pattern_depth(value) else: l = 1 if l > num: num = l return num def largest_attribute(self): """ Returns the length of the largest nested tuple in the current event dict """ size = 1 values = [] for attr, value in self.event.items(): l = get_expanded_len(value) if l > size: size = l return size # --- Methods for preparing and sending OSC messages to SuperCollider def now(self, attr="degree", x=0): """ Calculates the values for each attr to send to the server at the current clock time """ modifier_event_n = self.event_n attr_value = self.attr[attr] # If we are referencing other players' values, make sure they're updated first if isinstance(attr_value, PlayerKey): if attr_value.parent in self.queue_block.objects( ) and attr_value.parent is not self: self.queue_block.call(attr_value.parent, self) else: attr_value = modi(asStream(attr_value), self.event_n + x) # If the item is a PGroup - make sure any generator values are forced into one type if isinstance(attr_value, PGroup): attr_value = attr_value.forced_values() # If the attribute isn't in the modf dictionary, default to 0 modf_value = modi(self.modf[attr], modifier_event_n + x) if attr in self.modf else 0 # Combine attribute and modifier values if not (self.synthdef == SamplePlayer and attr == "degree"): # Don't bother trying to add values to a play string... try: attr_value = attr_value + modf_value except TypeError: pass return attr_value def get_event(self): """ Returns a dictionary of attr -> now values """ attributes = copy(self.attr) prime_funcs = {} # self.event = {} for key in attributes: value = self.event[key] = self.now(key) if isinstance(value, PlayerKey): value = value.now() # Look for PGroupPrimes if isinstance(value, PGroup): if value.has_behaviour(): cls = value.__class__ name = cls.__name__ getaction = True if name in prime_funcs: if len(value) <= len(prime_funcs[name][1]): getaction = False if getaction: prime_funcs[name] = [key, value, value.get_behaviour()] # Make sure the object's dict uses PlayerKey instances if key not in self.__dict__: self.__dict__[key] = PlayerKey(value, parent=self) elif not isinstance(self.__dict__[key], PlayerKey): self.__dict__[key] = PlayerKey(value, parent=self) else: self.__dict__[key].update(value) # Add largest PGroupPrime function for name, func in prime_funcs.items(): prime_call = func[-1] if prime_call is not None: self.event = prime_call(self.event, func[0]) return self def osc_message(self, index=0, **kwargs): """ Creates an OSC packet to play a SynthDef in SuperCollider, use kwargs to force values in the packet, e.g. pan=1 will force ['pan', 1] """ message = [] fx_dict = {} # Calculate frequency / buffer number if self.synthdef != SamplePlayer: degree = group_modi(kwargs.get("degree", self.event["degree"]), index) octave = group_modi(kwargs.get("oct", self.event["oct"]), index) root = group_modi(kwargs.get("root", self.event["root"]), index) freq = miditofreq( midi(kwargs.get("scale", self.scale), octave, degree, root)) message = ['freq', freq] else: degree = group_modi(kwargs.get("degree", self.event['degree']), index) sample = group_modi(kwargs.get("sample", self.event["sample"]), index) buf = int(Samples[str(degree)].bufnum(sample)) message = ['buf', buf] attributes = self.attr.copy() # Go through the attr dictionary and add kwargs for key in attributes: try: # Don't use fx keywords or foxdot keywords if key not in FxList.kwargs() and key not in self.keywords: group_value = kwargs.get(key, self.event[key]) val = group_modi(group_value, index) ## DEBUG if isinstance(val, (Pattern, PGroup)): print "In osc_message:", key, group_value, self.event[ key], val # Special case modulation if key == "sus": val = val * self.metro.beat_dur() * group_modi( kwargs.get('blur', self.event['blur']), index) elif key == "amp": val = val * group_modi( kwargs.get('amplify', self.event['amplify']), index) message += [key, val] except KeyError as e: WarningMsg("KeyError in function 'osc_message'", key, e) # See if any fx_attributes for key in self.fx_attributes: if key in attributes: # All effects use sustain to release nodes fx_dict[key] = [] # Look for any other attributes require e.g. room and verb for sub_key in FxList[key].args: if sub_key in self.event: if sub_key in message: i = message.index(sub_key) + 1 val = message[i] else: try: val = group_modi( kwargs.get(sub_key, self.event[sub_key]), index) if isinstance(val, Pattern): print sub_key, val except TypeError as e: val = 0 except KeyError as e: del fx_dict[key] break # Don't send fx with zero values, unless it is a timevar or playerkey i.e. has a "now" attr if val == 0 and not hasattr(val, 'now'): del fx_dict[key] break else: fx_dict[key] += [sub_key, val] return message, fx_dict def send(self, **kwargs): """ Sends the current event data to SuperCollder. Use kwargs to overide values in the """ size = self.largest_attribute() * pattern_depth(self.event.values()) banged = False sent_messages = [] delayed_messages = [] freq = [] bufnum = [] last_msg = None for i in range(size): # Get the basic osc_msg osc_msg, effects = self.osc_message(i, **kwargs) if "freq" in osc_msg: freq_value = osc_msg[osc_msg.index("freq") + 1] if freq_value not in freq: freq.append(freq_value) # Look at delays and schedule events later if need be try: delay = float( group_modi(kwargs.get('delay', self.event.get('delay', 0)), i)) except: print "delay is", self.event['delay'] if 'buf' in osc_msg: buf = group_modi( kwargs.get('buf', osc_msg[osc_msg.index('buf') + 1]), i) else: buf = 0 if buf not in bufnum: bufnum.append(buf) amp = group_modi( kwargs.get('amp', osc_msg[osc_msg.index('amp') + 1]), i) # Any messages with zero amps or 0 buf are not sent <- maybe change that for "now" classes if (self.synthdef != SamplePlayer and amp > 0) or (self.synthdef == SamplePlayer and buf > 0 and amp > 0): synthdef = self.get_synth_name(buf) if delay > 0: if (delay, osc_msg, effects) not in delayed_messages: # Schedule the note to play in the future & to update the playerkeys self.metro.schedule( send_delay(self, synthdef, osc_msg, effects), self.event_index + float(delay)) delayed_messages.append((delay, osc_msg, effects)) if self.bang_kwargs: self.metro.schedule(self.bang, self.metro.now() + delay) else: # Don't send duplicate messages if (osc_msg, effects) not in sent_messages: # --- New way of sending messages all at once compiled_msg = self.server.sendPlayerMessage( synthdef, osc_msg, effects, ) # -- We can specify to send immediately as opposed to all together at the end of the block if kwargs.get("send_now", False): # If send_now is True, then send is being called from somewhere else and so # the the osc message is added to the immediate block self.metro.current_block.osc_messages.append( compiled_msg) else: self.queue_block.osc_messages.append(compiled_msg) sent_messages.append((osc_msg, effects)) if not banged and self.bang_kwargs: self.bang() banged = True # Store the last message so we can compare if delayed last_msg = (osc_msg, effects) self.freq = freq self.buf = bufnum return def get_synth_name(self, buf=0): if self.synthdef == SamplePlayer: numChannels = Samples.getBuffer(buf).channels if numChannels == 1: synthdef = "play1" else: synthdef = "play2" else: synthdef = str(self.synthdef) return synthdef #: Methods for stop/starting players def kill(self): """ Removes this object from the Clock and resets itself""" self.isplaying = False self.repeat_events = {} self.reset() return def stop(self, N=0): """ Removes the player from the Tempo clock and changes its internal playing state to False in N bars time - When N is 0 it stops immediately""" self.stopping = True self.stop_point = self.metro.now() if N > 0: self.stop_point += self.metro.next_bar() + ( (N - 1) * self.metro.bar_length()) else: self.kill() return self def pause(self): self.isplaying = False return self def play(self): self.isplaying = True self.stopping = False self.isAlive = True self.__call__() return self def follow(self, lead=False): """ Takes a Player object and then follows the notes """ if isinstance(lead, self.__class__): self.degree = lead.degree self.following = lead else: self.following = None return self def solo(self, arg=True): if arg: self.metro.solo.set(self) else: self.metro.solo.reset() return self def num_key_references(self): """ Returns the number of 'references' for the attr which references the most other players """ num = 0 for attr in self.attr.values(): if isinstance(attr, PlayerKey): if attr.num_ref > num: num = attr.num_ref return num def lshift(self, n=1): self.event_n -= (n + 1) return self def rshift(self, n=1): self.event_n += n return self def reverse(self): """ Sets flag to reverse streams """ for attr in self.attr: try: self.attr[attr] = self.attr[attr].pivot(self.event_n) except AttributeError: pass return self def shuffle(self): """ Shuffles the degree of a player. """ # If using a play string for the degree if self.synthdef == SamplePlayer and self.playstring is not None: # Shuffle the contents of playgroups among the whole string new_play_string = PlayString(self.playstring).shuffle() new_degree = Pattern(new_play_string).shuffle() else: new_degree = self.attr['degree'].shuffle() self._replace_degree(new_degree) return self def mirror(self): """ The degree pattern is reversed """ self._replace_degree(self.attr['degree'].mirror()) return self def rotate(self, n=1): """ Rotates the values in the degree by 'n' """ self._replace_degree(self.attr['degree'].rotate(n)) return self def _replace_degree(self, new_degree): # Update the GUI if possible if self.widget: if self.synthdef == SamplePlayer: if self.playstring is not None: # Replace old_string with new string (only works with plain string patterns) new_string = new_degree.string() self.widget.addTask(target=self.widget.replace, args=(self.line_number, self.playstring, new_string)) self.playstring = new_string else: # Replaces the degree pattern in the widget (experimental) # self.widget.addTask(target=self.widget.replace_re, args=(self.line_number,), kwargs={'new':str(new_degree)}) self.playstring = str(new_degree) setattr(self, 'degree', new_degree) return def multiply(self, n=2): self.attr['degree'] = self.attr['degree'] * n return self def degrade(self, amount=0.5): """ Sets the amp modifier to a random array of 0s and 1s amount=0.5 weights the array to equal numbers """ if not self.degrading: self.amp = Pwrand([0, 1], [1 - amount, amount]) self.degrading = True else: ones = int(self.amp.count(1) * amount) zero = self.amp.count(0) self.amp = Pshuf(Pstutter([1, 0], [ones, zero])) return self def changeSynth(self, list_of_synthdefs): new_synth = choice(list_of_synthdefs) if isinstance(new_synth, SynthDef): new_synth = str(new_synth.name) self.synthdef = new_synth # TODO, change the >> name return self """ Modifier Methods ---------------- Other modifiers for affecting the playback of Players """ def offbeat(self, dur=0.5): """ Off sets the next event occurence """ self.attr['delay'] += (dur - self.offset) self.offset = dur return self def strum(self, dur=0.025): """ Adds a delay to a Synth Envelope """ x = self.largest_attribute() if x > 1: self.delay = asStream([tuple(a * dur for a in range(x))]) else: self.delay = asStream(dur) return self def __repr__(self): return "a '%s' Player Object" % self.synthdef def info(self): s = "Player Instance using '%s' \n\n" % self.synthdef s += "ATTRIBUTES\n" s += "----------\n\n" for attr, val in self.attr.items(): s += "\t{}\t:{}\n".format(attr, val) return s def bang(self, **kwargs): """ Triggered when sendNote is called. Responsible for any action to be triggered by a note being played. Default action is underline the player """ if kwargs: self.bang_kwargs = kwargs elif self.bang_kwargs: print self.bang_kwargs bang = Bang(self, self.bang_kwargs) return self
def TEST(): standard_tuning = (Note("E", 2), Note("A", 2), Note("D", 3), Note("G", 3), Note("B", 3), Note("E", 4)) Gibson = Guitar(23, standard_tuning) Ibanez = Guitar(25, standard_tuning) Major = Scale("Major", (2, 2, 1, 2, 2, 2), 'three_notes') Natural_minor = Scale("Natural Minor", (2, 1, 2, 2, 1, 2), 'three_notes') c_major_scale = Major.get_scale_notes("C") a_natural_minor_scale = Natural_minor.get_scale_notes("A") print('Gibson:') # for s in Gibson.strings: # for note in s: # print(note, end="") # print("\n") print('Gibson C major all notes:') c_all = Gibson.get_all_scale_notes(c_major_scale) for i in c_all: print(i) print('\n') print('Gibson C major three notes per string:') c_three = Gibson.get_three_notes(c_major_scale, 0) for i in c_three: print(i) print('\n') print('Gibson C major box pattern:') c_five = Gibson.get_box_pattern(c_major_scale, 1) for i in c_five: print(i) print('\n') print('Gibson C major one string pattern:') c_five = Gibson.get_one_string_pattern(c_major_scale, 1) for i in c_five: print(i) print('\nIbanez:') # for s in Ibanez.strings: # for note in s: # print(note, end="") # print("\n") print('Ibanez A natural minor all notes:') c_all = Ibanez.get_all_scale_notes(a_natural_minor_scale) for i in c_all: print(i) print('\n') print('Ibanez A natural minor three notes per string:') c_three = Ibanez.get_three_notes(a_natural_minor_scale, 0) for i in c_three: print(i) print('\n') print('Ibanez A natural minor box pattern:') c_five = Ibanez.get_box_pattern(a_natural_minor_scale, 1) for i in c_five: print(i) print('\n') print('Ibanez A natural minor box pattern:') c_five = Ibanez.get_one_string_pattern(a_natural_minor_scale, 3) for i in c_five: print(i)
class datalog: def __init__(self, filename, Cport, Tport, Sport): self.filename=filename self.Cport = Cport self.Tport = Tport self.Sport = Sport self.con = ConductivityProbe(Cport, 115200) self.con.openC() self.T = TemperatureProbes(Tport, 115200) self.T.openC() self.S = Scale(Sport, 19200) self.S.openC() f = open(self.filename, "w+") f.write("Cond\tWeight\tHotIn\tHotOut\tColdIn\tColdOut\tMonth\tDay\tHour\tMinute\tSecond\n") f.close() print("Waiting for first second of minute...") time = t.localtime(None).tm_sec while(time != 0): time = t.localtime(None).tm_sec def getdata(self, printInterval, saveInterval, exitWeight): month = [] day = [] hour = [] minute = [] second = [] cond = [] wt = [] temp = [] i = 0 m = float(0) e = 0 dd = 0 n = 0 print("Cond", "Weight","HotIn", "HotOut", "ColdIn","ColdOut","Month","Day","Hour","Minute","Second",sep='\t') d = datetime.date.today() c = datetime.datetime.now() h = c.hour mi = c.minute sec = c.second dayy = d.day mo = d.month conn=self.con.line() weight=self.S.line() #print(type(weight)) temps=self.T.line() print(conn, weight, temps, mo, dayy, h, mi, sec, sep='\t') while (True): #Get current date and time d = datetime.date.today() c = datetime.datetime.now() h = c.hour mi = c.minute sec = c.second dayy = d.day mo = d.month if (c.microsecond < 1000): temp = self.S.line() if (temp!= weight and temp!="" and temp!=None): weight=temp if (sec == 0) and (m % saveInterval == 0) and (c.microsecond < 1000): conn=self.con.line() temps=self.T.line() print(conn, weight, temps, mo, dayy, h, mi, sec, sep='\t') self.S.flushh() f=open(self.filename, "a+") f.write(str(conn) + "\t" + str(weight) + "\t" + temps + "\t" + str(mo) + "\t" + str(dayy) + "\t" + str(h) + "\t" + str(mi) + "\t" + str(sec) + "\n") f.close() n = n+1 self.S.flushh() elif (sec == 0) and (m % printInterval == 0) and (c.microsecond < 1000): conn=self.con.line() temps=self.T.line() print(conn, weight, temps, mo, dayy, h, mi, sec, sep='\t') self.S.flushh() self.con.flushh() self.T.flushh() else: pass if (sec == 0) and (c.microsecond < 100): m = m+1 if (float(weight) >= float(exitWeight)): conn=self.con.line() temps=self.T.line() print(conn, weight, temps, mo, dayy, h, mi, sec, sep='\t') f=open(self.filename, "a+") f.write(str(conn) + "\t" + str(weight) + "\t" + temps + "\t" + str(mo) + "\t" + str(dayy) + "\t" + str(h) + "\t" + str(mi) + "\t" + str(sec) + "\n") f.close() #self.finishup() break
#! /bin/python3 import sys import time as t import datetime from CProbe import ConductivityProbe from TProbes import TemperatureProbes from Scale import Scale con = ConductivityProbe(1, 115200) con.openC() T = TemperatureProbes(0, 115200) T.openC() S = Scale(0, 19200) S.openC() printInterval = float( input( "What interval (in minutes) would you like the data to be printed? ") ) saveInterval = float( input( "What interval (in minutes) would you like the data to be saved to a text file? " )) exitWeight = str( input("At what distillate weight would you like the program to end? ")) filename = str(input("What would you like the file name to be? ")) + ".csv" f = open(filename, "w+") print("Opened file")
class ResNetBlock(Subnet): ''' On the main path, the first convolution block has (1x1) kernel, zero padding. The second convolution block has (3x3) kernel, (1,1) padding and stride of 1. The third convolution block has (1x1) kernel, zero padding and stride of 1. The skip path has either identity mapping or a convolution block with (1x1) kernel and zero padding. The number of output channels is the same as that of the third convolution block on the main path. Parameters required: 'instanceName': name of the block 'skipMode': slect the operations on the skip path, 'conv' or 'identity' 'skipStride': stride of the convolution block on the skip path 'stride1': stride of the first convolution block on the main path 'outChannel1': number of output channel of the first convolution block on the main path 'outChannel2': number of output channel of the second convolution block on the main path 'outChannel3': number of output channel of the third convolution block on the main path 'activationType': activation function of the non-linear block, 'ReLU' or 'sigmoid' ''' # 'conv' mode has a convolution block on the skip path. 'identity' mode is strict pass through. skipModes = ['conv', 'identity'] def __init__(self, para): Subnet.__init__(self, para) self.layerList = [] self.fork = Fork2({'instanceName': para['instanceName'] + '_fork'}) self.layerList.append(self.fork) self.skipMode = para['skipMode'] if self.skipMode == 'conv': convPara4 = { 'instanceName': para['instanceName'] + '_skipConv1', 'padding': False, 'padShape': (0, 0), 'stride': para['skipStride'], 'outChannel': para['outChannel3'], 'kernelShape': (1, 1), 'bias': False } self.skipConv = Conv2D(convPara4) self.skipNorm = Normalize( {'instanceName': para['instanceName'] + '_skipNorm'}) self.skipScale = Scale( {'instanceName': para['instanceName'] + '_skipScale'}) self.layerList.append(self.skipConv) self.layerList.append(self.skipNorm) self.layerList.append(self.skipScale) convPara1 = { 'instanceName': para['instanceName'] + '_mainConv1', 'padding': False, 'padShape': (0, 0), 'stride': para['stride1'], 'outChannel': para['outChannel1'], 'kernelShape': (1, 1), 'bias': False } convPara2 = { 'instanceName': para['instanceName'] + '_mainConv2', 'padding': True, 'padShape': (1, 1), 'stride': 1, 'outChannel': para['outChannel2'], 'kernelShape': (3, 3), 'bias': False } convPara3 = { 'instanceName': para['instanceName'] + '_mainConv3', 'padding': False, 'padShape': (0, 0), 'stride': 1, 'outChannel': para['outChannel3'], 'kernelShape': (1, 1), 'bias': False } self.mainConv1 = Conv2D(convPara1) self.mainNorm1 = Normalize( {'instanceName': para['instanceName'] + '_mainNorm1'}) self.mainScale1 = Scale( {'instanceName': para['instanceName'] + '_mainScale1'}) self.mainActivation1 = Activation({ 'instanceName': para['instanceName'] + '_mainReLU1', 'activationType': para['activationType'] }) self.layerList.append(self.mainConv1) self.layerList.append(self.mainNorm1) self.layerList.append(self.mainScale1) self.layerList.append(self.mainActivation1) self.mainConv2 = Conv2D(convPara2) self.mainNorm2 = Normalize( {'instanceName': para['instanceName'] + '_mainNorm2'}) self.mainScale2 = Scale( {'instanceName': para['instanceName'] + '_mainScale2'}) self.mainActivation2 = Activation({ 'instanceName': para['instanceName'] + '_mainReLU2', 'activationType': para['activationType'] }) self.layerList.append(self.mainConv2) self.layerList.append(self.mainNorm2) self.layerList.append(self.mainScale2) self.layerList.append(self.mainActivation2) self.mainConv3 = Conv2D(convPara3) self.mainNorm3 = Normalize( {'instanceName': para['instanceName'] + '_mainNorm3'}) self.mainScale3 = Scale( {'instanceName': para['instanceName'] + '_mainScale3'}) self.layerList.append(self.mainConv3) self.layerList.append(self.mainNorm3) self.layerList.append(self.mainScale3) self.sum = Sum2({'instanceName': para['instanceName'] + '_sum'}) self.activation3 = Activation({ 'instanceName': para['instanceName'] + '_outReLU3', 'activationType': para['activationType'] }) self.layerList.append(self.sum) self.layerList.append(self.activation3) self.bottomInterface = self.fork self.topInterface = self.activation3 def stack(self, top, bottom): self.top = top self.bottom = bottom if self.skipMode == 'conv': self.fork.fork(self.skipConv, self.mainConv1, bottom) self.skipConv.stack(self.skipNorm, self.fork.skip) self.skipNorm.stack(self.skipScale, self.skipConv) self.skipScale.stack(self.sum.skip, self.skipNorm) else: self.fork.fork(self.sum.skip, self.mainConv1, bottom) # main path self.mainConv1.stack(self.mainNorm1, self.fork.main) self.mainNorm1.stack(self.mainScale1, self.mainConv1) self.mainScale1.stack(self.mainActivation1, self.mainNorm1) self.mainActivation1.stack(self.mainConv2, self.mainScale1) self.mainConv2.stack(self.mainNorm2, self.mainActivation1) self.mainNorm2.stack(self.mainScale2, self.mainConv2) self.mainScale2.stack(self.mainActivation2, self.mainNorm2) self.mainActivation2.stack(self.mainConv3, self.mainScale2) self.mainConv3.stack(self.mainNorm3, self.mainActivation2) self.mainNorm3.stack(self.mainScale3, self.mainConv3) self.mainScale3.stack(self.sum.main, self.mainNorm3) # sum if self.skipMode == 'conv': self.sum.sum(self.activation3, self.skipScale, self.mainScale3) else: self.sum.sum(self.activation3, self.fork.skip, self.mainScale3) self.activation3.stack(top, self.sum)
class Player(Repeatable): # Set private values __vars = [] __init = False # These are used by FoxDot keywords = ('degree', 'oct', 'freq', 'dur', 'delay', 'blur', 'amplify', 'scale', 'bpm', 'sample') # Base attributes base_attributes = ('sus', 'fmod', 'vib', 'slide', 'slidefrom', 'pan', 'rate', 'amp', 'room', 'buf', 'bits') play_attributes = ('scrub', 'cut') fx_attributes = FxList.kwargs() metro = None server = None # Tkinter Window widget = None default_scale = Scale.default() default_root = Root.default() def __init__(self): # Inherit Repeatable.__init__(self) # General setup self.synthdef = None self.id = None self.quantise = False self.stopping = False self.stop_point = 0 self.following = None self.queue_block = None self.playstring = "" self.buf_delay = [] # Visual feedback information self.envelope = None self.line_number = None self.whitespace = None self.bang_kwargs = {} # Modifiers self.reversing = False self.degrading = False # Keeps track of which note to play etc self.event_index = 0 self.event_n = 0 self.notes_played = 0 self.event = {} # Used for checking clock updates self.old_dur = None self.old_pattern_dur = None self.isplaying = False self.isAlive = True # These dicts contain the attribute and modifier values that are sent to SuperCollider self.attr = {} self.modf = {} # Keyword arguments that are used internally self.scale = None self.offset = 0 # List the internal variables we don't want to send to SuperCollider self.__vars = self.__dict__.keys() self.__init = True self.reset() # Class methods @classmethod def Attributes(cls): return cls.keywords + cls.base_attributes + cls.fx_attributes + cls.play_attributes # Player Object Manipulation def __rshift__(self, other): """ The PlayerObject Method >> """ if isinstance(other, SynthDefProxy): self.update(other.name, other.degree, **other.kwargs) self + other.mod for method, arguments in other.methods.items(): args, kwargs = arguments getattr(self, method).__call__(*args, **kwargs) return self raise TypeError( "{} is an innapropriate argument type for PlayerObject".format( other)) return self def __setattr__(self, name, value): if self.__init: # Force the data into a TimeVar or Pattern if the attribute is used with SuperCollider if name not in self.__vars: value = asStream(value) if not isinstance( value, (PlayerKey, TimeVar.var)) else value # Update the attribute dict self.attr[name] = value # Update the current event self.event[name] = modi(value, self.event_index) return self.__dict__[name] = value return def __eq__(self, other): return self is other def __ne__(self, other): return not self is other # --- Startup methods def reset(self): # --- SuperCollider Keywords # Left-Right panning (-1,1) self.pan = 0 # Sustain and blur (aka legato) self.sus = 1 # Amplitude self.amp = 1 # Rate - varies between SynthDef self.rate = 1 # Audio sample buffer number self.buf = 0 # Reverb self.verb = 0.25 self.room = 0.00 # Frequency modifier self.fmod = 0 # Buffer self.sample = 0 # --- FoxDot Keywords # Duration of notes self.dur = 0.5 if self.synthdef == SamplePlayer else 1 self.old_pattern_dur = self.old_dur = self.attr['dur'] self.delay = 0 # Degree of scale / Characters of samples self.degree = " " if self.synthdef is SamplePlayer else 0 # Octave of the note self.oct = 5 # Amplitude mod self.amplify = 1 # Legato self.blur = 1 # Tempo self.bpm = None # Frequency and modifier self.freq = 0 # Offbeat delay self.offset = 0 self.modf = dict([(key, [0]) for key in self.attr]) return self # --- Update methods def __call__(self, **kwargs): # If stopping, kill the event if self.stopping and self.metro.now() >= self.stop_point: self.kill() return # If the duration has changed, work out where the internal markers should be if self.dur_updated(): try: self.event_n, self.event_index = self.count() except TypeError: print("TypeError: Innappropriate argument type for 'dur'") self.old_dur = self.attr['dur'] # Get the current state dur = 0 while True: self.get_event() # Set a 'None' to 0 if self.event['dur'] is None: dur = 0 # If there are more than one dur (happens sometimes because of threading), only use first elif hasattr(self.event['dur'], '__iter__'): dur = float(self.event['dur'][0]) else: # Normal duration dur = float(self.event['dur']) # Skip events with durations of 0 if dur == 0: self.event_n += 1 else: break # Play the note if self.metro.solo == self and kwargs.get( 'verbose', True) and type(self.event['dur']) != rest: self.freq = 0 if self.synthdef == SamplePlayer else self.calculate_freq( ) self.send() # If using custom bpm if self.event['bpm'] is not None: try: tempo_shift = float(self.metro.bpm) / float(self.event['bpm']) except: tempo_shift = 1 dur *= tempo_shift # Schedule the next event self.event_index = self.event_index + dur self.metro.schedule(self, self.event_index, kwargs={}) # Change internal marker self.event_n += 1 if not self.reversing else -1 self.notes_played += 1 return def count(self, time=None): # Count the events that should have taken place between 0 and now() n = 0 acc = 0 dur = 0 now = time if time is not None else self.metro.now() durations = self.rhythm() total_dur = float(sum(durations)) if total_dur == 0: WarningMsg("Player object has a total duration of 0. Set to 1") self.dur = total_dur = durations = 1 acc = now - (now % total_dur) try: n = int(len(durations) * (acc / total_dur)) except TypeError as e: WarningMsg(e) self.stop() return 0, 0 while True: dur = float(modi(durations, n)) if acc + dur > now: break else: acc += dur n += 1 # Store duration times self.old_dur = self.attr['dur'] # Returns value for self.event_n and self.event_index self.notes_played = n return n, acc def update(self, synthdef, degree, **kwargs): # SynthDef name self.synthdef = synthdef if self.isplaying is False: self.reset() # If there is a designated solo player when updating, add this at next bar if self.metro.solo.active() and self.metro.solo != self: self.metro.schedule(lambda: self.metro.solo.add(self), self.metro.next_bar() - 0.001) # Update the attribute values special_cases = ["scale", "root", "dur"] # Set the degree if synthdef is SamplePlayer: self.playstring = degree setattr(self, "degree", degree if len(degree) > 0 else " ") elif degree is not None: self.playstring = str(degree) setattr(self, "degree", degree) # Set special case attributes self.scale = kwargs.get("scale", self.__class__.default_scale) self.root = kwargs.get("root", self.__class__.default_root) # If only duration is specified, set sustain to that value also if "dur" in kwargs: self.dur = kwargs['dur'] if "sus" not in kwargs and synthdef != SamplePlayer: self.sus = self.attr['dur'] if synthdef is SamplePlayer: pass # self.old_pattern_dur # self.old_dur = self.attr['dur'] # Set any other attributes for name, value in kwargs.items(): if name not in special_cases: setattr(self, name, value) # Calculate new position if not already playing if self.isplaying is False: # Add to clock self.isplaying = True self.stopping = False self.event_index = self.metro.next_bar() self.event_n = 0 self.event_n, _ = self.count(self.event_index) self.metro.schedule(self, self.event_index) return self def dur_updated(self): dur_updated = self.attr['dur'] != self.old_dur if self.synthdef == SamplePlayer: dur_updated = (self.pattern_rhythm_updated() or dur_updated) return dur_updated def step_duration(self): return 0.5 if self.synthdef is SamplePlayer else 1 def rhythm(self): # If a Pattern TimeVar if isinstance(self.attr['dur'], TimeVar.Pvar): r = asStream(self.attr['dur'].now().data) # If duration is a TimeVar elif isinstance(self.attr['dur'], TimeVar.var): r = asStream(self.attr['dur'].now()) else: r = asStream(self.attr['dur']) # TODO: Make sure degree is a string if self.synthdef is SamplePlayer: try: d = self.attr['degree'].now() except: d = self.attr['degree'] r = r * [(char.dur if hasattr(char, "dur") else 1) for char in d.flat()] return r def pattern_rhythm_updated(self): r = self.rhythm() if self.old_pattern_dur != r: self.old_pattern_dur = r return True return False def char(self, other=None): if other is not None: try: if type(other) == str and len(other) == 1: #char return BufferManager.bufnum(self.now('buf')) == other raise TypeError("Argument should be a one character string") except: return False else: try: return BufferManager.bufnum(self.now('buf')) except: return None def calculate_freq(self): """ Uses the scale, octave, and degree to calculate the frequency values to send to SuperCollider """ # If the scale is frequency only, just return the degree if self.scale == Scale.freq: try: return list(self.event['degree']) except: return [self.event['degree']] now = {} for attr in ('degree', 'oct'): now[attr] = self.event[attr] try: now[attr] = list(now[attr]) except: now[attr] = [now[attr]] size = max(len(now['oct']), len(now['degree'])) f = [] for i in range(size): try: midinum = midi(self.scale, modi(now['oct'], i), modi(now['degree'], i), self.now('root')) except: WarningMsg( "Invalid degree / octave arguments for frequency calculation, reset to default" ) print now['degree'], modi(now['degree'], i) raise f.append(miditofreq(midinum)) return f def f(self, *data): """ adds value to frequency modifier """ self.fmod = tuple(data) p = [] for val in self.attr['fmod']: try: pan = tuple((item / ((len(val) - 1) / 2.0)) - 1 for item in range(len(val))) except: pan = 0 p.append(pan) self.pan = p return self # Methods affecting other players - every n times, do a random thing? def stutter(self, n=2, **kwargs): """ Plays the current note n-1 times. You can specify some keywords, such as dur, sus, and rate. """ if self.metro.solo == self and n > 0: dur = float(kwargs.get("dur", self.dur)) / int(n) delay = 0 for stutter in range(1, n): delay += dur sub = { kw: modi(val, stutter - 1) for kw, val in kwargs.items() } self.metro.schedule(func_delay(self.send, **sub), self.event_index + delay) return self # --- Misc. Standard Object methods def __int__(self): return int(self.now('degree')) def __float__(self): return float(self.now('degree')) def __add__(self, data): """ Change the degree modifier stream """ self.modf['degree'] = asStream(data) return self def __sub__(self, data): """ Change the degree modifier stream """ data = asStream(data) data = [d * -1 for d in data] self.modf['degree'] = data return self def __mul__(self, data): """ Multiplying an instrument player multiplies each amp value by the input, or circularly if the input is a list. The input is stored here and calculated at the update stage """ if type(data) in (int, float): data = [data] self.modf['amp'] = asStream(data) return self def __div__(self, data): if type(data) in (int, float): data = [data] self.modf['amp'] = [1.0 / d for d in data] return self # --- Data methods def largest_attribute(self): """ Returns the length of the largest nested tuple in the attr dict """ # exclude = 'degree' if self.synthdef is SamplePlayer else None exclude = None size = len(self.attr['freq']) for attr, value in self.event.items(): if attr != exclude: try: l = len(value) if l > size: size = l except: pass return size # --- Methods for preparing and sending OSC messages to SuperCollider def now(self, attr="degree", x=0): """ Calculates the values for each attr to send to the server at the current clock time """ modifier_event_n = self.event_n attr_value = self.attr[attr] attr_value = modi(asStream(attr_value), self.event_n + x) ## If this player is following another, update that player first if attr == "degree" and self.following != None: if self.following in self.queue_block.objects(): self.queue_block.call(self.following, self) # If the attribute isn't in the modf dictionary, default to 0 try: modf_value = modi(self.modf[attr], modifier_event_n + x) except: modf_value = 0 # If any values are time-dependant, get the now values try: attr_value = attr_value.now() except: pass try: modf_value = modf_value.now() except: pass # Combine attribute and modifier values try: ## if attr == "dur" and type(attr_value) == rest: ## ## value = rest(attr_value + modf_value) ## ## else: value = attr_value + modf_value except: value = attr_value return value def get_event(self): """ Returns a dictionary of attr -> now values """ # Get the current event self.event = {} attributes = copy(self.attr) for key in attributes: # Eg. sp.sus returns the currently used value for sustain self.event[key] = self.now(key) # Make sure the object's dict uses PlayerKey instances if key not in self.__dict__: self.__dict__[key] = PlayerKey(self.event[key]) elif not isinstance(self.__dict__[key], PlayerKey): self.__dict__[key] = PlayerKey(self.event[key]) else: self.__dict__[key].update(self.event[key]) # Special case: sample player if self.synthdef == SamplePlayer: try: event_dur = self.event['dur'] if isinstance(self.event['degree'], PlayGroup): buf_list = ((0, self.event['degree']), ) event_buf = [0] else: buf_list = enumerate(self.event['degree']) event_buf = list(range(len(self.event['degree']))) self.buf_delay = [] for i, bufchar in buf_list: if isinstance(bufchar, PlayGroup): char = BufferManager[bufchar[0]] # Get the buffer number to play buf_mod_index = modi(self.event['sample'], i) event_buf[i] = char.bufnum(buf_mod_index).bufnum delay = 0 for n, b in enumerate(bufchar[1:]): if hasattr(b, 'now'): b = b.now() char = BufferManager[b] buf_mod_index = modi(self.event['sample'], i) delay += (bufchar[n].dur * self.event['dur']) self.buf_delay.append( (char.bufnum(buf_mod_index), delay)) else: char = BufferManager[bufchar] # Get the buffer number to play buf_mod_index = modi(self.event['sample'], i) event_buf[i] = char.bufnum(buf_mod_index).bufnum self.event['buf'] = P(event_buf) except TypeError: pass return self def osc_message(self, index=0, **kwargs): """ NEW: Creates an OSC packet to play a SynthDef in SuperCollider, use kwargs to force values in the packet, e.g. pan=1 will force ['pan', 1] """ freq = float(modi(self.attr['freq'], index)) message = ['freq', freq] fx_dict = {} attributes = self.attr.copy() # Go through the attr dictionary and add kwargs for key in attributes: try: # Don't use fx keywords or foxdot keywords if key not in FxList.kwargs() and key not in self.keywords: val = modi(kwargs.get(key, self.event[key]), index) # Special case modulation if key == "sus": val = val * self.metro.beat() * modi( kwargs.get('blur', self.event['blur']), index) elif key == "amp": val = val * modi( kwargs.get('amplify', self.event['amplify']), index) message += [key, float(val)] except: pass # See if any fx_attributes for key in self.fx_attributes: if key in attributes: # All effects use sustain to release nodes fx_dict[key] = [] # Look for any other attributes require e.g. room and verb for sub_key in FxList[key].args: if sub_key in self.event: if sub_key in message: i = message.index(sub_key) val = float(message[i + 1]) else: try: val = float( modi( kwargs.get(sub_key, self.event[sub_key]), index)) except TypeError as e: # If we get None, there was an error, set the value to 0 val = 0 # Don't send fx with zero values if val == 0: del fx_dict[key] break else: fx_dict[key] += [sub_key, val] return message, fx_dict def send(self, **kwargs): """ Sends the current event data to SuperCollder. Use kwargs to overide values in the """ size = self.largest_attribute() banged = False sent_messages = [] delayed_messages = [] for i in range(size): osc_msg, effects = self.osc_message(i, **kwargs) delay = modi(kwargs.get('delay', self.event['delay']), i) buf = modi(kwargs.get('buf', self.event['buf']), i) amp = osc_msg[osc_msg.index('amp') + 1] # Any messages with zero amps or 0 buf are not sent if (self.synthdef != SamplePlayer and amp > 0) or (self.synthdef == SamplePlayer and buf > 0 and amp > 0): if self.synthdef == SamplePlayer: numChannels = BufferManager.getBuffer(buf).channels if numChannels == 1: synthdef = "play1" else: synthdef = "play2" else: synthdef = str(self.synthdef) if delay > 0: # Sometimes there are race conditions, so make sure delay is just one value while hasattr(delay, "__len__"): delay = delay[i] if (delay, osc_msg, effects) not in delayed_messages: self.metro.schedule( send_delay(self, synthdef, osc_msg, effects), self.event_index + delay) delayed_messages.append((delay, osc_msg, effects)) if self.bang_kwargs: self.metro.schedule(self.bang, self.metro.now() + delay) else: # Don't send duplicate messages if (osc_msg, effects) not in sent_messages: self.server.sendPlayerMessage(synthdef, osc_msg, effects) sent_messages.append((osc_msg, effects)) if not banged and self.bang_kwargs: self.bang() banged = True if self.buf_delay: for buf_num, buf_delay in self.buf_delay: # Only send messages with amps > 0 i = osc_msg.index('amp') + 1 if osc_msg[i] > 0: # Make sure we use an integer number buf_num = int(buf_num) if buf_num > 0: i = osc_msg.index('buf') + 1 osc_msg[i] = buf_num numChannels = BufferManager.getBuffer( buf_num).channels if numChannels == 1: synthdef = "play1" else: synthdef = "play2" if (buf_delay + delay, osc_msg, effects) not in delayed_messages: self.metro.schedule( send_delay(self, synthdef, osc_msg, effects), self.event_index + buf_delay + delay) delayed_messages.append( (buf_delay + delay, osc_msg, effects)) return #: Methods for stop/starting players def kill(self): """ Removes this object from the Clock and resets itself""" self.isplaying = False self.repeat_events = {} self.reset() return def stop(self, N=0): """ Removes the player from the Tempo clock and changes its internal playing state to False in N bars time - When N is 0 it stops immediately""" self.stopping = True self.stop_point = self.metro.now() if N > 0: self.stop_point += self.metro.next_bar() + ( (N - 1) * self.metro.bar_length()) else: self.kill() return self def pause(self): self.isplaying = False return self def play(self): self.isplaying = True self.stopping = False self.isAlive = True self.__call__() return self def follow(self, lead, follow=True): """ Takes a now object and then follows the notes """ self.degree = lead.degree self.following = lead return self def solo(self, arg=True): if arg: self.metro.solo.set(self) else: self.metro.solo.reset() return self def num_key_references(self): """ Returns the number of 'references' for the attr which references the most other players """ num = 0 for attr in self.attr.values(): if isinstance(attr, PlayerKey): if attr.num_ref > num: num = attr.num_ref return num """ State-Shift Methods -------------- These methods are used in conjunction with Patterns.Feeders functions. They change the state of the Player Object and return the object. See 'Player.Feeders' for more info on how to use """ def lshift(self, n=1): self.event_n -= (n + 1) return self def rshift(self, n=1): self.event_n += n return self def reverse(self): """ Sets flag to reverse streams """ self.reversing = not self.reversing if self.reversing: self.event_n -= 1 else: self.event_n += 1 return self def shuffle(self): """ Shuffles the degree of a player. If possible, do it visually """ if self.synthdef == SamplePlayer: self._replace_string(PlayString(self.playstring).shuffle()) else: self._replace_degree(self.attr['degree'].shuffle()) return self def mirror(self): if self.synthdef == SamplePlayer: self._replace_string(PlayString(self.playstring).mirror()) else: self._replace_degree(self.attr['degree'].mirror()) return self def rotate(self, n=1): if self.synthdef == SamplePlayer: self._replace_string(PlayString(self.playstring).rotate(n)) else: self._replace_degree(self.attr['degree'].rotate(n)) return self def _replace_string(self, new_string): # Update the GUI if possible if self.widget: # Replace old_string with new string self.widget.addTask(target=self.widget.replace, args=(self.line_number, self.playstring, new_string)) self.playstring = new_string setattr(self, 'degree', new_string) return def _replace_degree(self, new_degree): # Update the GUI if possible if self.widget: # Replace old_string with new string self.widget.addTask(target=self.widget.replace_re, args=(self.line_number, ), kwargs={'new': str(new_degree)}) self.playstring = str(new_degree) setattr(self, 'degree', new_degree) return def multiply(self, n=2): self.attr['degree'] = self.attr['degree'] * n return self def degrade(self, amount=0.5): """ Sets the amp modifier to a random array of 0s and 1s amount=0.5 weights the array to equal numbers """ if not self.degrading: self.amp = Pwrand([0, 1], [1 - amount, amount]) self.degrading = True else: ones = int(self.amp.count(1) * amount) zero = self.amp.count(0) self.amp = Pshuf(Pstutter([1, 0], [ones, zero])) return self def changeSynth(self, list_of_synthdefs): new_synth = choice(list_of_synthdefs) if isinstance(new_synth, SynthDef): new_synth = str(new_synth.name) self.synthdef = new_synth # TODO, change the >> name return self """ Modifier Methods ---------------- Other modifiers for affecting the playback of Players """ def offbeat(self, dur=0.5): """ Off sets the next event occurence """ self.attr['delay'] += (dur - self.offset) self.offset = dur return self def strum(self, dur=0.025): """ Adds a delay to a Synth Envelope """ x = self.largest_attribute() if x > 1: self.delay = asStream([tuple(a * dur for a in range(x))]) else: self.delay = asStream(dur) return self def __repr__(self): return "a '%s' Player Object" % self.synthdef def info(self): s = "Player Instance using '%s' \n\n" % self.synthdef s += "ATTRIBUTES\n" s += "----------\n\n" for attr, val in self.attr.items(): s += "\t{}\t:{}\n".format(attr, val) return s def bang(self, **kwargs): """ Triggered when sendNote is called. Responsible for any action to be triggered by a note being played. Default action is underline the player """ if kwargs: self.bang_kwargs = kwargs elif self.bang_kwargs: print self.bang_kwargs bang = Bang(self, self.bang_kwargs) return self
from Scale import Scale import time from random import randint from threading import Thread from pythonosc import udp_client from pythonosc import osc_message_builder from pythonosc import osc_server from pythonosc import dispatcher client = udp_client.UDPClient("127.0.0.1", 8103) scale = Scale() timer = time.time() calibrationStarted = False def parseLightChange(index, r, g, b): scale.changeColor(index, [r, g, b]) dispatcher = dispatcher.Dispatcher() dispatcher.map("/changeLight", parseLightChange) server = osc_server.ThreadingOSCUDPServer(("127.0.0.1", 8102), dispatcher) print("ready to serve") serverThread = Thread(target = server.serve_forever) print("readier") serverThread.daemon = True serverThread.start()
import RPi.GPIO as GPIO def generate_image_name(): return "{}.png".format(datetime.now().isoformat()) # logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG) display = Display() print("[0/2] Starting setup...") display.print("[0/2] Setup\n\rstarted") file_upload = FileUpload() snipe_it = SnipeIT() reader = Scanner() scale = Scale() print("[0/2] Taring the scale. Remove everything and press Enter.") _ = input() print("[0/2] Taring the scale...") scale.tare() print("[1/2] Scale taring complete.") # initialize the video stream and allow the camera sensor to warm up print("[1/2] Starting video stream...") camera = Camera() print("[2/2] Video stream started...") print("[2/2] Setup complete") display.print("[2/2] Setup\n\rcomplete") try:
class Dosificadora: def __init__(self): #Crear el objeto de la clase dosificadora ##Convenciones: axxxx: a significa atributo #Con-> Concentrado #Min-> Mineral #Lev-> Levadura #Puertos de control para las valvulas self.avTolva = 2 self.avMineral = 16 self.avLevadura = 27 #Puertos de asignacion de las celdas de carga self.alsensorC1 = (11, 9) #Formato tupla: (dt,sck) self.alsensorC2 = (22, 10) self.alsensorC3 = (24, 23) self.alsensorC4 = (12, 6) self.alsensorML = (19, 13) #Puertos control de motores self.amCon = (7, 8) #Formato tupla: (Encendido, velocidad) self.amMin = (20, 21) #Formato tupla: (velocidad, sentido) self.amLev = (25, 26) #Sensibilidades celdas de carga self.asMin = 1030.3320 self.asLev = 2563.3821 self.asC1 = 1 self.asC2 = 1 self.asC3 = 1 self.asC4 = 1 self.asConc = 53.2201 #Valores de Tara para cada celda de carga self.asZeroMin = 0 self.asZeroLev = 0 self.asZeroC1 = 0 self.asZeroC2 = 0 self.asZeroC3 = 0 self.asZeroC4 = 0 #Masas objetivo self.aConObj = 1 self.aMinObj = 1 self.aLevObj = 1 self.aMasaObj = [self.aConObj, self.aMinObj, self.aLevObj] #Parametros del filtro tamizador y media movil self.aPeso_kbuffer = [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]] #Formato lista [Con,Min,Lev] self.aSk = [0.0, 0.0, 0.0] #Formato listas [Con,Min,Lev] self.aContador = [0, 0, 0] self.aDato_k_1 = [0.0, 0.0, 0.0] self.aX_k_1 = [0.0, 0.0, 0.0] self.aPeso_kbuffer = np.zeros((3, 20), dtype=np.float32) #Valores para algoritmo de control self.aMultiplo = [0.8, 0.8, 0.8] #Formato listas [Con,Min,Lev] self.aDeltaRef = [0.0, 0.0, 0.0] self.aInt = [0.0, 0.0, 0.0] self.aKp = [0.00051743, 0.0051743, 0.0] self.aKi = [0.0, 0.0, 0.0] self.aKd = [0.00080848, 0.0080848, 0.0] self.aN = [0.3704, 0.0, 0.3704] self.aVk_1 = 0.0 self.aEk_1 = 0.0 self.aYk_1 = 0.0 self.aDk_1 = 0.0 self.aUk_1 = 0 self.aRk_1 = 0 self.aInt_Retardo = 0 self.aTcontador = 0 self.aDoCalcularKp = [True, True, True] self.aPWM = [0.0, 0.0, 0.0] self.aAceleracion = [300.0, 0.0, 0.0] #Otros atributos self.asText = "________________" #Separador de Textos self.minCon = 39.0 #Menor ciclo de PWM permitido para el concentrado self.maxCon = 99.0 #Mayor ciclo de PWM permitido para el concentrado self.razon = [ 60.0, 50.0, 10.0 ] #Mayor tasa de cambio permitida por el filtro tamizador #Formato lista [Con,Min,Lev] self.aConCrucero = 70.0 #Velocidad crucero motor Con self.aConMin = 60.0 #Minima velocidad para mover el motor self.aEspacio = "_________________" def __del__(self): #Metodo destructor de objeto nombre = self.__class__.__name__ print(nombre, "Destruido") def inicializarPuertos(self): #Encargado de iniciar el estado de los puertos de RPi. print("\n________________\nIniciando puertos\n________________\n") #Configurar puertos #Valvulas GPIO.setup(self.avTolva, GPIO.OUT) GPIO.setup(self.avMineral, GPIO.OUT) GPIO.setup(self.avLevadura, GPIO.OUT) #Motores #Concentrado GPIO.setup(self.amCon[0], GPIO.OUT) GPIO.setup(self.amCon[1], GPIO.OUT) #Mineral GPIO.setup(self.amMin[0], GPIO.OUT) GPIO.setup(self.amLev[0], GPIO.OUT) #Levadura GPIO.setup(self.amMin[1], GPIO.OUT) GPIO.setup(self.amLev[1], GPIO.OUT) #Colocar todos los puertos en BAJO "LOW". GPIO.output(self.avTolva, 0) GPIO.output(self.avMineral, 0) GPIO.output(self.avLevadura, 0) GPIO.output(self.amCon[0], 0) GPIO.output(self.amCon[1], 0) GPIO.output(self.amMin[0], 0) GPIO.output(self.amMin[1], 0) GPIO.output(self.amLev[0], 0) GPIO.output(self.amLev[1], 0) def inicializarMotores(self): #Iniciar el estado de los motores #Frecuencia de PWM self.amMinPWM = GPIO.PWM(self.amMin[0], 300) #Formato tupla: (velocidad, sentido) self.amLevPWM = GPIO.PWM(self.amLev[0], 300) #Formato tupla: (velocidad, sentido) self.amConPWM = GPIO.PWM(self.amCon[1], 250) ##Iniciar PWM en valor 0 self.amMinPWM.start(0) self.amLevPWM.start(0) self.amConPWM.start(0) def inicializarCeldas(self): #Inciar celdas de carga print( "\n________________\nIniciando celdas de carga\n________________\n" ) #Formato tupla: self.alsensorA = (dt,sck) #Celda de carga Concentrado C1 self.ahxC1 = Scale(self.alsensorC1[0], self.alsensorC1[1], 1, 80) #Celda de carga Concentrado C2 self.ahxC2 = Scale(self.alsensorC2[0], self.alsensorC2[1], 1, 80) #Celda de carga Concentrado C3 self.ahxC3 = Scale(self.alsensorC3[0], self.alsensorC3[1], 1, 80) #Celda de carga Concentrado C4 self.ahxC4 = Scale(self.alsensorC4[0], self.alsensorC4[1], 1, 80) #Celda de carga Levadura Mineral self.ahxML = Scale(self.alsensorML[0], self.alsensorML[1], 1, 80) self.resetearCeldas() def encenderMotores(self, motor): #Metodo que activa los motores #Entrada: self-> Objeto propio de python # motor-> Selector del motor: # Con: Concentrado, Min: mineral Lev: levadura if (motor == 'Con'): if self.aConObj != 0: #Encendido motor Con velocidad = 99 #self.aConCrucero self.amConPWM.ChangeDutyCycle(velocidad) GPIO.output(self.amCon[0], 1) else: print("Masa es 0, concentrado no encendido") return if (motor == 'Min'): if self.aMinObj != 0: self.amMinPWM.ChangeFrequency(750) self.amMinPWM.ChangeDutyCycle(50) else: print("Masa igual a 0, mineral no encendido") return if (motor == 'Lev'): if self.aLevObj != 0: self.amLevPWM.ChangeFrequency(750) self.amLevPWM.ChangeDutyCycle(50) else: print("Masa igual a 0, levadura no encendido") return else: print("Motor no encontrado") def desacelerarMotores(self, motor): #Metodo que desacelera los motores if (motor == 'Con'): velocidad = self.aConMin self.amConPWM.ChangeDutyCycle(velocidad) return if (motor == 'Min'): self.amMinPWM.ChangeFrequency(200) self.amMinPWM.ChangeDutyCycle(50) return if (motor == 'Lev'): self.amLevPWM.ChangeFrequency(200) self.amLevPWM.ChangeDutyCycle(50) return else: print("Motor no encontrado") return def apagarMotores(self, motor, condicion): #Detener motores #Entradas: motor: Seleccion del motor deseado # Con -> Concentrado # Min -> Mineral # Lev -> Levadura # Condicion: Indica si el motor no fue apagado en la iteracion anterior if (motor == 'Con'): GPIO.output(self.amCon[0], 0) self.amConPWM.stop() if condicion: print("Concentrado apagado") return if (motor == 'Min'): self.amMinPWM.ChangeFrequency(50) self.amMinPWM.ChangeDutyCycle(0) if condicion: print("Mineral apagado") return if (motor == 'Lev'): self.amLevPWM.ChangeFrequency(50) self.amLevPWM.ChangeDutyCycle(0) if condicion: print("Levadura apagado") return else: print("Motor no encontrado") return def abrirCerrarValvulas(self, valvula, condicion): #Metodo de abrir y cerrar valvulas #Entradas: valvula: # Tolv -> Puerta de la tolva Romana # Min -> Compuerta del mineral # Lev -> Compuerta levadura # condicion: # 0 -> Valvula cerrada # 1 -> Valvula abierta if (valvula == 'Tolv'): GPIO.output(self.avTolva, condicion) return if (valvula == 'Min'): GPIO.output(self.avMineral, condicion) return if (valvula == 'Lev'): GPIO.output(self.avLevadura, condicion) return else: print("Valvula incorrecta") def cambiarSensibilidad(self, celda, sensibilidad): #Metodo para cambiar la sensibilidad de la celda de carga: (depuracion) #Formato de celda: 'Min','Lev','A','B' #Entradas: celda: A1, A2, B1, B2, Min, Lev print("Cambiando sensibilidad") if (celda == 'A1'): self.asA1 = sensibilidad self.axA.select_channel(channel='A') self.axA.set_scale_ratio(sensibilidad) return if (celda == 'A2'): self.asA2 = sensibilidad self.axA.select_channel(channel='B') self.axA.set_scale_ratio(sensibilidad) return if (celda == 'B1'): self.asB1 = sensibilidad self.axB.select_channel(channel='A') self.axB.set_scale_ratio(sensibilidad) return if (celda == 'B2'): self.asB2 = sensibilidad self.axB.select_channel(channel='B') self.axB.set_scale_ratio(sensibilidad) return if (celda == 'Min'): self.asMin = sensibilidad self.axML.select_channel(channel='A') self.axML.set_scale_ratio(sensibilidad) return if (celda == 'Lev'): self.asLev = sensibilidad self.axML.select_channel(channel='A') self.axML.set_scale_ratio(sensibilidad) return else: print("Celda no encontrada") def leerMineral(self, lecturas): #Leer el peso del mineral en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar mineral = 0.0 for i in range(lecturas): masaMin = -( (self.ahxML.weighOnce()) - self.asZeroMin) #/self.asMin mineral += masaMin mineral / lecturas return mineral def leerLevadura(self, lecturas): #Leer el peso del mineral en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar masaLev = (self.ahxML.weighOnce() - self.asZeroLev) / self.asLev return masaLev def leerConcentrado(self, lecturas): #Leer el peso del concentrado en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de promediar y devolver concentrado = 0.0 for i in range(lecturas): Conc1 = self.ahxC1.weighOnce() - self.asZeroC1 Conc2 = self.ahxC2.weighOnce() - self.asZeroC2 Conc3 = self.ahxC3.weighOnce() - self.asZeroC3 Conc4 = -(self.ahxC4.weighOnce() - self.asZeroC4) Conc = (Conc1 + Conc2 + Conc3 + Conc4) / (4 * self.asConc) concentrado += Conc concentrado = concentrado / lecturas return float(concentrado) def cerrarSteppers(self): #Metodo para apagar puertos de velocidad de los motores self.amMinPWM.stop() self.amLevPWM.stop() self.amConPWM.stop() def leer4Concentrado(self): #Metodo para leer por separado cada celda de carga del concentrado (depuracion) Conc1 = self.ahxC1.weighOnce() - self.asZeroC1 Conc2 = self.ahxC2.weighOnce() - self.asZeroC2 Conc3 = self.ahxC3.weighOnce() - self.asZeroC3 Conc4 = -(self.ahxC4.weighOnce() - self.asZeroC4) print("%d\t%d\t%d\t%d" % (Conc1, Conc2, Conc3, Conc4)) def leer4ConcentradoRaw(self, lecturas): #Metodo para leer cada celda del concentrado sin restar tara (depuracion) Conc1 = self.ahxC1.weighOnce() Conc2 = self.ahxC2.weighOnce() Conc3 = self.ahxC3.weighOnce() Conc4 = self.ahxC4.weighOnce() print("%d\t%d\t%d\t%d" % (Conc1, Conc2, Conc3, Conc4)) def tararConcentrado(self, imprimir=False, lecturas=30): #Metodo para tarar los amplificadores del concentrado if imprimir: print("Tarando") self.asZeroC1 = self.ahxC1.weigh(lecturas) self.asZeroC2 = self.ahxC2.weigh(lecturas) self.asZeroC3 = self.ahxC3.weigh(lecturas) self.asZeroC4 = self.ahxC4.weigh(lecturas) if imprimir: print("Tara del concentrado\n%d\t%d\t%d\t%d\t" % (self.asZeroC1, self.asZeroC2, self.asZeroC3, self.asZeroC4)) def tararMineral(self, printVal=False, lecturas=30): #Metodo para tarar mineral self.asZeroMin = self.ahxML.weigh(lecturas) if printVal: print("\tTara del mineral %d" % (self.asZeroMin)) def tararLevadura(self, printVal=False, lecturas=30): #Metodo para tarar levdura self.asZeroMin = self.ahxML.weigh(lecturas) if printVal: print("\tTara de la levadura %d" % (self.asZeroMin)) def filtradorTamizador(self, dato, alimento, periodos=5): #Metodo para filtrar y tamizar los valores de las celdas de carga #Se aplica un filtro de media movil con tres periodos, #luego se eliminan las lecturas que presenten cambios abruptos respecto de los valores predecesores. if alimento == 'Con': #Tamizar if ((abs(dato - self.aDato_k_1[0])) > self.razon[0]): datoT = self.aX_k_1[0] else: datoT = dato #Filtrar self.aSk[0] = self.aSk[0] - self.aPeso_kbuffer[0][ self.aContador[0]] + datoT concentrado = self.aSk[0] / periodos self.aPeso_kbuffer[0][self.aContador[0]] = datoT #Mover el contador y retrasar las muestras self.aContador[0] += 1 self.aDato_k_1[0] = dato self.aX_k_1[0] = datoT if self.aContador[0] == periodos: self.aContador[0] = 0 return concentrado if alimento == 'Min': #Tamizar if ((abs(dato - self.aDato_k_1[1])) > self.razon[1]): datoT = self.aX_k_1[1] else: datoT = dato #Filtrar self.aSk[1] = self.aSk[1] - self.aPeso_kbuffer[1][ self.aContador[1]] + datoT mineral = self.aSk[1] / periodos self.aPeso_kbuffer[1][self.aContador[1]] = datoT #Mover el contador y retrasar las muestras self.aContador[1] += 1 self.aDato_k_1[1] = dato self.aX_k_1[1] = datoT if self.aContador[1] == periodos: self.aContador[1] = 0 return mineral if alimento == 'Lev': #Tamizar if ((abs(dato - self.aDato_k_1[2])) > self.razon[2]): datoT = self.aX_k_1[2] else: datoT = dato #Filtrar self.aSk[2] = self.aSk[2] - self.aPeso_kbuffer[2][ self.aContador[2]] + datoT levadura = self.aSk[2] / periodos self.aPeso_kbuffer[2][self.aContador[2]] = datoT #Mover el contador y retrasar las muestras self.aContador[2] += 1 self.aDato_k_1[2] = dato self.aX_k_1[2] = datoT if self.aContador[2] == periodos: self.aContador[2] = 0 return levadura else: print("Alimento no encontrado") def inRangeCoerce(self, dato, minimo=0.0, maximo=100.0): #Metodo que limita los valores de una variable if dato > maximo: return maximo if dato < minimo: return minimo else: return dato def normalizarVelocidadConcentrado(self, dato): #Metodo para normalizar los valores del concentrado #Debido a la electronica, el valor de PWM permitido es entre 39 y 99. #Fuera de esos valores comienza a presentarse comportamiento erratico. dato = self.inRangeCoerce(dato, 0, 100) dato = (self.maxCon - self.minCon) / 100 * dato + self.minCon return dato #Metodos para resumir bloques de la secuencia def tararCeldas(self): #Metodo para tarar todas las cedas de carga. Permite no hacerlo desde el main self.leerMineral(80) print("________________\nTarando Concentrado\n________________\n") self.tararConcentrado(80, True) print("Zero A1 ", self.asZeroC1) print("Zero A2 ", self.asZeroC2) print("Zero B1 ", self.asZeroC3) print("Zero B2 ", self.asZeroC4) print("________________\nTarando Mineral\n________________\n") self.tararMineral(80) print("________________\nTarando Levadura\n________________\n") self.tararLevadura(80) def resetearCeldas(self): print("Reseteando celdas de carga concentrado") #Celdas del concentrado self.ahxC1.turnOff() time.sleep(0.5) self.ahxC1.turnOn() time.sleep(0.5) self.ahxC1.turnOff() time.sleep(0.5) self.ahxC1.turnOn() time.sleep(0.5) self.ahxC2.turnOff() time.sleep(0.5) self.ahxC2.turnOn() time.sleep(0.5) self.ahxC3.turnOff() time.sleep(0.5) self.ahxC3.turnOn() time.sleep(0.5) self.ahxC4.turnOff() time.sleep(0.5) self.ahxC4.turnOn() time.sleep(0.5) print("Reseteando celdas de carga Mineral y Levadura") self.ahxML.turnOff() time.sleep(0.5) self.ahxML.turnOn() time.sleep(0.5) def filtroButterWorth(self, xk): self.yk = ( 0.7769 * self.xk_1 #- 0.007079*self.xk_2 + 0.2231 * self.yk_1) #- 0.000002 * self.yk_2) #Retrasar muestras #self.xk_4 = self.xk_3 #self.xk_3 = self.xk_2 self.xk_2 = self.xk_1 self.xk_1 = xk #self.yk_4 = self.yk_3 #self.yk_3 = self.yk_2 self.yk_2 = self.yk_1 self.yk_1 = self.yk return self.yk def controlPDCon(self, yk): #Comienza algoritmo de control #Calculo del error ek = (self.aMasaObj[0] - yk) #Estimacion del control PD pk = self.aKp[0] * (ek) dk = ((self.aKd[0] * self.aN[0]) * (ek - self.aEk_1) + self.aDk_1) / (1 + self.aN[0] * 0.05) pidk = pk + dk + 0.3 #Compensacion de componente no lineal pidk = 100 * self.inRangeCoerce(pidk, 0, 0.99) self.amConPWM.ChangeDutyCycle(pidk) #Termina algoritmo de control #Retrasa las muestras self.aYk_1 = yk self.aDk_1 = dk self.aEk_1 = ek self.aPWM[0] = pidk def controlPDLev(self, yk): #Comienza algoritmo de control #Calculo del error ek = (self.aMasaObj[2] - yk) #Estimacion del control PD pk = self.aKp[2] * (ek) dk = ((self.aKd[2] * self.aN[2]) * (ek - self.aEk_1) + self.aDk_1) / (1 + self.aN[2] * 0.05) pidk = pk + dk + 0.4 #Compensacion de componente no lineal pidk = self.inRangeCoerce(pidk, 0, 0.99) pidk = self.escalar(pidk, 0, 1400) self.amLevPWM.ChangeFrequency(pidk) #Termina algoritmo de control #Retrasa las muestras self.aYk_1_Lev = yk self.aDk_1_Lev = dk self.aEk_1_Lev = ek self.aPWM[2] = pidk def escalar(self, dato, outMin, outMax, inMin=0, inMax=1): m = (outMin - outMax) / (inMin - inMax) b = outMin - inMin * m dato = dato * m + b return dato ##----- Metodos para pruebas por separado ----- ## def InicializarCeldasTR(self): #Inicializa solamente las celdas de carga de la tolva romana self.ahxC1 = Scale(self.alsensorC1[0], self.alsensorC1[1], 1, 80) #Celda de carga Concentrado C2 self.ahxC2 = Scale(self.alsensorC2[0], self.alsensorC2[1], 1, 80) #Celda de carga Concentrado C3 self.ahxC3 = Scale(self.alsensorC3[0], self.alsensorC3[1], 1, 80) #Celda de carga Concentrado C4 self.ahxC4 = Scale(self.alsensorC4[0], self.alsensorC4[1], 1, 80) def InicializarCeldasML(self): #Inicializa las celdas de carga del mineral/Levadura self.ahxML = Scale(self.alsensorML[0], self.alsensorML[1], 1, 80) def ResetearCeldasTR(self): #Resetea las celdas de carga del concentrado print("Reseteando celdas de carga concentrado") self.ahxC1.turnOff() self.ahxC2.turnOff() self.ahxC3.turnOff() self.ahxC4.turnOff() time.sleep(0.5) self.ahxC1.turnOn() self.ahxC2.turnOn() self.ahxC3.turnOn() self.ahxC4.turnOff() time.sleep(0.5) def resetearCeldasML(self): #Resetea las celdas de carga del Mineral/Levadura print("Reseteando celdas de carga Mineral-Levadura") #Celdas del Mineral/Levadura self.ahxML.turnOff() time.sleep(0.5) self.ahxML.turnOn() ## --- Metodos para pruebas individuales -------- def probarCeldasMinLev(self, tiempo): #Obtiene muestras de la celda de carga por una cantidad determinada de tiempo print(self.aEspacio) print("Probando celdas de carga Mineral-Levadura") print(self.aEspacio) self.InicializarCeldasML() self.resetearCeldasML() self.tararMineral(False, 80) self.tararLevadura(False, 80) print("Sin filtro\tCon Filtro") tic = time.time() while True: Min = self.leerMineral(80) #Calcular filtro de media movil en linea MinF = self.filtradorTamizador(Min, 'Min', 5) print("%f\t%f" % (Min, MinF)) toc = time.time() #Condicion de parada para el ciclo if ((toc - tic) >= tiempo): break def probarCeldasTR(self, tiempo): #Obtiene muestras de la celda de carga por una cantidad determinada de tiempo print(self.aEspacio) print("Probando celdas de carga Tolva Romana") print(self.aEspacio) self.InicializarCeldasTR() self.ResetearCeldasTR() self.tararConcentrado(False, 80) print("Sin filtro\tCon Filtro") tic = time.time() while True: Con = self.leerConcentrado(80) #Calcular filtro de media movil en linea ConF = self.filtradorTamizador(Con, 'Con', 5) print("%f\t%f" % (Con, ConF)) toc = time.time() #Condicion de parada para el ciclo if ((toc - tic) >= tiempo): break def obtenerFuncionRampaTR(self, maxSpeed=99): #metodo que se usa para obtener la rampa de velocidad del citrocom aceleracion = True print(self.aEspacio) print("Obteniendo rampa") print(self.aEspacio) self.inicializarPuertos() self.InicializarCeldasTR() self.ResetearCeldasTR() self.tararConcentrado() self.inicializarMotores() self.amConPWM.ChangeDutyCycle(99) print("Arrancado") self.encenderMotores('Con') c = 0 self.amConPWM.start(0) while True: if aceleracion: for i in range(10, maxSpeed, 1): masaConc = self.leerConcentrado(4) masaConcF = self.filtradorTamizador(masaConc, 'Con', 5) self.amConPWM.ChangeDutyCycle(i) time.sleep(0.1) print("%f\t%f\t%f" % (masaConc, masaConcF, i)) for i in reversed(range(10, maxSpeed, 1)): masaConc = self.leerConcentrado(4) masaConcF = self.filtradorTamizador(masaConc, 'Con', 5) self.amConPWM.ChangeDutyCycle(i) time.sleep(0.1) print("%f\t%f\t%f" % (masaConc, masaConcF, i)) else: if (c == 0): self.amConPWM.ChangeDutyCycle(maxSpeed) c += 0
def InicializarCeldasML(self): #Inicializa las celdas de carga del mineral Levadura self.ahxML = Scale(self.alsensorML[0], self.alsensorML[1], 1, 80)
def testTransposedScale(self): for S, R in self.KnownTransposedScale: T = Scale(S[0]).TransposeTo(S[1]) self.assertEqual(T, R) print(S[0], "transposed to", S[1], "yields", T)
def __init__(self, para): Net.__init__(self, para) convPara1 = { 'instanceName': 'RN18' + '_Conv1', 'padding': True, 'padShape': (1, 1), 'stride': 1, 'outChannel': para['c1OutChannel'], 'kernelShape': (3, 3), 'bias': False } self.conv1 = Conv2D(convPara1) self.norm1 = Normalize({'instanceName': 'RN18' + '_Norm1'}) self.scale1 = Scale({'instanceName': 'RN18' + '_Scale1'}) self.activation1 = Activation({ 'instanceName': 'RN18' + '_Activation1', 'activationType': 'ReLU' }) self.layerList.append(self.conv1) self.layerList.append(self.norm1) self.layerList.append(self.scale1) self.layerList.append(self.activation1) convPara2 = { 'instanceName': 'RN18' + '_Conv2', 'padding': True, 'padShape': (1, 1), 'stride': 2, 'outChannel': para['c2OutChannel'], 'kernelShape': (3, 3), 'bias': False } self.conv2 = Conv2D(convPara2) self.norm2 = Normalize({'instanceName': 'RN18' + '_Norm2'}) self.scale2 = Scale({'instanceName': 'RN18' + '_Scale2'}) self.activation2 = Activation({ 'instanceName': 'RN18' + '_Activation2', 'activationType': 'ReLU' }) self.layerList.append(self.conv2) self.layerList.append(self.norm2) self.layerList.append(self.scale2) self.layerList.append(self.activation2) self.rnb1 = ResNetBlock({ 'instanceName': 'RN18' + '_RNB1', 'skipMode': 'identity', 'skipStride': 0, 'stride1': 1, 'outChannel1': int(para['rnb1OutChannel'] / 4), 'outChannel2': int(para['rnb1OutChannel'] / 4), 'outChannel3': para['rnb1OutChannel'], 'activationType': 'ReLU' }) self.layerList.append(self.rnb1) self.rnb2 = ResNetBlock({ 'instanceName': 'RN18' + '_RNB2', 'skipMode': 'identity', 'skipStride': 0, 'stride1': 1, 'outChannel1': int(para['rnb1OutChannel'] / 4), 'outChannel2': int(para['rnb1OutChannel'] / 4), 'outChannel3': para['rnb1OutChannel'], 'activationType': 'ReLU' }) self.layerList.append(self.rnb2) self.rnb3 = ResNetBlock({ 'instanceName': 'RN18' + '_RNB3', 'skipMode': 'identity', 'skipStride': 0, 'stride1': 1, 'outChannel1': int(para['rnb1OutChannel'] / 4), 'outChannel2': int(para['rnb1OutChannel'] / 4), 'outChannel3': para['rnb1OutChannel'], 'activationType': 'ReLU' }) self.layerList.append(self.rnb3) self.rnb4 = ResNetBlock({ 'instanceName': 'RN18' + '_RNB4', 'skipMode': 'conv', 'skipStride': 2, 'stride1': 2, 'outChannel1': int(para['rnb4OutChannel'] / 4), 'outChannel2': int(para['rnb4OutChannel'] / 4), 'outChannel3': para['rnb4OutChannel'], 'activationType': 'ReLU' }) self.layerList.append(self.rnb4) self.rnb5 = ResNetBlock({ 'instanceName': 'RN18' + '_RNB5', 'skipMode': 'identity', 'skipStride': 1, 'stride1': 1, 'outChannel1': int(para['rnb4OutChannel'] / 4), 'outChannel2': int(para['rnb4OutChannel'] / 4), 'outChannel3': para['rnb4OutChannel'], 'activationType': 'ReLU' }) self.layerList.append(self.rnb5) self.pool1 = Pool({ 'instanceName': 'RN18' + '_pool1', 'poolType': 'ave', 'stride': para['pSize'], 'kernelShape': (para['pSize'], para['pSize']) }) self.layerList.append(self.pool1) self.fc1 = FullyConnected({ 'instanceName': 'RN18' + '_fc1', 'outChannel': para['classNum'], 'bias': True }) self.layerList.append(self.fc1) self.softmax = Softmax({'instanceName': 'RN18' + '_softmax'}) self.layerList.append(self.softmax) self.bottomInterface = self.conv1 self.topInterface = self.softmax self.softmax.setNet(self)
def __init__(self, para): Subnet.__init__(self, para) self.layerList = [] self.fork = Fork2({'instanceName': para['instanceName'] + '_fork'}) self.layerList.append(self.fork) self.skipMode = para['skipMode'] if self.skipMode == 'conv': convPara4 = { 'instanceName': para['instanceName'] + '_skipConv1', 'padding': False, 'padShape': (0, 0), 'stride': para['skipStride'], 'outChannel': para['outChannel3'], 'kernelShape': (1, 1), 'bias': False } self.skipConv = Conv2D(convPara4) self.skipNorm = Normalize( {'instanceName': para['instanceName'] + '_skipNorm'}) self.skipScale = Scale( {'instanceName': para['instanceName'] + '_skipScale'}) self.layerList.append(self.skipConv) self.layerList.append(self.skipNorm) self.layerList.append(self.skipScale) convPara1 = { 'instanceName': para['instanceName'] + '_mainConv1', 'padding': False, 'padShape': (0, 0), 'stride': para['stride1'], 'outChannel': para['outChannel1'], 'kernelShape': (1, 1), 'bias': False } convPara2 = { 'instanceName': para['instanceName'] + '_mainConv2', 'padding': True, 'padShape': (1, 1), 'stride': 1, 'outChannel': para['outChannel2'], 'kernelShape': (3, 3), 'bias': False } convPara3 = { 'instanceName': para['instanceName'] + '_mainConv3', 'padding': False, 'padShape': (0, 0), 'stride': 1, 'outChannel': para['outChannel3'], 'kernelShape': (1, 1), 'bias': False } self.mainConv1 = Conv2D(convPara1) self.mainNorm1 = Normalize( {'instanceName': para['instanceName'] + '_mainNorm1'}) self.mainScale1 = Scale( {'instanceName': para['instanceName'] + '_mainScale1'}) self.mainActivation1 = Activation({ 'instanceName': para['instanceName'] + '_mainReLU1', 'activationType': para['activationType'] }) self.layerList.append(self.mainConv1) self.layerList.append(self.mainNorm1) self.layerList.append(self.mainScale1) self.layerList.append(self.mainActivation1) self.mainConv2 = Conv2D(convPara2) self.mainNorm2 = Normalize( {'instanceName': para['instanceName'] + '_mainNorm2'}) self.mainScale2 = Scale( {'instanceName': para['instanceName'] + '_mainScale2'}) self.mainActivation2 = Activation({ 'instanceName': para['instanceName'] + '_mainReLU2', 'activationType': para['activationType'] }) self.layerList.append(self.mainConv2) self.layerList.append(self.mainNorm2) self.layerList.append(self.mainScale2) self.layerList.append(self.mainActivation2) self.mainConv3 = Conv2D(convPara3) self.mainNorm3 = Normalize( {'instanceName': para['instanceName'] + '_mainNorm3'}) self.mainScale3 = Scale( {'instanceName': para['instanceName'] + '_mainScale3'}) self.layerList.append(self.mainConv3) self.layerList.append(self.mainNorm3) self.layerList.append(self.mainScale3) self.sum = Sum2({'instanceName': para['instanceName'] + '_sum'}) self.activation3 = Activation({ 'instanceName': para['instanceName'] + '_outReLU3', 'activationType': para['activationType'] }) self.layerList.append(self.sum) self.layerList.append(self.activation3) self.bottomInterface = self.fork self.topInterface = self.activation3
class RN18(Net): ''' ResNet18 has a total of 18 layers: Note that some parameters are predetermined. The parameters need to be specified are in ''. For all ResNetBlock modules, the output sizes of stage 1 and stage 2 conv2D blocks equals to 1/4 of that of the final stage. Conv1 - kernel:(3x3), pad:(1,1), stride:1, output: 'c1OutChannel' Conv1 - kernel:(3x3), pad:(1,1), stride:2, output: 'c2OutChannel' # H and W reduced by half RNB1 - skipMode:identity, output : 'rnb1OutChannel' RNB2 - skipMode:identity, output : same as RNB1 RNB3 - skipMode:identity, output : same as RNB1 RNB4 - skipMode:conv, skipStride:2, output : 'rnb4OutChannel' # H and W reduced by half RNB5 - skipMode:identity, output : same as RNB4 pool - average pooling of RNB5 per channel, reducing output to 'rnb4OutChannel', need to specify 'pSize', which is used to specify stride and kernel size fc - outChannel: 'classNum' softmax - final classification layer ''' def __init__(self, para): Net.__init__(self, para) convPara1 = { 'instanceName': 'RN18' + '_Conv1', 'padding': True, 'padShape': (1, 1), 'stride': 1, 'outChannel': para['c1OutChannel'], 'kernelShape': (3, 3), 'bias': False } self.conv1 = Conv2D(convPara1) self.norm1 = Normalize({'instanceName': 'RN18' + '_Norm1'}) self.scale1 = Scale({'instanceName': 'RN18' + '_Scale1'}) self.activation1 = Activation({ 'instanceName': 'RN18' + '_Activation1', 'activationType': 'ReLU' }) self.layerList.append(self.conv1) self.layerList.append(self.norm1) self.layerList.append(self.scale1) self.layerList.append(self.activation1) convPara2 = { 'instanceName': 'RN18' + '_Conv2', 'padding': True, 'padShape': (1, 1), 'stride': 2, 'outChannel': para['c2OutChannel'], 'kernelShape': (3, 3), 'bias': False } self.conv2 = Conv2D(convPara2) self.norm2 = Normalize({'instanceName': 'RN18' + '_Norm2'}) self.scale2 = Scale({'instanceName': 'RN18' + '_Scale2'}) self.activation2 = Activation({ 'instanceName': 'RN18' + '_Activation2', 'activationType': 'ReLU' }) self.layerList.append(self.conv2) self.layerList.append(self.norm2) self.layerList.append(self.scale2) self.layerList.append(self.activation2) self.rnb1 = ResNetBlock({ 'instanceName': 'RN18' + '_RNB1', 'skipMode': 'identity', 'skipStride': 0, 'stride1': 1, 'outChannel1': int(para['rnb1OutChannel'] / 4), 'outChannel2': int(para['rnb1OutChannel'] / 4), 'outChannel3': para['rnb1OutChannel'], 'activationType': 'ReLU' }) self.layerList.append(self.rnb1) self.rnb2 = ResNetBlock({ 'instanceName': 'RN18' + '_RNB2', 'skipMode': 'identity', 'skipStride': 0, 'stride1': 1, 'outChannel1': int(para['rnb1OutChannel'] / 4), 'outChannel2': int(para['rnb1OutChannel'] / 4), 'outChannel3': para['rnb1OutChannel'], 'activationType': 'ReLU' }) self.layerList.append(self.rnb2) self.rnb3 = ResNetBlock({ 'instanceName': 'RN18' + '_RNB3', 'skipMode': 'identity', 'skipStride': 0, 'stride1': 1, 'outChannel1': int(para['rnb1OutChannel'] / 4), 'outChannel2': int(para['rnb1OutChannel'] / 4), 'outChannel3': para['rnb1OutChannel'], 'activationType': 'ReLU' }) self.layerList.append(self.rnb3) self.rnb4 = ResNetBlock({ 'instanceName': 'RN18' + '_RNB4', 'skipMode': 'conv', 'skipStride': 2, 'stride1': 2, 'outChannel1': int(para['rnb4OutChannel'] / 4), 'outChannel2': int(para['rnb4OutChannel'] / 4), 'outChannel3': para['rnb4OutChannel'], 'activationType': 'ReLU' }) self.layerList.append(self.rnb4) self.rnb5 = ResNetBlock({ 'instanceName': 'RN18' + '_RNB5', 'skipMode': 'identity', 'skipStride': 1, 'stride1': 1, 'outChannel1': int(para['rnb4OutChannel'] / 4), 'outChannel2': int(para['rnb4OutChannel'] / 4), 'outChannel3': para['rnb4OutChannel'], 'activationType': 'ReLU' }) self.layerList.append(self.rnb5) self.pool1 = Pool({ 'instanceName': 'RN18' + '_pool1', 'poolType': 'ave', 'stride': para['pSize'], 'kernelShape': (para['pSize'], para['pSize']) }) self.layerList.append(self.pool1) self.fc1 = FullyConnected({ 'instanceName': 'RN18' + '_fc1', 'outChannel': para['classNum'], 'bias': True }) self.layerList.append(self.fc1) self.softmax = Softmax({'instanceName': 'RN18' + '_softmax'}) self.layerList.append(self.softmax) self.bottomInterface = self.conv1 self.topInterface = self.softmax self.softmax.setNet(self) def stack(self, top, bottom): self.top = top self.bottom = bottom self.conv1.stack(self.norm1, bottom) self.norm1.stack(self.scale1, self.conv1) self.scale1.stack(self.activation1, self.norm1) self.activation1.stack(self.conv2, self.scale1) self.conv2.stack(self.norm2, self.activation1) self.norm2.stack(self.scale2, self.conv2) self.scale2.stack(self.activation2, self.norm2) self.activation2.stack(self.rnb1, self.scale2) self.rnb1.stack(self.rnb2, self.activation2) self.rnb2.stack(self.rnb3, self.rnb1) self.rnb3.stack(self.rnb4, self.rnb2) self.rnb4.stack(self.rnb5, self.rnb3) self.rnb5.stack(self.pool1, self.rnb4) self.pool1.stack(self.fc1, self.rnb5) self.fc1.stack(self.softmax, self.pool1) self.softmax.stack(top, self.fc1) self.softmax.setSource(bottom)
class Dosificadora: def __init__(self): #Crear el objeto de la clase dosificadora ##Convenciones: axxxx: a significa atributo #Con-> Concentrado #Min-> Mineral #Lev-> Levadura #Puertos de control para las valvulas self.avTolva = 2 self.avMineral = 16 self.avLevadura = 27 #Puertos de asignacion de las celdas de carga self.alsensorC1 = (11, 9) #Formato tupla: (dt,sck) self.alsensorC2 = (22, 10) self.alsensorC3 = (24, 23) self.alsensorC4 = (12, 6) self.alsensorML = (19, 13) #Puertos control de motores self.amCon = (7, 8) #Formato tupla: (Encendido, velocidad) self.amMin = (20, 21) #Formato tupla: (velocidad, sentido) self.amLev = (25, 26) #Sensibilidades celdas de carga self.asMin = 1030.3320 self.asLev = 2563.3821 self.asC1 = 1 self.asC2 = 1 self.asC3 = 1 self.asC4 = 1 self.asConc = 50.380 #Valores de Tara para cada celda de carga self.asZeroMin = 0 self.asZeroLev = 0 self.asZeroA1 = 0 self.asZeroA2 = 0 self.asZeroB1 = 0 self.asZeroB2 = 0 #Masas objetivo self.aConObj = 1 self.aMinObj = 1 self.aLevObj = 1 #Parametros del filtro de media movil self.peso_k_1 = [0, 0, 0] #Formato de lista [Con,Min,Lev] self.peso_k_2 = [0, 0, 0] #Formato lista [Con,Min,Lev] #Otros atributos self.asText = "________________" #Separador de Textos self.minCon = 39 #Menor ciclo de PWM permitido para el concentrado self.maxCon = 99 #Mayor ciclo de PWM permitido para el concentrado self.razon = [ 800, 50, 10 ] #Mayor tasa de cambio permitida por el filtro tamizador #Formato lista [Con,Min,Lev] self.aConCrucero = 70 #Velocidad crucero motor Con self.aConMin = 60 #Minima velocidad para mover el motor def __del__(self): #Metodo destructor de objeto nombre = self.__class__.__name__ print nombre, "Destruido" def inicializarPuertos(self): #Encargado de iniciar el estado de los puertos de RPi. print("\n________________\nIniciando puertos\n________________\n") #Configurar puertos #Valvulas GPIO.setup(self.avTolva, GPIO.OUT) GPIO.setup(self.avMineral, GPIO.OUT) GPIO.setup(self.avLevadura, GPIO.OUT) #Motores #Concentrado GPIO.setup(self.amCon[0], GPIO.OUT) GPIO.setup(self.amCon[1], GPIO.OUT) #Mineral GPIO.setup(self.amMin[0], GPIO.OUT) GPIO.setup(self.amLev[0], GPIO.OUT) #Levadura GPIO.setup(self.amMin[1], GPIO.OUT) GPIO.setup(self.amLev[1], GPIO.OUT) #Colocar todos los puertos en BAJO "LOW". GPIO.output(self.avTolva, 0) GPIO.output(self.avMineral, 0) GPIO.output(self.avLevadura, 0) GPIO.output(self.amCon[0], 0) GPIO.output(self.amCon[1], 0) GPIO.output(self.amMin[0], 0) GPIO.output(self.amMin[1], 0) GPIO.output(self.amLev[0], 0) GPIO.output(self.amLev[1], 0) def inicializarMotores(self): #Iniciar el estado de los motores #Frecuencia de PWM self.amMinPWM = GPIO.PWM(self.amMin[0], 300) #Formato tupla: (velocidad, sentido) self.amLevPWM = GPIO.PWM(self.amLev[0], 300) #Formato tupla: (velocidad, sentido) self.amConPWM = GPIO.PWM(self.amCon[1], 250) ##Iniciar PWM en valor 0 self.amMinPWM.start(0) self.amLevPWM.start(0) self.amConPWM.start(0) def inicializarCeldas(self): #Inciar celdas de carga print( "\n________________\nIniciando celdas de carga\n________________\n" ) #Formato tupla: self.alsensorA = (dt,sck) #Celda de carga Concentrado C1 self.ahxC1 = Scale(self.alsensorC1[0], self.alsensorC1[1], 1, 80) #Celda de carga Concentrado C2 self.ahxC2 = Scale(self.alsensorC2[0], self.alsensorC2[1], 1, 80) #Celda de carga Concentrado C3 self.ahxC3 = Scale(self.alsensorC3[0], self.alsensorC3[1], 1, 80) #Celda de carga Concentrado C4 self.ahxC4 = Scale(self.alsensorC4[0], self.alsensorC4[1], 1, 80) #Celda de carga Levadura Mineral self.ahxML = Scale(self.alsensorML[0], selfalsensorML[1], 1, 80) #Inicializa, resetea y tara A print( "\n________________\nConfigurando Amplificador C1\n________________\n" ) #Resetear amplificador C1 self.ahxA.reset() self.ahxA.set_gain(gain=64) #Configurar ganancia para el canal A self.ahxA.select_channel(channel='A') self.ahxA.set_reference_unit(1) #Resetear calibracion amplificador C1 self.ahxA.select_channel(channel='B') self.ahxA.set_offset(0) self.ahxA.select_channel(channel='A') print('\tConfigurado\n') # -------------------------------------------------------------# ##Configurar amplificador C2 #Inicializa, resetea y tara amplificador C2 print( "\n________________\nConfigurando Amplificador C2\n________________\n" ) print("\tReseteando...") self.ahxA.reset() #Resetear amplificador C2 self.ahxB.set_gain(gain=64) #Configurar ganancia para el canal A self.ahxB.select_channel(channel='A') self.ahxB.set_reference_unit(1) #Resetear calibracion amplificador C2 self.asZeroB1 = self.ahxA.tare(1) #Tarar celda de carga self.ahxB.select_channel(channel='B') self.asZeroB2 = self.ahxA.tare(1) self.ahxB.set_offset(0) self.ahxB.select_channel(channel='A') print('\tConfigurado\n') ##Configurar amplificador Min Lev #Inicializa, resetea y tara Min Lev print( "\n________________\nConfigurando Amplificador Min Lev\n________________\n" ) print("\tReseteando...") self.ahxML.reset() #Resetear amplificador print('\tConfigurado') self.ahxML.set_gain(gain=64) #Configurar ganancia para el canal A self.ahxML.select_channel(channel='A') self.ahxML.set_reference_unit(1) #Calibrar celda A self.asZeroMin = self.ahxML.tare(1) #Tarar celda de carga self.ahxML.select_channel(channel='B') self.asZeroLev = self.ahxML.tare(1) self.ahxML.set_offset(0) self.ahxML.select_channel(channel='A') def encenderMotores(self, motor): #Metodo que activa los motores #Entrada: self-> Objeto propio de python # motor-> Selector del motor: # Con: Concentrado, Min: mineral Lev: levadura if (motor == 'Con'): if self.aConObj != 0: #Encendido motor Con velocidad = self.aConCrucero self.amConPWM.ChangeDutyCycle(velocidad) GPIO.output(self.amCon[0], 1) else: print "Masa es 0, concentrado no encendido" return if (motor == 'Min'): if self.aMinObj != 0: self.amMinPWM.ChangeFrequency(750) self.amMinPWM.ChangeDutyCycle(50) else: print "Masa igual a 0, mineral no encendido" return if (motor == 'Lev'): if self.aLevObj != 0: self.amLevPWM.ChangeFrequency(750) self.amLevPWM.ChangeDutyCycle(50) else: print "Masa igual a 0, levadura no encendido" return else: print("Motor no encontrado") def desacelerarMotores(self, motor): #Metodo que desacelera los motores if (motor == 'Con'): velocidad = self.aConMin self.amConPWM.ChangeDutyCycle(velocidad) return if (motor == 'Min'): self.amMinPWM.ChangeFrequency(200) self.amMinPWM.ChangeDutyCycle(50) return if (motor == 'Lev'): self.amLevPWM.ChangeFrequency(200) self.amLevPWM.ChangeDutyCycle(50) return else: print "Motor no encontrado" return def apagarMotores(self, motor, condicion): #Detener motores #Entradas: motor: Seleccion del motor deseado # Con -> Concentrado # Min -> Mineral # Lev -> Levadura # Condicion: Indica si el motor no fue apagado en la iteracion anterior if (motor == 'Con'): GPIO.output(self.amCon[0], 0) self.amConPWM.stop() if condicion: print("Concentrado apagado") return if (motor == 'Min'): self.amMinPWM.ChangeFrequency(50) self.amMinPWM.ChangeDutyCycle(0) if condicion: print("Mineral apagado") return if (motor == 'Lev'): self.amLevPWM.ChangeFrequency(50) self.amLevPWM.ChangeDutyCycle(0) if condicion: print("Levadura apagado") return else: print("Motor no encontrado") return def abrirCerrarValvulas(self, valvula, condicion): #Metodo de abrir y cerrar valvulas #Entradas: valvula: # Tolv -> Puerta de la tolva Romana # Min -> Compuerta del mineral # Lev -> Compuerta levadura # condicion: # 0 -> Valvula cerrada # 1 -> Valvula abierta if (valvula == 'Tolv'): GPIO.output(self.avTolva, condicion) return if (valvula == 'Min'): GPIO.output(self.avMineral, condicion) return if (valvula == 'Lev'): GPIO.output(self.avLevadura, condicion) return else: print("Valvula incorrecta") def cambiarSensibilidad(self, celda, sensibilidad): #Metodo para cambiar la sensibilidad de la celda de carga: (depuracion) #Formato de celda: 'Min','Lev','A','B' #Entradas: celda: A1, A2, B1, B2, Min, Lev print("Cambiando sensibilidad") if (celda == 'A1'): self.asA1 = sensibilidad self.axA.select_channel(channel='A') self.axA.set_scale_ratio(sensibilidad) return if (celda == 'A2'): self.asA2 = sensibilidad self.axA.select_channel(channel='B') self.axA.set_scale_ratio(sensibilidad) return if (celda == 'B1'): self.asB1 = sensibilidad self.axB.select_channel(channel='A') self.axB.set_scale_ratio(sensibilidad) return if (celda == 'B2'): self.asB2 = sensibilidad self.axB.select_channel(channel='B') self.axB.set_scale_ratio(sensibilidad) return if (celda == 'Min'): self.asMin = sensibilidad self.axML.select_channel(channel='A') self.axML.set_scale_ratio(sensibilidad) return if (celda == 'Lev'): self.asLev = sensibilidad self.axML.select_channel(channel='A') self.axML.set_scale_ratio(sensibilidad) return else: print("Celda no encontrada") def leerMineral(self, lecturas): #Leer el peso del mineral en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar #Mineral puerto A del sensor self.ahxML.select_channel(channel='A') masaMin = -( (self.ahxML.get_value(lecturas)) - self.asZeroMin) / self.asMin return masaMin def leerLevadura(self, lecturas): #Leer el peso del mineral en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar self.ahxML.select_channel(channel='B') masaLev = (self.ahxML.get_value(lecturas) - self.asZeroLev) / self.asLev return masaLev def leerConcentrado(self, lecturas): #Leer el peso del concentrado en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar self.ahxA.select_channel(channel='A') Conc1 = (self.ahxA.get_value(lecturas) - self.asZeroA1) self.ahxA.select_channel(channel='B') Conc2 = (self.ahxA.get_value(lecturas) - self.asZeroA2) self.ahxB.select_channel(channel='A') Conc3 = (self.ahxB.get_value(lecturas) - self.asZeroB1) self.ahxB.select_channel(channel='B') Conc4 = (self.ahxB.get_value(lecturas) - self.asZeroB1) Conc = (Conc1 + Conc2 + Conc3 + Conc4) / 2 * self.asConc #Nota: De momento se estan leyendo solo las celdas de los puertos A del concentrado # las celdas B presetan problemas de retardos en las lecturas return Conc def cerrarSteppers(self): #Metodo para apagar puertos de velocidad de los motores self.amMinPWM.stop() self.amLevPWM.stop() self.amConPWM.stop() def leer4Concentrado(self): #Metodo para leer por separado cada celda de carga del concentrado (depuracion) self.ahxA.select_channel(channel='A') Conc1 = (self.ahxA.get_value(1) - self.asZeroA1) self.ahxA.select_channel(channel='B') Conc2 = (self.ahxA.get_value(1) - self.asZeroA2) self.ahxB.select_channel(channel='A') Conc3 = (self.ahxB.get_value(1) - self.asZeroB1) self.ahxB.select_channel(channel='B') Conc4 = (self.ahxB.get_value(1) - self.asZeroB1) print("%d\t%d\t%d\t%d" % (Conc1, Conc2, Conc3, Conc4)) def leer4ConcentradoRaw(self, lecturas): #Metodo para leer cada celda del concentrado sin restar tara (depuracion) self.ahxA.select_channel(channel='A') Conc1 = (self.ahxA.get_value(lecturas)) self.ahxA.select_channel(channel='B') Conc2 = (self.ahxA.get_value(lecturas)) self.ahxB.select_channel(channel='A') Conc3 = (self.ahxB.get_value(lecturas)) self.ahxB.select_channel(channel='B') Conc4 = (self.ahxB.get_value(lecturas)) print("%d\t%d\t%d\t%d" % (Conc1, Conc2, Conc3, Conc4)) return def tararConcentrado(self, lecturas=30): #Metodo para tarar los amplificadores del concentrado self.ahxA.select_channel(channel='A') self.asZeroA1 = self.ahxA.get_value(lecturas) self.ahxA.select_channel(channel='B') self.asZeroA2 = self.ahxA.get_value(lecturas) self.ahxB.select_channel(channel='A') self.asZeroB1 = self.ahxB.get_value(lecturas) self.ahxB.select_channel(channel='B') self.asZeroB2 = self.ahxB.get_value(lecturas) def tararMineral(self, lecturas=30): #print self.ahxML.GAIN #Metodo para tarar mineral self.ahxML.select_channel(channel='A') self.asZeroMin = self.ahxML.get_value(lecturas) print("\tTara del mineral %d" % (self.asZeroMin)) def tararLevadura(self, lecturas=30): #Metodo para tarar levdura self.ahxML.select_channel(channel='B') self.asZeroMin = self.ahxML.get_value(lecturas) print("\tTara de la levadura %d" % (self.asZeroMin)) def filtradorTamizador(self, dato, alimento): #Metodo para filtrar y tamizar los valores de las celdas de carga #Se aplica un filtro de media movil con tres periodos, #luego se eliminan las lecturas que presenten cambios abruptos respecto de los valores predecesores. if alimento == 'Con': #Tamizar if ((abs(dato - self.peso_k_1[0])) > self.razon[0]): dato = self.peso_k_1[0] print "Tamizado" #Filtrar concentrado = (dato + self.peso_k_1[0] + self.peso_k_2[0]) / 3 self.peso_k_2[0] = self.peso_k_1[0] self.peso_k_1[0] = concentrado return concentrado if alimento == 'Min': #Tamizar if ((abs(dato - self.peso_k_1[1])) > self.razon[1]): dato = self.peso_k_1[1] print "Tamizado" #Filtrar mineral = (dato + self.peso_k_1[1] + self.peso_k_2[1]) / 3 self.peso_k_2[1] = self.peso_k_1[1] self.peso_k_1[1] = mineral return mineral if alimento == 'Lev': #Tamizar if ((abs(dato - self.peso_k_1[2])) > self.razon[2]): dato = self.peso_k_1[2] print "Tamizado" #Filtrar levadura = (dato + self.peso_k_1[2] + self.peso_k_2[2]) / 3 self.peso_k_2[2] = self.peso_k_1[2] self.peso_k_1[2] = levadura return levadura else: print("Alimento no encontrado") def inRangeCoerce(self, dato, minimo=0.0, maximo=100.0): #Metodo que limita los valores de una variable if dato > maximo: return maximo if dato < minimo: return minimo else: return dato def normalizarVelocidadConcentrado(self, dato): #Metodo para normalizar los valores del concentrado #Debido a la electronica, el valor de PWM permitido es entre 39 y 99. #Fuera de esos valores comienza a presentarse comportamiento erratico. dato = self.inRangeCoerce(dato, 0, 100) dato = (self.maxCon - self.minCon) / 100 * dato + self.minCon return dato #Metodos para resumir bloques de la secuencia def tararCeldas(self): #Metodo para tarar todas las cedas de carga. Permite no hacerlo desde el main self.leerMineral(30) print("________________\nTarando Concentrado\n________________\n") self.tararConcentrado(30) print("Zero A1 ", self.asZeroA1) print("Zero A2 ", self.asZeroA2) print("Zero B1 ", self.asZeroB1) print("Zero B2 ", self.asZeroB2) print("________________\nTarando Mineral\n________________\n") self.tararMineral(30) print("________________\nTarando Levadura\n________________\n") self.tararLevadura(30) self.tararMineral(30) def resetearCeldas(self): print("Reseteando celdas de carga concentrado") #Celdas del concentrado self.hxC1.turnOff() time.sleep(0.5) self.hxC1.turnOn() time.sleep(0.5) self.hxC1.turnOff() time.sleep(0.5) self.hxC1.turnOn() time.sleep(0.5) self.hxC2.turnOff() time.sleep(0.5) self.hxC2.turnOn() time.sleep(0.5) self.hxC3.turnOff() time.sleep(0.5) self.hxC3.turnOn() time.sleep(0.5) self.hxC4.turnOff() time.sleep(0.5) self.hxC4.turnOn() time.sleep(0.5) print("Reseteando celdas de carga Mineral y Levadura") self.hxML.turnOff() time.sleep(0.5) self.hxML.turnOn() time.sleep(0.5)
def __init__(self, title_word_length, content_word_length, title_char_length, content_char_length, fs_btm_tw_cw_length, fs_btm_tc_length, fs_idf_100_pl_length, class_num, word_embedding_matrix, char_embedding_matrix, word_idf_embedding_matrix, char_idf_embedding_matrix, optimizer_name, lr, metrics): # set attributes self.title_word_length = title_word_length self.content_word_length = content_word_length self.title_char_length = title_char_length self.content_char_length = content_char_length self.fs_btm_tw_cw_length = fs_btm_tw_cw_length self.fs_btm_tc_length = fs_btm_tc_length self.class_num = class_num self.word_embedding_matrix = word_embedding_matrix self.char_embedding_matrix = char_embedding_matrix self.optimizer_name = optimizer_name self.lr = lr self.metrics = metrics # Placeholder for input (title and content) title_word_input = Input(shape=(title_word_length,), dtype='int32', name="title_word_input") cont_word_input = Input(shape=(content_word_length,), dtype='int32', name="content_word_input") title_char_input = Input(shape=(title_char_length,), dtype='int32', name="title_char_input") cont_char_input = Input(shape=(content_char_length,), dtype='int32', name="content_char_input") # Embedding layer with K.tf.device("/cpu:0"): word_embedding_layer = Embedding(len(word_embedding_matrix), 256, weights=[word_embedding_matrix], trainable=True, name='word_embedding') title_word_emb = word_embedding_layer(title_word_input) cont_word_emb = word_embedding_layer(cont_word_input) char_embedding_layer = Embedding(len(char_embedding_matrix), 256, weights=[char_embedding_matrix], trainable=True, name='char_embedding') title_char_emb = char_embedding_layer(title_char_input) cont_char_emb = char_embedding_layer(cont_char_input) word_idf_embedding_layer = Embedding(len(word_idf_embedding_matrix), 1, weights=[word_idf_embedding_matrix], trainable=False, name='word_idf_embedding') title_word_idf_emb = word_idf_embedding_layer(title_word_input) cont_word_idf_emb = word_idf_embedding_layer(cont_word_input) char_idf_embedding_layer = Embedding(len(char_idf_embedding_matrix), 1, weights=[char_idf_embedding_matrix], trainable=False, name='char_idf_embedding') title_char_idf_emb = char_idf_embedding_layer(title_char_input) cont_char_idf_emb = char_idf_embedding_layer(cont_char_input) title_word_emb = concatenate([title_word_emb, title_word_idf_emb]) cont_word_emb = concatenate([cont_word_emb, cont_word_idf_emb]) title_char_emb = concatenate([title_char_emb, title_char_idf_emb]) cont_char_emb = concatenate([cont_char_emb, cont_char_idf_emb]) # Create a convolution + max pooling layer title_content_features = list() for win_size in range(1, 8): # batch_size x doc_len x embed_size title_content_features.append( GlobalMaxPooling1D()(Conv1D(100, win_size, activation='relu', padding='same')(title_word_emb))) title_content_features.append( GlobalMaxPooling1D()(Conv1D(100, win_size, activation='relu', padding='same')(cont_word_emb))) title_content_features.append( GlobalMaxPooling1D()(Conv1D(100, win_size, activation='relu', padding='same')(title_char_emb))) title_content_features.append( GlobalMaxPooling1D()(Conv1D(100, win_size, activation='relu', padding='same')(cont_char_emb))) # add btm_tw_cw features + btm_tc features fs_btm_tw_cw_input = Input(shape=(fs_btm_tw_cw_length,), dtype='float32', name="fs_btm_tw_cw_input") fs_btm_tc_input = Input(shape=(fs_btm_tc_length,), dtype='float32', name="fs_btm_tc_input") fs_btm_raw_features = concatenate([fs_btm_tw_cw_input, fs_btm_tc_input]) fs_btm_emb_features = Dense(1024, activation='relu', name='fs_btm_embedding')(fs_btm_raw_features) fs_btm_emb_features = Dropout(0.5, name='fs_btm_embedding_dropout')(fs_btm_emb_features) title_content_features.append(fs_btm_emb_features) title_content_features = concatenate(title_content_features) # add word share features fs_idf_100_pl_input = Input(shape=(fs_idf_100_pl_length,), dtype='float32', name="fs_idf_100_pl_input") preds_prior = Activation("sigmoid")(Scale()(fs_idf_100_pl_input)) # Full connection title_content_features = Dense(3600, activation='relu', name='fs_embedding')(title_content_features) title_content_features = Dropout(0.5, name='fs_embedding_dropout')(title_content_features) # Prediction preds_lh = Dense(class_num, activation='sigmoid')(title_content_features) preds = Multiply(name='prediction')([preds_prior, preds_lh]) self._model = Model([title_word_input, cont_word_input, title_char_input, cont_char_input, fs_btm_tw_cw_input, fs_btm_tc_input, fs_idf_100_pl_input], preds) if 'rmsprop' == optimizer_name: optimizer = optimizers.RMSprop(lr=lr) elif 'adam' == optimizer_name: optimizer = optimizers.Adam(lr=lr, beta_1=0.9, beta_2=0.999, epsilon=1e-08) else: optimizer = None self._model.compile(loss=binary_crossentropy_sum, optimizer=optimizer, metrics=metrics) self._model.summary()
def inicializarCeldas(self): #Inciar celdas de carga print( "\n________________\nIniciando celdas de carga\n________________\n" ) #Formato tupla: self.alsensorA = (dt,sck) #Celda de carga Concentrado C1 self.ahxC1 = Scale(self.alsensorC1[0], self.alsensorC1[1], 1, 80) #Celda de carga Concentrado C2 self.ahxC2 = Scale(self.alsensorC2[0], self.alsensorC2[1], 1, 80) #Celda de carga Concentrado C3 self.ahxC3 = Scale(self.alsensorC3[0], self.alsensorC3[1], 1, 80) #Celda de carga Concentrado C4 self.ahxC4 = Scale(self.alsensorC4[0], self.alsensorC4[1], 1, 80) #Celda de carga Levadura Mineral self.ahxML = Scale(self.alsensorML[0], selfalsensorML[1], 1, 80) #Inicializa, resetea y tara A print( "\n________________\nConfigurando Amplificador C1\n________________\n" ) #Resetear amplificador C1 self.ahxA.reset() self.ahxA.set_gain(gain=64) #Configurar ganancia para el canal A self.ahxA.select_channel(channel='A') self.ahxA.set_reference_unit(1) #Resetear calibracion amplificador C1 self.ahxA.select_channel(channel='B') self.ahxA.set_offset(0) self.ahxA.select_channel(channel='A') print('\tConfigurado\n') # -------------------------------------------------------------# ##Configurar amplificador C2 #Inicializa, resetea y tara amplificador C2 print( "\n________________\nConfigurando Amplificador C2\n________________\n" ) print("\tReseteando...") self.ahxA.reset() #Resetear amplificador C2 self.ahxB.set_gain(gain=64) #Configurar ganancia para el canal A self.ahxB.select_channel(channel='A') self.ahxB.set_reference_unit(1) #Resetear calibracion amplificador C2 self.asZeroB1 = self.ahxA.tare(1) #Tarar celda de carga self.ahxB.select_channel(channel='B') self.asZeroB2 = self.ahxA.tare(1) self.ahxB.set_offset(0) self.ahxB.select_channel(channel='A') print('\tConfigurado\n') ##Configurar amplificador Min Lev #Inicializa, resetea y tara Min Lev print( "\n________________\nConfigurando Amplificador Min Lev\n________________\n" ) print("\tReseteando...") self.ahxML.reset() #Resetear amplificador print('\tConfigurado') self.ahxML.set_gain(gain=64) #Configurar ganancia para el canal A self.ahxML.select_channel(channel='A') self.ahxML.set_reference_unit(1) #Calibrar celda A self.asZeroMin = self.ahxML.tare(1) #Tarar celda de carga self.ahxML.select_channel(channel='B') self.asZeroLev = self.ahxML.tare(1) self.ahxML.set_offset(0) self.ahxML.select_channel(channel='A')
import sys import time as t from time import sleep import datetime from CProbe import ConductivityProbe from TProbes import TemperatureProbes from Scale import Scale # Request Sensor Ports/Connection info C = ConductivityProbe(1, 115200) C.openC() T = TemperatureProbes(0, 115200) T.openC() S = Scale(0, 19200) S.openC() #Request File name for raw conductivty data filenameConductivity = str( input( "What would you like the file name for the raw conductivity data to be? " )) + ".csv" fileConductivity = open(filenameConductivity, "w+") print("Opened Conductivity file") fileScale.close() print("Closed Conductivity file") #Request File name for raw temperature data filenameTemperature = str( input(
class Dosificadora: def __init__(self): #Crear el objeto de la clase dosificadora ##Convenciones: axxxx: a significa atributo #Con-> Concentrado #Min-> Mineral #Lev-> Levadura #Puertos de control para las valvulas self.avTolva = 2 self.avMineral = 16 self.avLevadura = 27 #Puertos de asignacion de las celdas de carga self.alsensorC1 = (11,9) #Formato tupla: (dt,sck) self.alsensorC2 = (22,10) self.alsensorC3 = (24,23) self.alsensorC4 = (12,6) self.alsensorML = (19,13) #Puertos control de motores self.amCon = (7,8) #Formato tupla: (Encendido, velocidad) self.amMin = (20,21) #Formato tupla: (velocidad, sentido) self.amLev = (25,26) #Sensibilidades celdas de carga self.asMin = 1030.3320 self.asLev = 2563.3821 self.asC1 = 1 self.asC2 = 1 self.asC3 = 1 self.asC4 = 1 self.asConc = 53.2201 #Valores de Tara para cada celda de carga self.asZeroMin = 0 self.asZeroLev = 0 self.asZeroC1 = 0 self.asZeroC2 = 0 self.asZeroC3 = 0 self.asZeroC4 = 0 #Masas objetivo self.aConObj = 1 self.aMinObj = 1 self.aLevObj = 1 #Parametros del filtro tamizador y media movil self.aPeso_kbuffer = [[0.0,0.0,0.0,0.0,0.0,0.0],[0.0,0.0,0.0,0.0,0.0,0.0],[0.0,0.0,0.0,0.0,0.0,0.0]] #Formato lista [Con,Min,Lev] self.aSk = [0.0, 0.0,0.0 ] #Formato listas [Con,Min,Lev] self.aContador = [0, 0, 0 ] self.aDato_k_1 = [0, 0, 0 ] self.aX_k_1 = [0, 0, 0 ] #Otros atributos self.asText = "________________" #Separador de Textos self.minCon = 39.0 #Menor ciclo de PWM permitido para el concentrado self.maxCon = 99.0 #Mayor ciclo de PWM permitido para el concentrado self.razon = [60.0,50.0,10.0] #Mayor tasa de cambio permitida por el filtro tamizador #Formato lista [Con,Min,Lev] self.aConCrucero = 70.0 #Velocidad crucero motor Con self.aConMin = 60.0 #Minima velocidad para mover el motor #Parametros filtro Butterworth """self.xk = 0.0 self.xk_1 = 0.0 self.xk_2 = 0.0 self.xk_3 = 0.0 self.xk_4 = 0.0 self.yk = 0.0 self.yk_1 = 0.0 self.yk_2 = 0.0 self.yk_3 = 0.0 self.yk_4 = 0.0 """ #Control PI self.ik = 0.0 self.kp = 0.003625 self.ki = 0.0003 #0.00065 self.ref = 0.0 def __del__(self): #Metodo destructor de objeto nombre = self.__class__.__name__ print(nombre, "Destruido") def inicializarPuertos(self): #Encargado de iniciar el estado de los puertos de RPi. print("\n________________\nIniciando puertos\n________________\n") #Configurar puertos #Valvulas GPIO.setup(self.avTolva,GPIO.OUT) GPIO.setup(self.avMineral,GPIO.OUT) GPIO.setup(self.avLevadura,GPIO.OUT) #Motores #Concentrado GPIO.setup(self.amCon[0],GPIO.OUT) GPIO.setup(self.amCon[1],GPIO.OUT) #Mineral GPIO.setup(self.amMin[0],GPIO.OUT) GPIO.setup(self.amLev[0],GPIO.OUT) #Levadura GPIO.setup(self.amMin[1],GPIO.OUT) GPIO.setup(self.amLev[1],GPIO.OUT) #Colocar todos los puertos en BAJO "LOW". GPIO.output(self.avTolva,0) GPIO.output(self.avMineral,0) GPIO.output(self.avLevadura,0) GPIO.output(self.amCon[0],0) GPIO.output(self.amCon[1],0) GPIO.output(self.amMin[0],0) GPIO.output(self.amMin[1],0) GPIO.output(self.amLev[0],0) GPIO.output(self.amLev[1],0) def inicializarMotores(self): #Iniciar el estado de los motores #Frecuencia de PWM self.amMinPWM = GPIO.PWM(self.amMin[0],300) #Formato tupla: (velocidad, sentido) self.amLevPWM = GPIO.PWM(self.amLev[0],300) #Formato tupla: (velocidad, sentido) self.amConPWM = GPIO.PWM(self.amCon[1],250) ##Iniciar PWM en valor 0 self.amMinPWM.start(0) self.amLevPWM.start(0) self.amConPWM.start(0) def inicializarCeldas(self): #Inciar celdas de carga print("\n________________\nIniciando celdas de carga\n________________\n") #Formato tupla: self.alsensorA = (dt,sck) #Celda de carga Concentrado C1 self.ahxC1 = Scale(self.alsensorC1[0], self.alsensorC1[1], 1, 80) #Celda de carga Concentrado C2 self.ahxC2 = Scale(self.alsensorC2[0], self.alsensorC2[1], 1, 80) #Celda de carga Concentrado C3 self.ahxC3 = Scale(self.alsensorC3[0], self.alsensorC3[1], 1, 80) #Celda de carga Concentrado C4 self.ahxC4 = Scale(self.alsensorC4[0], self.alsensorC4[1], 1, 80) #Celda de carga Levadura Mineral self.ahxML = Scale(self.alsensorML[0], self.alsensorML[1], 1, 80) self.resetearCeldas() def encenderMotores(self,motor): #Metodo que activa los motores #Entrada: self-> Objeto propio de python # motor-> Selector del motor: # Con: Concentrado, Min: mineral Lev: levadura if (motor=='Con'): if self.aConObj!=0: #Encendido motor Con velocidad = 99#self.aConCrucero self.amConPWM.ChangeDutyCycle(velocidad) GPIO.output(self.amCon[0],1) else: print("Masa es 0, concentrado no encendido") return if (motor=='Min'): if self.aMinObj!=0: self.amMinPWM.ChangeFrequency(750) self.amMinPWM.ChangeDutyCycle(50) else: print("Masa igual a 0, mineral no encendido") return if (motor=='Lev'): if self.aLevObj!=0: self.amLevPWM.ChangeFrequency(750) self.amLevPWM.ChangeDutyCycle(50) else: print("Masa igual a 0, levadura no encendido") return else: print("Motor no encontrado") def desacelerarMotores(self,motor): #Metodo que desacelera los motores if(motor=='Con'): velocidad = self.aConMin self.amConPWM.ChangeDutyCycle(velocidad) return if(motor=='Min'): self.amMinPWM.ChangeFrequency(200) self.amMinPWM.ChangeDutyCycle(50) return if(motor=='Lev'): self.amLevPWM.ChangeFrequency(200) self.amLevPWM.ChangeDutyCycle(50) return else: print("Motor no encontrado") return def apagarMotores(self,motor,condicion): #Detener motores #Entradas: motor: Seleccion del motor deseado # Con -> Concentrado # Min -> Mineral # Lev -> Levadura # Condicion: Indica si el motor no fue apagado en la iteracion anterior if (motor=='Con'): GPIO.output(self.amCon[0],0) self.amConPWM.stop() if condicion: print("Concentrado apagado") return if (motor=='Min'): self.amMinPWM.ChangeFrequency(50) self.amMinPWM.ChangeDutyCycle(0) if condicion: print("Mineral apagado") return if (motor=='Lev'): self.amLevPWM.ChangeFrequency(50) self.amLevPWM.ChangeDutyCycle(0) if condicion: print("Levadura apagado") return else: print("Motor no encontrado") return def abrirCerrarValvulas(self,valvula,condicion): #Metodo de abrir y cerrar valvulas #Entradas: valvula: # Tolv -> Puerta de la tolva Romana # Min -> Compuerta del mineral # Lev -> Compuerta levadura # condicion: # 0 -> Valvula cerrada # 1 -> Valvula abierta if (valvula=='Tolv'): GPIO.output(self.avTolva,condicion) return if (valvula =='Min'): GPIO.output(self.avMineral,condicion) return if (valvula =='Lev'): GPIO.output(self.avLevadura,condicion) return else: print("Valvula incorrecta") def cambiarSensibilidad(self,celda,sensibilidad): #Metodo para cambiar la sensibilidad de la celda de carga: (depuracion) #Formato de celda: 'Min','Lev','A','B' #Entradas: celda: A1, A2, B1, B2, Min, Lev print("Cambiando sensibilidad") if (celda=='A1'): self.asA1 = sensibilidad self.axA.select_channel(channel='A') self.axA.set_scale_ratio(sensibilidad) return if (celda=='A2'): self.asA2 = sensibilidad self.axA.select_channel(channel='B') self.axA.set_scale_ratio(sensibilidad) return if (celda=='B1'): self.asB1 = sensibilidad self.axB.select_channel(channel='A') self.axB.set_scale_ratio(sensibilidad) return if (celda=='B2'): self.asB2 = sensibilidad self.axB.select_channel(channel='B') self.axB.set_scale_ratio(sensibilidad) return if (celda=='Min'): self.asMin = sensibilidad self.axML.select_channel(channel='A') self.axML.set_scale_ratio(sensibilidad) return if (celda=='Lev'): self.asLev = sensibilidad self.axML.select_channel(channel='A') self.axML.set_scale_ratio(sensibilidad) return else: print("Celda no encontrada") def leerMineral(self,lecturas): #Leer el peso del mineral en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar #Mineral puerto A del sensor masaMin = -((self.ahxML.weighOnce())-self.asZeroMin)/self.asMin return masaMin def leerLevadura(self,lecturas): #Leer el peso del mineral en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar masaLev = (self.ahxML.weighOnce()-self.asZeroLev)/self.asLev return masaLev def leerConcentrado(self,lecturas): #Leer el peso del concentrado en gramos. #Entrada: lecturas -> Cantidad de veces que el sensor se lee antes de retornar Conc1 = self.ahxC1.weighOnce()-self.asZeroC1 Conc2 = self.ahxC2.weighOnce()-self.asZeroC2 Conc3 = self.ahxC3.weighOnce()-self.asZeroC3 Conc4 = -(self.ahxC4.weighOnce()-self.asZeroC4) Conc = (Conc1+Conc2+Conc3+Conc4)/(4*self.asConc) #Nota: De momento se estan leyendo solo las celdas de los puertos A del concentrado # las celdas B presetan problemas de retardos en las lecturas return float(Conc) def cerrarSteppers(self): #Metodo para apagar puertos de velocidad de los motores self.amMinPWM.stop() self.amLevPWM.stop() self.amConPWM.stop() def leer4Concentrado(self): #Metodo para leer por separado cada celda de carga del concentrado (depuracion) Conc1 = self.ahxC1.weighOnce()-self.asZeroC1 Conc2 = self.ahxC2.weighOnce()-self.asZeroC2 Conc3 = self.ahxC3.weighOnce()-self.asZeroC3 Conc4 = -(self.ahxC4.weighOnce()-self.asZeroC4) print("%d\t%d\t%d\t%d"%(Conc1,Conc2,Conc3,Conc4)) def leer4ConcentradoRaw(self,lecturas): #Metodo para leer cada celda del concentrado sin restar tara (depuracion) Conc1 = self.ahxC1.weighOnce() Conc2 = self.ahxC2.weighOnce() Conc3 = self.ahxC3.weighOnce() Conc4 = self.ahxC4.weighOnce() print("%d\t%d\t%d\t%d"%(Conc1,Conc2,Conc3,Conc4)) def tararConcentrado(self,imprimir= False,lecturas=30): #Metodo para tarar los amplificadores del concentrado if imprimir: print("Tarando") self.asZeroC1 = self.ahxC1.weigh(80) self.asZeroC2 = self.ahxC2.weigh(80) self.asZeroC3 = self.ahxC3.weigh(80) self.asZeroC4 = self.ahxC4.weigh(80) if imprimir: print("Tara del concentrado\n%d\t%d\t%d\t%d\t"% (self.asZeroC1,self.asZeroC2,self.asZeroC3,self.asZeroC4)) def tararMineral(self,printVal=False,lecturas=30): #Metodo para tarar mineral self.asZeroMin = self.ahxML.tare(lecturas,False) if printVal: print("\tTara del mineral %d"%(self.asZeroMin)) def tararLevadura(self,printVal=False,lecturas = 30): #Metodo para tarar levdura self.asZeroMin = self.ahxML.tare(lecturas,False) if printVal: print("\tTara de la levadura %d"%(self.asZeroMin)) def filtradorTamizador(self,dato,alimento): #Metodo para filtrar y tamizar los valores de las celdas de carga #Se aplica un filtro de media movil con tres periodos, #luego se eliminan las lecturas que presenten cambios abruptos respecto de los valores predecesores. if alimento == 'Con': #Tamizar if ((abs(dato-self.aDato_k_1[0]))>self.razon[0]): datoT = self.aX_k_1[0] #print("Tamizado") else: datoT = dato #Filtrar self.aSk[0] = self.aSk[0]-self.aPeso_kbuffer[0][self.aContador[0]]+datoT concentrado = self.aSk[0]/5 self.aPeso_kbuffer[0][self.aContador[0]] = datoT #Mover el contador y retrasar las muestras self.aContador[0] += 1 self.aDato_k_1[0] = dato self.aX_k_1[0] = datoT if self.aContador[0] == 5: self.aContador[0] = 0 return concentrado if alimento == 'Min': #Tamizar if ((abs(dato-self.peso_k_1[1]))>self.razon[1]): dato = self.peso_k_1[1] print("Tamizado") #Filtrar mineral = (dato+self.peso_k_1[1]+self.peso_k_2[1])/3 self.peso_k_2[1] = self.peso_k_1[1] self.peso_k_1[1] = mineral return mineral if alimento == 'Lev': #Tamizar if ((abs(dato-self.peso_k_1[2]))>self.razon[2]): dato = self.peso_k_1[2] print("Tamizado") #Filtrar levadura = (dato+self.peso_k_1[2]+self.peso_k_2[2])/3 self.peso_k_2[2] = self.peso_k_1[2] self.peso_k_1[2] = levadura return levadura else: print("Alimento no encontrado") def inRangeCoerce(self,dato, minimo = 0.0, maximo = 100.0): #Metodo que limita los valores de una variable if dato > maximo: return maximo if dato < minimo: return minimo else: return dato def normalizarVelocidadConcentrado(self,dato): #Metodo para normalizar los valores del concentrado #Debido a la electronica, el valor de PWM permitido es entre 39 y 99. #Fuera de esos valores comienza a presentarse comportamiento erratico. dato = self.inRangeCoerce(dato,0,100) dato = (self.maxCon-self.minCon)/100 * dato + self.minCon return dato #Metodos para resumir bloques de la secuencia def tararCeldas(self): #Metodo para tarar todas las cedas de carga. Permite no hacerlo desde el main self.leerMineral(80) print("________________\nTarando Concentrado\n________________\n") self.tararConcentrado(80,True) print("Zero A1 ",self.asZeroC1) print("Zero A2 ",self.asZeroC2) print("Zero B1 ",self.asZeroC3) print("Zero B2 ",self.asZeroC4) print("________________\nTarando Mineral\n________________\n") self.tararMineral(80) print("________________\nTarando Levadura\n________________\n") self.tararLevadura(80) def resetearCeldas(self): print("Reseteando celdas de carga concentrado") #Celdas del concentrado self.ahxC1.turnOff() time.sleep(0.5) self.ahxC1.turnOn() time.sleep(0.5) self.ahxC1.turnOff() time.sleep(0.5) self.ahxC1.turnOn() time.sleep(0.5) self.ahxC2.turnOff() time.sleep(0.5) self.ahxC2.turnOn() time.sleep(0.5) self.ahxC3.turnOff() time.sleep(0.5) self.ahxC3.turnOn() time.sleep(0.5) self.ahxC4.turnOff() time.sleep(0.5) self.ahxC4.turnOn() time.sleep(0.5) print("Reseteando celdas de carga Mineral y Levadura") self.ahxML.turnOff() time.sleep(0.5) self.ahxML.turnOn() time.sleep(0.5) def filtroButterWorth(self,xk): self.yk = (0.7769*self.xk_1 #- 0.007079*self.xk_2 + 0.2231*self.yk_1) #- 0.000002 * self.yk_2) #Retrasar muestras #self.xk_4 = self.xk_3 #self.xk_3 = self.xk_2 self.xk_2 = self.xk_1 self.xk_1 = xk #self.yk_4 = self.yk_3 #self.yk_3 = self.yk_2 self.yk_2 = self.yk_1 self.yk_1 = self.yk return self.yk def controlPI(self,xk): if ((xk +250) < self.aConObj): ek = self.aConObj-xk PI = ek*self.kp+self.ki*self.ik PIl = self.inRangeCoerce(PI,0,99) self.amConPWM.ChangeDutyCycle(PIl) self.ik = ek*0.1+self.ik return PI else: self.apagarMotores("Con",False) #Anti Windup self.inRangeCoerce(self.ik,-100/self.ki,100/self.ki)