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.
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.
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!
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)