ProgResFind.c

 

This program demonstrates a possible algorithm for use in obtaining a specific resistance value in a 16-bit programmable resistor card, using stored calibration values for enhanced accuracy.

 

/* Program: ProgResFind.c */

/* Programmable resistor: find a 16-bit code to give a particular resistance value */

/* D.C.H  16/8/01 */

/* Overall accuracy is determined by the accuracy of the calibration values employed */

 

#include <stdio.h>

 

/* To  output debug info... */

/* *** #define DEBUG */

 

/* === SEARCH VALUES ====================================================== */

/* The resistance value to search for, ohms */

double search_res = 1000.0;

/* The required tolerance (fractional) */

double search_tol    = 0.0005;        /* = 0.05% */

 

/* === CALIBRATION VALUES ================================================= */

/* Offset resistance value, ohms: includes connector and wiring.

   This example includes a 50R offset resistor. */

/* For accuracy, this should ideally be a CALIBRATED value */

double res_offset = 50.2;

/* The installed resistor values, ohms */

/* For accuracy better than resistor tolerance these must be CALIBRATED values,

   not NOMINAL ones. */

double res_value[16] =

{

    0.12,

    0.22,

    0.56,

    1.13,

    2.26,

    4.42,

    8.2,

    18.0,

    37.4,

    71.5,

    143.0,

    287.0,

    576.0,

    1130.0,

    2260.0,

    4530.0

};

 

/* Relay closed-contact resistance, ohms: assumed identical for all relays */

double res_contact = 0.1;

/* ======================================================================== */

 

/* Prototype */

long find_code(double value, double tolerance);

 

int main(void)

{

    long code;

    printf("Programmable Resistor Code Finder\n");

    printf("=================================\n");

    printf("D.C.H  16/8/01\n\n");

    printf("Search for %8.2f ohms (+/- %1.3f%%)...\n", search_res, search_tol * 100);

    code = find_code(search_res, search_tol);

    if (code < 0)

        printf("No code matches this value within the specified tolerance\n");

    else

        printf("Code 0x%04X\n", code);

    return 0;

}

 

/* Function: parallel resistor calculation */

double parallel_resistance(double r1, double r2)

{

    return ((r1 * r2) / (r1 + r2));

}

 

/* Function: find the first code whose actual value  matches the search value

   within the specified tolerance band.

   Returns the code (0x0000 thru 0xFFFF).

   If no code generates a value that lies within the specified tolerance band,

   returns -1.

   The method simply searches all codes - some optimisation is possible. */

long find_code(double value, double tolerance)

{

    long code;

    int bit;

    double res;

    /* Search all codes */

    for (code = 0; code < 0x10000L; code++)

    {

        res = res_offset;

        for (bit = 0; bit < 16; bit++)

        {

            if (code & (1 << bit))

            {

                /* This bit is ON (switch closed) */

                res += parallel_resistance(res_value[bit], res_contact);

            }

            else

            {

                /* This bit is OFF (switch open) */

                res += res_value[bit];

            }

        }

        if ( res > (value * (1.0 - tolerance)) && res < (value * (1.0 + tolerance)) )

        {

#ifdef DEBUG

            printf("Code 0x%04X = %8.2f ohms\n", code, res);

#endif

            return code;

        }

    }

    return -1;

}