4. Uwagi

  • Regulator rozmyty musi działać w pętli sprzężenia zwrotnego, w każdym kroku symulacji musi wypracować odpowiednie sterowanie. Przygotowany symulator modeluje działanie obiektu (procesu) jak i układu regulacji.
  • Struktura wewnętrzna symulatora składa się ze ścieżek przetwarzania (Path), które z kolei zbudowane są z poszczególnych bloków funkcyjnych (pochodne klasy Block). Uproszona wersja struktury, konieczna do zrozumienia jak zaimplementować i uruchomić nowy blok funkcyjny, została przedstawiona na rysunku poniżej. Szczególnym rodzajem bloku funkcyjnego jest podsystem (Subsystem), który zbudowany jest z określonych składowych bloków funkcyjnych. Poszczególne podsystemy zdefiniowane są w postaci odrębnych klas w bibliotece szablonów (templates.py).

    Uproszczony schemat struktury wewnętrznej symulatora
    Uproszczony schemat struktury wewnętrznej symulatora
  • Przykładem utworzenia podsystemu użytkownika jest szablon regulatora PID – klasa PID (w templates.py). Uproszczony listing klasy pokazano poniżej. Wszystkie elementy składowe regulatora PID i ich konfiguracja zawarte są w konstruktorze __init__().

    Listing: Definicja klasy PID (skrót)
    
    """
        Implementation of classical PID controller.
    """
    class PID(Subsystem):
        """
            @param _name unique (in parent object) block name
            @param _inputs required inputs ([Value, ...]): SP [m], PV [m], mode, cv_man
            @param _tp sampling time
        """
        def __init__(self, _name, _inputs, _tp):
            super().__init__(_name, _inputs)
    
            # Define processing structure in the form of interconnected subblocks
            # - add function block
            sp_filt = self.add_block( FirstOrderInertia('sp_filt', _tp, 1, 0.1) )
            # - add block input and connect to subsystem input
            sp_filt.add_input(self.input(0))
    	...
            # Define subsystem outputs (add and connect to block output): CV [%], e
            self.add_output(cv.output(0))
            self.add_output(e.output(0))
                

    Użytkownik odpowiedzialny jest za:

    • dodanie poszczególnych bloków składowych,
    • podłączenie wejść bloków do wejść podsystemu lub innych bloków,
    • zdefiniowanie niezbędnych wyjść podsystemu.

    Ważne jest aby nowy regulator rozmyty miał te same wyjścia (i w tej samej kolejności) co regulator klasyczny PID (czyli CV i e, dodatkowo dodano wyjście de) gdyż ma go zastąpić, a inne bloki korzystają z wyjścia regulatora.

  • Przykładem zastosowania ścieżki jest ścieżka modułu sterowania (controller_sim) zdefiniowana w symulatorze. Ze względu na podłączenie kolejnych bloków do wyjścia regulatora zastosowano tą samą nazwę bloku regulatora rozmytego co regulatora PID.

    Listing: Fragment konstruktora TtsPidSim.__init__() związany z definiowaniem podsystemu sterowania
    
    # Controller path
    #   working with tpcont = tpsim * pr.control (default=0.2 [s])
    controller_sim = Path('controller_sim', self.pr['control'])
    self.paths['controller_sim'] = controller_sim
    
    #   PV measurement. Block also used to make control feedback.
    pv_noise = controller_sim.add_block( Random('pv_noise', 0, 0.0013333333333) )
    pv_measure = controller_sim.add_block( SumDiff('pv_measure', [1, 1]) )
    pv_measure.add_input(pv_noise.output(0))
    
    controller = controller_sim.add_block( PID('controller', [sp.output(0), pv_measure.output(0), cvman.output(0)], self.tp*self.pr['control']) )
    #   add ins/outs: controller parameters
    self.add_in_var('kp', controller.blocks['kp'].const)
    self.add_in_var('Ti', controller.blocks['ti'].const)
    self.add_in_var('Td', controller.blocks['td'].const)
    self.add_in_var('Bias', controller.blocks['bias'].const)
    self.add_in_var('Ienable', controller.blocks['i_enable'].const)
    self.add_in_var('Denable', controller.blocks['d_enable'].const)
    self.add_in_var('PIDmode', controller.blocks['mode'].const)
    
    #   - monitoring variables: CV, PV, e
    self.add_out_var('CV', controller.output(0))
    self.add_out_var('PV', pv_measure.output(0))
    self.add_out_var('e', controller.output(1))
                
  • Dodanie nowej struktury przetwarzania, takiej jak regulator rozmyty, można zrealizować poprzez wykorzystanie jednej lub kilku z następujących możliwości:

    • dodanie nowego bloku funkcyjnego – wygodne rozwiązanie do realizacji określonych cyklicznych obliczeń na zestawie sygnałów wejściowych i wyznaczających zestaw sygnałów wyjściowych, np. implementacja modelu rozmytego o 2 wejściach i jednym wyjściu,
    • dodanie nowej ścieżki – wygodne rozwiązanie do realizacji złożonego przetwarzania składającego się z kilku bloków funkcyjnych (dostępnych w symulatorze lub dodanych przez użytkownika),
    • modyfikacja metody simulation_step() symulatora - nie jest to zalecane podejście,
    • realizacja przetwarzania poza symulatorem, w tym przypadku symulator działa bez regulatora, a wymiana danych następuje w każdym kroku poprzez zdefiniowane wejścia/wyjścia symulatora - nie jest to zalecane podejście.