Displaying report 1-1 of 1.
Reports until 15:42, Thursday 11 December 2014
H1 ISC
daniel.sigg@LIGO.ORG - posted 15:42, Thursday 11 December 2014 - last comment - 08:21, Friday 12 December 2014(15560)
Integrator Filter Module (IFM)

A new type of filter block is now available in the real-time system. The Integrator Filter Module (IFM) implements a single integrator only, but has a couple of additional features compared to a standard filter module:

The attached screen shot represents the new IFM. The available parameters are

The testpoint and EPICS channel names are the same as in the standard filter module:

The SFM uses a bit encoded momentary switch for its enables. However, this requires state notation code support; and the IFM uses individual EPICS bi channels.

Images attached to this report
Comments related to this report
daniel.sigg@LIGO.ORG - 01:14, Friday 12 December 2014 (15568)

C Code

/*  This is an integrator with output limiter and bleed off
    Inputs:
    1. Error signal (double)
    2. Excitation input (double)
    3. Request word (bit encoded int)
    -----------------------------------------------------------------------
    Bit     Name            Description
    -----------------------------------------------------------------------
     0      Filter          Request for integrator to run
     1      Input Switch    Request for input switch to be on
     2      Offset Switch   Request for offset to be enabled 
     3      Limit Switch    Request for the limit switch to be engaged
     4      Output Switch   Request for the ouptut switch to be on
     5      Hold Output     Request for the output to hold
     6      Bleed Enable    Request for filter to bleed off
     7      Bias Enable     Request for output bias to be on
    15      Decimation      Request for output decimation (8Hz single pole)
    -----------------------------------------------------------------------
    4. Offset input (double)
    5. Gain input (double)
    6. Unity gain frequency in Hz (double)
    7. Bleed rate in cts/s (double)
    8. Maximum absolute value/limiter (double)
    9. Bias input (double)
   10. Model rate in Hz (double)
   Outputs:
    1. Control signal (double)
    2. IN1 ouptut (double)
    3. IN2 output (double)
    4. OUT ouptut (double) 
    5. Decimated control signal (double) 
    6. Status word (bit encoded int)
    -----------------------------------------------------------------------
    Bit     Name            Description
    -----------------------------------------------------------------------
     0      Coeff Reset     not used.
     1      Master Reset    Momentary; when set, INT will reset all 
                            filter history buffers.
     2      Input On/Off    Enables/disables signal input to INT.
     3      Offset Switch   Enables/disables application of INT input
                            offset value.
     4      Filter Request  Set to one when an INT filter is requested ON,
                            or zero when INT filter requested OFF 
     5      Filter Status   Set to one by INT when an INT filter is ON, 
                            or zero when INT filter is OFF 
     6      Limiter Switch  Enables/disables application of INT output 
                            limit value.
     7      Limiter Status  Set for 1 sec, when the limiter is enabled 
                            and the output value became too large.
     8      Decimation      Enables/Disables application of decimation 
            Switch          filter to INT OUT16 calculation.
     9      Output Switch   Enables/Disables INT output (INT OUT and 
                            OUT16 variables)
    10      Hold Output     If (!bit 26 && bit27), INT OUT will be held 
                            at last value.
    11      Bleed Enable    If set, the accumulated integrator value will
                            be bled off with the specifed bleed rate 
    12      Bias Enable     If set, a bias will be added to the output
    -----------------------------------------------------------------------
*/

#define INTFILTER 0x01
#define INTINPUT 0x02
#define INTOFFSET 0x04
#define INTLIMIT 0x08
#define INTOUTPUT 0x10
#define INTHOLD 0x20
#define INTBLEED 0x40
#define INTBIAS 0x80
#define INTDEC 0x8000

#define PI 3.1415926535897932384626433832795028841971693993751058

#ifdef _WIN32
typedef enum {false, true} bool;
#define isnan(s) 0
#define printk(s) 
#endif

bool myfinite (double s)
{
    // By IEEE 754 rule, 2*Inf equals Inf
    return !isnan(s) && ((s == 0) || (s != 2*s));
}

void Integrator (double* in, int ins, double* out, int outs)
{ 
    /* INPUT and OUTPUT vars for Integrator function block */
    double inval = 0.0;
    double exc = 0.0;
    int req = 0;
    double ofs = 0.0;
    double gain = 0.0;
    double ugf = 0.0;
    double bleed = 0.0;
    double limit = 0.0;
    double bias = 0.0;
    double rate = 16384;

    double outval = 0.0;
    double in1 = 0.0; 
    double in2 = 0.0; 
    double out1 = 0.0; 
    static double out16 = 0.0;
    int stat = 0;

    /* local vars */
    static int error = 0;
    static double oldout = 0.0;
    static double holdval = 0.0;
    static int limcount = 0;
    double val = 0.0;
    double g = 0.0;

    /* argument check */
    if ((ins != 10) || (outs != 6)) {
        if (!(error & 0x1)) {
            printk("Integrator: wrong number of inputs and/or outputs\n");
            error |= 0x1;
        }
        return;
    }

    // Read input values
    inval = myfinite (in[0]) ? in[0] : 0.0; // must be finite
    exc = myfinite (in[1]) ? in[1] : 0.0; // must be finite
    req = (int) (myfinite (in[2]) ? in[2] : 0); // must be finite
    ofs = myfinite (in[3]) ? in[3] : 0.0; // must be finite
    gain = myfinite (in[4]) ? in[4] : 0.0; // must be finite
    ugf = myfinite (in[5]) && (in[5] > 0) ? in[5] : 0.0; // must be finite and non-negative
    bleed = myfinite (in[6]) && (in[6] > 0) ? in[6] : 0.0; // must be finite and non-negative
    limit = myfinite (in[7]) ? (in[7] > 0 ? in[7] : -in[7]) : 0.0; // must be finite, take abs
    bias = myfinite (in[8]) ? in[8] : 0.0; // must be finite
    rate = (in[9] >= 0) ? in[9] : 1.0; // must be finite and positive

    // Add offset and muliply with gain
    val = inval;
    if (req & INTOFFSET) {
        val += ofs;
    }
    val *= gain;
    // input switch and input test points
    in1 = val;
    if (!(req & INTINPUT)) {
        val = 0.0;
    }
    val += exc;
    in2 = val;

    // Calculate filter
    if (req & INTFILTER) { // filter on
        g = 2*ugf/rate;
        if (g > 1) { // ugf above Nyquist!
            g = 1.0;
        }
        oldout = oldout+PI*g*val; 
    }
    else { // filter is off
        oldout = val;
    }
    // enforce limits when on
    if (req & INTLIMIT) {
        if (oldout < -limit) { // lower limit exceeded
            oldout = -limit;
            limcount = (int)rate + 1;
        }
        else if (oldout > limit) { // upper limit exceeded
            oldout = limit;
            limcount = (int)rate + 1;
        }
    }
    if (limcount > 0) {
        --limcount;
    }

    // Bleed off integrator value if selected
    if (req & INTBLEED) {
        g = bleed/rate;
        if (oldout > g) {
            oldout -= g;
        }
        else if (oldout < -g) {
            oldout += g;
        }
        else {
            oldout = 0.0;
        }
    }

    // Output testpoint
    out1 = oldout;

    // Output enabled
    if (req & INTOUTPUT) {
        val = oldout;
    }
    else {
        val = 0.0;
    }

    // Add bias if selected
    if (req & INTBIAS) {
        val += bias;
    }

    // Hold output if selected
    if (req & INTHOLD) {
        outval = holdval;
    }
    else { // no hold
        outval = val;
        holdval = val;
    }

    // Compute decimated output: 8Hz single pole low pass
    if (req & INTDEC) {
        g = 2*8.0/rate;
        if (g > 1) {
            g = 1.0;
        }
        g *= PI;
        out16 = (1-g)*out16+g*outval;
    }
    else { // no decimation
        out16 = outval;
    }

    // Set status
    stat = 0;
    stat |= (req & INTINPUT) ? 0x0004 : 0;
    stat |= (req & INTOFFSET) ? 0x0008 : 0;
    stat |= (req & INTFILTER) ? 0x0010 : 0;
    stat |= (req & INTFILTER) ? 0x0020 : 0;
    stat |= (req & INTLIMIT) ? 0x0040 : 0;
    stat |= limcount ? 0x0080 : 0;
    stat |= (req & INTDEC) ? 0x0100 : 0;
    stat |= (req & INTOUTPUT) ? 0x0200 : 0;
    stat |= (req & INTHOLD) ? 0x0400 : 0;
    stat |= (req & INTBLEED) ? 0x0800 : 0;
    stat |= (req & INTBIAS) ? 0x1000 : 0;

    // Write output values
    out[0] = outval;
    out[1] = in1;
    out[2] = in2;
    out[3] = out1;
    out[4] = out16;
    out[5] = stat;
}
daniel.sigg@LIGO.ORG - 08:21, Friday 12 December 2014 (15577)

Here is the corresponding simulink block.

Images attached to this comment
Displaying report 1-1 of 1.