Automatically Change SP Value - auto_control

Cogent Tools Demo and Tutorials: Version 4.0
Prev | Chapter 5. The PID Emulator (`emul.g`) | Next

# 5.3. Automatically Change SP Value - `auto_control`

This part of the program gives the PID Emulator the ability to run either manually or automatically, shifting the set point at random every specified number seconds.

       /********************************************************
        *            Automatically Change SP Value             *
        ********************************************************/

       /* Initialize a global variable for the automatic timer. */
       AUTO_TIMER = nil;

       /* Register points, exceptions, and echos with the DataHub.
        * The FREQ_001 variable holds the delay for automatic change of SP. */
       AUTO_001 = register_point(#AUTO_001);
       add_exception_function(#AUTO_001, #(AUTO_TIMER = auto_control(FREQ_001)));
       add_echo_function(#AUTO_001, #(AUTO_TIMER = auto_control(FREQ_001)));

The on/off value is registered (using the Gamma `register_point` function) as a datahub point (`AUTO_001`), so that it can be accessed by other programs in the Cogent Tools Demo. The point gets its functionality with the `add_exception_function` function, which calls a specified function whenever its datahub point changes value. Here, for example, the `auto_control` function will be evaluated whenever the `AUTO_001` datahub point changes value. The datahub point name and the `auto_control` function are quoted with the `#` quote operator to protect them from evaluation while the parser reads the code.

We also need to register the variable `FREQ_001` as a datahub point. This variable holds the value corresponding to the frequency of change (number of seconds) when automatic mode is on. We write a default value of `8` if the current value is outside the desired range of `1` to `20`, and then apply the `add_exception_function` as above.

       FREQ_001 = register_point(#FREQ_001);
       if (FREQ_001 < 1 || FREQ_001 > 20)
            write_point(#FREQ_001, 8);
       add_exception_function(#FREQ_001, #(AUTO_TIMER = auto_control(FREQ_001)));

The `auto_control` function starts and stops a timer (`auto_timer`) that changes the set point (`SP_001`) value to random numbers between `0` and `100`, at regularly timed intervals.

       /*--------------------------------------------------------------------
        * Function:    auto_control
        * Returns:     a timer number
        * Description: Sets a timer to change the value of SP at a specified
        *              frequncy.
        *------------------------------------------------------------------*/
       function auto_control(freq)
       {
         if (AUTO_001 != 0)
           {
             /* Start a timer to move SP to random settings. */
             if (AUTO_TIMER == nil)
               {
                 if (45 < SP_001 && SP_001 < 55)
                   write_point(#SP_001, 80);
                 else
                   write_point(#SP_001, 50);
                 AUTO_TIMER = every(eval(freq), `write_point(#SP_001, (random() * 100)));

In this line we set the timer with the `every` function. Every `freq` seconds the `SP_001` datahub point will be changed to a random number between 0 and 100, using the Gamma `random` function. With that line alone, however, there would be a pause before anything changed. To give the user the feeling that "something happened" when the Automatic mode button is pressed in the Monitor interface, we force a change in the value of the `SP_001` datahub point before setting the timer. If the value is at or close to `50`, we move it to `80`, otherwise we move it to `50`. Multiple clicks will cause the value to toggle between `50` and `80`.

               }
             else
               {
                 /* Cancel an existing timer. */
                 cancel(AUTO_TIMER);
                 AUTO_TIMER = nil;
                 auto_control(FREQ_001);
               }
           }

The Gamma `cancel` function takes a timer number for its argument, and cancels the associated timer. If the Automatic mode button is pressed On in the Monitor, we have to check first to see if `AUTO_TIMER` has a value, and if so, cancel the timer. Otherwise we would get two or more timers firing, causing the `SP_001` value to change more frequently than we want.

Of course, we also want to cancel the timer when the Automatic mode button is pressed Off.

         else
           {
             /* Cancel the timer if the AUTO_001 button is not pressed. */
             if (AUTO_TIMER != nil)
               {
                 cancel(AUTO_TIMER);
                 AUTO_TIMER = nil;
               }
           }
         AUTO_TIMER;
       }

Prev | Home | Next
The Plant Model - `change_procvar` | Up | Emulating the PID Loop - `change_values`

Copyright 1995-2002 by Cogent Real-Time Systems, Inc.