mcp4018: Add initial support for the mcp4018 digipot

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2019-02-12 20:15:11 -05:00
parent a090b31713
commit cc4ecef88b
3 changed files with 107 additions and 1 deletions

View File

@ -778,6 +778,31 @@
# default is to not scale the 'channel_x' parameters. # default is to not scale the 'channel_x' parameters.
# Statically configured MCP4018 digipot connected via two gpio "bit
# banging" pins (one may define any number of sections with an
# "mcp4018" prefix).
#[mcp4018 my_digipot]
#scl_pin:
# The SCL "clock" pin. This parameter must be provided.
#sda_pin:
# The SDA "data" pin. This parameter must be provided.
#wiper:
# The value to statically set the given MCP4018 "wiper" to. This is
# typically set to a number between 0.0 and 1.0 with 1.0 being the
# highest resistance and 0.0 being the lowest resistance. However,
# the range may be changed with the 'scale' parameter (see
# below). This parameter must be provided.
#scale:
# This parameter can be used to alter how the 'wiper' parameter is
# interpreted. If provided, then the 'wiper' parameter should be
# between 0.0 and 'scale'. This may be useful when the MCP4018 is
# used to set stepper voltage references. The 'scale' can be set to
# the equivalent stepper amperage if the MCP4018 is at its highest
# resistance, and then the 'wiper' parameter can be specified using
# the desired amperage value for the stepper. The default is to not
# scale the 'wiper' parameter.
# Configure an SX1509 I2C to GPIO expander. Due to the delay incurred # Configure an SX1509 I2C to GPIO expander. Due to the delay incurred
# by I2C communication you should NOT use SX1509 pins as stepper enable, # by I2C communication you should NOT use SX1509 pins as stepper enable,
# step or dir pins or any other pin that requires fast bit-banging. They # step or dir pins or any other pin that requires fast bit-banging. They

View File

@ -95,7 +95,7 @@ Klipper supports many standard 3d printer features:
* Support for run-time configuration of TMC2130, TMC2208, TMC2224, and * Support for run-time configuration of TMC2130, TMC2208, TMC2224, and
TMC2660 stepper motor drivers. There is also support for current TMC2660 stepper motor drivers. There is also support for current
control of traditional stepper drivers via AD5206, MCP4451, MCP4728, control of traditional stepper drivers via AD5206, MCP4451, MCP4728,
and PWM pins. MCP4018, and PWM pins.
* Support for common LCD displays attached directly to the printer. A * Support for common LCD displays attached directly to the printer. A
default menu is also available. default menu is also available.

81
klippy/extras/mcp4018.py Normal file
View File

@ -0,0 +1,81 @@
# MCP4018 digipot support (via bit-banging)
#
# Copyright (C) 2019 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
class SoftwareI2C:
def __init__(self, config, addr):
self.addr = addr << 1
self.update_pin_cmd = None
# Lookup pins
ppins = config.get_printer().lookup_object('pins')
scl_pin = config.get('scl_pin')
scl_params = ppins.lookup_pin(scl_pin, share_type='sw_scl')
self.mcu = scl_params['chip']
self.scl_pin = scl_params['pin']
self.scl_main = scl_params.get('class')
if self.scl_main is None:
self.scl_main = scl_params['class'] = self
self.scl_oid = self.mcu.create_oid()
self.cmd_queue = self.mcu.alloc_command_queue()
self.mcu.register_config_callback(self.build_config)
else:
self.scl_oid = self.scl_main.scl_oid
self.cmd_queue = self.scl_main.cmd_queue
sda_params = ppins.lookup_pin(config.get('sda_pin'))
self.sda_oid = self.mcu.create_oid()
if sda_params['chip'] != self.mcu:
raise ppins.error("%s: scl_pin and sda_pin must be on same mcu" % (
config.get_name(),))
self.mcu.add_config_cmd("config_digital_out oid=%d pin=%s"
" value=%d default_value=%d max_duration=%d" % (
self.sda_oid, sda_params['pin'], 1, 1, 0))
def build_config(self):
self.mcu.add_config_cmd("config_digital_out oid=%d pin=%s value=%d"
" default_value=%d max_duration=%d" % (
self.scl_oid, self.scl_pin, 1, 1, 0))
self.update_pin_cmd = self.mcu.lookup_command(
"update_digital_out oid=%c value=%c", cq=self.cmd_queue)
def i2c_write(self, msg):
msg = [self.addr] + msg
send = self.scl_main.update_pin_cmd.send
# Send ack
send([self.sda_oid, 0])
send([self.scl_oid, 0])
# Send bytes
sda_last = 0
for data in msg:
# Transmit 8 data bits
for i in range(8):
sda_next = not not (data & (0x80 >> i))
if sda_last != sda_next:
sda_last = sda_next
send([self.sda_oid, sda_last])
send([self.scl_oid, 1])
send([self.scl_oid, 0])
# Transmit clock for ack
send([self.scl_oid, 1])
send([self.scl_oid, 0])
# Send stop
if sda_last:
send([self.sda_oid, 0])
send([self.scl_oid, 1])
send([self.sda_oid, 1])
class mcp4018:
def __init__(self, config):
self.i2c = SoftwareI2C(config, 0x2f)
self.scale = config.getfloat('scale', 1., above=0.)
self.start_value = config.getfloat('wiper',
minval=0., maxval=self.scale)
config.get_printer().register_event_handler("klippy:connect",
self.handle_connect)
def handle_connect(self):
self.set_dac(self.start_value)
def set_dac(self, value):
val = int(value * 127. / self.scale + .5)
self.i2c.i2c_write([val])
def load_config_prefix(config):
return mcp4018(config)