Setting a 40-296 Potentiometer Channel

    The schematic for a 40-296 (or 50-296) potentiometer resistor chain is shown below (extracted from the product manual).

    Diagram of module 40-296

    Setting a 16x2 potentiometer

    Each resistor chain comprises resistor chains for the lower and upper arms of the potentiometer with a Wiper tap at the junction of the two arms.

    The potentiometer is set by controlling the resistors such that the sum of both arms is constant. In the simpler case of a potentiometer using the entire resistor chain, the upper resistor must be the binary complement of the lower chain.

    Note however that the bit order of the resistors are reversed, so the pattern for the upper arm must be the reverse bit order of the complement of the lower arm.

    A function that performs the required actions for a 16 bit resistor chain (16 lower and 16 upper) is listed below:

    (NOTE: in the interest of clarity no error checking is performed in any of the code examples below)

    unsigned int calculate_296_pattern(unsigned int x)
        unsigned int maskl = 1<<15;
        unsigned int maskh = 1 << 16;
        unsigned int result = x |= 0xffff0000;
            if ((x & maskl) == maskl) result &= ~maskh;
            maskl >>= 1;
            maskh <<= 1;
        } while (maskl > 0);
        return ~result;

    The requested resistance value of he lower arm is passed to the function, the upper 16 bits of the 32-bit contained are set to logic 1.

    One-by-one each bit of the lower 16-bits of that value is checked and where a logic 1 is present the corresponding bit of the upper 16 is set to logic 0.

    Finally the entire 32-bit pattern in inverted and returned to the caller, This pattern will set both lower and upper resistor chains to the correct values.

    This will create a potentiometer with an overall value of 65535 Ohms where the wiper may be set to any 1 Ohm step across the entire potentiometer range.

    Other sizes

    The 16x2 version is the simplest case to consider, but Pickering also provide cards with 8, 12 and 24 bit chains. These need to be treated slightly differently.

    The 8x2 bit and 12x2 bit versions are fairly simply implemented by modification of the masks in the above example.

    // 8-bit
    unsigned int maskl = 1 << 7;
    unsigned int maskh = 1 << 8;
    unsigned int result = x |= 0xffffff00;
    // 12-bit
    unsigned int maskl = 1 << 11;
    unsigned int maskh = 1 << 12;
    unsigned int result = x |= 0xffffff00;

    Cards with 24-bit chains require a little more work since the final pattern occupies 48 bits and must be passed to the card as an array of two 32-bit words.

    void calculate_pattern(unsigned int x, unsigned int *q)
        int64_t r = x;
        uint64_t maskl = (uint64_t)1 << 31;
        uint64_t maskh = (uint64_t)1 << 32;
        uint64_t result = r |= 0xffffffff00000000;
            if ((r & maskl) == maskl) result &= ~maskh;
            maskl >>= 1;
            maskh <<= 1;
        } while (maskl > 0);
        q[0] = ~(result & 0x00000000ffffffff);
        result >>= 32;
        q[1] = ~((unsigned int)result);
    int _tmain(int argc, _TCHAR* argv[])
        unsigned int  output[2];
        reverse(r, output);

    In this case a 2 element array of 32-bit values is declared and passed to the function which performs the calculation using 64-bit variables and then converts the result and places it into the array.

    Other values

    It may be that the user wished to emulate a potentiometer with a different overall value, say for example a 50 kOhm potentiometer on the above 16x2 bit chain.

    In these cases the upper resistor is not set to the binary complement of the lower value, but rather to a value such that the sum of the two resistors remains constant at the required overall value. For example if the lower resistor is 1 kOhm and the overall value is 50 kOhm then the upper resistor must be set to 49 kOhm.

    void calculateBothResistors(unsigned int lower,
                                unsigned int total,
                                int resistor_size,
                                unsigned int *result)
        unsigned int upper = total - lower;  // calculate upper resistor value
            // initialize masks
        unsigned int mask = 1 << (resistor_size-1);
        uint64_t masku = 1 << resistor_size;
        uint64_t pattern = 0;
            if ((upper & mask) == mask)
                pattern |= masku;
            mask >>= 1;
            masku <<= 1;
        } while (masku > 0);
        pattern |= (uint64_t)lower;
            // split 64 bit value into a pair of 32 bit values
        result[0] = ~(pattern & 0x00000000ffffffff);
        pattern >>= 32;
        result[1] = ~((unsigned int)pattern);

    Here, resistor_size is the size of a single resistor, so 8, 12, 16 or 24.

    total is the overall potentiometer value required and lower is the value of the lower arm of that potentiometer

    This function fills in the values of a 2 element array ready to be sent as a pattern to the potentiometer sub_unit.

    Need Help´╝č


    Information on software drivers, product comparisons and technical support for our entire product range.


    Product Selector

    This tool will help you narrow down our offering to get you the correct switch and simulation solution you need.

    Try the selector

    Resource center

    Success storiesproduct videos and more—find the information you need about our switching and simulation.

    Resources you need

    Worldwide presence

    Find support across the globe, with offices and agents in the Americas, Europe and Asia. 

    Find local office or agent