Beispiel #1
0
 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
Beispiel #2
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)
Beispiel #3
0
 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)
Beispiel #7
0
 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()
Beispiel #8
0
    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
Beispiel #10
0
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
Beispiel #12
0

@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)
Beispiel #13
0
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
Beispiel #14
0
 def testScale(self):
     for S, R in self.KnownScale:
         P = Scale(S).ToIntervalPattern()
         self.assertEqual(P, R)
         print(S, "to interval pattern yields", R)
Beispiel #15
0
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
Beispiel #16
0
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
Beispiel #18
0
#! /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")
Beispiel #19
0
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)
Beispiel #20
0
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
Beispiel #21
0
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()
Beispiel #22
0
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:
Beispiel #23
0
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
Beispiel #24
0
 def InicializarCeldasML(self):
     #Inicializa las celdas de carga del mineral Levadura
     self.ahxML = Scale(self.alsensorML[0], self.alsensorML[1], 1, 80)
Beispiel #25
0
 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)
Beispiel #26
0
    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)
Beispiel #27
0
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()
Beispiel #28
0
    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
Beispiel #29
0
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)
Beispiel #30
0
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)
Beispiel #31
0
    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()
Beispiel #32
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')
Beispiel #33
0
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)