MCR-86-675 

PROGRAM MAINTENANCE MANUAL 

FOR 

NICKEL CADMIUM BATTERY EXPERT SYSTEM 

NAS8-35922 

DEVELOPED: .FOR 

NASA/MARSHALL SPACE FLIGHT CENTER 

HUNTSVILLE, ALABAMA 

VERSION 1 

PREPARED BY 

MARTIN MARIETTA CORPORATION 

AEROSPACE DIVISION 

DENVER, COLORADO 

OCTOBER 1986 

PGB (BdSA-CR- NICKEL 179G33) CACMIU): PROGliAfl EAllEBY BAIESEIANCE EXEEBB SYSTEW, IAPJUAL 887-2GU72 

VEBSJGY 1 (Bartin darietta Aerc+&ace) 132 p 

CSCL 1oc Unclas 

G3/33 u5235 
b' . 

SECTION 1 . GENERAL ............................................. 1 

1.1 Purpose ........................................ 1 

1.2 Project Reference .............................. 1 

1.3 Terms and Abbreviations ........................ 1 

3 

3 

SECTION 2 . SYSTEM DESCRIPTION .................................. 2.1 System Application .............................. 2.2 Security ....................................... 2 

2.3 NICBES General Description ..................... 2 

2.4 NICBES Program Description ...................... 2.4.1 Data-Handler Description ................- 

2.4.1.1 datacl.bat. .................... 2 

2.4.1.2 hst.h. ......................... 4 

2.4.1.3 data-hdl . c ..................... 5 

2.4.1.4 read-dat.c ..................... 9 

9 

3 

2.4.1.5 process-c ..................... 15 

2.4.1.6 writ-fi1.c .................... 22 

2.4.1.7 Interrupt Handler ............. 25 

2.4.2 Expert System Descrition ............... 28 

2.4.2.1 start.prg ....................... 3 '7 

2.4.2.2 faultd.prg .................... 29 

2.4.2.3 advice.prg .................... 30 

2.4.2.4 showpak.prg ................... 30 

2.4.2.5 grafpak.prg ................... 31 

2.4.2.6 utility.prg ................... 31 

2.4.2.7 prolog.ini .................... 32 

SECTION 3 . ENVIRONMENT ........................................ 33 

3.1 Equipment Environment ......................... 33 

3.2 Support Software .............................. 33 

3.3 Data Base ..................................... 33 

3.3.1 General Characteristics ................ 33 

3.3.2 Organization and Detailed Description .. 33 

TABLE OF CONTENTS 

SECTION 4 . PROGRAM MAINTENANCE PROCEDURES ..................... 36 

4.1 Conventions ................................... 36 

4.2 Verification Procedures ....................... 36 

4.3 Error Conditions .............................. 36 

4.4 Special Maintenance Procedures ................ 36 

4.6 Listings ..................................... 37 

4.5 Special Maintenance Programs .................. 37 

i 
TABLE OF CONTENTS CONTINUED 

APPENDIX A - Data-Handler Code Listings 

APPENDIX B - Expert System Code and Documentation Listings 

APPENDIX C - Test Procedures 

ILLUSTRATIONS 

FIGURE 1 - DATA-HANDLER FLOW DIAGRAM ....................... 3 

FIGURE.2 - EXPERT SYSTEM FLOW DIAGRAM.. ................... 28 

ii 
SECTION 1. GENERAL 

1.1 Purpose of the Program Maintenance Manual. 

The objective for writing this Program Maintenance Manual for project 

Nickel-Cadmium Battery Expert System (NICBES), Contract Number : 

NAS8-35922, is to provide the maintenance programmer personnel with the 

information necessary to effectively maintain or enhance the system. 

1.2 Project References. 

NICBES is an Expert System for fault diagnosis and advice of the 

Nickel-Cadmium Batteries found in the Hubble Space Telescope !HST' 

Electrical Power System (EPS) Testbed located at Marshall Space Flight, 

Center (MSFC). NICBES resides on a dedicated IBM-PC AT and operates in 

two modes. The first mode is the Data-Handler which is written in 

MICROSOFT C. The second mode is the Expert System which is written in 

ARITY PROLOG, a logical programming language. The following documents and 

manuals serve as reference materials for NICBES: 

NICBES User's Manual - September 1986 

IBM-PC AT Manuals 

ARITY PROLOG Manuals - Version 4.1 

MICROSOFT C Manuals 

1.3 Terms and Abbreviations. 

AH1 

e 

AIIO 

bprc 

ccc 

DOD 

EOC 

EOD 

EOF 

EPS 

HST 

MMDA 

MSFC 

NICBES 

sow 

SPA 

- ampere hours in 

- ampere hours out 

- battery protection and reconditioning circuits 

- charge current controllers 

- depth of discharge 

- end of charge 

- end of discharge 

- end of file 

- electrical power system 

- Hubble Space Telescope 

- Martin Marietta Denver Aerospace 

- Marshall Space Flight Center 

- Nickel-Cadmium Battery Expert System 

- Statement of Work 

- solar panel array 

1 
SECTION 2. SYSTEM DESCRIPTION 

2.1 System Application. 

NICRES was developed 3s an assistant for engineers working on the EST EPS 

Testbed to aid in decision making with regard to the Nickel-Cadmium 

Batteries. NICBES analysis depends on the particular testbeu 

configuration at MSFC, see Figure 1, and the particular Battery 

manufacturer. 

2.2 Security. 

There are no security requirements. 

2.3 General Description. 

NICBES, as programmed for the IBM-PC AT, a single tasking computer, 

requires two independent processes. The first is the Data-Handler which 

processes incoming telemetry every one minute. Input to the Data-Handler 

comes from the DEC LSI-11 over a RS232 to the IBM-PC AT. Each telemetrsburst contains 370 integer and floating point values preceeded by the 

character ’A’. There are 96 minutes in one orbit. An orbit is composed 

of a discharge and charge phase. An orbit starts at the beginning of the 

@ discharge phase and ends at the completion of the charge phase. Once this process is completed (for 12 orbits total), the Expert System of 

NICBES can be run. Input to the Expert System consists of processed data 

files output by the Data-Handler. Output from the Expert System inc.ludes 

fault diagnosis, battery status and advice, plus decision supporr. mv 

Expert System screen displays can be routed to the STAR-SD-15 Printer for 

hardcopy. 

2.4 Program Description. 

Program Descriptions for NICBES will be given in two sets. First the 

Data-Handler will be described and then the Expert System. 

2.4.1 Data-Handler. 

The Data-Handler, written in MICROSOFT Cy is installed on the IBM-PC AT 

according to the procedures listed in the MICROSOFT C Manual. All the 

following programs can be found under C:\USR . This is also where they 

should be executed. The data output files are also written to this 

directory. See Figure 1 for Data-Handler Flow Diagram. 

2.4.1.1 datacl.bat 

datacl.bat creates the executable for the Data-Handler. It compiles 

data-hdl.c, the main control routine, and then links all the other object 

files needed. The result is data-hdl.exe which invokes the 

Data-Handler. The user simply types ’data-hdl’ from the DOS prompt to 

execute the Data-Handler. If changes are made to any of the ’C’ 

programs, they must be recompiled (’msc fi1ename.c;’) and then relinked 

(’datacl’) to create a new executable. ’printf’ statements used in 0 development have been left in the programs but commented out. These 

statements are can be reinstated for debugging purposes. 

2 
DATA-HANDLER FLOW DIAGRAM 

> 

serri ni 0 

incmplt0 1 -PROCESS DATA 

34 

OR USER SIGNAL, i-’ 1 L ’\** wri te-fi 7 a(j i 

-‘ 

FINISH, ELSE 

CONTINUE 
1 'PROCESS DATA * 

WRITE FILES 

RE-IN IT ALiZE LL pracessi] , 

1 

a 
2.4.1.2 hst. h 

hst.h contains all the header items for the Data-Handler. It starts with 

define statements for errors, phases and data files. It also lists the 

needed system include files. Last are the structure and matrix 

definitions for global arrays. 

Define Statements: 

SUCCESS 1 

FAIL 0 

EOC 2 

EOD 3 

EVMIN 1 

DEFLT -9999.0 

SHOWF(N)DAT N where N = 1 to 13 

CURFCNIDAT N where N = 14 to 16 

FAULTDAT 17 

Include files: 

stdio.h, stdlib.h, pr0cess.h and errn0.h 

Global Structure for storing telemetry run, hid[O] = last run, 

hid[l] = current run. 

hid[i].year In t i=Otol 

hid[i].day In t col 0 = last telemetry run 

hid[i].hour Int col 1 = current telemetry run 

hid[i].min Int 

hid[i].sec Int 

hid[i].orbit In t 

hid[i] .phase Int 0 if discharge, 1 if charge 

hidii] .day-min Int minute in charge phase 

hid[ iJ .night-min Int minute in discharge phase 

hid[i].batd[j].battno Int 

hid[i].batd[j].cellv[k] Real 

hid[i].batd[j].cellp[k] Real 

hid[i].batd[j].batv Real 

hid[i].batd[j].batc Real 

hid[i].batd[j].bprcc Real 

hid[i].batd[j].batemp[k] Real 

hid[i].batd[j].batrecond Int 

j = 0 to 5, for 6 batteries 

k = 0 to 22, for 23 cells 

p => pressure, v =? volts, 

c => current 

batt reconditioning current 

6 temp sensors per battery 

int flag for reconditioning 

per battery 

hid[i].spac[kj Real k = 0 to 12, for 13 SPAS 

hid[i].bd[kj.busv Real k = 0 to 2, for 3 busses 

hid[i].bd[kJ.busc 

The global matrices and arrays which support the data files 3re 

documented in Appendix A of the code listing for hst.h 

4 
2.4.1.3 data hd1.c 

data-hi1.c is the main driver for the Data-Handler. Following is a 

description of all the 'Cy routines in this program imain0, init.', 

read-initi !, finish!), sig-catch(), process(j and incomplete!.) 1. 

Identification: main 

Function: main is the Data-Handler driver. It controls the program 

flow and determines the times for events to happen. 

Input: No Input, although argc and argv make it possible to easily 

add inputs. 

Processing: Keeps track of Orbit and Phase. Controls program flow by 

its routine calling sequence. 

Output: Error Message written to screen if more than CILIMIT consecutive 

incomplete telemetry runs. 

Error Message if fault is detected. 

Message written to screen at the completion of each orbit. 

Local Variables: 

orbitno - Counter for number of orbits 

err - recieves return from read-data() 

phase-signal - EOC, EOD or EVMIN 

phase1 - phase of previous telemetry run 

phase2 - phase of current telemetry run 

Global Variables: 

EOC, EOD, EVMIN 

FAULTDAT 

fault[] 

FAIL 

hid[] 

Interfaces: Calls init(), process(), finish(), sig-catch(), incomplete!) 

read-dat.c - read-data() 

writ-fi1.c - wf0. 

pr0cess.c - check-fault() 

Error Handling: If read-data encounterd an EOF while reading the 

telemetry stream, FAIL is returned. If there are 

CILIMIT consecutive incomplete runs, Data-Handler 

is shutdown after the fault flag is set to 1. 

If a fault was detected the fault flag is set to 1 

and the Data-Handler is exited. 

5 
, I , 

Identification:. ini t 

Function: Sets the communication port, initializes interrupt handler, 

and calls buffer initialization and read telemetry 

initialization routines. 

Input: No input. 

Processing: No processing. 

Outputs: Error message stating that an EOF was found while reading 

the telemetry stream and that the system is shutting down. 

Local Variables: 

err - receives return value from read-init0. 

port - communication port 

Global Variables: None 

Interfaces: Called by main. 

Calls system signal() and setgort(), read-init(), 

interrupt handler - serinio and pr0cess.c - df-initi). 

Error Handling: If read-init() returns FAIL, system will shutdown. 

Identification: read-init 

Function: initializes telemetry reading to first full orbit. 

An orbit starts at the beginning of. the discharge phase. 

Input: No input. 

Processing: Reads the telemetry stream until night-min = 1, start of 

discharge phase. This signifies the start of an orbit. 

process() is then called to process this first set of data 

Output: Prints message to the screen "Starting first full orbit". 

Local Variables: err - receives return value from read-data(j. 

Global Variables: 

FAIL, DEFLT, EVMIN 

hid[] 

Interfaces: Called by init(). 

Calls process(), incomplete(), 

read-dat. c - read-data() . 

Error Handling: If read-data() returns FAIL, control is passed back to 

init() also with a FAIL message. 

6 
Identification: finish 

Function: Exits Data Handler. 

Input: No input. 

Processing: Ends interrupt handler, writes data output files and calls 

exit(). 

output: No output. 

Local Variables: None. 

Global Variables: EOC, EOD 

Interfaces: Called by main(), init(), sig-catch(), incomplete() or 

read-dat.c - get2(). 

Calls writ fi1.c - write-file(), system exit!), 

and interrupt handler - serrst(). 

Error Handling: None. 0 

Identification: sig-catch 

Function: Catches "'C' signal input by operator to halt Data-Handler. 

input: User signal input '"Cy. 

Processing: No processing. 

Output: Writes message to screen, "Interrupt caught; exiting!" 

Local Variables: None. 

Global Variables: None 

Interfaces: Calls finish(). 

Error Handling: None. 

7 
Identification: process 

Funct.ion: Calls the routines necessary to process the telemetry. 

Input: phase-signal - EOC, EOD or EVMIN 

orbitno - 0 to N, N is the number of orbits. 

Processing: No processing. 

Output: No output. 

Local Variables: None. 

Global Variables: None. 

Interfaces: Calls pr0cess.c - process-data(), df-initl!), 

writ-fi1.c - write-file(). 

Error Handling: None. 

Identification: incomplete() 

Function: Checks for CILIMIT number of consecutive incomplete telemetry 

bursts. 

Input; None. 

Processing: If there are CILIMIT consecutive incomplete telemetry runs 

fault flags are set, fault.dat is written and finish() is 

called. 

Output: Error message. 

Local Variables: None. 

Global Variables: 

CILIMIT - Limit for consecutive incomplete telemetry runs 

conseq-incmplt - counter for incomplete telemetry bursts 

FAULTDAT 

fault[] 

Interfaces: Called by main() and read-init(). 

Calls finishij and writ-fi1.c - wf(j. 

8 
2.4.1.4 read dat.c 

read-dat.c is the routine which reads the telemetry from the interrupt 

handler buffer. Following is a description of all the 'Cy routines in 

this file (read-data:), proc-syncO, proc-head(j, proc-bat':, proc: 

solar(), read-buffer(), get10 and get20 ). 

Function: Read telemetry from DEC LSI-11 over RS232 every 1 minute. 

Input: No input, however telemetry from HST EPS Testbed, 370 values 

preceded by 'A', is utilized. 

Processing: Calls routines to read telemetry. 

Output: Returns FAIL or SUCCESS. 

Telemetry is placed in structured arrary hidl11 for later 

processing. A description of the structure of hid follows: 

Local Variables err - return value from proc-head(), procbat0, 

proc-solar () . 

Global Variables: 

TlLIMIT, TZLIMIT 

buf[] - intermediate character storage array. 

count - keeps count of data values per telemetry burst. 

FAIL, SUCCESS 

Interfaces: Called by main(). 

Calls proc-sync(), proc-head(), proc-bat(), proc-solar(.j. 

Error Handling: If proc-head(), proc-bato or proc-solar() return 'a 

FAIL, reading is stopped and control is returned to the 

read-data() call in main(). 

9 
Identification: proc-sync 

Function: Synchronize reading data to start of telemetry burst. 

Input: No input, but uses telemetry burst, first character is 'A'. 

Processing: Checks input characters until character 'A" is found. 

Also checks for a shutdown signal from the DEC LSI-11. 

Output: Can write message to screen "Sync Received!" 

Can write message to screen "Received shutdown signal from 

DEC LSI-ll!" 

Local Variables: 

cc - character found in the interrupt handler's buffer. 

Global Variables: 

fault [ 3 

FAULTDAT 

Interfaces: Called by read-data(). 

Calls data-hd1.c - finish!), writ-fi1.c - wfo, 

get10 and getZ(). 

Error Handling: Error Message if shutdown signal from DEC LSI-11. 

Identification: proc-head 

Function: Read header data from input buffer. 

Input: No input, but uses telemetry stream. 

Processing: Read header data from input buffer into buf[]. Use sscanf 

to put characters into integer format. 

Output: Integer header data put into global structured array hid[l]. 

Returns FAIL or SUCCESS. 

Local Variables err - return value of read-buffer(). 

Global Variables: 

FAIL, SUCCESS 

hi.d i j 

buf[l 

Interfaces: Called by read-data(). 

Calls read-buffer(). 

Error Handling: If read-buffer() returns a FAIL, proc-head() stops and 

0 

returns FAIL to read-data(). 

10 
Identification: proc-bat 

Function: Read battery data from input buffer. 

Input: No input, but uses telemetry, 57 values for each of the 6 

batteries. 

Processing: Read battery data from input buffer into buf[l. Use sscanf 

to put characters into integer and floating point format. 

Output: Integer and real battery data put into global structured array 

hid[l]. Returns FAIL or SUCCESS. 

Local Variables err - return value from read-buffer(). 

Global Variables: 

FAIL, SUCCESS 

hid[ 3 

buf[l 

Interfaces: Called by read-data(). 

Calls read-buffer(). 

Error Handling: If read-buffer!) returns a FAIL, proc-bat() stops and 

returns FAIL to read-data(). 

Identification: proc-solar 

Function: Read SPA and bus data from input buffer. 

Input: No input, but uses telemetry, 13 SPA and 6 bus values. 

Processing: Read SPA and bus data from input buffer into buf[]. Use 

sscanf to put characters into floating point format. 

Output: SPA and bus data put into global structured array hid[l]. 

Returns FAIL or SUCCESS. 

Local Variables err - return value from read-buffer(). 

G 1 ob a 1 Var iab 1 es : 

FAIL, SUCCESS 

hid[] 

buf [ ] 0 Interfaces: Call'ed by read-data(). 

Calls read-buffer(). 

Error Handling: If read-buffer() returns a FAIL, proc-solar() stops and 

returns FAIL to read-data(). 

11 
Identification: read-buffer 

Function: Puts characters from interrupt handler buffer into buF[j. 

Input: k is the actual number of telemetry values to be read. 

Processing: Get next character in interrupt handler buffer, this 

includes newlines and <CR>s. Characters are put in buf[]. 

Output: Returns found characters in buf[J to calling routine. 

Returns FAIL or SUCCESS. 

Local Variables nl-count - counts telemetry values read by counting 

newlines. 

Global Variables: 

count 

EOF 

FAIL, SUCCESS 

buf[l 

Interfaces: Called by proc-head(), proc-bat(), proc-solar(). 

Calls getl(). 

Error Handling: If EOF is encountered while reading the telemetry 

stream, read-buffer!) is stopped and FAIL is returned 

to the calling routine. 

12 
Identification getlo 

Function: Reads characters from interrupt handler buffer during 

telemetry burst. 

Input: None. 

Processing: Gets characters from interrupt handler buffer. Checks 

time and count to insure complete telemetry runs are read. 

Output: Returns EOF or character. 

Local Variables: 

cc - character read from interrrupt handler buffer. 

tO - start time for timer. 

tn - current time 

timer - difference between tn and to. 

Global Variables: 

count 

EOF 

TlLIMIT - maximum time to wait for next character 

Interfaces: Called by read-buffer() and proc-sync(). 

Calls interrupt handler b-char(). 

Error Handling: If a character is not read within 3 given time limit 

it is assumed to be an incomplete telemetry burst. 

Passes EOF back to read-buffer(). 

13 
identification get20 

Function: Reads characters from interrupt handler Duffer at the start 

of a telemetry run. 

Input: . None. 

Processing: Gets characters from interrupt handler buffer. Checks 

time to insure the beginning of telemetry is read within 

TZLIMIT time limit. 

Output: Returns character. Writes Error Message if time limit exceeded. 

Local Variables: 

cc - character read from interrrupt handler buffer. 

tO - start time for timer. 

tn - current time 

timer - difference between tn and to. 

Global Variables: 

EOF 0 T2LIMIT - maximum time to wait for next character 

fault[! 

.FAULTDAT 

Interfaces:' Called by proc-sync(). . 

Calls interrupt handler b-char:). 

Error Handling: If a character is not read within a given time limit 

it is assumed that a telemetry run is missed. 

Sets fault flag to 1, writes fault.dat, writes Error 

Message "No communication in 3 minutes; exiting!", and 

exits. 

14 
_- 

2.4.1.5 process.~ 

pr0cess.c processes the current telemetry which has been stored in his-* 

by read-dat. c. Following is a description of all the 'C' routines in 

this file (df-init0, df-initlO, hidtohido, move-buffers' ), move( ), 

process-data(), check-fault() ). 

Identification: df-init 

Function: Start up initialization counters and globally defined 

structures, matrices and arrays. 

Input: No input, but uses globally defined structures and arrays. 

Processing: Sets counters, matrices and arrays to 0 or DEFLT. 

output: No output. 

Local Variables: None. 

Global Variables: 

DEFLT - default value = -9999.0. Signifies missing data. 

no-druns - number of discharge runs in an orbit. 

no-cruns - number of charge runs in an orbit. 

fault[] 

FAULTDAT 

DATA FILE 

showf 1. dat 

showf2. dat 

showf 3. dat 

showf4.dat 

showf5.dat 

showf6.dat 

showf7.dat 

showf8.dat 

showf9. dat 

showfl0.dat 

showfll.dat 

showf 12. dat 

showfl3.dat 

curf2. dat 

CORRESPONDING BUFFER 

eod-voltage( 6,12 I 

hc-voltage(6,lZ: 

high-buffer (6 

rc-ratio(6,lZj 

ahi(6) 

ah00 (6) 

cv-eod-hv(6,lZ) 

cv-eod-lv(6,lZ) 

cv_eod_av(6,12) 

cv-hc-hv(6,lZ) 

cv-hc-lv (. 6,12) 

cv-hc-av (6'12 1 

cellv_eod(6,12) 

cellv_hc[6,23) 

avgt(6,48) 

avg_temp(6,12: 

avg-temp-buffer(61 

cp-eod (6,23 ) 

cp_eoc(6,23) 

time_tc(6,12) 

trickle(6) 

rc-orb i t ( 6 ) 

bc_drc(6,48) 

aho(6,12) 

batt-avg(6) 

15 
I 

Interfaces: Called by data-hd1.c - init!). 

Error Handling: None. 

Identification: df-initl 

Function: After each telemetry burst is read, certain counters, 

structures and arrays used for processing need to be 

re-initialized. There are 3 cases - EOC, EOD or EVMIN. 

Input: phase-signal - EOC, EOD or EVMIN. Also uses globally defined 

structures, arrays and matrices. 

Processing: Sets counters, variables and arrays to 0 or DEFLT (-9999.). 

output: No output. 

Local Variables: None. 

Global Variables: 

DEFLT - default value = -9999.0. Signifies missing data. 

no-druns - number of discharge runs in an orbit. 

no-cruns - number of charge runs in an orbit. 

EOC, EOD, EVMIN 

DATA FILE 

showf2.dat 

' showf3.dat 

showf6. dat 

showf7. dat 

showf8.dat 

showf9. dat 

showf 10. dat 

curf2. dat 

Interfaces: Called by data-hdl 

Error Handling: None. 

CORRESPONDING BUFFER 

high-buffer(6) 

ahoo (6 ) 

ahi(6) 

cellv-eod(6,lZ) 

cellv_hc(6,23) 

avgt ( 6,48) 

avg-temp-buffer( 6) 

cp-eod ( 6,2 3 ) 

cp_eoc(6,23) 

batt-avg(6) 

c - process. 

16 
Identification: hidtohid 

Function: After each telemetry burst is read and processed, the data 

in hidill is put in hi'd[O] to prepare for next data burst 

which will be stored in hid[lj. 

Input: No input. 

Processing: Puts hid[l] column into hid[0] column. 

Output: No output. 

Local Variables: None. 

Global Variables: 

hid[] 

DEFLT 

Interfaces: Called by df-initlo. 

Error Handling: None. 

17 
Identification: move-buffers 

Function: Prepares the globally defined matrices for move(.). 

The affected matrices are those associated with data files 

containing data for 12 orbits. When more than 12 orbits 

have been processed, the arrays need to be shifted so that 

they contain the only the last 12 orbit’s data. 

There are two cases - EOC and EOD. 

Input: phase-signal - tells whether charge or discharge phase. - 

Processing: Prepares matrices and then calls move(>. 

Output: No output. 

Local Variables None. 

Global Variables: 

EOC, EOD 

DATA FILE 

showf 1. dat 

showf2. dat 

showf3. dat 

showf4. dat 

showf5. dat 

showf9.dat 

showfll.dat 

showfl3.dat 

Interfaces: Called by process-data(). 

Calls move(). 

CORRESPONDING BUFFER 

eod-voltage(6,lZ) 

hc_voltage(6,12) 

rc_rati0(6,12) 

cv_eod_hv(6,12) 

cv-eod-lv(6,lZj 

cv-eod-av ( 6,12 1 

cv-hc-hv!S,12: 

cv-hc-lv 6,12 ) 

cv_hc_av(6,12) 

avg_ternp(6,12) 

time_tc(6,12) 

aho(6,lZ) 

Error Handling: None. 

18 
Identification: move 

Function: When the Data-Handler continues after 12 completed orbits, 

the 6x12 matrices must loose their first column, the remaining 

data must be shifted one column to the left and the next 

orbit’s data will be put in the 12th column. You hence always 

have the latest 12 orbits. 

Input: buffer[] to be moved. 

Processing: Shift columns in buffer one column to the left, dropping the 

first column. Set the 12th column to DEFLT (-9999.1. 

output: No output. 

Local Variables: None. 

Global Variables: DEFLT - default value = -9999.0. 

Interfaces: Called by move-buffers:). a Error Handling: None. 

Identification: process-data 

Function: 96 minutes of telemetry making up each orbit, 3re summarized 

mathematically in preparation for writing the data to output 

files. There are 3 cases - EOC, EOD and EVMIN. . 

Input: phase-signal - EOC, EOC’ or EVMIN. 

orbitno - 0 to N, where N is the number of orbits. 

Processing: Data is prepared for showf(n).dat, n = 1 to 13 

and curf(n), n = 1 to 3. Following, in Section 3.3.2 on 

data bases, a description is given of each data file’s 

functional requirements. 

Output: No output. 

Local Variables: 

col - 0 to 11, matches orbit to column number of matrices. 

sum - variable used to sum 6 temperature sensors per battery. 

avg - sum / 6 to give average temperature of battery per min. 

current-min - sum of night-min and day-min. 

jj - flag to do processing on even minutes. 

xl - used to find maximums. 

x2 - used to find minumums. 

x3 - used to find averages. 

x - miscellaneous variable. 

19 

0 
Global Variables: 

DEFLT - default value = -9999.0. Signifies missing data. 

no-druns - number of discharge runs in an orbit. 

no-cruns - number of charge runs in an orbit.. 

DCHGLIMIT - necessary number of discharge runs per orbit. 

CHGLIMIT - necessary number of charge runs per orbit. 

DATA FILE 

showfl.dat 

showf2.dat 

showf3.dat 

showf4.dat 

showf5.dat 

showf6. dat 

showf7.dat 

showf8. dat 

showf9. dat 

showf 10. dat 

showfll.dat 

showf 12. dat 

showfl3.dat 

curf2. dat 

CORRESPONDING BUFFER 

eod_voltagei6,12) 

hc_voltage(6,12) 

high-buffer (6) 

rc_ratio(6,12) 

ahi (6) 

ahoo (6) 

cv-eod-hv (6,12 i 

cv-eod-lv(6,lZ.l 

cv_eod_av(6,12j 

cv-hc-hv(6,12) 

cv-hc-lv(6,lZ) 

cv-hc-av(6,lZ) 

cellv_eod(6,12j 

cellv_hc(6,23) 

avgt (6,48) 

avg_ternp(6,12> 

avg-temp-buffer ( 6 j 

cp_eod(6,23j 

cp-eoc (6,23) 

time_tc(6,12j 

trickle(6) 

rc-orbit(6) 

bc_drc(6,48) 

aho( 6,12) 

batt-avg(6) 

The indented buffers are working arrays which support the 

main arrays. The data files followed by blanks require no 

processing but directly use telemetry from hidil:. 

In addition process-data determines if it is necessary to 

call move-buffers and keeps count of number of charge and 

discharge runs per orbit. 

I Interfaces: Called by main(). 

I 

Error Handling: Checks that no division by zero occurs. 

Checks that enough charge and discharge runs have been 

recorded to validate the processed data. Else DEFLT is 0 left in the global matrices and process() stops. 

20 
Identification: check-fault!) 

Function: Detects faults in telemetry. 

Input: No Input. 

Processing: There are four fault categories that are checked: 

1. Power Supplies 

3. SPA current < 5 amps during first 5 minutes of charge phase. 

b. SPA current >= 8 amps for 1-SPAS (1,3,5,7,9,11). 

c. SPA current > 5 amps during discharge phase. 

SPA current >= 16 amps for 2-SPAS (2,4,6,8,10,12,13). 

2. Batteries 

a. Cell voltage <= 0 volts for any cell in any battery. 

b. Cell voltage > 1.55 volts for any cell in any battery. 

3. Load Banks 

a. Sum of 3 bus currents > 99 amps. 

b. Load < 5 amps on any single bus during discharge phase. 

4. Temperature 

a. Average of the 6 temperature sensors > 25 C or i -10 C. 

Output: Returns FAIL or SUCCESS 

Local Variables: 

x - miscellaneous floating point number. 

sum - sum of various arrays. 

Global Variables: 

FAIL, SUCCESS 

hid[] 

Interfaces: Called by data-hd1.c - main(). 

Error Handling: Returns FAIL if fault found, SUCCESS if not. 

21 
2.4.1.6 writ fi1.c 

writ-fi1.c contains the '2' routines needed to write the processed data 

buffers to output files. Following is a description uf all the 'C' 

routines in this file (wf(), write-fit.), write_f2(),writovf3( ), write 

file() i. 

Identification: write-file 

Function: Determines which data files should be written. There are 3 

cases - EOC, EOD or EVMIN. 

Input: phase-signal - EOC, EOD or EVMIN. 

Processing: According to the time, wf is called to write the data 

output files. Following is a time chart: 

TIME 

EOC 

EOD 

EVMIN 

DATA FILES 

showf2.dat 

showf3.dat 

showf5. dat 

showf6.dat 

showf7. dat 

showf8.dat 

showf9. dat 

showfll.dat 

showf 12. dat 

showfl.dat 

showf4.dat 

showf6.dat 

showfl0.dat 

s tatf 1. dat 

curf 1. dat 

curf2. dat 

curf3.dat 

fault.dat is written initially with fault flag = 0, and then 

only after fault flag is set to 1. 

Output: Error message is written to the screen 

"Couldn't open 'filename'!''. 

Local Variables: err - return value from wf(). 

Global Variables: 

EOC, EOD, EVMIN 

SHOWF(N)DAT for N = 1 to 13 

CURF (N.) DAT for N = 1 to 3 

22 
Interfaces: Called by data-hd1.c - process() and finishi). 

Calls wf(). 

Error Handling: If a data file can not be opened, a message is written 

to the screen. No other action is taken. 

Identification: wf 

Function: Write output files for Expert System from globally defined 

matrices and arrays containing summarized telemetry. There 

is a case statement for each data file. 

Input: Name of the data file to be written. 

Processing: Open output f.iles, write processed data from matrices in 

list format, then close output file. 

Output: Data files to be used by the Expert System. 

Returns FAIL or SUCCESS. 

0 Local Variables: 

err - return value from write-fl(), write-fZC), write-f3: : 

sfp - output file pointer. 

Global Variables: 

SHOWF(N)DAT for N = 1 to 13 

CURF(N)DAT for N = 1 to 3, and FAULTDAT 

FAIL, SUCCESS 

hid[ J 

DATA FILE 

showf 1. dat 

showf2.dat 

showf3.dat 

showf4. dat 

showfti. dat 

showf6.dat 

showf7.dat 

showf8.dat 

showf9.dat 

showfl0.dat 

showfll.dat 

showfl2. dat 

showf 13. dat 

curf2.dat 

23 

CORRESPONDING BUFFER 

eod-voltage(6,lZ) 

hc-voltage(6,lZ) 

rc-ratio(6,lZ) 

cv_eod_hv(6,12) 

cv-eod-lv (6,12) 

cv_eod_av(6,12) 

cv-hc-hv (6,12 j 

cv-hc-lv(6,lZ) 

cv-hc-av (6,12 j 

. cellv_eod(6,12) 

cellv_hc(6,23) 

avgt (6,48) 

avg-temp(6,lZ) 

cp_eod(6,23) 

cp_eoc(6,23) 

time,tc(6,12) 

rc-orbit(6) 

bc_drc(6,48) 

aho(6,lZ) 

batt-avg(6) 
Interfaces: Called by write-file(), 

data-hd1.c - main(), incomplete(), 

read-dat.c - get20.. 

Calls write-fl(1, write-f2(jY write-f3(j, 

system fopen(), fcloseo and fprintfo. 

Error Handling: Returns FAIL if data file can not be opened. 

Note: List format means that data is contained in brackets and separated 

by commas. A main list holds all the sublists and ends with a 

peroid. Following is an example for showfl.dat: 

show(l,[[al,bl,cl,dl,el,fl~glyhl,il,jl,kl,ll]y 

[a2,b2,~2,d2,e2,f2,gZ, ..............I, 

[a3, ................................I, 

[a4, .................................. [as, ................................I, 

[as, ................................I]). 

In this example there are 12 columns, one per orbit. Orbital data is 

listed in chronological order. 0 

identification: write-fl 

Function: Write output files for Expert System from globally defined 

matrices and arrays containing summarized telemetry. 

Input: filename, buffer and file number to be written to output file. 

Processing: Open output files, write processed data in list format, 

then close output file. 

Output: Data files to be used by the Expert System. 

Returns FAIL or SUCCESS. 

Local Variables file - output file pointer. 

Global Variables: FAIL, SUCCESS 

Interfaces: Called by wf() for showfl, showf2, showf3, showf9, statl. 

Calls system fopen(), fcloseo and fprintfo. 

Error Handling: Returns FAIL if data file can not be opened. 

24 
Identification: write-fz 

Function: Write output files for Expert System from globally defined 

matrices and arrays containing summarized telemetry. 

Input: filename, buffer and file number to be written to output, file. 

Processing: Open output files, write processed data in list format, 

then close output file. 

Output: Data files to be used by the Expert System. 

Returns FAIL or SUCCESS. 

Local Variables: file - output file pointer. 

Global Variables: FAIL, SUCCESS 

Interfaces: Called by wf() for showf4 and.showf5. 

Calls system fopen(), fclose() and fprintfo. 

Error Handling: Returns FAIL if data file can not be opened. 0 

Identification: write-f3 

Function: Write output files for Expert System from globally defined 

matrices and arrays containing summarized telemetry. 

Input: filename, buffer and file number to be written to output file. 

Processing: Open output files, write processed data in list format, 

then close output file. 

Output: Data files to be used by the Expert System. 

Returns FAIL or SUCCESS. 

Local Variables: file - output file pointer. 

Global Variables: FAIL, SUCCESS 

Interfaces: Called by wf() for showf6 and showf7. 

Calls system fopen(), fclose() and fprintfo. 

Error Handling: Returns FAIL if data file can not be opened. 

25 
2.4.1.7 Interrupt Handler 

The Interrupt Handler takes over control of the IBM poling technique for 

receiving data over 3 communication net. Instead each incoming character 

is retrieved in a buffer which can be accessed by the Data-Handlcr 

programs. This is to insure that the telemetry is read accurately and not 

written over. 

These are the programs needed: 

seria1.c and serial.obj 

com-cfns.c and corn-cfns.obj 

com-fns. asm and com-fns. ob j 

serset . asm and serset. ob j 

fixup.asm and fixup.0b.j 

Functions directly called from the Data-Handler are: 

data-hd1.c - init!) calls serinio 

- finish() calls serrst() 

read-dat.c - get10 calls b-char() 

get20 calls b-char() 

Include files required are: 

serial. h 

entry . h 

asment. h 

asmexi t . h 

sasment. h 

sasmexit. h 

26 
2.4.2 Expert Svstem. 

The Expert System is written in ARITY PROLOG which is installed on the 

IBM-PC AT according to the procedures listed in the ARITY PROLOG Manual. 

All the following programs can be found under C::PROLOG. This is alsv 

where they should be executed. The set of data files to be used for the 

Expert System analysis need to be copied to C:\PROLOG. Unlike the ‘C’ 

programs, the PROLOG programs of made up of many predicates and control is 

implemented by predicate calls to other predicates. In 3 way this 1s 

similar to subroutines at a smaller level. The programs have been grouped 

to be modular. See Figure 2 for Expert System Flow Diagram. 

2.4.2.1 start-prq 

Identification: start 

Function: Main control routine for the Expert System. It calls other 

segments of the Expert System via the utilization of user 

menus. 

Input: fault. dat, curf 1. dat and user responses to menus. 

Processing: First fault.dat is checked to see if the fault flag has been 

set to 1. If so, faultd.prg is called to perform fault 

diagnosis. The user can then opt for more information. 

In this case or if no fault, the Main Menu is written to 

the screen from which the user can select from Plots and 

Graphs, Battery Status or Advice. Next the user is asked 

to select Battery. 

Control is passed to one of the above 3 choices with the 

selected Battery. Further menus are shown for Plots and 

Graphs and for Advice. The user can always opt for another 

Battery selection or to Quit to the Main Menu where they can 

opt to Quit NICBES. 

Output: Menus and control parameters which are passed to other 

portions of the Expert System telling what the user’s choices 

are in response to menus, and which Battery to view. 

Interfaces: Invoked by prolog.ini, the PROLOG initiation program. 

Start calls functions in faultd.prg, status.prg, advice.prg, 

showpak.prg and utility.prg . 

27 
EXPERT SYSTEM FLOW DIAGRAM 

S V STEM I NIT I A L I PAT 1 DN 

PROLDEINI 

L 

CONTROLLER AND 

MENU INTERFACE 

START.PRG I- FAULT FLAG = f J FAULT DIAGNOSIS 

1 FAULTD.PRG j 

t 

DECISION SUPPORT 

SHO WPAK.PRG 

I GRAPHICS SUPPOR 

GRAFPAKPRG 

BATTERY STATUS 

STATUSPRG 

FIGURE 2 

t 

(BATTERY ADVICE i 

I 1 I ADV1CE.PRG 

PROGRAM SUPPORT1 

UTIL1TY.PRG 

28 
2.4.2.2 faul td. prq 

Identification; faultd 

Function: Perform fault diagnosis for the HST EPS Testbed. 

Input: curf2.dat and curf3.dat 

Processing: Five conditions are checked to determine the source of the 

fault. See faultd.doc in Appendix B. 

. Output: Output is in the form of screen report detailing the fault 

cause(s> and advising on correctional procedures. 

Interfaces: Called by start.prg - fault-diag/O. 

2.4.2.3 status.pr~ 

Identification: status 

Function: Status analysis is performed for Batteries 1 to 6. 

Input: Battery number (Bat), showf3.dat, showf4.dat, showf8.dat, 

showfl3.dat 

Processing: Status checks reconditioning flag first. If battery is 

being reconditioned status stops because data would be 

misleading. If not, temperature, workload, charging 

scheme and divergence are checked using averages which are 

compared to thr6shold values. See status.doc in Appendix B. 

Output: Output is in the form of a screen report detailing the 

condition of the battery with respect to the above checks. 

Interfaces: Called by start.prg - battery-status(Bat). 

Calls functions in utility-prg. 

29 
2.4.2.4 advice. prq 

Identification: advice 

Function: Advice uses trend analysis for voltage, recharge ratio, 

temperature and divergence to give further detail on three 

subjects: whether a battery needs reconditionin, changes in 

charging scheme or changes in workload. 

Input: Battery number (Bat), Advice Menu Choice (1 to 3), showfl.dat, 

showfZ.dat, showf3.dat, showf5.dat, showf9.dat and showfl3.dat. 

Processing: Depending on the Choice, data files are read, trends 3re 

derived using the difference of two weighting functions and 

deviation factors. These trends are then compared to 

conditions to tell whether a battery needs to be changed. 

Explanations are given to back up the resulting diagnosis. 

See advice.doc in Appendix B.. 

Output: Output is in the form of a screen report detailing Battery 

Advice and explanations. 

Interfaces: Called by start.prg -- - advice(Bat,Choicej. 

Calls functions in utility.prg. 

2.4.2.5. showpak. prg 

Identification: showpak 

Function: Decision Support portion of the Expert System providing 

12 Plots to the user for each battery. 

Input: Plot (N), Battery Number (Bat), Orbit number (Orbit), 

showf#.dat (# from 1 to 12). 

Processing: Data from the appropriate data file, for the appropriate 

Battery is read. The data structure show/ll, containing 

the parameters needed for plotting, is called. 

See showpak.doc in Appendix B. 

Output: Plotting parameters are passed to grafpak.prg 

Interfaces: Called by start.prg - show-view(N,Bat,Orbit). 

Calls functions in grafpak.prg and utility.prg. 

30 
2.4.2.6 grafpak. prg 

I den t i f i cat i on : g r a f p alc 

Function: Draws to the screen the any of the 12 available plots, 

per battery. 

Inputs: List of points to be plotted and all plotting parameters 

including captions. 

- Processing: Uses graphics primitives to draw plots on the screen. 

Plots have X and Y axes, title, header and points displayed 

in color and symbol. Missing data and data out of range are 

also displayed. See grafpak.doc in Appendix B for more 

details and start.doc for a listing of the graphs. 

Outputs: Plots drawn to the screen. 

Interfaces: Called by showpak.prg - graphplus/6 and plot/8. 

Calls functions in utility.prg 

e 2.4.2.7 utility.pr-q 

Identification: utility 

Function: Collection of miscellaneous Prolog functions used by one 01- 

more of the Prolog routines. 

Inputs: Parameters are passed for the particular function call. 

Processing: Depends on the function call. See utility.doc in Appendix B 

for detailed description of the functions as well 3s built-in 

Arity functions. Details on the handling of data files is 

also described there. 

Outputs: Sends requested values back to the calling function. 

Interfaces: Called by start.prg, faultd.prg, status.prg, advice.prg, 

showpak. prg, grafpak. prg. 

31 
2.4.2.8 prolog-ini 

I dent if icat ion : pro log. ini 

Function: Consults the programs needed to run the Expert System 

Inputs: No inputs. 

Processing: start.prg, faultd.prg, status.prg, advice.prg, showpak.prg 

grafpak.prg and utility.prg are loaded at the initiation of 

Prolog, when the user enters 'api' at the DOS prompt. 

All data files are copied to the NICBES directory. 

The currenet data files and fault.dat are also loaded. 

The Expert System is then called into operation. 

outputs: No output. 

Interfaces: No interfaces. 

32 
SECTION 3. ENVIRONMENT 

3.1 Equipment Environment. 

The following computer equipment is needed for the execution of NICEES: 

DEC LSI-11 

RS232 cable connector 

IBM-PC AT 

STAR-SD-15 Printer 

3.2 Software Suvport 

The following computer software is needed for the execution of NICBES: 

DOS (IBM’s operating system) 

MICROSOFT C 

ARITY PROLOG - Version 4.1 

3.3 Data Base 

The following paragraphs will detail the data base utilized by WICDES. 

3.3.1 General Characteristics. 

As NICBES is actually two systems, a data base description will be given 

for each. 

First for the Data-Handler whose data base consists of telemetry, received 0 and processed every one minute. This dynamic data base is not stored, but 

condensed and summarized by performing mathematical operations. The final 

historical data will be written to files for use by the Expert System. 

The only limitations for the telemetry are time constraints and reading 

and writing validity. 

The data base for the Expert System consists of the data output files 

written by the Data-Handler. These files are static and should not be 

modified. However, they can be stored in uniquely referrenced locations 

for later review. 

3.3.2 Organization and Detailed Description. 

Telemetry for the Data-Handler: 

Start of Telemetry Burst 

A 

Header Information (Integer) 

1. year 

2. day of year - 198X 

3. hour 7 0 to 24 

4. minute - 0 to 60 

5. second - 0 to 60 

6. orbit - Positive Integer 

7. phase - 0 for discharge, 1 for charge 

8. day minute (minute in charge) - 0 to 70 0 9. night minute (minute in discharge) - 0 to 37 

33 
Battery Information (for each of 6 batteries) 

10 - 351, 57 values for each battery 

battery number Integer 1 - 6 

cell voltage 23 Reals -2 to -+2 volts 

cell pressure 23 Integers 0 to 150 psi 

battery voltage Real 0 to 30 volts 

battery current Real -30 to +25 amps 

negative for discharge phase 

positive for charge phase 

bprc current Real 0 to 5 amps 

temperature sensors 6 Reals -15 to 30 (degrees C) 

battery reconditioning Integer 0 for no, 1 for yes 

Miscellaneous Information 

352 - 364 Solar Array current 13 Reals 0 to 20 amps 

365 - 367 Bus Voltage 3 Reals 0 to 40 volts 

368 - 370 Bus current 3 Reals 0 to 90 amps 

Reals are five place floating point numbers. Each telemetry value is 

sent one per line with an associated new line and carriage return. 370 

values are sent every one minute, 96 minutes per orbit. 

Data Files for the Expert System: 

All data files are written in list format. All the show files have 6 

lists, one for each battery. All the data files are loaded into the 

PROLOG Expert System as facts. See documentation in Appendix B for 

details. 

fault.dat - Contains 3 fault flag = 1 if there was a fault 

= 0 if no fault was detected. 

curfl.dat - Contains the current orbit number and 

a reconditioning flag for each battery = 1 for reconditioning 

= 0 no reconditioning. 

curf2.dat - Contains Phase (charge or discharge) 

Day-min 

Current from 13 SPAS (Solar Panel Array) 

Current from 3 Busses 

Average Temperature for 6 Batteries 

curf3.dat - Contains 6 battery cell voltages (23 per battery) 

showfl.dat - File contains battery voltage at EOD for last 12 orbits, in 

chronological order. 

showf2.dat - File contains the battery voltage during high in-charge 

period, last 12 orbits. 

34 
showf3.dat - File contains the recharge ratio = AHO/AHI per orbit for 12 

orbits. 

showf3.dat - File contains cell voltages at EOD, with the high value, io^ 

v3lue and average of all values, in this order for each of the last 12 

orbits 

showf5.dat - File contains cell voltages at high-charge: high, ?ow and 

average of all values, order H,L,A, for each of last 12 orbits, per 

battery. 

showf6.dat - File contains 23 cell voltages at EOD for each battery, from 

the latest orbit. 

showf7.dat - File contains 23 cell voltages at high-charge for eacn 

battery, from latest orbit. 

showf8.dat - File contains the averages of the six temperature sensors 

(degrees C), at two minute intervals over the latest orbit. The first 

value in this file is the minute into orbit, followed by the temperature 

readings for the batteries. 

showf9.dat - File contains the average battery temperatures per orbit for 

the last 12 orbits. 

showfl0.dat - File contains the 23 cell pressures taken at EOC and thttn 

EOD for each battery in the last full orbit. 

showfll-dat - File contains the time on trickle charge for each battery 

from last 12 orbits. 

showfl2.dat - File contains battery current during reconditioning, at 

2-minute intervals, for last reconditioning of each battery. It is 

recorded every 2 minutes, only when battery reconditioning is 1 and only 

for one orbit. The file contains zeroes until a battery is reconditioned. 

showfl3.dat - File contains AH0 summed at EOD over last 12 orbits. 

35 
. 

SECTION 4. PROGRAM MAINTENANCE PROCEDURES 

4.1 Conventions. 

Each routine in 

weli as code d 

the programs comprising the Data-Handler have headers as 

.ocumentation. The Expert System files are documented in 

separte files having the same name as the Prolog program but with 'doc' as 

their extension. 

a. Conventional extensions to file names are designed as nmemonic 

identifiers (file and variable names) based upon descriptive 

abbreviations of function title. 

C 'C' programs 

ob j object files 

exe executable files 

asm assembler programs 

Prg Prolog programs 

dat data files 

doc document files 

b. Refer to SAMSO EX 2.3.3 and MIL-STD-847 (Documentation). 

4.2 Verification Procedures. 

Any enhancements added to the Data-Handler should be verified by checking 

the data output files. It is always wise to test the changes on a small 

test case before running the whole procedure. One enhancement that could 

be made is to increase the error checking on incoming telemetry so that 

faults could be detected directly from the Data-Handler. Another 

enhancement would be to check the ranges on each telemetry value as it is 

read in. 

Changes to the Expert System logic would have to be verified by a Nickel 

Cadmium Battery 'expert' for validity. These could include changes to the 

deviation factors, threshold variations and adding conditions to be 

checked. Enhancements to the screen displays can obviously be checked by 

running the Expert System and viewing the screen. 

The Test Procedures listed in Appendix C will give you a baseline upon 

which to verify any changes. 

4.3 Error Conditions. 

There are no special provisons for operating system errors. Procedures to 

take at such instances would include rebooting the IBM-PC AT, checking to 

see that all files are intact and starting the NICBES system again. 

4.4 Special Maintenance Procedures. 

Data files written by the Data-Handler need to be archived for Later use. 

One way of doing this would be to create a data directory at the root. 

Then for each set of data files created, a sub-dir,ectory could be created 

into which the data file set could be copied. This sub-directory can then 

be referrenced by location and time. A command file - data.bat, has been 

@ written for just this purpose. It is located in C:\USR. To run data.bat simply enter 'data directory-name <CR>'. The directory-name can be a 

date as 01-16-87 for later referencing. 

36 
It is also wise to make periodic backups of the NICBES system 3s well as 

the accumulated data. There is no need to backup the YICROSOFT C 

directories (except C:\.USR) or the ARITY PROLOG files as these can always 

be re-installed from their original disks. 

4.5 Special Maintenance Programs. 

There are no special maintenance programs. 

4.6 Listings. 

All NICBES program listings will accompany this Maintenance Yanual. The 

'Cy programs are documented internally while the Prolog programs ore 

documented in files with the same name as the Prolog routine but with 

'doc' as their extension. APPENDIX A contains the Data-Handler listings. 

APPENDIX B contains the Expert System listings. 

37 
APPENDIX A 

DOCUMENTED CODE LISTINGS FOR THE DATA-HANDLER 
ORlGMAL PAGE fS 

W POOR QUUm 

HST. H 

;.: 

a-1 
ORIGINAL PAW fS 

OF POOR QUALm 
/ ':I: i .:I. ! 

4- 3 
. 
DATA-HDL . C 
, . 

ORIGINAL PAGE Is 

OF POOR C)Um 
ORIGINAL PAGE IS 

Of POOR QU- 
READ-DAT. C 

#define TlLIMIT 2 

?define T2LIMIT 180 

#include "hst. h" 

char buf [2048] ; 

int count; 

float ce11[23]; 

......................................................................... 

read-data0 /* Read telemetry from DEC LSI-11 over RS232 every 1 min.*s 

< 

/* Call proc-sync to read start character 'A', call proc-head to rend*/ 

/* header info, proc-bat() to read battery data, and proc-solar to *i 

/* to read SPA and bus data *:: 

int err; 

Proc-sYncO ; 

count = 0; 

if ((err = proc-heado) == FAIL) return(FA1L); 

if ((err = proc-bat()) == FAIL) return(FA1L); 

if ((err = proc-solar()) == FAIL) return(FA1L); 

return(SUCCESS); 

1 /* end read-data */ 

~*******************************************************%********~******~ 

proc-sync() /* Synchronize reading data to start of telernetrv burst.* 

i 

char cc; 

while (cc = get2()) /* Get character from */ 

/* interrupt hdlr buffer *: 

if (cc == 'A'>- /* If 'A',telemetry start*;.' 

{ i* printf ("Sync Received! \n") ; */ 

break; 

if(cc == 'B') 

I 

/* If 'B', shutdown *,/, 

i 

printf("\n\nReceived shutdown signal from DEC LSI-ll!\n"); 

i* fault[O] = 1; 

fault[l] = ?; 

wf (FAULTDAT) ; */ 

. finish(); 

1 

} /* end while loop */ 

cc = getlo; 

cc = getlo; 

} /* end proc-sync */ 

/* Read newline and CR t! 

/* to position pointer at*,: 

/* next character */ 

Et- 1 -R 
.......................................................................... 

proc-head0 /* Read header data from input buffer. *,/ 

int err: 

if ((err = read-buffer(9)) == FAIL) ;* Resd 9 header items t: 

return!FAIL): 

sscanf (buf, "ZdXd%d%d%d%d%d%d%d" , /* Put header data in buf*/ 

Rhid[l].year,&hidil].day, /* into structured array */ 

&hid[l].hour,&hid[l].min, /* hid[l] in int format *: 

&hid[l].sec,Rhid[l].orbit,&hid[lj.phase, 

&hid[l].day-min,&hid[l].night-min); /* Print header data ** 

/* printf("time=Xd\nday=%d\nhour=%d\nmin=kd\nsec=%d\norbit=%d\nphase=~d\n, 

day-min=%d\nnight-min=%d\n\n", 

hid[l].year,hid~l].day,hid[l].hour,hid[l].min,hid~l].sec, 

hid[l].orbit,hid[l].phase,hid[l].day_min,hid[l].night-minj: */ 

return(SUCCESS); 

j /* end proc-head */ 
/*******J********************************************~*****************~~ 

{ 

proc-bat ( j /* Read battery data from input buffer. t/ 

int j,k,err; 

for! k=O; kt:6: k++j ,;* For 6 batteries */ 

1 if ((err = read-buffer(1)) == FAIL) /* Read battery no .1: /I 

return(FA1L); 

/* 

s s canf ( buf , "?id" , &hid [ 1 ] . bat d [ k ] . bat t no ) : i* Put Suf */ 

/* contents into hid[l] k,' 

printf("batt no = %d, count = %d\n",hid[l].batd[kj.battno,counti: x 

if ((err = read-buffer(23)) == FAIL)/* Get 23 cell voltages *,i 

return(FA1L); 

sscanf (buf , "tftfXf %fXf%f%f%f %f%f%f%f%f%f %f%f?if %f %f %f %f rf%f " , &cell[O],&cell~l!,&cell[~],&cell[3l,&cell[4~,&cell~~~, 

&cell[6l,&cell[7],&cell[8],&cell[9],&cell[lO],&cell~ll~, 

&ce11[12],&ce11[13],&cell[l4],&cell[l~],&cell[l6],&cell~li~, 

&ce11[18l,&ce11[19],&ce11[20],&cell~21],&cell[ZZ~~: 

for (j=O;j<23;j++) 

hid[l].batd[k].cellv[j] = cell[j]; 

if ((err = read-buffer(23)) == FAIL) /* Get 23 cell pressures x. 

return (FAIL) ; 

s s can f ( b u f , " 5 f % f % f % f X f % f % f % f % f t f Y f % f f f 5% f X f Z f 0; f5 f ?L f ?6 f % f 5 f 0: f " , &cell~O],&cell[l],&cell~2],&cell[3j,&cell~4],&cell~~~, 

&cell[6],&cell[7],&celi[8],&cell[9],&cell[lO~,&c~ll~ll~, 

&cell~12],&ce11[13],&cell[l4],&cellj151,&cell[l6],&cell[li~, '.-I31 \. &ce11~18],&ce11[19],&cell[2OJ,&cell[2l],&cell~~ -J! 9 

for (j=O;j<Z3;j++) 

hid[l].batd[k].cellp[j] = cell[j]; 

if ((err = read-buffer(l0)) == FAIL)/* Get remaining 10 bat */ 

return(FA1L) ; 

sscanf (buf, "%f%f%f%f%f%f%f%f%f%d", /* Put buf contents */ 

&hid[l] .batd[k] .batv, /* into hid[l] *i 

&hid[l].batd[k].batc,&hid[l].batd[k].bprcc, 

&hid[l].batdik].batemp[O],&hid[l].batd[k].batemp~l~, 

&hid[l].batd[k].batemp[Z],&hid[l].batd~k].batemp~3~, 

&nid[i].batdik].batempi4j,&hidilj.batdik~.bat~m~~~~, 

&hid[l].batd[k].batrecond); 

1 /* end for loop, battery 1 to 6 */ 

 SUCCESS) ; 

1 /* end proc-bat */ 

p- 3 -e 
......................................................................... 

proc-solar0 /* Read SPA and bus data from input buffer. */ 

int j,err; 

if (!err = read-buffertl3)) == FAIL! [* Get 13 SPA values * /' 

returniFAIL1; /* values from buffer t 

/* Put buf contents into * 

sscanf (buf, "?;fXf?~fXf%fXfXf#f~f#f~~f~f~ft', /* hid: 11 k 

&hid[lj.spac~O],&hidyll.spac~l],&hid~l].spac~Z~, 

&hid[l].spac[3],&hid[l].spac[4!,&hid[l].spac[5j, 

&hid[l].spac[6~,&hid[~].spac[7],&hid[l].spac[8j, 

&hid[l].spac[9],&hid[lJ .spac[lO],&hid[l].spac[ll], 

&hid[l].spacilZ]); 

if ((err = read-buffer(6)) == FAIL) /* 3 busses, volt snd b! 

return(FA1L); /* current for each *. 

sscanf (buf , "XfXf%fXf%f%f", i* Put buf contents * j 

&hid[l].bd[O].busv, /* into hidill *I 

&hid~l].bd[O].busc,&hid[l].bd[l].busv,&hid[l].bd[l~.busc, 

&hid[l].bd[Z].busv,&.hid[l].bd[Z].busc); 

/* printf("so1ar count = %d\n",count); */ 

i * j. 

I/* for(j=O;j<s;j++j */ /* Print bus data * 

print f ( "bd [ 0;d j . busv = %f\n", j , hid [ 1 j . bd [ j 3 . busv ) ; 

printf("bd[%d].busc = %f\n", j,hid[l].bd[J].busc); 3 */ 

return(SUCCESS); 

j /* end proc-solar */ 

&- 4 -cc 
/**********************~**********1:*************************************~ 

int k; /* handler buffer and puts them in buf;? *, read-buffer(kj ;* Retrieves telemetry values from interrupt*/ 

int i=O, nl-count = 0; 

while(nl-count != k) /'* For k data points x; 

1 

if ((buf[i! = getlo) == EOF: /* Get each character *, 

return(FA1L); /* from input buffer and *I 

if(buf[i? == '\I-') /* put in buf, including *, 

/* newline and CR *, 

count++ ; /* count values read per */ 

/* telemetry run */ 

nl-count++; /* Returns FAIL if EOF */ 

if ((buf[i] = getlo) == EOF) /* read before end of * ,' 

return(FA1L); /* telemetry burst */ 

{- 

i 

i++; 

1 

buf[i] = '\O'; 

return(SUCCESS); 

/* sets end of data in *,; 

/'* in buf[i] 1: i' 

. i /* end read-buffer */ :I * * * * * * * * * ** * * ** * * * * * * * ** * * * * * * * * ** * * * * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * 

get10 /* get character from interrupt handler buffer * 

char cc; 

long to, tn, timer; 

time(&tO); /* initial time * ,: 

while ((cc = b-charo) == EOF) /* get char from interrupt*, 

{ /* handler buffer, EOFs */ 

/* start timer = tn - tO *,: timer = time(&tn) - to; /* tn is current time *! 

i* printf("get: count = Yd, timer = %ld\n",count,timer); */ 

if ((count < 370) && (timer > TlLIMIT)) /* check for incmplt*i 

return(E0F); /* run, TlLIMIT exceeded */ 

1 

returnicc) ; 

} /* end get */ 
/******s****************************************************************/ 

get2() ;* get character from interrupt handler buffer X/ f 

char cc; 

long to, tn, timer: 

time(&tO): 

while ((cc = b-char()) == EOF) 

, 

timer = time(&tnj - to; 

if (timer > T2LIMIT) 

printf(”No communication for 3 

fault[l] = -1; 

fault[O] = 1; 

wf (FAULTDAT) ; 

finish() ; 

1 

1 

return(cc); 

} /* end get */ 

,‘* initial tine t/ 

/* read char from interrupt*’ 

,/* handler buffer, EOFs *I 

/* start timer = tn - tO *,’ 

/* tn is current time 

I* Exit if T2LI4IIT is 

/* exceeded => No Commun.* 

minutes; exiting!\n”); /* wrrte fault flags *: 

*’ *‘ 
PROCESS. C 

+define DCHGLIMIT 30 

*define CHGLIMIT 50 

iinclude "hst. h" 

int no-druns,no-cruns; 

.......................................................................... 

df-init!) /* Initialization of buffers*/ r 

i 

int i,j; 

/* printf ("in df-init\n") ; */ 

fault[O] = 0; 

fault[l] = 0; 

no-cruns = no-druns = 0; 

for (i=O; iC6; i++) 

i 

batt-avgt [ i] = DEFLT; 

avg-temp-buffer[i] = 0.0; 

high-buffer[i] = DEFLT; 

ahoo[i] = 0.0; 

ahi[i] = 0.0; 

rc-orbitli] = 0; 

trickle[i] = 0; 

for (j=O;jilZ;j++) 

i 

eod-voltage[i] [jj = DEFLT; 

hc-voltage[ i] [ j] = DEFLT; 

cv-eod-hv[ij[j] = DEFLT; 

cv-eod-hv [ i] [ jj '= DEFLT; 

cv-eod-av[i][j] = DEFLT; 

cv-hc-hv[i][j] = DEFLT; 

cv-hc-lv[i][j] = DEFLT; 

cv-hd-av [ i ] [ j] = DEFLT; 

avg-temp[i] [j] = DEFLT; 

aho[i][j] = DEFLT; 

time-tc[i] [jj = DEFLT; 

rc-rstio[i][j] = DEFLT; 

1 

for (j=O;j<23;j++) 

cellv-eod[i][j] = DEFLT; 

ceilv-hc[i] [jj = DEFLT; 

cp-eod[ i] [ j] = DEFLT; 

cp-eoc[ i] [ j] = DEFLT; 

1 

/* FAULTDAT buffer *! 

/* FAULTDAT buffer * ,/ 

it run counters */ 

/* for 6 batteries *. 

/* CURFZDAT buffer $! 

/* SHOWFSDAT work buffer */ 

/* SHOWFZDAT work buffer */ 

/* SHOWF3DAT work buffer */ 

/* SHOWF3DAT work buffer *,I 

,'* SHOWF11DAT work buffer* ' 

/* SHOWFlZDAT buffer *. 

/* for 12 orbits * ,' 

/* 

/* 

/* 

/* 

/* 

/* 

/* 

/* 

/* 

/* 

/* 

/* 

SHOWFlDAT buffer 

SHOWFZDAT buffer 

SHOWF3DAT buffer 

SHOWF4DAT buffer 

SHOWF4DAT buffer 

SHOWF4DAT buffer 

SHOWF5DAT buffer 

SHOWF5DAT buffer 

SHOWF5DAT buffer 

SHOWFSDAT buffer 

SHOWFl3DAT buffer 

SHOWFllDAT buffer 

X' 

*, 

*,I *. 

*/ *.' 

*/ *' 

*/ 

*i' 

*I' *' 

/* for 23 cells per batt */ 

/* SHOWFGDAT buffer */ 

/* SHOWF7'DAT buffer *i 

/* SHOWFlODAT buffer *// 

/* SHOWFlODAT buffer *,/ 

P- 1-P 
for (j=O;j<48;j++) 

avgtri] [j] = DEFLT; 

bc-drc[i][jJ = 0.0; 

> 

wf c, FAULTDAT! ; 

3 /tend df-init *// 

/* SHOWFBDAT buffer */ 

/* SHOWFlBDAT buffer */' 

,'* write no fault yet x 

k- 2-Q 
......................................................................... 

int phase-signal; /* to be re-initialized. */ 

< 

df-initl(phase-signal) /+ After each telemetry burst is read, or after*/ 

/* EOC or EOD, buffers used for processing need*: 

int i,j; 

:* printf!"in df-initl \n",!; */' 

switch(phase-signal) 

case EOC: 

no-cruns = no-druns = 0; 

for (i=O;i<6;i++) 1. 

avg-temp-buffer[i] = 0.0; 

high-buffer[i] = DEFLT; 

ahi[i] = 0.0; 

ahoo[iJ = 0.0; 

for (j=O;j<23;j++) 

cellv-hc[ i] [ j J = DEFLT; 

cp-eoc[ i] [ j] = DEFLT; 

cp-eod[i] [ j] = DEFLT; 

cellv-eod[i][j] = DEFLT; 

1 

for i j=O; j<48; j++) 

avgt[iJ:j] = DEFLT; 

break: 

case EVMIN: 

for (i=O; i<6; i++) 

hidtohido; 

break; 

batt-avgt [ i] = DEFLT; 

1 /* end switch */ 

} /* end df-initl */ 

/* start switch */ 

/* EOC case 

/* run counters 

*/ * :' 

/* SHOWFSDAT work buffer */ 

/* SHOWFZDAT work buffer */ 

/* SHOWF3DAT work buffer */ 

/* SHOWFSDAT work buffer */' 

/* for 23 cells per batt *,/ 

/t SHOWF7DAT buffer *./ 

/* SHOWFlODAT buffer * I' 

/* SHOWFlODAT buffer */ 

/* SHOWFGDAT buffer ai 

/* SHOWF8DAT buffer *:i 

/* end EOC case *; 

/* No EOD case */' 

/* Every Minute case *j 

/* for 6 batteries */ 

/* CURFZDAT buffer */' 

,l* switch hid columns */ 

/* end EVMIN case * i 

pr- 3 -P 
. 

a ......................................................................... 

hidtohido /* After each telemetry burst is read and processed, the */ 

/* data in hid[l] is put in hid[O] to prepare for next *.' 

/* data burst which will be read into hid[lj. a .' 

1 

int i, j; 

,!* printf ( "in hidtodhid, ready to exchange buffers\n"); ti' 

hidC0j.year = hid[l].year; /* switch header items *:' 

hid[O].day = hid[l].day; 

hid[O].hour = hid[l].hour; 

hid[O].min = hid[l].min; 

hid[O].sec = hid[l].sec; 

hid[O].orbit = hid[l].orbit; 

hid[O].phase = hid[l].phase; 

hid[l].phase = DEFLT; 

hid[O].day-min = hid[l].day-min; 

hid[l].day-min = DEFLT; 

hid[O].night-min = hid[l].night-mini 

for (i=O; i<6; i++) /* switch battery items */ 

hid[O].batd[iJ.battno = hid[l].batd[i].battno; 

for (j=O;j<23;j++) /* for 23 cells per batt *,I' 

{ 

hid[O].batd[i].cellv[j] = hid[l].batd[i].cellvrjll 

hid[l].batd[i].cellv[j! = DEFLT; 

hid[O].batd[i].cellp[j] = hid:lJ.batd[i:.cellp[j:: 1 

i 

hid[O].batd[i] .batv = hid[l].batd[i].batv; 

hid[0] .batd[i] .batc = hid[l] .batd[i] .batc; 

hid[O].batd[i].bprcc = hid[l].batd[i].bprcc; , 

for (i=O; i<13; i++) /* switch SPA items *,.' 

hid[O].spac[i] = hid[l].spac[i]; 

hid[l].spac[i] = DEFLT; 

for (i=O;i<3;i++) /* switch bus items 

hid[O].bd[i].busv = hid[l].bd[i].busv; 

hid[O].bd[i].busc = hid[l].bd[i].busc; 

hid[l] .bd[i] .busc = DEFLT; 

{ 

> 

3 /* end hidtohid */ 

*/ 

A-4% 
......................................................................... 

?: 

move-buffers(phase-signal) /* Prepares the global buffers for move */ 

int phase-signal; 

<;* printf("in move-buffers, ready to move buffers\n"); t/ 

switch(phase-signalj /* start switch 

case EOC: 

moveihc-voltage); 

move(avg-temp); 

move(time-tc); 

move!cv_hc-hv) ; 

move(cv-hc-lv); 

move(cv-hc-av); 

break; 

case EOD: 

move(eod-voltage); 

moveirc-ratio); 

moveiaho); 

move(cv-eod-hv); 

move(cv-eod-lv); 

move(cv-eod-av); 

break; 

:f ' 

/* start EOC case t. 

/* SHOWF2DAT buffer *' 

/* SHOWFSDAT buffer * .' 

/* SHOWFllDAT buffer *.' 

/* SHOWFSDAT buffer *: 

;* end EOC case * ,/ 

/* start EOD case *: 

/* SHOWFlDAT buffer il: " 

/* SHOWFSDAT buffer * 

/* SHOWF13DAT buffer */ 

/* SHOWFIDAT buffer *< 

/* end EOD case 

/* no EVMIK case 

%/' *. 

j i* end switch */ 

:. /* end move-buffers0 */ 

/*****************************************************************%**~~~/ 

move(buffer) /* If the Data-Handler contines after 12 completed orbitst 

/* the buffers(6,12) will lose their first column, the t: 

/* remaining data will be shifted one column to the left,* 

/* the next orbits data will be put in the 12th column. t' 

float buffer[6][12]; 

i 

int i,j,jj; 

for(i=O; i<6; i++) /* for 6 battery rows */ c 

1. 

for (j=O;j<lO;j++) /* for 11 orbit columns XI 

i /* column 1 is dropped %' 

jj = j+l; /* shift each column one */ 

buffer[i][j] = buffer[i][jj]; /* column to the left * 

3 

buffer[i] [ll] = DEFLT; /* initialize 12th column*/ 

1 

} /* end move */ 

R- 5-Q 
.......................................................................... 

process-data(phase-signa1,orbitno) ,'* Perform mathematical operations */ 

int phase-signal, orbitno; /* results in global buffers. */' 

i 

/* to summarize telemetry. Keeps t 

int current-min,col; 

int jj,i,j: 

float x,sl,x2,x3; 

float sum,avg; 

I'* printfi "in process-data\n") ; */ 

if (orbitno > 11) 

i 

col = 11; 

move-buffers(phase-signal); 

)else col = orbitno; 

switch(phase-signal) /* start switch */ 

T 

case EOC: 

jj = no-cruns + no-druns; 

if (jj < (CHGLIMIT + DCHGLIMIT)) 

break; 

j* start EOC case */ 

/t Enough runs? t,' 

for (i=O; i<6; i++) /* for 6 batteries */ 

c 

avg-templi] [colj = avg-temp-buffer[i]/jj; /* SHOWFSDAT buffer*!/ 

if (ahoo[i] != 0.0) /* SHOWFSDAT buffer :* ; 

rc-ratio[iJicol] = ahi[i]/ahoo[i]; 

if (trickle[i] != 0) /* SHOWFllDAT bufTer * /' 

time-tc[iJ[col] = trickle[i]; 

for(j=O;j<23;j++) /* for 23 cells per batt f:' 

cp-eoc[i][j] = hid[O].batd[i].cellpEj!; 

/* SHOWFlODAT buffer */ 

*/ 1 

break; /* end EOC case 
case EOD: 

if (no-druns < DCHGLIMIT) 

break: 

for!i=O: i<6; i++) 

/* start EOD case */ 

/* Enough discharge runs?*/ 

,I* for 6 batteries * ,! 

1 

eod-voltageii] icolj = hid[O].batdji].bstv; 

/* SHOWFlDAT buffer *, 

aho[iJ[col] = ahoo[i]; /’% SHOWF13DAT buffer *; 

xl = DEFLT; 

x2 = -DEFLT; 

x3 = 0.0: 

for(j=O;j<23;j++) 

i* high, low, avg of cell*.’ * .:

/* voltage at EOD 

/* for 23 cells per batt Jc/ 

J 

break; 

x = hid[O].batd[i].cellv[j]; 

if (x > xl) xl = x; 

if (x < x2) x2 = x; 

x3 = x3 + x; 

cellv-eod[ i] [ j] = hidC0 J . batd[ i] . cellv [ j] ; 

cp-eod[ i J [ j] = hid[0] . batd[ i J . cellp [ j] ; 

cv-eod-hv[i][col] = xl; 

cv-eod-lv[i] [col] = x2; 

cv-eod-av[i][col] = x3 ,’ 23.0; 

/’* SHOWFGDAT buffer 

/% SHOWFlODAT buffer 

/* SHOWF4DAT buffer 

1 

:* end EOD case 

*/’ 

*i * .:

c .’ 
/* start EVMIN case */ 

current-min = hid[l].night-min + hid[l].day-min; 

if (!(current-min t 2)) jj = current-minj2; 

jj = -1; 

for (i=O; i<6: i++j /* for 6 batteries x, 

sum = 0.0; 

for (j=O;j<6:j++) /* for 6 batt temp sensors*/ 

sum = sum + hid[l].batd[i].batemp[j]; 

avg = sum / 6.0; /* 3vg temp per battery J/ 

batt-avgtji] = avg; /* CURFZDAT buffer * 

avg-temp-bufferii] = avg-temp-buffer[i] avg; /* SHOWFSDAT buffer *' 

if (jj != -1) /* every 2 minutes */ 

{. avgt [i] [ jj J = avg; /* SHOWF8DAT buffer t I' 

if (hid[l].batd[i].batrecond) /* SHOWFlSDAT buffer x. 

{ 

if ((rc-orbit[ij != hid[l].orbit) && 

(rc-orbit[i] != 0)) 

rc-orbit[i] = hid[l].orbit; 

for (j=O; j<48; j++) 

{ 

bc-drc[iJ[j] = 0.0; 

bc-drc[ij[jj] = hid[l].batd[i].batc; 

J 

1 

1 
. , 

a if (hid[l].phase) /* CHARGE PHASE */ 

{ 

no-cruris++; 

for (,i=O; i<6; i++) 

/* increment charge runs f: 

/* for 6 batteries * 

xl = high-bufferfi]; /* high, low, svg of ceii*; 

x2 = -DEFLT; /* volts at high-charge * 

x3 = 0.0; 

for(j=O;j<23;j-+) /* for 23 cells per batt*,' 

i; 

x = hid[l].batd[ij.cellv[j!; 

if (x > xl) xl = x; 

if !x < xZ) x2 = x; 

x3 = x3 + x; 

1 

cv-hc-lvCi] [col] = x2; /* SHOWF5DAT buffer 

if (high-buffer[i] < xl) 

cv-hc-hv[i] [col] = xl; 

cv-hc-av[i][col] = x3 / 23.0; 

hc-voltage[i] [col] = hid[l] .batd[i] .batv; 

/* SHOWFZDAT buffer ti' 

for (j=O;j<23;j++) /X SHOWF7DAT buffer */ 

cellv-hc [ i j [ j ] = hid[ 11 . batd[ i] . cellv [ j j ; 

x = hid[l].batd[i].batc; 

ahiCi] = ahi[i] + !x/60.0); /* SHOWFSDAT work buffer *' 

print f ( "ahi [ %d] = Xf \n" , i , ahi [ i j j : 

if (x < 3.0) 

1 

trickle[i] = trickle[i]++;/* SHOWFllDAT work bufferr' 

I /* end CHARGE case T 

jelse{ 

if (!hid[l].phase) /* DISCHARGE PHASE *; 

{ 

no-druns++; i* incr discharge runs t/ 

for(i=O;i<6;i++) /f for 6 batteries *' 

ahoo[i] = ahoo[i] - (hid[l].batd[i].batci60.0); 

1 /* SHOWF3DAT work buffer */' 

*,: 1 /* end DISCHARGE case * break; /t end EVMIN case 

1 /* end switch */ 

1 /t end process-data() ti 

9 -? 
......................................................................... 

check-fault ( ) /* check telemetry for a fault */ 

int i, j; 

float x,sum; 

x = hid[l!.spac[i]; 

if ((hid[l].day-min < 5) && (x < 5.0)) 

j = (i + l)/Z; 

if (j) 

{ 

}else{ 

j 

return(FA1L); 

if (x >= 16.0) return(FA1L); 

if (x >= 8.0) return(FA1L); 

if (!hid[l].phase && (x > 5.0)) return(FA1L); 

I 

for (i=O; i<6; i++) 

sum = 0.0; 

for (j=O;j<6;j++) 

sum = sum + hid[l].batd[i:.batemp[J]: 

{ 

1 

if ((sum > 25.0) :: (sum < -10)) return(FA1L); 

for (j=O;j<23;j++) 

i 

x = hid[l].batd[i].cellv[j]; 

if ((x <= 0.0) :: (x > 1.55)) return(FA1L); 

1 

1 

sum = 0.0; 

for (i=O; i<3; i++); 

x = hid[l].bd[i].busc; 

sum = sum + x; 

if(!hid[lj.phase && (x ( 5.0)) return(FA1L); 

1 

if (sum ? 99.0) return(FA1L); 

return(SUCCESS); 

} ,’* end check-fault */ 
t 

WRIT-FIL. C 

#include "hst. h" 

......................................................................... 

write-file(phase-signa1; /* Determines which data files should *, 

.i n t phase-s ignal; /* be written at this time. t/ 

int err; 

/* printf ("at write-file\,n"); */ 

switch(phase-signal) ,'* start switch *, 

i 

case EOC: /* start EOC case */ 

if (!(err = wf(SHOWF2DAT))) printf("Cou1dn't open ~s\nn,"showf2.dat"!; 

if (!(err = wf(SHOWF3DAT))) printf("Cou1dn't open %s\n","showf3.dat"~; 

if !!(err = wf(SHOWF5DAT))) printf("Cou1dn't open Xs\n1',"showf5.dat"~; 

if (!(err = wf(SHOWF7DAT))) printf("Cou1dn't open ~~s'\n","showf7.dat"~; 

if (! (err = wf(SHOWF8DAT)) 1 printf(."Couldn't open ~s\n","showf8.dat"~: 

if (.!(err = wf(SHOWF9DAT))) printf("Cou1dn't open Zs\n","showfS.dat" : 

if (! (err = wf(SHOWF11DAT))) printf("Cou1dn't open ?~s\n","showf!i.dat" : 

if (! (err = wf(SHOWF12DAT))) printf("Cou1dn't open Ys\,n",."showf12.dat"': 

if (! (err = wf(SHOWF1ODAT))) printf("Cou1dn't open Xs\n","showflO.dat"): 

break: /t end EOC case * / 

case EOD: 

if (! (err = wf(SHOWF1DAT)) > printf("Cou1dn't open o~S\n","showfl.dat" : 

if (!(err = wf(SHOWF4DAT))) printf!"Couldn't open ~~sS~\n","showf4.dat":

if (!(err = wf(,SHOWFGDAT))) printf("Cou1dn't open ~~s\n","showf6.dat"!: 

if (! (err = wf(SHOWF13DAT))) printf("Cou1dn't open ?~s\n","statfl.dat" ', 

break: /* end EOC case .x .' 

case EVMIN: /* start EVMIN case * ,! 

if (! (err = wf(CURF2DAT))) printf("Cou1dn't open ~~s\~n","curfZ.dat"): 

if (!(err = wf(CURF3DAT))j printf("Cou1dn't open Xs\,n","curf3.datf'); 

if (! (err = wf(CURF1DAT))) printf("Cou1dn't open %s\n","fault.dat"i: 

break; /* end EVMIN case *i 

} /* 'end switch */ 

} /* end write-file */ 
......................................................................... 

/* containing summarized and condensed telemetry. */' 

int filename; /* Files are written at EOC, EOD or Every Minute. c .: 

wf(fi1enamej /* Write output files for Expert System from buffers */ 

FILE tsfp: /a Show File# Pointer*/ 

int i, jyerr; 

switch f i lename) /* Write data output File A' 

c 

case S HOWF 1D AT : /* Write showfl.dat, contains .j! 

err = write~fl("showfl.dat",eod_voltage,l~; /* EOD voltages per t 

return(err); /'* orbit, per batt f 

case SHOWF2D AT : \* Write showfZ.dat, contains * 

err = write-fl("showf2.dat1',hc-voltage,2); /* high-voltages per *,/ 

return(err); /* orbit, per battery*, 

case SHOWFSDAT: /* Write showf3.dat, contains *' 

err = write-fl("showf3.dat",rc-ratio,3); /* recharge ratio per * 

return(err) ; /* orbit, per battery zi 

case . SHOWF4DAT: /* Write showf4.dat) contains *; 

err = write,f2("showf4.dat'~,cv~eod_hv,cv_eod~lv,cv~eo~~av,~~; 

return(err); /* high, low & avg cell volts f. 

per orbit and per battery * 

case SHOWF5DAT: /* Write showfS.dat, contziins:c 

err = write~f2!,"showf5.dat",cv_hc~hvycv~hc~lv,cv~hc~av,~~; 

return (err) ; /* high, low t& avg of 23 cellx 

/* voltages st high charge * 

/* per orbit, per battery * 

case SHOWFGDAT: /* Write showf6.dat, containsf' 

err = write~f3("showf6.dat",cellv_eod,6); /* 23 cell voltages at*,; 

return(err); /* EOC,per orbit, per battery*( 

case SHOWF7DAT: /* Write showf?.dat, containsf; 

err = write-f3("showf7.dat",cellv-hc,7); /* 23 cell voltages at *: 

/* high charge per */ 

return(err); /* orbit, per battery f, 
0 

case -SHOWF8DAT: /* Write showfB.dat, contains*l' 

if ((sfp = fopen("showf8.dat","w")) )= 0) /* average temp per X, 

1 it batt every 2 mins *,' r 

fprintf(sfp, "showf(8, ["); 

for (i=O: i(6; 1--) 

r 

fprintf (sfp, ":") : 

for ij=O; j<48; jtij 

r.,-., 

t 

if (j ? = 47) fprintf (, sfp, "?if, ", avgt 1: : J j ,; J 

e Is e f pr in t f ( s f p , "?; f " , av gt i i j [ j j > ; 

1 

if (i != 5) fprintf(sfp,"] ,\,n"); 

else fprint f (sfp, "1 3 ) . ") ; 

3 

fclose( sfp) ; 

return(SUCCESS); 

}else return(FA1L); 

case SHOWFSDAT : /* Write showfg.dat, contains*.' 

err = write-fl("showf9.d3t",3vg-temp79); /* average temperature * 

returnierr); /* per orbit, per bait Ik: 

case SHOWF 1 OD AT : /* Write showflO.dat, cont3ins* 

if ((sfp = fopen("showflO.dat",'*w")) >= 0) /* 23 cell pressures b 

i /* at EOC & EOD for last fuil * 

fprintf(sfp, "showf(l0, [">; /* orbit, per battery ?. 

for ii=O; ii6; i++) 

fprintf(sfp, "["I; 

for (j=O; j<23; j*+) 

f print f ( sf p , "ff , " , cp-eod [ i I [ j 3 ; 

for (j=O; j<23; j++) 

if (j != 22) fprintf(sfp,"kf,",cp_eocCilrj:)l 

else fprintf (sfp , "%f", cp-eoc [ i 1 [ j J ) ; 

3 

if (i != 5) fprintf(sfp, "1 ,\n"); 

e 1s e f pr in t f ( sf p , *' ] ] ) . " ) ; 

1 

fclose(sfp); 

return(SUCCESS); 

!else return(FA1L);- 

pt- 3-w 
case SHOWFllDAT: jt Write showfll.dat, contains* 

err = write~fl~"showfll.dat", time-tc, 11); !* trickle time per * 

return(err); /* orbit, per battery k 

c'as e SHOWF12DAT: /* Write showf12.dat, contilln~

if ({sfp = fopenit'showfl2.dat'',"w")) ?= 0: '* bat.tery currpnt = 

/* durlng recondltionlng TI 

fprintf(sfp, "showf(l2, ["); 2 min intervals per batter:: 

for (i=O; i<6; i++) ? 

f p r in t f ( s f p , for (j=O; j<48; j++) 

" [ ?Ad , " , r c- o rb i t [ i j 1 ; 

{ 

1 

if (i != 5) fprintf(sfp, "1,jn"); 

else fprintf(sfp, "1 j)."); 

if (j != 47) fprintf(sfp,"%f,",bc-drc[i] [jj); 

else fprintf(sfp,"Xf",bc-drc[i] [ j]); 

fclose(sfp) ; 

return(SUCCESS); 

]else return( FAIL) ; 

case SHOWF13DAT: /t Write showl3.dat, contains. 

err = write-fl("showfl3.dat",aho,l3); /* AH0 per orbit,per battery 

return(err) ; 

case CURFlDAT: /* Write curfl.dat, contains 

if ((sfp = fopen('~curfl.dat'',"wn)) >= 0) It .orbit number hi ,f 

/* reconditioning flags per ' 

fprintf(sfp, "curf(1, [Yd, [",hid[l] .orbit!; j* battery 

for (j=O; j<6; j++) 

* 

i 

if (j != 5) 'fprintf(sfp,"Xd,",hid[l].batd[j].batrecond~; 

else fprintf(sfp, "%d]]).",hid[l] .batd[jj .batrecond~; 

f close (sfp) ; 

return(SUCCESS); 

}else return(FA1L); 

A- 4-. \J 
case CURFZDAT: /* Write curf2.datY contains*.; 

if ((sfp = fopen("curf2.dat","wn)) >= 0) /* AHI,XHO, phase,*/ 

/* 13 SPA currents, average *:? 

/* temperature for each battt.' 

{ 

f pr in t f ( sf p, "curf ( 2, [?id, ?id , \n [ " , hid [ 11 . phase, hid [ 1 j . day-mi n :! : 

for (j=O; j'13; j++! 4 

if ( j ! = 12 ) fpr in t f s f p , "06f , " , hid [ 1 3 . spnc j j j ; 

else fprintf(sfp,"%f",hid[l] .spac[j; j; , 

J 

fprintf(sfp, "1 , \n["j I 

for (j=O; j<3; j++j 

{ 

if (j != 2) fprintf(sfp, "~f,",hid~l].bd[j].busc); 

else fprintf(sfp, "%f",hid[l].bd[j].busc); 

1 

fprintf (sfp, "I, \n[") ; 

for (j=O; j<S; j++) 

i 

1 

fclose(sfp); 

return(SUCCESS); 

if ( j ! = 5) fprint f ( sfp , "#f , " , bat t -avgt [ j 3 ; 

else fpr in t f (sf p , "%f 3 ] ) . '' , bat t-avgt [ j 1 ) ; 

!else return (FAIL) ; 

case CURFSDAT: ,'* Write curf3.dat, contains 7. 

if ((sfp = fopen~''curf3.datn,"w")) >= 0) /* day min, night rnrn L 

r /* 23 cell voltages per batt 3' i 

fprintf(sfp, "curf(3, ["); 

for (i=O; i<6; i++) 

i 

fprintf(sfp, 'I[*'>; 

for (j=O; j<23; j++) 

if (j 

else fprintf(sfp,"Xf", hid[l] .batd[i] .cellv[ j] ;; 

! = 22)fprintf (sfp,"%f, ", hidill .batd[i] . cellv [j1 

if (i != 5) fprintf(sfp, "J,\n"); 

else fprintf(sfp, "Ij)."); 

1 

fclose(sfp); 

return(SUCCESS); 

} else return(FA1L); 
, 

case FAULTDAT: /* fault.dat has fault */ 

if ((sfp = fopen(,"fault.dat","w")) >= 0) /* flag1 = 0 or 1 */ 

i /* flag:! = 0 or -1 $/ 

fprintf i sfp, "fault ( [?id, %dj ) . ", fault [O! , fault [ 1, 1 ; 

fclose(sfp); 

return(SUCCESS); 

:else return(FA1L); 

1 /* end of switch *; 

j /* end of wf X/ 
......................................................................... 

write-fl(filename,buffer,number) /* Write output file for Expert System*' 

char *filename; /* buffers containing summarized telemetry. *, 

float bufferL61 [12:; 

int number ; 

I, 

FILE *file; 

int i,j; 

if ((file = fopen(filename,"w")) >= 0) 

{L 

fprintf(file, "showf(%d, [",number); 

for (i=O; i<6; ii+> 

c 

fprintf(file, "["I; 

for (j=O; j<12; j++> 

if (j != 11) fprintf(file, "Yf,", buffer[ijijl); 

else fprintf(file, "%f", buffer[i] [j]); 

{ 

1 

if (i != 5) fprintf(file, "j ,\n"); 

else fprintf(file, "1 I)."); 

;b 

fclose(fi1e); 

return(SUCCESS); 

]else return(FA1L); 

j /* end write-fl *,' 

fi-7-w 
........................................................................ 

write_f2ifilename,bufferl,bufferZ,buffer3,number) 

char *filename: j* containing summarized and condensed telemetry. 

float bufferl[6j[lZ],buffer2[6] :12],buffer3[6][12:: 

int number; 

/* Write output files for Expert System from buffers * 

x 

FILE *file; 

int i,j; 

if ((file = fopen(filename,"w")) >= 0) 

L 

f p r in t f ( f i 1 e, 

for (i=O; i<6; i++) 

" show f i ?& d , i " , numb e r ) ; 

{ 

fprint f ( f i 1 e, 

for (j=O; j<12; j++) 

" [ " ) ; 

fprintf(file, "Xf,",bufferl[i] [jl); 

for (j=O; j<12; j++) 

fprint f ( file, "Yf , " , buff er2 [ i 3 [ j 1 ) ; 

for (j=O; j<12; j++) 

t 

if ( j 

else fprintf(file, "%f",buffer3[i] [jj); 

! = 11 ) fpr i n t f ( f i 1 e , "Xf , " , buff er3 [ i j j 1 ? ; 

1 

if (i I= 5) fprintf(file, "1 ,\n"); 

e 1 s e fp r in t f ( f i 1 e, " ] 3 ) . " ) ; 

1 

fclose (file) ; 

return(SUCCESS); 

)else return(~A1~); 

) /* end write-f2 */ 
.......................................................................... 

write-f3(filename,buffer,number) ,'* Write output file for Expert System*; 

char *filename; /* from buffers containing summarized telemetry. T 

float buffer[6] [23j; 

int number; 

FILE *file: 

int i, j; 

if ((file = fopen(filename,"w")) ?= 0) r 

f p r in t f ( f i 1 e, 

for (i=O; i<6; i-+) 

" s how f ( % d , [ " , numb e r 1 ; 

fprintf(file, "i"); 

for (j=O; j<23; j++) 

{ 

if (j != 22) fprintf(file,"%f,", buffer[i] [jj); 

else fprintf(file,"?~f", buffer[i] [jl); 

1 

if (i != 5) fprintf(file,!'!,\n"); 

else fprintf(file, "]I)."); 

1 

fclose(fi1e); 

return(SUCCESS); 

)else return(FA1L); 

} /* end write-f3 */ 
APPENDIX B 

CODE AND DOCUMENTATION FOR EXPERT SYSTEM 
PROLOG. IN1 

This is the initialization file for ARITY PROLOG. The directives 

in this file are run every time the Prolog interpreter is called, 

by typing "api" from the NICBES directory. Prolog.ini consults 

all the PROLOG programs needed to run NICBES (start.prg, 

faultd.prg, utility.prg, showpak.prg, grafpak.prg, status.prg, 

advice.prg). Any additional routines added to this package should 

be included in prolog.ini. All the data files necessary for 

the execution of the Expert System are copied to the NICBES 

directory. The current data files (curflN).dat, N = 1 to 3) and 

fault.datare loaded. begin/O is called to initiate the Expert System 
:- [’utility.pr~’,’showpak.p~~’,’grafpak.prg’y’start.prg’,’advice.prg’, 

’status.prg ’faultd.prg . 

% :Y shell(’copy c:\usr\showf*.dat .’)¶ 

x shell(’copy c:\usr\curf*.dat .’)’ 

% shell(’copy c:\usr\fault.dat .’). 

:- begin. 
Start.prg is the main driver for the NICBES. It calls faultd.prg 

if a fault flag is set. Otherwise is prints menus to the screen so 

that the user, by making selections, can determine what portion of 

the system to view next. 

....................................................................... 

PREDICATES AVAILABLE IN START.PRG 

begin/O--calls fault to read the fault flag. It also calls curf(1) to 

get the orbit number and reconditioning flags, which are both 

asserted to the data base for use by other routines. begin/l then 

calls eval-flag/l. begin/O is called by prolog.ini. 

eval-flag(F1ag)--if Flag is 1, control is passed to faultd.prg for 

fault diagnosis. When finished, the user is asked whether more 

information is desired. The user’s response is validated by chcckl/l 

and then continue/l is called. If Flag is 0, eval-flagil consults all 

the show files to load the data as facts. complete/l is then called 

to insure that enough values are present in the data set for accurate 

analysis. If there are too many missing data points the user is onlp 

allowed to view the graphics portion of the Expert System. sequence/l 

is called next to prepare the horizontal axis for plots which will be 

drawn later. write-message/l then brings up the Main Menu. 

eval-flag/l called by begin/O. 

continue(yes/noj--If yes, eval-flag(0) is called. ‘If no, all data files 

are deleted from the NICBES directory and PROLOG is halted. 

The user is returned to DOS. 

write-message(N)--brings the Main Menu to the screen and waits for user 

input which is checked for validity by check2/2. N is a flag which 

determines the allowable selections by the user. write-message/l 

operates in a repeat-fail loop so that the user can always come back to 

the Main Menu. There are 4 selections in the menu: 

NICBES MAIN MENU 

1. PLOTS AND GRAPHS 

2. BATTERY STATUS 

3. ADVICE ON RECONDITIONING, WORKLOAD AND CHARGE 

4. Quit NICBES 

ENTER YOUR SELECTION (e.g. l<CR> ): 

write-messagejl is called by eval-flag(0). It calls battery/l. 

battery(Choice)--Choice (1 - 4) is the item selection from the Main Menu. 

battery(4) calls continue(n0) to halt the Expert System. battery/l 

asks the user to select a battery. The user’s response is validated by 

check/2. exccute/2 is then called to execute the Main Menu Choice for 
the chosen battery. battery/l is in a repeat-fail loop so that the the 

user can make multiple battery selections. 

execute(Choice,Bat)--is called by write-message/l to pass control to the 

Choice selected in the Main Menu. There are 3 cases. 

execute(1,Bat)--Plots and Graphs. A Graphics Menu is written on the 

screen with 12 plots per battery. The user may also make another 

Battery Selection or Quit to the Main Menu. User’s choice is checked 

for validity by calling check/2. After the graph has been drawn on the 

screen the user is asked to enter ’<CR>’ when ready to continue. 

execute/2 is in a repeat-fail loop so that the Graphics Menu will always 

return until the user opts to return to the Main MEnu. show-viewi3 

(showpak.prg) is called to generate the plots. 

GRAPHICS MENU FOR BATTERY N 

1--Battery Voltage at EOD for last 12 orbits 

2--Rattery Voltage at high in-charge for last 12 orbits 

3--Recharge ratio for last 12 orbits 

3--Cell Voltages at EOD; high, low, average for last 12 orbits 

5--Cell Voltages at high in-charge; high, low, avg, last 12 orbits 

6--Cell Voltages at EOD for latest orbit 

7--Cell Voltages at high in-charge for latest orbit 

8--Average Battery Temperature for latest orbit, each 2 min 

9--Average Battery Temperature for last 12 orbits 

10-Cell Pressures at EOC and EOD for latest orbit 

11-Time on Trickle Charge for last 12 orbits 

12-Battery Current during reconditioning, 1 orbit, each 2 min 

13-Quit for Another Battery Selection 

14-Quit to Main Menu 

Enter choice (e.g. 5<CR> ): 

execute(2,Bat)--activates the Status analysis portion. .4 header is 

written to the screen, STATUS FOR BATTERY N, LATEST ORBIT NN. Then 

battery-status/l is called to analyze Battery Status after which the 

user can opt to make another Battery selection and return to Status or 

Quit to the Main Menu. 

execute(3,Bat)--An Advice Menu of five items is displayed to the user. 

User’s response is checked for validity by check/2. morei2 is called 

to activate the Advice portion of the Expert System. execute/Z is in a 

repeat-fail loop so that the Advice Menu will always return until the 

user opts to return to the Main Menu. 

BATTERY ADVICE MENU FOR BATTERY E 

1. RECONDITION BATTERY? 

2. CHANGE CHARGING REGIME? 

3. CHANGE WORKLOAD? 

4. QUIT FOR ANOTHER BATTERY SELECTION 

5. QUIT TO MAIN MENU 

ENTER CHOICE (e.g. 1<CR> ): 

. 
more(Choice,Bat)--writes a header to the screen, ADVICE FOR BkTTERY N, 

LATEST ORBIT NN. advice/2 (advice.prg) is then called. more/2 is called 

by execute(3,-). 
. 

ORIGINAL PAGE 1s 

apooRQUm 


3- 7-5 
Faultd.prg is the fault diagnosis section of NTCBES. It uses the 

current data contained in curfl.dat, curf2.dat, and curf3.dat to 

diagnose alarms to the system. Faultd.pr-g is automatically 

invoked by the system when the C language data handler det.ects an 

anomaly. It loads values into the database, diagnoses the 

problem, and cleans up the database, then quits. It is not 

accessible by the user. If more than one fault exists, it will 

diagnose them all. 

ALARMS FOR NICBES SYSTEM: 

More than 18 faults trigger the suggestion to "Check the control 

computer." This is a means to quantify the statement 

"lots of crazy data coming out means the control computer is faulty." 

The data handler monitors the telemetry as it comes in, and looks for 

values that indicate a serious malfunction of the system, for which the 

DEC LSI-11 has sent an alarm to the engineer. The alarms are in five 

categories: 

1. Power supplies 

Current from any SPA less than 5 A. durizg first five minutes of 

the day is a failure of power supply or control circuitry. 

Current greater than 8 A. for 1-SPAS (1,3,5,7,9,11) or 16 A. for 2-SPAS 

(2,4,6,8,10,12,13) is a failure in control circuitry. 

a. current < 5 A during first 5 minutes of charge period 

--check the 13 SPA currents (SPA I), phase is 1, day min. <= 5. 

b. current >= 8 A for 1-SPAs, >= 16 A for 2-SPAS 

--check the 13 SPA currents. 

c. current > 5 A during discharge period 

--check the 13 SPA currents, phase is 0. 

2. Batteries 

Cell voltage for any cell less than 0 means a failure in BPRC, 

and voltage of 0 means a short to a cell. Cell voltage for any 

cell greater than 1.55V. is a failure in control limit circuitry. 

a. Cell voltage <= 0 for any cell in any battery 

--check cell voltages 

b. Cell voltage > 1.55 for any cell in any battery 

a- 1 -e 
--check cell voltages 

3. Load banks 

Tf the sum of the current on busses A, R and C (Vl, V3, V3 in 

code) is greater than 99 A., bus overload has occurred, a failure 

of the control circuitry or load banks. If any of the bus currents 

is less than 5 A. during discharge period, a failure of control 

circuitry has occurred. 

a. Sum of three bus currents ? 99 A 

--sum the three bus currents (Bus I). 

b. Load < 5 A on any single bus during discharge period 

--check the three bus currents when phase = 0. 

4. Temperature 

If 1 battery has high temperature ( > 25C) during charge cycle, thermal 

runaway is suggested. If 2 or more have high temperature, it is 

suggested that the chamber be checked for cooling malfunction. 

If 1 or more batteries are cold ( < -lOC>, it is suggested that 

the chamber be checked for failure of coolant control (failed ON). 

Average of the six temperature sensors > 25 degrees or C -10 degrees 

--take the average of the six temp sensors. 

5. Communication 

More than two telemetry runs missed mean either a system shutdown 

or a communication failure to the PC and will trigger an alarm 

diagnosis by NICBES. NICBES resets the fault.dat flag file to 0. 

after an alarm diagnosis, so it is ready to start again when the 

system is restarted. 

No data coming into PC. 

------------_---__----------------------------------------------------- 

CURRENT DATA FILES: 

curf(2,[Phase,Day_rnin,Curlist,Vlist,Templist]). 

where Curlist contains 13 SPA Currents 

Vlist contains 3 Bus Currents 

Templist contains Average Temperature for 6 Batteries 

curf(3,[Voltlist]). 

where Voltlist contains 6 sublists, one for each battery, 

with 23 Cell Voltages each. 

fault([fault flag, Type]). 

--------------------______^_____________------------------------------- 

THE PREDICATES AVAILABLE IN FAULTD.PRG 
fault-diag--uses the current data files loaded in the database by 

prolog.ini to find the faults which cause alarms to the testbed system. 

Five classesof faults are diagnosed by calls to comm-fail/O, 

power-cir-fail/O, loadbank-fail/O, chamber-fail/O, and cell-fail,,'O. 

A message is written to the screen as each of the above are checked. 

If any of these five predicates discover a fault, they write a message 

to the screen. After diagnosis is done, diagnoseio checks the 

counter 20. If' more than 18 fault lines have been written in fault 

diagnosis, it suggests that the control computer be checked for 

sending bad data. It would be unlikely for that many faults 

to occur otherwise. diagnose/O is called automatically from 

eval-flag(1) (start.prg). 

comm-fail--checks fault([-,Type]). The Data-Handler will set this 

to -1 if it detects a failure in communication, 3 missed telemetry 

runs. comm-fail/O is called by diagnose/O. Fault diagnosis can still 

analyze last set of current data files. This may however be 

misleading so handle with caution. If no problem found, a message 

will be written to the screen so stating. 

chamber-fail--checks battery temperatures from Templist. If 

only one battery is hot ( > 25C), it suggest5 checking for thermal 

runaway. If more than one battery is hot, it suggests checking 

coolant control. If any battery is cold ( < -lOC), it suggests 

checking coolant control failed on. chamber-fail/O will always 

succeed, so that other faults can be diagnosed as well. If no 

problems found, a message will be written to the screen so stating. 

chamber_fail/O calls check_temp/Z . It is called by fault-dingi0. 

check-temp(Tempfist,Phase)--calls check-t to recursively check the list 

of temperatures. Counters 1 and 2 are used to store the number of 

high or low values found, respectively. Counter 3 is used to keep 

track of which batteries temperatures are being checked. checkl-t/3 

is called to check highs and lows. Diagnostic messages are printed. 

check_temp/2 is called by chamber-fail/O. 

check-t([HIT])--checks the head of the list (H) for missing data 

(-9999), or temperature out of range, prints a message if either 

condition holds, then calls itself on the tail of the list (T). 

Counter 3 keeps track of which battery is being checked. Counter 

1 keeps track of how many high values, and counter 2 counts low 

values. 

checkl-t(Highs,Lows,Phase)--checks number of Highs and Lows. Diagnostic 

messages are written to the screen. 

loadbank-fail--uses Phase and Vlist from curf(2,-j. check-busi2 and 

checkl-bus/Z are called to check for problems in the load bank. 

find_sum/2 is called to get the sum of the 3 bus voltages. 

loadbank-fail/O always succeeds, so that other problems can also 

be diagnosed. If no problems found, a message will be written to 
the screen so stating. load-bank/O is called from fault-diag/O. 

check-bus(Vlist,Phase)--checks bus values for missing data (-9999). 

If any bus has less than 5 A during discharge phase, failure 

of load bank or control circuitry is diagnosed. check-bus/J 

is called by loadbank-fail/O. 

checkl-bus(Sum,Phase!--if the sum of the bus currents is over 99A, 

failure of load bank or control circuitry is diagnosed. 

Called by loadbank-fail/O. 

power_cir-fail--uses Day-min, Fhase and Curlist from curf(2,-), then 

calls check_cur/3 to diagnose failures in SPAs. Counter 3 is used 

to keep track of which bus is being checked. power-cir-fail/O 

always succeeds, so other faults can also be diagnosed. If no 

problems found, a message will be written to the screen so stating. 

power-cir-fail is called by fault-diag/O. 

check-cur([H:T],Phase,M)--checks data from the list of SPA currents (Curlist' 

recursively, checking an item, then calling itself on the 

tail of the list. It checks for missing data (-9999)) then checks 

for malfunctions in SPAs. Possible malfunctions are current 

less than 5 A in first five minutes of charge period, current 

. from any SPA in discharge period, current of greater than 8 A 

from 1-SPAS (1,3,5,7,9,11), or current of greater than 16 A 

from 2-SPAS (2,4,6,8,10,12,13). check_cur/3 writes diagnostic 

messages to the screen. It is called by power_cir_fajl/0. 

cell - fsil--uses Voltlist from curf(3,-). Calls check-voltil to check 

each battery cell for problems. If no problems found, a message 

will be written to the screen so stating. 

cell-fail/O is called by fault-diag/O. 

check-volt(Volt1ist)--sets counter 3 to keep track of which cell is being 

checked. It recurses through the 6 lists of cell voltages, one for 

each battery. The recursive function read_volt/2 is called to check 

the voltages. check-volt/Z is called from cell-fail/O. 

read-volt([H:T],N)--checks the head of the list (H) for missing 

data (-99991, voltage of 0 (diagnoses hard short), negative 

voltage (diagnoses BPRC failure), and' voltage over 1.55 

(diagnoses overcharge). read_volt/2 then calls itself on the 

tail of the list (T). Counter 3 is used to keep track of which 

cell is being checked, for use in the failure messages. read_volt/2 

is called from check-volt/l. 


ORIGINAL PAGE I3 

OF POOR QUAW 
ORiGINIAL PAGE tS 

OF POOR QUAUTY 
ORIGINAL PAGE IS 

OF POOR QUALI'fY 
ORIGINAL PAGE IS 

OF POOR QUALrrV 

5-10 -c 
Status.prg has the STATUS portion of NI.CBES. Selecting Battery St.atus 

from the Main Menu for battery n (n is 1 through 6) will trigger the 

checking of battery n for reconditioning, temperature, workload, 

charging scheme, and divergence. Messages will be printed on the screen. 

The STATUS section uses averages of data from some of the showf(n).dats 

in its analysis. If nothing is wrong with the battery, a message 

is written to this effect. Problems with the battery often 

produce messages to use "Plots and Graphs" or "Advice" for more information 

........................................................................... 

The following conditions are examined: 

Condi ti on Status-- 

Temperature average over last orbit < 0, Cold 

and over last 12 orbits < 0 

Temperature avg. over last orbit > 11, Hot or possible overcharging 

and over last 12 orbits > 10 

Temperature avg. over last orbit > 11, Possible overcharging 

and over last 12 orbits < 10 

@ AH0 average over last 12 orbits < 3 

(3.0 Ampe;e-hours), and avg. EOD 

voltage < 27 

AH0 average over last 12 orbits i 14 

(14.0 Ampere-hours) 

Recharge ratio average < 1.020 

and avg. high-charge voltage < 32.5V 

Underwork 

Overwork 

Insufficient charge . 

High-charge voltage > 33.8 Possible overcharge 

Divergence average > .8V between 

high and low cells 

High cell minus average greater than 

(avg. minus low cells) + 1 

High divergence 

Too many cells to 

low values 

battery-statusiBat)--First, battery-statusji checks for reconditioning. 

If the battery is being reconditioned, status analysis stops 

at that point, since data will be misleading. Otherwise, four 

procedures are called, temp-status/l, work-status/l, 0 charge-status/l, and div-status/l. Each of these procedures 

0-1-p 
writes messages to the screen and increments counter 15 if 

problems are found. If counter 15 is still zero, a message is 

written to the screen that the battery seems healthy. 

battery-status/l is called from execute(2,Bat) (start.prg!. 

temp_status(Bat)--showf(8,-) (temperature over last. orbit) and showf(9,-; 

(average temperature over last 12 orbits) are used in analysis. 

get_data/5 is called to get the appropriate battery data and then to 

find the its average. Finally, check_temp/3 is called to analyze the 

data. temp-status/l will always succeed, even if no problem is found, 

so that status analysis can continue. If no problem was found a 

message will be printed to the screen. 

temp-statusjl is called from battery-status/l. 

work-~tatus(Bat)--showf(l3,_) (AH0 for last 12 orbits) and showf(l,-) 

(EOD battery voltage over last 12 orbits) is used to analyze workload 

status. get_data/5 is called to get the appropriate battery data and 

then to find the its average. Analysis is done by calling check_work,’3. 

find-avgf2 is called to find averages. work-status/l will always 

succeed, so that status analysis can continue. If no problem was found 

a message will be printed to the screen. 

It is called from battery-status/l. 

charge-~tatus(Bat)--showf(3,-) (recharge ratio) and showf(Z,-) (high 

cell voltage during charge) is used to analyze charge status. 

get-data/!i is called to get the appropriate battery data and then io 

find the its average. Analysis is done by calling check_charge;3. 

charge-status/l will always succeed. If no problem was found a 

message will be printed to the scroe~. It is called from 

battery-status/l. 

get_data(Bat,Nl,N2,Avgl,AvgZ)--Nl and N2 reference the show files, Bat 

is the selected battery. get_list/3 is called to get the 

data list for the appropriate show file and battery. find-avgj2 

is then called to calculate the average for each data list. 

Cut is used to prevent backtracking. get_data/5 is called by 

temp-status/l, work-status/l, charge-status/l. 

div_status(Bat)--showf(4,_) (EOD divergence) is used to analyze divergence. 

get_list/3 is used to get the appropriate battery data, find-div/.j is 

called to find highs, lows and averages, then eval-div is used to 

analyze the divergence. div-status/l will always succeed. If no 

problem was found a message will be printed to the screen. 

It is called from battery-statusjl. 

check-recond(List)--checks the single value passed it by battery-status/l. 

If this value is 1, the battery is in reconditioning, and a message 

is printed on the screen. No further status analysis is done. 

check-temp(Oavg,AvglZ,Bat)--If average temperature in last orbit and 

average temperature over last 12 orbits are both below zero, 

a message that the battery is cold is given. If average temperature 

8- 2 -9 
. 

over the last orbit is over 11, and average over last 12 

orbits is over 10, a message is given that the battery is hot. 

If average over last orbit is greater than 11, and average over 

last 12 orbits is less than 10, a message is given to check 

chamber or check for overcharging. check-temp is called by 

temp-status/l. 

check-work(Bat ,Ahoavg,Eodv)--analyzes the battery for overwork or underwork. 

If the average AH0 is less than 3 ampere-hours, and EOD voltage 

is less than 27 V, a message that the battery may have memory 

effect is given. If the average AH0 is greater than 14 amperehours, a message is given that the battery is overworked. check_work/’3 

is called from work-status/l. 

check-charge(Rr,Cavg,Bat)--analyzes the battery for overcharging or 

undercharging. If recharge ratio is greater than 1.020, and high 

battery voltage during charge is less than 32.5, a message is given 

that the charging scheme may be insufficient. If in-charge high 

voltage is greater than 34 volts, a message is given that 

possible dangerous overcharging may be occurring. ‘In-charge high 

voltage average greater than 33.6 volts triggers a message to 

check for overcharging. check_charge/3 is called from charge-s tatus;2 

find-div(List,Avg,Div,Highs,Lows)--Given a List taken from 

showf(4,-) or showf(5,-), find_div/5 calls break_list/4 to break 

the list into a list of high values, a list of low values, and a 

list of average values for cell voltages. find_avg/2 is then 

called on each of these lists to find the average high reading (Highs,, 

low reading (Lows) and average reading (Avg) over the 12 orbits. 

Div is instantiated to Highs minus Lows. find_div/5 is called by 

div-status/l. 

eval-div(Div,Avg,Highs,Lows,Bat)--evaluates two measures of 

divergence, using variables passed out from find-div. eval_div/5 

writes a message that divergence is high if Div is greater than 

0.8. If Avg is closer to Lows than to Highs by a noticeable margin 

(11, a message is given that too many cells are migrating to low 

values. eval-div is called by div-status/l. 
ORlGlNAL PAGE 1s 

OF POOR QUALM 

34-Q 


3-7 -P 
. 

Advice.prg contains the ADVICE section of NICBES which goes into 

further detail on three subjects: whether a battery needs reconditioning, 

changes in charging scheme, or changes in workload. Select Advice from 

the Main Menu for battery n brings up a menu of three choices for the user. 

The ADVICE section finds trends in many of its data files, and uses them, 

along with averages, for analysis in greater depth. Messages to 

the user give trends and average values, as well as advice. 

ADVICE section, using trends in voltage, recharge ratio, divergence 

and temperature-- 

AH0 average (Ahoavg) is used for advice on workload. It is considered to 

be overly high above 14, high above 9, average around 7 and low below 3. 

EOD pressure (Eodpress) is considered to be high above 100, and fairly high 

above 90. EOC pressure (Eocpress) is considered to be high above 110, and 

fairly high above 100. 

Divergence (Div) is considered to be high above 0.8V (difference 

between high and low cells). 

.......................................................................... 

PREDICATES AVAILABLE IN ADVICE.PRG 

cidvice(Bat,Choice)--with choice 1, advice/:! calls get_one/6 to get data, 

and recond/5 to analyze it. With choice 2, advice/2 calls 

get-two/S to get data and chgchg/6 to analyze it. With choice 3, 

advice/2 calls get_three/4 to get data and chgwrk/3 to analyze it. 

advice/2 is called by more/2 (start.prg). 

get_two(TrendZ,Trend3,Div,TrendS,Eodpress,Eocpress,Bat)--The 

hand-crafted deviation factors are called (DevZ,Dev3,Dev5,Devg). 

Then get_list/3 is called to read data from showf(2,-) 

(in-charge cell high voltage), showf(3,-) (recharge ratio), 

showf(5,-) (in-charge divergence), showf(9,-) (temperature), 

and showf(lO,-) (cell pressure). Trend analysis is done on voltage, 

divergence and temperature by calling trend-analysis. find-divi5 is 

called to find average divergence. find-avg is called to find average 

cell pressure EOC (Eocpress) and EOD (Eodpress). get-two is called by 

advice/2. 

get_three(Trendl,Trend4,Ahoavg,Bat)--Hand-~rafted deviation 

factors are called (Devl,Dev4). Then get_list/3 is called to read 

data from showf(1,-) (EOD battery voitagej, showf(4,-j (EOD 

divergence) and Statf1,-) (ARO). 

trend_analysis/3 is called to derive Trend1 of voltage. disp_trend/3 

is called to find divergence trend. find_avg/2 is called to find 

average ABO. get-three is called by adviceI2. 
get-one(TrendlyTrend2,Trend3,Trend4,Trend5,Bat)--Hand-crafted 

deviation factors are called (Devl,Dev2,Dev3,Dev4,Dev5!. Then 

get_list/3 is called to read data from showf(l,-) (EOD 

battery voltage), showf(2,dat (in-charge cell high voltage), 

showf(3,-) (recharge ratio), showf($,-) (EOD divergence! and 

showf(5,-) (in-charge divergence). 

trend-analysisi3 is called for voltages and recharge ratio. 

disp_trend/3 is called to find trends for divergence data. 

get-one is called from advice/2. 

disp_trend(List,Trend,Dev)--br&ak_list/4 is called to break the 

divergence List into highs (Listl), lows (List31, and averages 

(List4). get_disp/3 is called to figure the divergence list (Divlist:. 

Then trend_analysis/3 is called on Divlist. disp-trendj3 is 

called by get_three/4 and get_one/6. 

get-disp(Listl,List2,List3)--is a recursive function to find the 

differences between corresponding values of two lists, and put the 

differences in a third list. It is used to find the divergence 

between high-voltage cells and low-voltage cells in the data from 

12 orbits. Missing data (-9999) in either of the comparands means 

that -9999 is written to the list of divergence. Comparison is 

done of the heads of the two lists, and the result is put in the 

head of the third list. Then get_disp/3 is called recursively on 

the tails of the lists. Halting condition for the recursion is the 

empty list. get-disp is called by disp_trend/3. 

trend-analysis(List,Trend,Dev)--analyzes trends in data using two 

simple mathematical functions. ?ind_wl/2 is called, which weights 

recent values more heavily, and sums the weighted values. Then 

find-w2/2 is called, which weights all the values equally, with 

the weight ((n+1)/2) chosen so that for a list of constant values, 

find-wl and find-w2 give the same sum. Then eval-trendi3 is called 

using the difference of the two weight functions (Diff), and the 

hand-crafted deviation factor (see dev/6 below) appropriate to the 

set of data being analyzed, and returns the Trend. trend_analysis/3 

is called by get-two/'l, get_three/6, and get_one/4). 

find-wl(Weight1,List)--given a list of n values, find_wl/2 

calls multwt/2 to multiply the first by 1, the second value by 2, 

the third by 3, and so on till the nth value is multiplied by n. 

find_wl/2 uses counter 12 to keep track of the number of 

items in the list. Weighttl is the sum of the individual products 

find-wl is called by trend_analysis/3. 

multwt(Wt,[H:T])--checks for missing data (-99), then calls 

itself recursively on the tail of the list (Tj until tne empty list is 

reached. Each recursive call that does not find a missing data item 

increments the counter. Then as multwt/2 climbs out of the recursion, 

the value of the counter is multiplied by the head of the 

list (H) at that time, and is added to the weight, which has 
been is initialized to 0 for the empty list. multwt/2 is 

called by find-w1/2. 

find-w2(Weight2,List)--initializes a counter, then calls find-sum 

on List to find the sum of the values. Then a weight factor is 

figured which will make Weight2 (from find-wZ) equal to Weight1 

(from find-wlj if the List contains all one constant value. This 

weight factor is figured by (n+1)/2 for a list with n elements, 

and is multiplied by the sum. find-w2 is called by trend-analysisi3. 

eval-trend(Dev,Diff,Trend)--takes the deviation factor, and the 

difference (Diff) between Weight1 and Weight2, and determines a 

trend. If the absolute value of Diff is less than Devi3, the 

trend is none. For positive Diff, Diff greater than Devi3 and 

less than Dev is considered to indicate the trend is slightly-up. 

Diff greater than Dev but less than 2 times Dev indicates the 

trend is up, and Diff greater than 2 times Dev indicates the 

trend is strongly-up. Similarly, negative Diff is slightly-down 

for Diff less than -Dev/3, down for Diff less than -Dev, and 

strongly-down for Diff less than 2 times Dev. Prolog syntax is 

used to advantage in this code, with atoms giving the trends. 

eval_trend/3 is called by trend_analysis/3. 

- 

recond(Tl,TZ,T3,T4,T5)--writes the trends (EOD voltage, in-charge 

high voltage, recharge ratio, EOD divergence and in-charge 

divergence) on the screen, and calls tel1-1/5 to analyze the 

trends to determine whether reconditioning is advisable. 

recond/5 is called by advice/2. 

chgchg(T2,T3,Div,TS,Eodpress,Eocpress)--writes the trends (in-charge 

voltage, recharge ratio, and temperature) on the screen, along 

with the averages (in-charge divergence, EOD pressure and EOC 

pressure). Then te11-2/6 is called to advise as to whether the 

charging scheme should be changed. chgchg/6 is called by advice/2. 

chgwrk(Tl,T4,Ahoavg)--writes EOD voltage and EOD divergence 

trends to the screen, along with the AH0 average. Then te11-3/3 

is called to advise if the workload should be changed. chgwrk/3 

is called by advice/2. 

tel1_3(Tl,T3,Ahoavg)--Six conditions are used by tell-3 to advise 

as to workload change. 

1. EOD voltage down, EOD divergence down, AH0 avg. less than 5 

2. EOD voltage strongly down, EOD divergence strongly down, AH0 

--loads probably too light. 

average less than 5 --losing capacity due to memory effect, 

try heavier load. 

3. AH0 average greater than 14 --possibly destructive overwork. 

4. AH0 average greater than 9 --heavy workload. 

5. EOD voltage down or strongly down, EOD divergence down or 

strongly down, AH0 average above 6 --losing capacity. Consider' 

reconditioning. 
6. none of the above --see no need to change workload. 

teIl_Z(T2,T3,Div,T9,Eodpress,Eocpress)--Nine conditions are used by 

te11-2/6 to determine if the battery should have its charging 

1. Temperature st.rongly up, EOll pressure greater than 100, 

. scheme changed. 

EOC pressure greater than 110 --overcharging causing high 

pressure. 

2. In-charge voltage strongly up --check for overcharging. 

3. EOD pressure greater than 80, EOC pressure greater than 

4. EOD voltage strongly down, in-charge voltage strongly down 

--undercharging may be seriously affecting capacity. 

5. EOD voltage down, in-charge voltage down --appears to be 

undercharged. 

6. EOD voltage strongly down or down, in-charge voltage strongly 

7. EOD voltage down, in-charge divergence greater than 0.8 

8. EOD voltage strongly down, in-charge divergence greater 

9. none of the above --see no need to change charge scheme. 

100 --charge rate may be too high. 

down or down --undercharging may be causing loss of voltage. 

--undercharging may be causing loss of voltage. 

than 8 --undercharging may be causing serious loss of voltage 

tell_l(Tl,T2,T3,T4,T5)--uses 11 conditions to determine if a 

battery needs to be reconditioned. 

1. EOD voltage strongly down, in-charge divergence strongly up 

2. EOD voltage strongly down, in-charge voltage strongly down 

3. EOD divergence strongly up, in-charge divergence strongly 

up --strongly. rising divergence indicates reconditioning. 

4. Voltage trends strongly down or down, recharge ratio and 

divergence trends strongly up or up --reconditioning is 

--reconditioning advised. 

--recondition soon. 

indicated by all five trends. 

5. Recharge ratio strongly up --reconditioning indicated. 

6. In-charge voltage is down or strongly down;in-charge 

7. EOD voltage down or strongly down, in-charge divergence 

8. Both divergences up --consider reconditioning. 

9. Recharge ratio up --consider reconditioning. 

10. Both voltages down --consider reconditioning. 

11. none of the above --see no need to recondition at present. 

divergence is up or strongly up --reconditioning recommended. 

up or strongly up --reconditioning indicated. 

dev(Devl,Dev2,Dev3,Dev4,Dev5,DevS)--Data structure, listed as a fact, 

which contains the hand-crafted deviation factors. Each one 

is associated with a data file. 

Devl=2 - showf(1,-) - EOD battery voltage 

Dev2=2 - showf(Z,-) - in-charge high battery voltage 

Dev3=0.02 - showf(3,-) - recharge ratio 

Dev4~0.15 - showf(4,-) - EOD cell voltage divergence 

Dev5=0.09 - showf(5,-) - in-charge cell divergence 
, 

Dev9=13 - showf(9,-) - battery temperature 

These values are used in the weighting scheme to analyze trends. 

To INCREASE sensitivity to trends-, lower the values. These need 

not be integers, but must be greater than 0. 

To change these values, put advice.prg in your favorite editor and 

revise the data structure dev/5. No other changes are necessary. 
ORIGINAL PAGE e 

POOR wAuIc11 
OWGINAL PAGE. #) 

OF POOR QUAutv 
, 

ORIGINAL PAGE & 

OF: POOR QlJAun 

3- 8 -A 
, 
t 

ORfbDNAL PAGE 

OF POOR QU- 
OWGIMAL PAGE IS 

OF POOR QUALm 
. 

Showpak.prg contains the DECISION SUPPORT system, which gives 

the 12 plots which are available to the user upon selecting 

Plots and Graphs from the Main Menu. The graphical primitives 

from Grafpak.prg are used in the plots. Showpak contains a few 

supporting data handling primitives and the titles, horizontal 

and vertical captions used in the plots. 

12 Plots in the DECISION SUPPORT package: 

1) EOD battery low plotted 26.4V. 

voltage high plotted 28.6V 

scale .2v 

2) In-charge high low plotted 32.0V 

cell voltage high plotted 34.2v 

scale .2v 

3) recharge ratio low plotted 1.010 

high plotted 1.055 

scale .005 

3) EOD divergence low plotted 1.05v 

high plotted 1.55V 

scale .05V (cell) 

5) In-charge low plotted 1.35V. 

divergence high plotted 1.55V. 

scale .02V. (cell) 

6) EOD cell V. low plotted 1.05V. 

divergence high plotted 1.55V. 

scale .05V. (cell) 

7) In-charge cell low plotted 1.36V. 

divergence high plotted 1.56V. 

scale .02V. (cell) 

8) Temperature low plotted -4c 

this orbit high plotted 11c 

scale 1c 

Yj Temp. avg. low plotted -42 

high plotted 11c 

scale 1C 

@ 10) Cell Pressure low plotted 30 
. 

0 EOD and EOC high plotted 140 

scale 10 units 

11) Time on low plotted 8 

trickle charge high plotted 28 minutes 

scale 2 minutes 

12) Reconditioning low plotted 0 A. 

current high plotted 14 A. 

scale 1 A. 

The above numbers can easily be manipulated to change range or 

scale of the plots, but. must remain integers. These changes can be 

made in Showpak.prg by editing the correct 'show' data structure. 

'show' has the following format: 

1. 

2. 

3. 

4. 

5. 

6. 

8. 

9. 

10. 

11. 

CI 

1. 

N - 

Vertcap - 

Horizcap - 

Title - 

H 

W 

Base - 

TOP 

Hscale 

Vscale - 

Start - 

- 

- 

- 

- 

the number of the plot (1 to 12) 

vertical caption 

horizontal caption 

graph title 

heigth of graph 

width of scale 

lower bound for data points plotted 

upper bound for data points plotted 

horizontal scale of values 

vertical scale of values 

start point of graph 

Changing the number of orbits plotted from 12 is more difficult, and 

will require chasing down many 11's and 12's' as well as rewriting the 

file handler portion of the code. 

Colors are 

1 = blue 

2 = green 

3 = light blue 

4 = red 

5 = pink 

6 = gold 

7 = white 

8 = gray 

Colors are set in predicates 

"wa(n,color)", where n is the number 

of characters of that color, and 

color is one of the numbers to 

the left. 

Symbols for the graphs are referrenced by their ASCII code. 

sho~-view(N,Bat,0rbitj--N specifies which plot is done, and Bat 

specifies which battery is displayed. Orbit gives the current 

orbit number. The data structure 'show', discussed above, is 

called to get all the captions and values needed for plot N. 

0 show_view/3 calls get_list/3 to read the appropriate data file. 

9- 2- D 
, 

Then graphplus/6 and pl0t/8 (in Grafpak.prg) are called to plot 

the display. Besides the information in 'show', only the color 

and symbol need to be passed. The present orbit is then written 

to the plot, if applicable. show-viewi3 is called by executej2, 

the Graphics Menu. 

show-viewi3 -- There are four cases; plot 10, plot 12, plot 4 and 5, 

and the r'est. Plot 10 displays 2 lines, plot 12 has the orbit no. 

preceeding its data, plot 3 and 5 display 3 lines each. For plots 

4,s and 10, breaklistj4 is called to break the data into 

lists, each one to be plotted on the same graph. plot/8 is then 

called for each list with a different color and symbol. 

write-orbitj0 -- writes 'Orbit' on the horizontal axis. Called by 

show_view/3. 

write-orbit/l -- writes 'Orbit' and the last orbit on the horizontal 

axis. Called by show_view/3. 

show/ll -- a data structure containing the captions and values needed 

to display the graphs. Itemized above. 
. 


Grafpak.prg contains graphic primitives and supporting predicates 

for Showpak.prg to use in giving the user plots and charts to aid 

in decision support. The procedures are written to be 

general-purpose so that plots may be altered easily. New plots may 

be developed by the programmer using these primitive operations. 

ArityjProlog graphical primitives 

Parameters in plot are 

(List, list of values to be plotted 

Hscale, distance horizontally between plotted points 

Vscale, vertical scale of values 

Base, lowest value plotted 

TOP , highest value plotted 

Color, color of the plotted points 

Coord, the horizontal positioning factor, generally starts 

with 11 (columns from left-hand side of screen), 

increments by "num" with each point (Start) 

Obj) ASCII code for symbol to be plotted 

Parameters in graphplus are 

(H, Rows in height (1 more than number 

of values wanted! 

needed to plot values--see "coord" 

w, Columns in width (5 more than the spaces 

Vcap 3 Vertical caption 

Heap, Horizontal caption 

Title) Title written above plot 

Built-in Graphics Primitives: 

tmove(x,y)-- moves the cursor to row x (rows are numbered 0 to 

24 beginning at the top) and column y (columns are numbered 0 to 

79 beginning at left). 

wc(n,char)-- prints n copies of char (given as an ASCII code 

or within single quotes) starting at the cursor. 

wa(n,color)--prints the next n characters in color (given as a number). 

1 = blue 2 = green 3 = It. blue 4 = red 

5 = pink 6 = gold 7 = white 8 = gray 

Characters can also be made flashing or inverse, in any of the colors, 

using this command. To see the attributes that are available, with 

the Arity interpreter running, type "['table.ari']." and when Arity 

returns "yestt type "table. " 
graphplusjH,W,Vcap,Hcap,Title,Bat)--creates the basic graph with 

height H and width W, vertical caption Vcnp (usually the scale), 

horizontal caption Hcap, and title Title including the battery 

number, Bat. H should be chosen to be 1 greater than the nuiiiber of 

rows (which is the number of possible values that will be plotted!. 

W should be chosen to be 5 wider than the spaces needed to plot the 

values. See plot/8 for more information. 

graphplusj6 calls graph(H,W,Hcap) to build the skeleton along 

with the horizontal caption, then calls write-vert(Vcap), and 

write-title(Title,R,Bat) to fill in the captions. write-header is 

also called to write information about missing data and data out of 

range at the the top of the graph. 

- 

graphplus/6 is called by show_view/3 in Showpak.prg, with the proper 

parameters of size and captions. 

graph(H,W,Hcap)--builds the skeleton graph of height H and width W, using 

vertical/Z for the vertical graphics characters making the left-hand 

side of the graph, and horizontal/2 for the lower edge. graph12 is 

called by graphplus/6. 

vertical(A,WZ)--uses graphics characters 180 (ticks) for the vertical 3x.i~ 

and 250 for the dots across the inside of the graph. 

horizontal(B,List)--uses graphics characters 196 and 194 for the bot.tom ecig'c 

of the graph. The tick marks are placed every five spaces. The 

elements of the List, containing the horizontal captions, are alined 

with the ticks but one line under. 

write-vert(L,P)--writes the list L along the left-hand side of 

the graph. Calls write-scale(L) which writes the list recursively. 

write-scale(L)--writes the vertical caption recursively from the 

list L. The empty list ([I) halts the recursion. 

write-title(S,P,Bat)--writes the Title along with the Bat, battery 

number, above the graph. S is the Title and P is the row 

position. 

plot(List,Hscale,Vscale,Base,Top,Color,Coord,Obj)--Plots the values in 

list List on the basic graph produced by graphplus/6. Hscale is the 

horizontal distance (in columns of the screen) between the points 

plotted. Vscale is the vertical scale of the graph. Base is 

the lowest value plotted, and Top is the highest value 

plotted. An attempt to plot any value outside this range will 

result in out of range values being plotted at the top of the graph 

and the actual values being written, in order at the top of the 
. 

screen. Top minus Base divided by Vscale will equal the number of 

rows upon which the graph is plotted. Color is the color of the 

plotted point. Coord is the horizontal positioning factor, as the 

plot moves across the screen from left to right. Coord ordinarily 

starts at column 11, and increments by either 1 or 5. Obj is the 

ASCII code for the symbol which will be plotted for each data puint. 

plot/8 calls plot_point/8 to recursively plot the points from 

the list L. When plot_point/8 is done, plot/8 changes the color 

back to white and moves the cursor to the top left-hand corner. 

plot/8 is called by show_view/3 in Showpak.prg with the data 

in the List and specific parameters for the plotting. 

plot~point([Head:Tai1],Hscale,Vscale,Base,Top,Coord,Color,O~j)--p~ot~point/8 

recursively plots the list of points, divided into Head and Tail, 

then calls itself on the Tail, having updated Coord for the next 

' point. The empty list halts the recursion. Hscale, Vscale, Base, 

Top, Coord, Color and Obj are the same as in plot/8. 

plot_point/8 calls place/7 to find the correct place for the 

plotted point, and plot it there in the correct color. 

place(Head,Vscale,Base,Top,Coord,Color,Obj)--figures the correct place 

for the plotted point, moves the cursor there, and plots the point. 

The value for missing data causes an asterisk in gold 

to be plotted on the low boundary line of the graph. place/7 

truncates values as it plots them. When values are out of range, 

p?ace/7 plots a synbc? at the top boundary of the graph and writes 

the value at the top of the screen. 

place/7 is called by plot_point/8. 
, 


Utility.prg is a collection of general Prolog predicates which arc used 

in one or more of the routines comprising NICBES. 

Data Files in the Expert System: 

All data files are loaded into PROLOG as facts in the following 

format: 

showf(N,List). N = 1 to 13 for showf(N).dat 

curf(N,List!. N = 1 to 3 for curf(N).dat 

fault([Flag,Type]). for fault.dat 

List for show files contains 6 sublists, one for each battery, 

seperated by commas. For example, in PROLOG, showfl.dat is loaded as: 

Actual data points are reals with 5 decimal places. -9999.0 

represents missing data points. There are 12 columns, one for each 

orbit in chronological order from oldest to latest. 

An example of the current data files is curf2.dat: 

curf(Z,[Phase,Day_min,[13 SPA Currents],[3 Bus Currents], 

[6 Average Battery Temperatures]]). 

----------------------------------------------------------------------- 

Built-in ARITY PROLOG Functions: 

nl--gives a new line (like carriage return). 

cls--clears the screen. 

Many of the functions use the ARITY PROLOG counters. There are 32 counters 

(0 to 31) which are accessible from any procedure in any file. The 

operations on a counter are: 

ctr-set(n,m) set counter n to value m 

ctr-is(n,A) A is instantiated to the value of counter n 

ct r-inc( n, A) counter n is incremented, and A is instantiated 

ct r-dec ( n, A) counter n is decremented, and A is instantiated 

to the previous value 

to the previous value 

Underscores (,) appearing in place of arguments signifies an anonymous 
variable--we do not care what the value is and will not be using 

it at this time. This'saves the system work. 

ifthen and ifthenelse use the following format: 

ifthen(X,Y) => if X then Y. 

ifthenelse(X,Y,Z) =? if X then Y else 2. 

var:Xj--succeeds if X is 3 variable. 

integer(X)--converts X to an integer. 

round(X,N)--rounds X to N decimal places. 

read-line(H,String)--reads string from file H. When H == 0, reads string 

from keyboard. ....................................................................... 

PREDICATES AVAILABLE IN UTILITY. PRG 

get-list(Bat.,N,List)--N tells which show file. get-list calls the particular 

'showf' fact which was loaded in eval-flag(0) (start.prg) and which is 

described above. find-nth is called next to find the data list 

corresponding to Bat, the battery of interest. This list is returned to 

the variable List. get_list/3 is called from complete/l, status.prg, 

advice.prg and showpak.prg. 

find_nth/4--given a list, find_nth/4 finds the Nth element of the list. 

It is called by get-listj3. 

append:Listl,List2,List3)--apFends List2 to Listl, with the 

result in List3. append/3 calls itself recursively, with the 

empty list the halting condition. 

break-list(List,Listl,ListZ,N)--breaks List into two lists. The first N 

items are put in Listl, and the remainder into List:!. After setting 

counter 1 with N, break_list/4 calls steal-item to recursively build 

the lists. break_list/4 is called by show_view/3 (grafpak.prg), 

disp_trend/3 (advice.prg) and find_div/5 (status.prg). 

steal~item([H:T],Listl,List2)--recursively traverses the tail of its first 

argument, decrementing the counter, until the counter is 0, or the first 

argument is the empty list. Then List:! is set to the remaining portion ol 

the original list (or the empty list), and Listl is built as steal-item': 

climbs out of the recursion. steal_item/3 is called by break-list/q. 

find-avg(List,Avg)--finds the average of a list of numbers. Counter 10 is 

set to count the number of items in the list. find-sum is called to 

sum them, then the average is found. find-avg is called by get-datal5 

and find_div/5 (status.prg). 

find-sum([H:T],Sum)--recursively finds the sum of a list of numbers. The 

head of the list (H) is checked for missing data (-9999), counter 10 

is incremented, then find-sum/Z is called on the tail (T) of the list. 
’r 7 

The empty list halts the recursion, then the sum is found as find-sum 

climbs out of the recursion. A missing data item is left out of the sum, 

and a message is printed. find_sum/2 is called from find_avg/2, find-wz. 

(advice.prg) and loadbank-fail10 (faultd.prg). 

sequence!Orbit)--creates the horizontal axis for those graphs using the 12 

latest orbits. It calls seqi3 to make this list and horiz-place;’l to pu’ 

it in the data structure show/ll. It is called by eval-flagil! 

(start. prg) . 

seq(H,T,[H:Z:)--Builds the list of last 12 orbits recursively from the latest 

orbit, T and the first orbit in this series, H. Called by sequenceil. 

horiz-place(List)--searches the data structures show/ll to find ones with 

variable Rcapl, the horizontal axis. It retracts these and then asserts 

them to the data base with the List in-the place of the variable. 

Called by sequence/l. 

cut-retracti0--retract fact and cut. Called by horiz-place/l. 

check(X,N)--used for checking the user input to menus. If the user 

selection X is >O and <= N (upper bound), the screen is 

cleared and program continues. If not, a message is written to 

the user saying ’YOUR CHOICE IS OUT OF RANGE!’. The user can 

then input a proper selection. Called by Status, Advice and Graphics 

menus in start.prg. 

check2(X,N)--used for checking the user input to Main Menu in start.prg. 

if the user selection X is ?O and either X <= N (upper bound! or equal 

to 3, the screen is cleared and program continues. If not, a message 

is written to the user saying ’YOUR CHOICE IS OUT OF RANGE!’. The user 

can then input a proper selection. 

checkl(X)--used for checking the user yes/no responses to menus. If the user 

input is either yes or no, the screen is cleared and program continues. 

If not, a message is written saying ’ANSWER IS OUT OF RANGE!’. The 

user can then re-enter a correct reply. Called by eval-flag(1) (start.pr. 

complete(M)--calls get_list/3 to look at show file 1. missing/2 returns the 

number of missing data points in show file 1. If there are more than 

4 missing values, M is set to 1 so only Graphics may be called from the 

Main Menu. Else M is set to 4 and all options from the Main Yenu will 

be valid. Called from eval-flag(0) (start.prg). 

missing(List,N-)--returns the number of missing data points,N from the List. 

Called by complete/l. 

reader(Atom)--reads input from the keyboard and returns it as an atom. 

Called by all menus in start.prg. 

one-assert(X)--if X is already in the data base, no action. Else 

the fact X is asserted to the data base. 0 

8-3-0 
ORIGINAL PAGE 1s 

k POOR guALm 
I -. .. , ... . .. .:.. i;;.'c:, c. T' , T , i. .,! 1 - 

ORIGINAL PAGE Is 

OF POOR QUALffV 
ORIIGIWAL PAGE IS 

OF POOR QUM 
APPENDIX C 

TEST PROCEDURES 

. 
1.0 

2.0 

4. 

Power on the IBM-PC AT and Printer. 

Run 

A. 

B. 

C. 

D. 

E. 

F. 

G. 

G. 

the Data-Handler. 

Data-Handler is in directory USR. 

Enter 'data-hdl' to execute Data-Handler. 

Check telemetry flow across RS232. 

Messages printed to screen: 

"Starting first full orbit", 

"#. ORBIT = N" - every 96 minutes. 

If a fault is detected, message printed to screen: 

"Fault detected; exiting!". 

If no communications being received, message printed to 

screen; "No communication for 3 minutes; exiting!". 

If 5 consecutive incomplete telemetry runs, message printed 

to screen; "Received 5 consecutive incomplete telemetry - 

runs; exiting!". 

'' In t e r r up t c a u gh t ; ex i t i n g ! " . When ready to quit Data-Handler enter '"C' . Message printed: 

Verify and Archive Data-Handler Output. 

A. View showf#.dat (1 to 13!,curf*.dat il to 3) and fauit.dst 

B. Archive data files under directory DATAFILES, 

for correct format. 

subdirectory 'DATE' where DATE is current date. 

Run 

A. 

B. 

C. 

D. 

E. 

F. 

G. 

H. 

I. 

Expert System. 

Expert System is in directory NICBES. 

Enter 'api' to execute Expert System. 

View Fault Diagnosis. 

a. Print Fault Diagnosis Report. 

View Main Menu and make all selections. 

Select battery. 

View Graphics Menu and make all selections for one battery 

a. Print one Plot. 

View Status for all batteries. 

a. Print Status Report for one battery. 

View Advice Menu and make all selections for one battery. 

a. Print Advice Report for one battery. 

Quit Expert System. 

I 

5. Verify Expert System Output. 

A. Review printed Reports and Plotss