This is more of a work project but also a fun thing I did after hours. At work someone needed a programmable resistor to quickly automate something so I bought a evaluation board for a dual channel programmable, digital resistor and wired it up to a pi to control it. I also wired up to a TTY to USB converter so the pi shows up as serial device on any computer to access its terminal. I then wrote a simple python script to communicate with it and set the two outputs to a given, calibrated value so the automation system could push command strings to the pi and get the intended impedance output. So I dubbed the project Georg, after Georg Ohm who discovered impedance.

Digital Pot Info

The TPL0102 is a 256-tap dual-channel digital potentiometer with I2C interface that also happens to have linux kernel drivers. It comes already mounted and ready to wire up as an evaluation kit. I used the eval kit for this setup.

georg

Example Usage Over Serial

pi@georg:~$ echo "wiper_a,82500" | python ~/resistance.py

Requested Resistance is: 82,500 ohms

Closest Available Resistance value is: 82,422.30 ohms

Step number: 223

Resistance value to be set is: 87,109.82 ohms
This is adjusted for the calibration factor so its not the same as what was requested!

Code

import sys
import smbus

######## Configuration #########################
# I2C channel 1 is connected to the GPIO pins
channel = 1
#device address
address = 0x50
######## Calibration ###########################
nominal_resistance = 100000
#these values below are what you change from part to part
wiper_a_resistance = 94600
wiper_b_resistance = 94600
################################################

#read the value piped in from the command line
piped = sys.stdin.read()
#split it at the comma
wiper, resistance  = piped.split(",")

#make sure the wiper (potentiometer channel) is properly defined
if (wiper == "wiper_a"):
        reg_write = 0x00
        calibration = wiper_a_resistance / nominal_resistance
elif (wiper == "wiper_b"):
        reg_write = 0x01
        calibration = wiper_b_resistance / nominal_resistance
else:
        print("Error - the wiper isn't properly defined. It can only be 'wiper_a' or 'wiper_b'")

#convert it to an integer
resistance = int(resistance)

#make sure its in range of the hardware
if (resistance < 0):
        print("Error, resistance cannot be less than 0 ohms")
        sys.exit()
elif (resistance > 100000):
        print("Error - resistance cannot be greater than 100,000 ohms")
        sys.exit()
else:
        print("\nRequested Resistance is: "+f"{resistance:,}"+" ohms")

print("\nClosest Available Resistance value is: "+f"{(round(resistance / 390.627) * 390.627):,.2f}"+" ohms")

#390.627 ohms per step on the potentiometer wiper
steps = round(resistance / (390.627 * calibration))
print("\nStep number (adjusted for calibration): "+f"{steps:,}")

if (steps > 255):
        print("Error, steps cannot be higher than 255. Rounding down to 255")
        steps = 255

#print out the estimated setpoint
output_resistance = steps * 390.627
print("\nResistance value to be set is: "+f"{output_resistance:,.2f}"+" ohms")
print("This is adjusted for the calibration factor so its not the same as what was requested!\n")

# Initialize I2C (SMBus)
bus = smbus.SMBus(channel)

#Write out I2C command: I2C address, register location, payload
bus.write_byte_data(address, reg_write, steps)