The messages displayed in the Controller's right-hand text box come from a single text file (messages.txt, shown below). The read_msg function (located in lib/common.g) is responsible for finding the requested message and inserting it into the text box.
/*-------------------------------------------------------------------- * Function: all_white * Returns: t or nil * Description: Determines whether a line contains only a blank space * or tab characters. *------------------------------------------------------------------*/ function all_white(line) { local i, len=strlen(line), white=t; for (i=0; i<len && white; i++) if (line[i] != ' ' && line[i] != '\t') white=nil; white; }
The read_msg uses the all_white function to identify lines with just white space or tabs.
/*-------------------------------------------------------------------- * Function: read_msg * Returns: A string * Description: Finds a message in the messages.txt file, reads each * line, and returns the whole message as a single string. * Uses the all_white function to create new lines. *------------------------------------------------------------------*/ function read_msg(msgno) { local fp, marker, msg = "", line = nil, white; fp = open("messages.txt", "r", nil); while(line != _eof_) { line = read_line(fp); marker = string("#", msgno);
The read_msg function opens the messages.txt file for reading using the Gamma open function. The while statement used with the Gamma read_line function lets us read the file line by line.
We find the line we need by looking for the marker "#msgno", where msgno is the message number parameter passed to the function as a string. The marker is constructed using the Gamma string function. The Gamma strstr function is used for making the comparison.
if ((strstr(line, marker)) == 0) { line = read_line(fp); msg = ""; while(line != "#END") { white = all_white(line); msg = string(msg, white ? "" : " ", line, white ? "\n" : ""); line = read_line(fp); } line = _eof_; } } close(fp); msg; }
Once we get to the message, we read past one blank line, read the first line of the message, and then enter a second while loop. Inside this loop we use the string function again to join each new line of the message to the previous lines, constructing one long string. Our string function arguments use a ternary operator to resolve the value of the white variable. When we get to a line containing #END, we leave both while loops, use the close function to close the file, and return the message string (msg).
The messages.txt file contains all the messages that appear in the Controller. Each message is marked by #number at the start of the title line, and #END at the end of the message, which are detected by the read_msg function. The extra line between each of these markers and the body of the message allows the text editor to reformat each message paragraph without disturbing the other lines of the file.
#1 Controller Welcome to the Cogent Tools Demo. This is the Controller, a Gamma program that controls the other programs in the demo. It automatically starts the Cascade NameServer and Cascade QueueServerfor interprocess communication (IPC); and then it starts the Cascade DataHub to handle rapid data transfer. Each program started is independent, communicating with the others via IPC. You can press the PID Emulator button to begin. #END #1.1 Process Status Text Box Note: Not in use-- needs "enter" and "leave" signals for a text box. This is the status of every Cogent process that is currently running on your system. The information is generated by the Cascade NameServer. The normal view is an edited version of the Cascade NameServer output, created by the Controller program. To view the unedited information, use the "Raw output" button. #END #2 PID Emulator PID Emulator The PID Emulator is a Gamma program (emul.g) that runs behind the scenes, generating data to emulate a PID loop. Every 1/10 second it generates data for the variables SP (set point), MV (control output), and PV (process variable), and sends the data to the Cascade DataHub. From there the data gets distributed to the other programs in the Demo. #END #3 Monitor Monitor The Monitor is a Gamma program (monitor.g) that monitors and controls the PID Emulator. From the Monitor you can adjust the PID Emulator, and get a visual representation of the SP, MV, and PV values. All values shown and all adjustments made from the Monitor are exchanged with the PID Emulator via the Cascade DataHub. #END #3.1 Monitor Auto On/Off button Monitor The 'Auto mode' button toggles the value of the Cascade DataHub point AUTO_001 between 0 (OFF) and 1 (ON). The PID Emulator is registered for the point AUTO_001, and when its value changes to 1, the PID Emulator sets an "every" timer. This changes the value of SP every FREQ seconds (as set by the FREQ spin button). When the button clicked OFF, the value of AUTO_001 changes to 0, and the "every" timer gets cancelled. #END #3.1a SP slider Monitor The 'SP: Set Point' slider lets you change the set point in the demo. This slider is also activated automatically by a timer with a built-in delay. You can start and stop the automatic reset by pressing the 'Auto mode' button. You can set the timer delay using the 'Delay' spin button. #END #3.2 FREQ of change spin button Monitor The 'Delay' spin button sets the value of FREQ_001 in the Cascade DataHub. The PID Emulator is registered for the point FREQ_001, and when that value changes, the PID Emulator resets frequency of the "every" timer to the new value. The new value becomes the new rate of change (in seconds) of SP when the automatic mode is ON. #END #3.3 Kp: Proportional spin button Monitor The 'Kp: Prop' spin button sets the proportional value PID1_Kp in the Cascade DataHub. This value is a proportion applied to the difference (or error) between the set point (SP) and the process variable (PV). The PID Emulator is registered for the point PID1_Kp, and when that value changes, the PID Emulator uses the new value. #END #3.4 Ki: Integral spin button Monitor The 'Ki: Int' spin button sets the integral value PID1_Ki in the Cascade DataHub. This value influences the rate of change of the control output (MV). The PID Emulator is registered for the point PID1_Ki, and when that value changes, the PID Emulator uses the new value. #END #3.5 Kd: Derivative spin button Monitor The 'Kd: Deriv' spin button sets the derivative value PID1_Kd in the Cascade DataHub. This value inhibits rapid changes, reducing the amount of overshoot. The PID Emulator is registered for the point PID1_Kd, and when that value changes, the PID Emulator uses the new value. #END #3.6 PROP: Proportional spin button Monitor The 'PROP: Proportional' spin button controls the proportion of PV:MV by setting the value of PROP_001 in the Cascade DataHub. The PID Emulator is registered for the point PROP_001, and when that value changes, the PID Emulator uses the new value. #END #3.7 INT: Integral spin button Monitor The 'INT: Integral' spin button controls the damping effect on PV by setting the value of INT_001 in the Cascade DataHub. The PID Emulator is registered for the point INT_001, and when that value changes, the PID Emulator uses the new value. #END #3.8 Good radio button Monitor The 'Good' button resets all the MV and PV spin buttons to set up an optimally performing PID loop. The new values are sent to the Cascade DataHub, which sends them along to the PID Emulator. Also, the FREQ spin button is set to 4 to get a higher rate of change in automatic mode, because the PV value in a Good PID loop generally stabilizes in about 1 second. #END #3.9 Poor radio button Monitor The 'Poor' button resets all the MV and PV spin buttons to set up a poorly performing PID loop. The new values are sent to the Cascade DataHub, which sends them along to the PID Emulator. Also, the FREQ spin button is set to 10 to get a low rate of change in automatic mode, because the PV value in a Poor PID loop might not stabilize for 8 or 9 seconds. #END #3.10 Oscillating radio button Monitor The 'Oscillating' button resets all the MV and PV spin buttons to set up an oscillating PID loop. The new values are sent to the Cascade DataHub, which sends them along to the PID Emulator. The Automatic mode button is set to OFF, since automatic mode is not necessary here. #END #3.11 Out-of-control radio button Monitor The 'Out-of-control' button resets all the MV and PV spin buttons to set up a PID loop with ever-increasing values. The new values are sent to the Cascade DataHub, which sends them along to the PID Emulator. The Automatic mode button is set to OFF, since automatic mode is not necessary here. #END #4 DataHub Viewer DataHub Viewer The DataHub Viewer is a Cogent utility (xdhview in GTK, phdhview in Photon) that gives you a window into the Cascade DataHub. Each data point is listed by name, and all of its attributes, such as value, confidence, and the date and time the point was last updated, are shown. From the DataHub Viewer you can select any point and manually change its attributes. #END #5 Log Log Log is a Gamma program (log.g) that demonstrates the Cascade TextLogger. The Cascade TextLogger takes data from the Cascade DataHub and writes it in ASCII format to a file or STDOUT. You can control how, when, and what data gets logged. In Linux, Log uses gnuplot to read the Cascade TextLogger files and generate plots of the data. #END #5.1 Any radio button Log The 'Any' collect button sends a (collect any) command to the Cascade TextLogger, causing it to write a new line whenever a logged point's value changes in the Cascade DataHub. Only the new values are written. Points whose values haven't changed are marked with an asterisk (*). This is the default setting. #END #5.2 Fill radio button Log The 'Fill' collect button sends a (collect fill) command to the Cascade TextLogger, causing it to write a new line whenever a logged point's value changes in the Cascade DataHub. Values for all the other points are filled in, even if they haven't changed. #END #5.3 All radio button Log The 'All' collect button sends a (collect all) command to the Cascade TextLogger, causing it to write a new line only when all of the logged point's values have changed in the Cascade DataHub. For example, in this demo, a line will be written right after SP changes its value, because all variables will have new values at that time. The values for MV and PV change frequently, but no lines are written until SP's value changes as well. #END #5.4 Insert Text button Log The 'Insert Text' button sends an (output) command to the Cascade TextLogger, causing it to write the line of text in the entry box to the output file. You can send any text string you like; the "#" character is not necessary. It appears in the example text because it marks the start of a comment for gnuplot, and when used at the beginning of the line it prevents creating gaps in the plots. #END #5.5 Send Cmd button Log The 'Send Cmd' button sends a command of your choice to the Cascade TextLogger. Commands are written in Lisp syntax, using parentheses. The (exit) command is given as an example. Please refer to the Cascade TextLogger Manual for a complete list of commands and documentation on their use and syntax. #END #5.6 Log to: button Log The 'Log to' button starts the Cascade TextLogger, using the configuration file tl.cfg, and according to the 'Collect' and 'Log to' options. The file that receives the log is named tloutput.dat. When the 'Log to' button is unclicked, the contents of tloutput.dat appear in the text display. #END #5.7 file check button Log The 'file' button sends (enable) and (disable) commands to the Cascade TextLogger to control logging to the tloutput.dat file. The contents of this file appear in the text display when the 'Log to' button is unclicked. #END #5.8 stdout check button Log The 'stdout' button sends (enable) and (disable) commands to the Cascade TextLogger to control logging to STDOUT. #END #5.9 Plot Recent button Log The 'Recent' plot button calls gnuplot to create a continuously updated plot of the last 15 seconds of logged data. It reads its data from two special data files: tlold.dat and tlrecent.dat. NOTE: To simulate a trend, we run gnuplot in a loop, creating a new plot every second. To close the plot window, you have to untoggle the 'Recent' button. Otherwise the window will continue to be redrawn until the Log program exits. #END #5.10 Plot All button Log The 'All' plot button calls gnuplot to create a continuously updated plot of the output.dat file. NOTE: Because the data for this plot is ever-increasing, gnuplot will use progressively more system resources to construct a plot. NOTE: To simulate a trend, we run gnuplot in a loop, creating a new plot every second. To close the plot window, you have to untoggle the 'All' button. Otherwise the window will continue to be redrawn until the Log program exits. #END #5.11 Demo message You can modify the log during run-time like this: ------------Collect------------ Any: logs any new data. Fill: logs any new data, filling in existing data. All: logs data only when all values have changed. Insert Text: Adds a line of text to the log. (note: the '#' is a comment character for gnuplot.) Send Cmd: Sends a command to the Cascade TextLogger. #END #6 History History History is a Gamma program (history.g) that demonstrates the Cascade Historian's ability to record data and make incisive queries. #END #6.2 Record Values History The 'Record Values' button enables the Cascade Historian to start recording data for MV and PV for the number of seconds indicated. The data for both of these points will be collected as long as the PID Emulator is running. #END #6.3 Update Display History The 'Update display' button sends a query to the Cascade Historian based on the current Interpolator options. The Start time is the number of seconds past midnight last night, and Duration is the length of the query in seconds. They are reset each time time the 'Record' button is used. The Time Interval specifies the period for the Periodic and Fixed Relative interpolators. Max. gap specifies data gap size where interpolation is to be suppressed. #END #6.31 NoInterpolator History The 'NoInterpolator' option lets you run a straight query with no interpolation. It plots the Y history (either MV or PV) versus time. #END #6.32 Periodic History The 'Periodic' interpolator option plots the Y history (either MV or PV) versus time. It is similar to the 'NoInterpolator' option, except you can specify a time interval and maximum gap for the time axis. #END #6.33 Relative History The 'Relative' interpolator option plots the Y history (either MV or PV) versus the X history (also either MV or PV). This interpolator inserts an extra value into the Y history for each value in the X history. #END #6.34 FixedRelative History The 'FixedRelative' interpolator option plots the Y history (either MV or PV) versus the X history (also either MV or PV). This interpolator inserts an extra value into the Y history for each value in the X history. It is similar to the 'Relative' option, except you can specify a time interval and maximum gap for the time axis. #END #6.35 Y or X History History The 'Y history' and 'X history' entries let you choose the variables for the Y-axis and X-axis (either MV or PV). #END #6.36 Start History The 'Start' entry lets you change the start time. This time is the number of seconds past midnight. Whenever you press the 'Record' button, the value entered here changes to the time you pressed the button. #END #6.37 Duration History The 'Duration' entry lets you specify how many seconds of the history you wish to include in your query. Whenever you press the 'Record' button, the value entered here changes to the number of seconds set in the Record spin button. #END #6.38 Time Interval History The 'Time Interval' entry is only used in queries with a timed interpolator (Periodic and FixedRelative). It sets the interval of time for the interpolator. #END #6.39 Max. gap History The 'Max. gap' entry is only used in queries with the Periodic interpolator. If the time between two data points exceeds this number of seconds, then data will not be interpolated between those points. This is useful if you have large gaps in your data set. #END #6.4 Plot Data History The 'Plot Data' button calls gnuplot to create a plot of the last query. Whenever you make a new query, the plot is automatically updated. NOTE: To support the automatic update feature, we run gnuplot in a loop, creating a new plot every second. To close the plot window, you have to untoggle the Plot Data' button. Otherwise the window will continue to be redrawn until the History program exits. #END #6.5 Deadband Types button History The 'Set up deadband types' button opens the Deadband Types window, where you can set the type of deadband on data collected for MV or PV. #END #6.51 Deadband: Full data set History The 'Full data set' option shows the history that was recorded with no deadband. #END #6.52 Deadband on, prior off History The 'Deadband on, prior value off' shows the history that was recorded with a standard deadband. #END #6.53 Deadband on, prior on History The 'Deadband on, prior value on' shows the history that was recorded with the deadband on, adding for each point displayed the value that was recorded immediately before. This can give a more accurate picture of the data set in certain circumstances. #END #6.54 Deadband Types Window History The Deadband Types window lets you set the type of deadband on data collected for MV or PV, to filter out redundant data. You can deadband the data itself on an absolute or percent basis, or both. And you can set time limits or count limits for when data gets collected. #END #6.55 Cancel History The 'Cancel' button reverts the values in the Deadband window back to what they were the last time the 'OK' button was clicked, and closes the window. #END #6.56 OK History The 'OK' button sends the query to the Cascade Historian and closes the Deadband window. The values last entered in the window are the ones sent. #END
Copyright © 1995-2010 by Cogent Real-Time Systems, Inc. All rights reserved.