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;
}