Next                   Up                       Back                       Contents

Επόμενο:ΠΑΡΑΛΛΗΛΗ ΤΑΞΙΝΟΜΗΣΗ Πάνω: Διάφορα Προβλήματα Παράλληλου Προγραμματισμού Πίσω: ΟΙ ΓΕΥΜΑΤΙΖΟΝΤΕΣ ΦΙΛΟΣΟΦΟΙ


 

ΣΥΣΤΗΜΑ ΚΕΝΤΡΙΚΗΣ ΘΕΡΜΑΝΣΗΣ

 

Το πρόγραμμα που ακολουθεί αποτελεί παράδειγμα συγχρονικής προσομοίωσης ενός πολυεργασιακού συστήματος ελέγχου διεργασιών (process control). Πρόκειται γιά ένα σύστημα κεντρικής θέρμανσης. Θα μπορούσε να είναι ένα σύστημα χημικής βιομηχανίας ή ένα σύστημα διοίκησης παραγωγής κ.ο.κ.
Το σχήμα που ακολουθεί παρουσιάζει το διάγραμμα ενός συστήματος κεντρικής θέρμανσης ενός σπιτιού. Το σπίτι έχει πέντε δωμάτια και το κάθε δωμάτιο έχει ένα θερμαντικό σώμα (room radiator) το οποίο ελέγχεται από έναν θερμοστάτη. Ο κάθε θερμοστάτης μπορεί να ελεγχθεί ξεχωριστά μέσω ρυθμιστή (knob). Οι ρυθμιστές είναι συνδεμένοι με τον κεντρικό διακόπτη (central.switch) που δίνει εντολές και στον καυστήρα (boiler) του συστήματος κεντρικής θέρμανσης. Το σύστημα σωλήνωσης (pipes) συνδέει τον καυστήρα με τα θερμαντικά σώματα στη σειρά, έτσι ώστε δημιουργείται ένας δακτύλιος που καταλήγει πάλι στον καυστήρα. Η εξωτερική θερμοκρασία (ο καιρός) διαδίδεται μέσω των παραθύρων κάθε δωματίου και γίνεται αντιληπτή από τον τοπικό θερμοστάτη κάθε δωματίου. Τελικά φυσικά υπάρχει ο ανθρώπινος παράγοντας που έχει τον έλεγχο του χρονοδιακόπτη και των θερμοστατών. Επιπλέον, στην προσομοίωση ο άνθρωπος γίνεται και λίγο 'θεός' καθορίζοντας τον καιρό.

image

 

 

Ο κώδικας του προγράμματος είναι ο ακόλουθος:

 

 

Program Susthma_Kentrikhs_Thermanshs; 
   Const 
     number_of_rooms=5; 
     max_boil_temp=8500;min_boil_temp=500;boil_tmp_inc=100; 
     max_temp=3500;min_temp=500;start_temp=550; 
     max_setting=9;min_setting=0;start_setting=5; 
     higher=1;lower=-1;incr=1; 
     interval=10; 
     margin=300;dissip=10;warm_up=15;size=5; 
     sett_step=300;    (*(max_temp-min_temp)div(max_setting-min_setting+1)*) 
     off_heat=0;on_heat=1; 
     false=0;true=1; 
     forever = 32000; 
     delay_const=1; 

   Type 
     chan=channel of integer; 
     Pin= array[0..number_of_rooms] of chan; 

  Var 
     Boiler_Switch,Boiler_Control,God:chan; 
     temp1,temp2:chan; 
     Pipes:array[0..number_of_rooms+1] of chan; 
     Knobs,Room_Windows:Pin; 
     Switch,r:integer; 

 

Η διεργασία αυτή είναι μια γεννήτρια τυχαίων αριθμών.

procedure random (r_x, r_n: real; var rnd: integer); 
     const 
       r_mod = 27296.0; 
       r_mult = 4525.0; 
      range = 10; 
     offset = 3; 
     var 
       r_seed: real; 
       x, n: integer; 

     begin 
       x := round(r_x + offset) mod range; 
       n := round(r_n + offset) mod range; 
       r_seed := x; 
       r_seed := r_seed * r_mult; 
       r_seed := r_seed / r_mod; 
      rnd := round(n * r_seed) mod range; 
    end; 

 

Η διεργασία αυτή προκαλεί απλά καθυστέρηση- δε κάνει τίποτα.

 procedure delay(times : integer); 
     var 
       i : integer; 
   begin 
     for i := 1 to times do 
   end; 

 

Η διεργασία που αρχικοποιεί την τιμή της heating;

  Procedure init_switch(var heating:integer); 
  
     begin 
        heating:=false; 
     end; 

 

Η διεργασία heat_is_on εκτελείται όταν ανοίξουμε τον κεντρικό διακόπτη.

   Procedure heat_is_on(var heating:integer;var start_heating:chan); 

     begin 
       if  heating=false then 
       begin 
          heating:=true; 
          start_heating:=true; 
       end; 
     end; 

 

Αντίθετα η παρακάτω διεργασία εκτελείται όταν κλείσουμε τον κεντρικό διακόπτη.

   Procedure heat_is_off(var heating:integer;var start_heating:chan); 
  
     begin 
          heating:=false; 
          start_heating:=false; 
     end; 

 

Η διεργασία Central_Switch είναι η διεργασία κεντρικού διακόπτη, η οποία δέχεται εντολές από το χειριστή (άνθρωπο) μέσω του καναλιού on_off_switch το οποίο κανονίζει αν το σύστημα είναι ανοικτό ή κλειστό. Αντίστοιχα στέλνει εντολή στον καυστήρα μέσω του καναλιού start_heating.

Procedure Central_Switch(Var on_off_switch,start_heating:chan); 
     Const 
       off_heat=0;on_heat=1; 
     Var 
       switch,temp,heating:integer; 
  
      begin 
       while clock < forever do 
       begin 
          init_switch(heating); 
          if on_off_switch? then 
          begin 
              switch:=on_off_switch; 
              if switch=on_heat then heat_is_on(heating,start_heating) 
              else if switch=off_heat then heat_is_off(heating,start_heating); 
          end; 
       end; 
    end; 

 

Αρχικοποίηση της θερμοκρασίας και της κατάστασης του boiler.

   Procedure init_boiler(var boiler_on,heating,temp:integer); 
  
     begin 
       temp:=start_temp; 
       boiler_on:=false; 
       heating:=false; 
     end; 

 

Η διεργασία αυτή ελέγχει τον καυστήρα και ανάλογα τον θέτει η λειτουργία ή τον κλείνει, πράγμα που εξαρτάται από την επικοινωνία του με τον κεντρικό διακόπτη.

   Procedure boil_contr(var on_signal,boiler_on,heating:integer); 
  
     begin 
       if  (on_signal=true) and  (heating=false) then 
       begin 
          boiler_on:=true; 
          heating:=true; 
       end 
       else if  (on_signal=false) and (heating=true) then 
       begin 
           boiler_on:=false; 
           heating:=false; 
       end; 
     end; 

 

Εδώ περιγράφεται η θέρμανση του νερού, όπου υπάρχουν τέσσερις καταστάσεις. Αν ο κεντρικός διακόπτης είναι ανοιχτός (heating = true) ο καυστήρας λειτουργεί ανεβάζονται βαθμιαία τη θερμοκρασία του νερού του κυκλώματος μέχρι να φτάσει στη μέγιστη θερμοκρασία (max_boil_temp). Όταν το νερό φθάσει τη μέγιστη θερμοκρασία  ο καυστήρας σταματά (boiler_on = false) και το νερό κυκλοφορεί μέσα από τα ψυχρότερα στρώματα. Όταν η θερμοκρασία φτάσει στη ελάχιστη θερμοκρασία (min_boil_temp) τότε ο καυστήρας ανατίθεται ξανά σε λειτουργία. Φυσικά στην περίπτωση που ο κεντρικός διακόπτη είναι κλειστός τότε η θερμοκρασία του νερού παραμένει αμετάβλητη.

   Procedure boiler_temp(temp: integer; var boiler_on, heating : integer; 
                        var initial_temp: chan); 
  
     begin 
       if (heating=true) and (boiler_on=true) then 
       begin 
          if (temp+boil_tmp_inc)>max_boil_temp then 
          begin 
             writeln('exei ftasei sthn anwterh thermokrasia-stamata proswrina'); 
             boiler_on:=false; 
             initial_temp:=max_boil_temp; 
          end 
          else begin 
            initial_temp:=temp+boil_tmp_inc; 
            writeln('h thermansh synexizetai'); 
            writeln('h thermokrasia einai',temp+boil_tmp_inc); 
            writeln; 
         end; 
       end 
       else if (heating=true) and (boiler_on=false) then 
       begin 
          if temp < min_boil_temp then 
            boiler_on:=true; 
            writeln('exei ftasei sthn katwterh thermokrasia-arxizei th thermansh'); 
            initial_temp:=temp; 
       end 
       else initial_temp:=temp; 
     end; 

 

Αυτή είναι η βασική διεργασία του καυστήρα, η οποία δέχεται είσοδο από τον κεντρικό διακόπτη, καθώς και από το σωλήνα που κλείνει το κύκλωμα των θερμαντικών σωμάτων.

   Procedure Boiler(var control,initial_temp,final_temp:chan); 
     Var 
       on_signal,boiler_on,heating,temp:integer; 
  
     begin 

        init_boiler(boiler_on,heating,temp); 
        while clock < forever do 
        begin 
          if control? then on_signal := control; 
          while on_signal = true do 
          begin 
            if control? then on_signal := control; 
            boil_contr(on_signal,boiler_on,heating); 
            if final_temp? then 
                temp := final_temp; 
            boiler_temp(temp, boiler_on,heating,initial_temp); 
          end; 
        end; 
    end; 

 

Η διεργασία αρχικοποίησης των ρυθμίσεων του θερμοστάτη στα δωμάτια, καθώς και της θερμοκρασίας μέσα και έξω από το δωμάτιο:

 Procedure init_room(var setting,room_temp,outside_temp,is_on:integer); 
  
     begin 
       setting:=start_setting; 
       room_temp:=start_temp; 
       outside_temp:=start_temp; 
       is_on:=false; 
    end; 

 

Εδώ υλοποιείται η ρύθμιση της κλίμακας του θερμοστάτη με αυξομειώσεις κατά μια θέση της κλίμακας από 0 εώς 9.

   Procedure adjust_knob(turn:integer;var setting:integer); 
  
     begin 
       if (turn=higher) and ((setting+incr)<=max_setting) then 
       begin 
         setting:=setting+incr; 
       end 
       else if (turn=lower) and ((setting-incr)>=min_setting) then 
       begin 
          setting:=setting-incr; 
       end; 
     end; 

 

Στην διεργασία operation ελέγχεται σε τακτά διαστήματα (interval) η θερμοκρασία του δωματίου. Αν αυτή είναι χαμηλότερη από τη ρύθμιση του θερμοστάτη τότε το θερμαντικό σώμα αρχίζει και λειτουργεί. Το δωμάτιο θερμαίνεται ανάλογα με το μέγεθός του (size). Η θερμοκρασία του δωματίου αυξάνει μέχρι την επιθυμητή οπότε και σταματά να απορροφά νέα θερμοκρασία

  Procedure operation(var room_temp,outside_temp,water_temp,is_on,setting:integer; 
var out:chan); 
     var 
       i,old_temp,gain,rnd:integer; 
  
     begin 
       random(clock,seqtime,rnd); 
       for i:=1 to rnd do 
    delay(delay_const); 
       old_temp:=room_temp; 
       room_temp:=room_temp+((outside_temp-room_temp) div dissip); 
       if is_on=true then 
       begin 
          gain:=(water_temp-room_temp) div warm_up; 
          out:=water_temp-gain; 
          room_temp:=room_temp+((water_temp-room_temp) div size); 
          if room_temp>((sett_step*setting)+min_temp+margin) then 
          begin 
            is_on:=false; 
          end; 
        end 
        else 
        begin 
           out:=water_temp; 
           if room_temp < (((sett_step*setting)+min_temp)-margin) then 
           begin 
             is_on:=true; 
           end; 
        end; 
      end; 

 

Η διεργασία του δωματίου αντιστοιχεί στο συνδυασμό του θερμαντικού σώματος με τον τοπικό θερμοστάτη και το ρυθμιστή του. Η διεργασία δέχεται τρεις εισόδους, δηλαδή τη θερμοκρασία του νερού που εισέρχεται στο θερμαντικό σώμα(water_temp), την εξωτερική θερμοκρασία του δωματίου (outside_temp) και την μεταβολή της ρύθμισης του θερμοστάτη (turn).

  Procedure Room(n:integer;Var control_knob,in,out,outside:chan); 
     var 
       water_temp,turn,is_on,setting,room_temp,outside_temp:integer; 

     begin 

       init_room(setting,room_temp,outside_temp,is_on); 
       while clock < forever do 
       begin 
         if control_knob? then 
         begin 
            turn:=control_knob; 
            adjust_knob(turn,setting); 
         end; 
         water_temp:=in; 
         operation(room_temp,outside_temp,water_temp,is_on,setting,out); 
         end; 
     end; 

 

Έλεγχος του κεντρικού διακόπτη από το χειριστή:

   Procedure control_interface(var heater:chan); 
     var 
       ch:char; 
  
     begin 
        writeln; 
        writeln('dwse 1 gia na anoikseis to geniko diakopth kai 0 gia na ton kleiseis'); 
        readln(ch); 
        if ch='0' then heater:=off_heat 
        else if ch='1' then heater:=on_heat 
        else writeln('lathos eisodos'); 
     end; 

 

Έλεγχος των ρυθμιστών των θερμοστατών των δωματίων:

   Procedure radiator_interface(var radiator_knobs:Pin); 
     var 
       n:integer; 
       ch:char; 
  
     begin 
       writeln('dwse ton arithmo toy dwmatioy gia allagh toy thermostash'); 
       writeln; 
       readln(n); 
       if (n>=0) and (n<=number_of_rooms) then 
       begin 
         writeln('dwse h gia anebasma toy thermostath kai l gia katebasma'); 
         writeln; 
         readln(ch); 
         if ch='h' then radiator_knobs[n]:=higher 
         else if ch='l' then radiator_knobs[n]:=lower 
         else writeln('lathos eisodos'); 
       end; 
    end; 

 

Προς χάριν της προσομοίωσης εδώ ο χειριστής ελέγχει και την εξωτερική θερμοκρασία.

   Procedure weat_interface(var weather_chan:chan); 
     var 
       n:integer; 
  
     begin 
       writeln('dwse thn e3wterikh thermokrasia,metaksi -5 kai 45'); 
       readln(n); 
       if (n >(-5)) and (n ‹ 45) then  weather_chan:=n*100 
       else writeln('lathos eisodos'); 
     end; 

 

Η διεργασία του χειριστή είναι ουσιαστικά η διεπαφή εισόδου του προγράμματος. Είναι ένα απλό σύστημα μενού που οδηγείται με τη πληκτρολόγηση χαρακτήρων ή αριθμών.

   Procedure Human(Var heater:chan;Var radiator_knobs:Pin;Var weather_chan:chan); 
     var 
       ch:char; 

     begin 
       while ch < >'*' do 
       begin 
           writeln; 
           writeln('dwse c gia elegxo kentrikoy diakopth,r gia elegxo twn rythmistwn'); 
           writeln('twn thermostatwn twn dwmatiwn,w gia elegxo ths ekswterikhs thermokrasias'); 
           writeln(' kai * gia termatismo'); 
           writeln; 
          readln(ch); 
          if ch='c'then control_interface(heater) 
          else if ch='r' then radiator_interface(radiator_knobs) 
          else if ch='w' then weat_interface(weather_chan) 
          else if ch='*' then writeln('dwsate tetrmatismo') 
          else writeln('lathos eisodos'); 
       end; 
     end; 

 

Αρχικοποίηση της θερμοκρασίας του καιρού.

   Procedure init_weather(var new_temp:integer); 

     begin 
       new_temp:=start_temp; 
     end; 

 

Εδώ απλά η εξωτερική θερμοκρασία διαδίδεται προς όλα τα δωμάτια.

   Procedure new_weather(new_temp:integer;var Windows:Pin); 
     var 
       r:integer; 

     begin 
       for r:=0 to number_of_rooms do 
       Windows[r]:=new_temp; 
     end; 

 

Η κύρια διεργασία του καιρού:

   Procedure Weather(Var Command:chan;Var Windows:Pin); 
     var 
       new_temp:integer; 
  
     begin 

       init_weather(new_temp); 
       while clock < forever do 
       begin 
         if command? then 
         begin 
            new_temp := command; 
            new_weather(new_temp,Windows); 
         end; 
      end; 
    end; 
  

   Procedure All_Rooms; 
   Begin 
     forall r:=0 to number_of_rooms do 
           Room(r,Knobs[r],Pipes[r],Pipes[r+1],Room_Windows[r]); 
   End; 

 

Και το κυρίως πρόγραμμα :

Begin 
     fork All_Rooms; 
     fork Central_switch(Boiler_Switch,Boiler_Control); 
     fork Boiler(Boiler_Control,Pipes[0],Pipes[number_of_rooms+1]); 
     fork Human(Boiler_Switch,Knobs,God); 
     fork Weather(God,Room_Windows); 
     join;join;join;join;join; 
   End. 

 

Αυτό το πρόγραμμα κάθε χρήστης μπορεί να το εκτελέσει με πολλούς διαφορετικούς τρόπους, ανάλογα με τις επιλογές που θα κάνει στα μενού. Η έξοδος του προγράμματος είναι η θερμοκρασία του νερού, με την οποία καταλαβαίνουμε πότε δουλεύει ο καυστήρας και πότε όχι.


          Next                   Up                       Back                       Contents

Επόμενο:ΠΑΡΑΛΛΗΛΗ ΤΑΞΙΝΟΜΗΣΗ Πάνω: Διάφορα Προβλήματα Παράλληλου Προγραμματισμού Πίσω: ΟΙ ΓΕΥΜΑΤΙΖΟΝΤΕΣ ΦΙΛΟΣΟΦΟΙ