COILING: Check coiling data

In Ushio, segmented coils were made in a very smart process (with completely worthless machines and priceless people). In each lamp, several parameters determined the electrical and thermal properties:

The coiling was done on a coiling machine. On a Molybdenum rod of a specific diameter, a Tungsten wire of a specific diameter was wound with a (sometimes varying) pitch. If the operator would pick the wrong rod (check with a caliper) things would go terribly wrong. Same when the warehouse guy would deliver the wrong wire or the mechanic would select the wrong coiling program (from EPROM).

Therefore a trick was found: if you know the total amount of Tungsten that's in a coil, you also know the mass of that coil segment. So in each specification, the coiling weight was specified and these weights were in a Lotus 123 spreadsheet. And each January the list was printed and distributed in the shop floor, no matter how many new lamps were introduced in between.
The big problem was the people calculating coiling weights. This was a set of rather complex formula's and an error was easily made, especially if the coiling weight was not determined by a lamp designer. So I made this program to check coiling weights fast and easy.

Coiling: the source

The source of COLING is small. Most of the job was reading in the coiling pattern and printing data on the screen.

MODULE Coiling;         (*  Version 1.2 *)

FROM    Display         IMPORT  SetCursorPosition, ClrEOS;
FROM    InOut           IMPORT  Write, WriteCard, WriteLn, WriteLine, WriteString, RedirectInput, 
                                CloseInput, ReadLine, ReadString, Read, termCH, Done;
FROM    Keyboard        IMPORT  KeyPressed, GetKey;
FROM    MathLib0        IMPORT  sqrt;
FROM    RealInOut       IMPORT  ReadReal;
FROM    RealConversions IMPORT  RealToString, StringToReal;
FROM    Strings         IMPORT  Append, CompareStr;
FROM    System          IMPORT  GetArg, Terminate;
FROM    Xchar           IMPORT  UpperString;

IMPORT  ASCII;

CONST   PiSquared           =  9.869604404;
        MinTurns            = 20.0 ;            (* Lower limit for segments *)
        DefaultWeightMargin =  0.03;

VAR     data            : ARRAY [0..127] OF CHAR;
        WireDiameter    : REAL;
        WireMG          : REAL;
        Mandrel         : REAL;
        CoilLength      : REAL;
        TotalTurns      : REAL;
        CoilWeight      : REAL;
        Pitch           : REAL;
        WeightMargin    : REAL;
        Segments        : CARDINAL;

        ErrorFlag       : BOOLEAN;


PROCEDURE Initialize;

VAR     n, m        : CARDINAL;
        count       : CARDINAL;
        option      : ARRAY [0..20] OF CHAR;

BEGIN
    ErrorFlag := FALSE;
    Segments := 0;
    GetArg (option, count);
    IF count = 0 THEN
        WriteLine ("Please specify the coilnumber on the commandline like in:");
        WriteLn;
        WriteLine ("ShowCoil 23117 <Enter>");
        Terminate (1)
    ELSE
        Append (option, ".UCD");
        RedirectInput (option);
        IF NOT Done THEN
            WriteLine ("File does not exist. Please try again.");
            Terminate (2)
        END
    END;
    SetCursorPosition ( 0,  0);     ClrEOS;
    SetCursorPosition ( 0,  0);     WriteString ("Processing and checking coiling data.");
    SetCursorPosition ( 0, 50);     WriteString ("Coil nr  :");
    SetCursorPosition ( 2,  0);     WriteString ("Wire MG  :");
    SetCursorPosition ( 2, 21);     WriteString ("mg/200 mm");
    SetCursorPosition ( 3,  0);     WriteString ("Diameter :");
    SetCursorPosition ( 3, 21);     WriteString ("mm �");
    SetCursorPosition ( 4,  0);     WriteString ("Mandrel  :");
    SetCursorPosition ( 4, 21);     WriteString ("mm �");
    SetCursorPosition ( 6,  1);     WriteString ("Total turns :");
    SetCursorPosition ( 7,  1);     WriteString ("Segments    :");
    SetCursorPosition ( 8,  1);     WriteString ("Length      :");
    SetCursorPosition ( 8, 23);     WriteString ("mm");
    SetCursorPosition ( 9,  1);     WriteString ("Pitch       :");
    SetCursorPosition ( 9, 23);     WriteString ("%");
    SetCursorPosition (10,  1);     WriteString ("Coil weight :");
    SetCursorPosition (10, 23);     WriteString ("g");

    SetCursorPosition ( 1, 50);     WriteString ("Approved :");
    SetCursorPosition ( 2, 50);     WriteString ("Document :");
    SetCursorPosition ( 6, 30);     WriteString ("Used in lamps:");
    SetCursorPosition (12,  0);     WriteString ("Remarks");

    SetCursorPosition (24,  1);     WriteString ("Ushio Europe Tilburg BV");
    SetCursorPosition (24, 59);     WriteString ("(c) QA section, 2000");

    WeightMargin := DefaultWeightMargin;
END Initialize;


PROCEDURE SkipLine;

VAR     ch      : CHAR;

BEGIN
    REPEAT
        Read (ch)
    UNTIL ch = ASCII.EOL;
END SkipLine;


PROCEDURE ProcessCoil;

VAR     ok                                  : BOOLEAN;
        buffer                              : ARRAY [0..89] OF CHAR;
        turns, length, SegLen, Factor,
        sum, ratio, cw                      : REAL;

BEGIN
    sum := Mandrel + WireDiameter;
    Factor := sum * sum * PiSquared;
    LOOP
        ReadString (buffer);
        IF CompareStr (buffer, "END") = 0 THEN EXIT END;
        IF buffer [0] = ';' THEN            (*  skip over comments              *)
            SkipLine
        ELSE                                (*  process data in coiling table   *)
            StringToReal (buffer, turns, ok);
            ReadString (buffer);
            StringToReal (buffer, length, ok);
            IF turns < 0.0 THEN
                turns := - turns;
                Pitch := 100.0 * length / (turns * WireDiameter);
            END;
            ratio := (length * length)/(turns * turns);
            SegLen := turns * sqrt (Factor + ratio);
            CoilLength := CoilLength + SegLen;
            TotalTurns := TotalTurns + turns;
            IF turns > MinTurns THEN
                INC (Segments);
            END;
            IF termCH # ASCII.EOL THEN SkipLine END     (* take care of comment *)
        END
    END;
    RealToString (TotalTurns, 1, 7, buffer, ok);
    SetCursorPosition ( 6, 15);     WriteString (buffer);
    SetCursorPosition ( 7, 16);     WriteCard (Segments, 6);

    RealToString (CoilLength, 1, 7, buffer, ok);
    SetCursorPosition ( 8, 15);     WriteString (buffer);

    SetCursorPosition ( 9, 16);     WriteCard (TRUNC (Pitch), 6);

    CoilWeight := CoilLength * WireMG / 200000.0;
    RealToString (CoilWeight, 4, 8, buffer, ok);
    SetCursorPosition (10, 14);     WriteString (buffer);

    SetCursorPosition (10, 30);     WriteString ("Upper :");
    cw := CoilWeight * (1.0 + WeightMargin);
    RealToString (cw, 4, 8, buffer, ok);
    SetCursorPosition (10, 37);     WriteString (buffer);
    WriteString (" g");

    SetCursorPosition (11, 30);     WriteString ("Lower :");
    cw := CoilWeight * (1.0 - WeightMargin);
    RealToString (cw, 4, 8, buffer, ok);
    SetCursorPosition (11, 37);     WriteString (buffer);
    WriteString (" g");
END ProcessCoil;


PROCEDURE ReadName (VAR buffer : ARRAY OF CHAR);

VAR     ch      : CHAR;
        n       : CARDINAL;

BEGIN
    n := 0;
    REPEAT
        Read (ch)
    UNTIL ch = '"';         (*  get rid off spaces  *)
    LOOP
        Read (ch);
        IF ch = '"' THEN EXIT END;
        buffer [n] := ch;
        INC (n)
    END;
    buffer [n] := 0C
END ReadName;


PROCEDURE ProcessData (option : ARRAY OF CHAR);

VAR     regel                    : ARRAY [0..89] OF CHAR;
        done, ok                 : BOOLEAN;
        line                     : CARDINAL;
        ch                       : CHAR;

BEGIN
    UpperString (option);
    IF CompareStr (option, "COILNR") = 0 THEN           (*  process coil number *)
        ReadString (regel);
        SetCursorPosition (0, 62);  WriteString (regel);
        IF termCH # ASCII.EOL THEN SkipLine END;

    ELSIF CompareStr (option, "MGWIRE") = 0 THEN
        ReadReal (WireMG);
        WireDiameter := sqrt (WireMG / 3020.0);         (*  convert Wire MG to diameter *)
        RealToString (WireMG, 1, 6, regel, ok);
        SetCursorPosition (2, 11);  WriteString (regel);    (*  print wire MG       *)
        RealToString (WireDiameter, 4, 6, regel, ok);
        SetCursorPosition (3, 13);  WriteString (regel);    (*  print wire diameter *)
        IF termCH # ASCII.EOL THEN SkipLine END;

    ELSIF CompareStr (option, "MANDREL") = 0 THEN
        ReadReal (Mandrel);
        RealToString (Mandrel, 2, 6, regel, ok);
        SetCursorPosition (4, 12);  WriteString (regel);
        IF termCH # ASCII.EOL THEN SkipLine END;

    ELSIF CompareStr (option, "APPROVED") = 0 THEN
        ReadString (regel);
        SetCursorPosition (1, 62);  WriteString (regel);
        IF termCH # ASCII.EOL THEN SkipLine END;

    ELSIF CompareStr (option, "WEIGHTMARGIN") = 0 THEN
        ReadReal (WeightMargin);
        WeightMargin := WeightMargin / 100.0;
        IF termCH # ASCII.EOL THEN SkipLine END;

    ELSIF CompareStr (option, "APPLICATION") = 0 THEN
        line := 6;
        done := FALSE;
        REPEAT
            ReadName (regel);
            SetCursorPosition (line, 50);   WriteString (regel);
            INC (line);
            LOOP            (*  this LOOP is needed to find "+" or EOL  *)
                Read (ch);
                IF ch = '+' THEN EXIT END;
                IF ch = ASCII.EOL THEN
                    done := TRUE;
                    EXIT
                END
            END
        UNTIL done;

    ELSIF CompareStr (option, "DOCUMENT") = 0 THEN
        ReadString (regel);
        SetCursorPosition (2, 62);  WriteString (regel);
        IF termCH # ASCII.EOL THEN SkipLine END;

    ELSIF CompareStr (option, "REMARK") = 0 THEN
        SetCursorPosition (13, 0);
        LOOP
            REPEAT
                ReadString (regel);
                IF regel [0] = 0C THEN EXIT END;
                WriteString (regel);
                Write (' ');
            UNTIL termCH = ASCII.EOL;
            WriteLn;
        END;

    ELSIF CompareStr (option, "SEGMENTS") = 0 THEN
        ProcessCoil;

    ELSE
        ErrorFlag := TRUE;
        WriteString ("No such option: ");
        WriteLine (option);
    END;
END ProcessData;


PROCEDURE GetData;

VAR     char        : CHAR;

BEGIN
    ReadString (data);
    char := data [0];
    IF (char = ';') AND (termCH # ASCII.EOL) THEN          (*  skip comments!      *)
        SkipLine
    ELSIF char # 0C THEN        (*  skip empty lines!   *)
        ProcessData (data);     (*  process parameters  *)
    END;
END GetData;


PROCEDURE ShutDown;

VAR     ch          : CHAR;

BEGIN
    REPEAT
        LOOP
            IF KeyPressed () THEN EXIT END
        END;
        GetKey (ch)
    UNTIL ch = ASCII.ESC;
    CloseInput;
    SetCursorPosition (0,0);    ClrEOS;
    WriteLine ("Thank you for using this program. Have a nice day.");
    WriteLn;
    WriteLine ("But remember: this is GNU GPL style FREE software!");
    WriteLn;
END ShutDown;


BEGIN
    Initialize;
    LOOP
        GetData;
        IF termCH = ASCII.EOF THEN EXIT END;
        IF ErrorFlag THEN EXIT END
    END;
    ShutDown;
END Coiling.
   
The coiling data was in UCD files, which are explained below.

UCD: Ushio Coiling Data

Below is an example of a coiling data file. It lists the Coilnumber (see also te 'Ruler' topic in this section), MGwire (weight of Tungsten, in mg, per 200 mm length), Mandrel (Molybdenum rod diameter) and the coiling pattern: turns speaks for itself. 'length' is the length of a coiled segment, in mm.

      
;       Ushio Coiling Data file
;       This is part of the Accessible Data Initiative (ADI)

Coilnr          00565
MGwire          500             ; in mg per 200 mm
Mandrel         1.5             ; in mm
Approved        21-04-2000

Segments
;       turns  length [mm]
;      ------  ------
        63.6    32.6
         1.0     7.0
        36.9    18.9
         1.0     7.0
        36.9    18.9
         1.0     7.0
        36.9    18.9
         1.0     7.0
       -36.9    18.9
         1.0     7.0
        36.9    18.9
         1.0     7.0
        36.9    18.9
         1.0     7.0
        36.9    18.9
         1.0     7.0
        36.9    18.9
         1.0     7.0
        63.6    32.6

        END

Application     "QIRZ 200-2500 KRN"
Document        TU4-E00565
Remark          Hot, hot, hot!
   
There is one number which is negative. Negative numbers were used to calculate the coiling pitch (turns per unit length). In this case the lamp was symmetric and the pitch was calculated from the middle section (for some obscure reason).

One more coiling file

Below is a nice example what 'Coiling' was made for: a multi segmented filament. Just take a look at the winding data (turns and length). This lamp produced a unique heating pattern, which would only suit one application in one single type of machine. Also: this was a nightmare to calculate the coiling weight for, as a human with his Casio handheld.

      
;       Ushio Coiling Data file
;       This is part of the Accessible Data Initiative (ADI)

Coilnr          02126
MGwire          97              ; in mg per 200 mm
Mandrel         0.9             ; in mm
Approved        08-06-2000

Segments
;       turns  length [mm]
;      ------  ------
        46.9    10.3
         2.2    15.3
        39.1     8.6
         2.2    15.3
        39.1     8.6
         2.2    15.3
        39.1     8.6
         2.2    15.3
        39.1     8.6
         2.2    15.3
       -41.4     9.1
         2.2    15.3
        68.7    15.1
         1.5    10.3
        67.3    14.8
         1.5    10.3
        67.3    14.8
         1.5    10.3
        67.3    14.8
         1.5    10.3
        67.3    14.8
         1.5    10.3
        67.8    14.9
         1.4    10.0
        81.4    17.9

        END

Application     "QIR 220-700 XSRE2-P"
Document        TU4-E02126
Remark          Wrong again!
   

Page created October 28, 2006 and