chipmisc: Add support for statically configured output pins

Allow digital and PWM output pins to be setup via new config
sections.  This makes it easier to setup pin configurations.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2017-08-24 09:34:31 -04:00
parent 6ab8567d51
commit 9d75c3b0ca
7 changed files with 193 additions and 74 deletions

83
config/example-extras.cfg Normal file
View File

@ -0,0 +1,83 @@
# This file serves as documentation for config parameters of
# additional devices that may be configured on a printer. The snippets
# in this file may be copied into the main printer.cfg file. See the
# "example.cfg" file for description of common config parameters.
# In a multi-extruder printer add an additional extruder section for
# each additional extruder. The additional extruder sections should be
# named "extruder1", "extruder2", "extruder3", and so on. See the
# "extruder" section in example.cfg for a description of available
# parameters.
#[extruder1]
#step_pin: ar36
#dir_pin: ar34
#...
#deactivate_gcode:
# A list of G-Code commands (one per line) to execute on a G-Code
# tool change command (eg, "T1") that deactivates this extruder and
# activates some other extruder. It only makes sense to define this
# section on multi-extruder printers. The default is to not run any
# special G-Code commands on deactivation.
#activate_gcode:
# A list of G-Code commands (one per line) to execute on a G-Code
# tool change command (eg, "T0") that activates this extruder. It
# only makes sense to define this section on multi-extruder
# printers. The default is to not run any special G-Code commands on
# activation.
# Heater cooling fans (one may define any number of sections with a
# "heater_fan" prefix). A "heater fan" is a fan that will be enabled
# whenever its associated heater is active.
#[heater_fan my_nozzle_fan]
# See the "fan" section for fan configuration parameters.
#pin: ar4
# The remaining variables are specific to heater_fan.
#heater: extruder
# Name of the config section defining the heater that this fan is
# associated with. The default is "extruder".
#heater_temp: 50.0
# A temperature (in Celsius) that the heater must drop below before
# the fan is disabled. The default is 50 Celsius.
# Statically configured digital output pins (one may define any number
# of sections with a "static_digital_output" prefix). Pins configured
# here will be setup as a GPIO output during MCU configuration.
#[static_digital_output my_output_pins]
#pins:
# A comma separated list of pins to be set as GPIO output pins. The
# pin will be set to a high level unless the pin name is prefaced
# with "!". This parameter must be provided.
# Statically configured PWM output pins (one may define any number of
# sections with a "static_pwm_output" prefix). Pins configured here
# will be setup as PWM outputs during MCU configuration.
#[static_pwm_output my_output_pwm]
#pin:
# The pin to configure as PWM output. This parameter must be
# provided.
#value:
# The value to statically set the PWM output to. This is typically
# set to a number between 0.0 and 1.0 with 1.0 being full on and 0.0
# being full off. However, the range may be changed with the 'scale'
# parameter (see below). This parameter must be provided.
#hard_pwm:
# Set this value to force hardware PWM instead of software PWM. Set
# to 1 to force a hardware PWM at the fastest rate; set to a higher
# number to force hardware PWM with the given cycle time in clock
# ticks. The default is to use software PWM.
#cycle_time: 0.100
# The amount of time (in seconds) per PWM cycle when using software
# based PWM. The default is 0.100 seconds.
#scale:
# This parameter can be used to alter how the 'value' parameter is
# interpreted. If provided, then the 'value' parameter should be
# between 0.0 and 'scale'. This may be useful when configuring a PWM
# pin that controls a stepper voltage reference. The 'scale' can be
# set to the equivalent stepper amperage if the PWM were fully
# enabled, and then the 'value' parameter can be specified using the
# desired amperage for the stepper. The default is to not scale the
# 'value' parameter.

View File

@ -2,7 +2,8 @@
# copy and edit this file to configure a new cartesian style # copy and edit this file to configure a new cartesian style
# printer. For delta style printers, see the "example-delta.cfg" # printer. For delta style printers, see the "example-delta.cfg"
# file. For corexy/h-bot style printers, see the "example-corexy.cfg" # file. For corexy/h-bot style printers, see the "example-corexy.cfg"
# file. # file. Only common config sections are described here - see the
# "example-extras.cfg" file for configuring less common devices.
# DO NOT COPY THIS FILE WITHOUT CAREFULLY READING AND UPDATING IT # DO NOT COPY THIS FILE WITHOUT CAREFULLY READING AND UPDATING IT
# FIRST. Incorrectly configured parameters may cause damage. # FIRST. Incorrectly configured parameters may cause damage.
@ -150,18 +151,6 @@ filament_diameter: 3.500
# otherwise cause retraction followed immediately by pressure # otherwise cause retraction followed immediately by pressure
# buildup. This setting only applies if pressure_advance is # buildup. This setting only applies if pressure_advance is
# non-zero. The default is 0.010 (10 milliseconds). # non-zero. The default is 0.010 (10 milliseconds).
#deactivate_gcode:
# A list of G-Code commands (one per line) to execute on a G-Code
# tool change command (eg, "T1") that deactivates this extruder and
# activates some other extruder. It only makes sense to define this
# section on multi-extruder printers. The default is to not run any
# special G-Code commands on deactivation.
#activate_gcode:
# A list of G-Code commands (one per line) to execute on a G-Code
# tool change command (eg, "T0") that activates this extruder. It
# only makes sense to define this section on multi-extruder
# printers. The default is to not run any special G-Code commands on
# activation.
# #
# The remaining variables describe the extruder heater. # The remaining variables describe the extruder heater.
heater_pin: ar10 heater_pin: ar10
@ -217,15 +206,6 @@ max_temp: 210
# Maximum temperature (mcu will shutdown if temperature is above # Maximum temperature (mcu will shutdown if temperature is above
# this value). This parameter must be provided. # this value). This parameter must be provided.
# In a multi-extruder printer add an additional extruder section for
# each additional extruder. The additional extruder sections should be
# named "extruder1", "extruder2", "extruder3", and so on. See the
# "extruder" section above for a description of available parameters.
#[extruder1]
#step_pin: ar36
#dir_pin: ar34
#...
# The heater_bed section describes a heated bed (if present - omit # The heater_bed section describes a heated bed (if present - omit
# section if not present). # section if not present).
[heater_bed] [heater_bed]
@ -323,17 +303,3 @@ max_z_accel: 30
# centripetal velocity cornering algorithm. A larger number will # centripetal velocity cornering algorithm. A larger number will
# permit higher "cornering speeds" at the junction of two moves. The # permit higher "cornering speeds" at the junction of two moves. The
# default is 0.02mm. # default is 0.02mm.
# Heater cooling fans (one may define any number of sections with a
# "heater_fan" prefix). A "heater fan" is a fan that will be enabled
# whenever its associated heater is active.
#[heater_fan my_nozzle_fan]
# See the "fan" section for fan configuration parameters.
#pin: ar4
# The remaining variables are specific to heater_fan.
#heater: extruder
# Name of the config section defining the heater that this fan is
# associated with. The default is "extruder".
#heater_temp: 50.0
# A temperature (in Celsius) that the heater must drop below before
# the fan is disabled. The default is 50 Celsius.

View File

@ -77,19 +77,6 @@ pin: PH5
[mcu] [mcu]
serial: /dev/ttyACM0 serial: /dev/ttyACM0
custom: custom:
# Turn off yellow led
set_digital_out pin=PB7 value=0
# Stepper micro-step pins
set_digital_out pin=PG1 value=1
set_digital_out pin=PG0 value=1
set_digital_out pin=PK7 value=1
set_digital_out pin=PG2 value=1
set_digital_out pin=PK6 value=1
set_digital_out pin=PK5 value=1
set_digital_out pin=PK3 value=1
set_digital_out pin=PK4 value=1
#set_digital_out pin=PK2 value=1
#set_digital_out pin=PK1 value=1
# Initialize digipot # Initialize digipot
send_spi_message pin=PD7 msg=0487 # X = ~0.75A send_spi_message pin=PD7 msg=0487 # X = ~0.75A
send_spi_message pin=PD7 msg=0587 # Y = ~0.75A send_spi_message pin=PD7 msg=0587 # Y = ~0.75A
@ -103,3 +90,15 @@ max_velocity: 300
max_accel: 3000 max_accel: 3000
max_z_velocity: 5 max_z_velocity: 5
max_z_accel: 100 max_z_accel: 100
# Enable 16 micro-steps on steppers X, Y, Z, E0, E1
[static_digital_output stepper_config]
pins:
PG1, PG0,
PK7, PG2,
PK6, PK5,
PK3, PK4,
PK2, PK1
[static_digital_output yellow_led]
pins: !PB7

View File

@ -77,17 +77,6 @@ hard_pwm: 1
[mcu] [mcu]
serial: /dev/ttyACM0 serial: /dev/ttyACM0
custom: custom:
# Turn off yellow led
set_digital_out pin=PB7 value=0
# Stepper micro-step pins
set_digital_out pin=PG1 value=1
set_digital_out pin=PG0 value=1
set_digital_out pin=PK7 value=1
set_digital_out pin=PG2 value=1
set_digital_out pin=PK6 value=1
set_digital_out pin=PK5 value=1
set_digital_out pin=PK3 value=1
set_digital_out pin=PK4 value=1
# Initialize digipot # Initialize digipot
send_spi_message pin=PD7 msg=0487 # X = ~0.75A send_spi_message pin=PD7 msg=0487 # X = ~0.75A
send_spi_message pin=PD7 msg=0587 # Y = ~0.75A send_spi_message pin=PD7 msg=0587 # Y = ~0.75A
@ -101,3 +90,14 @@ max_velocity: 500
max_accel: 3000 max_accel: 3000
max_z_velocity: 25 max_z_velocity: 25
max_z_accel: 30 max_z_accel: 30
# Enable 8 micro-steps on steppers X, Y, Z, E0
[static_digital_output stepper_config]
pins:
PG1, PG0,
PK7, PG2,
PK6, PK5,
PK3, PK4
[static_digital_output yellow_led]
pins: !PB7

43
klippy/chipmisc.py Normal file
View File

@ -0,0 +1,43 @@
# Code to configure miscellaneous chips
#
# Copyright (C) 2017 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import pins
######################################################################
# Statically configured output pins
######################################################################
class PrinterStaticDigitalOut:
def __init__(self, printer, config):
pin_list = [pin.strip() for pin in config.get('pins').split(',')]
for pin_desc in pin_list:
mcu_pin = pins.setup_pin(printer, 'digital_out', pin_desc)
mcu_pin.setup_static()
class PrinterStaticPWM:
def __init__(self, printer, config):
mcu_pwm = pins.setup_pin(printer, 'pwm', config.get('pin'))
mcu_pwm.setup_max_duration(0.)
hard_pwm = config.getint('hard_pwm', None, minval=1)
if hard_pwm is None:
mcu_pwm.setup_cycle_time(config.getfloat(
'cycle_time', 0.100, above=0.))
else:
mcu_pwm.setup_hard_pwm(hard_pwm)
scale = config.getfloat('scale', 1., above=0.)
value = config.getfloat('value', minval=0., maxval=scale)
mcu_pwm.setup_static_pwm(value / scale)
######################################################################
# Setup
######################################################################
def add_printer_objects(printer, config):
for s in config.get_prefix_sections('static_digital_output '):
printer.add_object(s.section, PrinterStaticDigitalOut(printer, s))
for s in config.get_prefix_sections('static_pwm_output '):
printer.add_object(s.section, PrinterStaticPWM(printer, s))

View File

@ -6,7 +6,7 @@
# This file may be distributed under the terms of the GNU GPLv3 license. # This file may be distributed under the terms of the GNU GPLv3 license.
import sys, optparse, ConfigParser, logging, time, threading import sys, optparse, ConfigParser, logging, time, threading
import util, reactor, queuelogger, msgproto, gcode import util, reactor, queuelogger, msgproto, gcode
import pins, mcu, extruder, fan, heater, toolhead import pins, mcu, chipmisc, extruder, fan, heater, toolhead
message_ready = "Printer is ready" message_ready = "Printer is ready"
@ -172,7 +172,7 @@ class Printer:
ConfigLogger(self.fileconfig, self.bglogger) ConfigLogger(self.fileconfig, self.bglogger)
# Create printer components # Create printer components
config = ConfigWrapper(self, 'printer') config = ConfigWrapper(self, 'printer')
for m in [pins, mcu, extruder, fan, heater, toolhead]: for m in [pins, mcu, chipmisc, extruder, fan, heater, toolhead]:
m.add_printer_objects(self, config) m.add_printer_objects(self, config)
self.mcu = self.objects['mcu'] self.mcu = self.objects['mcu']
# Validate that there are no undefined parameters in the config file # Validate that there are no undefined parameters in the config file

View File

@ -14,7 +14,6 @@ STEPCOMPRESS_ERROR_RET = -989898989
class MCU_stepper: class MCU_stepper:
def __init__(self, mcu, pin_params): def __init__(self, mcu, pin_params):
self._mcu = mcu self._mcu = mcu
self._oid = mcu.create_oid()
self._step_pin = pin_params['pin'] self._step_pin = pin_params['pin']
self._invert_step = pin_params['invert'] self._invert_step = pin_params['invert']
self._dir_pin = self._invert_dir = None self._dir_pin = self._invert_dir = None
@ -23,7 +22,7 @@ class MCU_stepper:
self._velocity_factor = self._accel_factor = 0. self._velocity_factor = self._accel_factor = 0.
self._mcu_position_offset = 0 self._mcu_position_offset = 0
self._mcu_freq = self._min_stop_interval = 0. self._mcu_freq = self._min_stop_interval = 0.
self._reset_cmd = self._get_position_cmd = None self._oid = self._reset_cmd = self._get_position_cmd = None
self._ffi_lib = self._stepqueue = None self._ffi_lib = self._stepqueue = None
self.print_to_mcu_time = mcu.print_to_mcu_time self.print_to_mcu_time = mcu.print_to_mcu_time
self.system_to_mcu_time = mcu.system_to_mcu_time self.system_to_mcu_time = mcu.system_to_mcu_time
@ -39,6 +38,7 @@ class MCU_stepper:
self._inv_step_dist = 1. / step_dist self._inv_step_dist = 1. / step_dist
def build_config(self): def build_config(self):
self._mcu_freq = self._mcu.get_mcu_freq() self._mcu_freq = self._mcu.get_mcu_freq()
self._oid = self._mcu.create_oid()
self._velocity_factor = 1. / (self._mcu_freq * self._step_dist) self._velocity_factor = 1. / (self._mcu_freq * self._step_dist)
self._accel_factor = 1. / (self._mcu_freq**2 * self._step_dist) self._accel_factor = 1. / (self._mcu_freq**2 * self._step_dist)
max_error = self._mcu.get_max_stepper_error() max_error = self._mcu.get_max_stepper_error()
@ -142,13 +142,12 @@ class MCU_endstop:
RETRY_QUERY = 1.000 RETRY_QUERY = 1.000
def __init__(self, mcu, pin_params): def __init__(self, mcu, pin_params):
self._mcu = mcu self._mcu = mcu
self._oid = mcu.create_oid()
self._steppers = [] self._steppers = []
self._pin = pin_params['pin'] self._pin = pin_params['pin']
self._pullup = pin_params['pullup'] self._pullup = pin_params['pullup']
self._invert = pin_params['invert'] self._invert = pin_params['invert']
self._cmd_queue = mcu.alloc_command_queue() self._cmd_queue = mcu.alloc_command_queue()
self._home_cmd = self._query_cmd = None self._oid = self._home_cmd = self._query_cmd = None
self._homing = False self._homing = False
self._min_query_time = self._mcu_freq = 0. self._min_query_time = self._mcu_freq = 0.
self._next_query_clock = self._home_timeout_clock = 0 self._next_query_clock = self._home_timeout_clock = 0
@ -160,6 +159,7 @@ class MCU_endstop:
self._steppers.append(stepper) self._steppers.append(stepper)
def build_config(self): def build_config(self):
self._mcu_freq = self._mcu.get_mcu_freq() self._mcu_freq = self._mcu.get_mcu_freq()
self._oid = self._mcu.create_oid()
self._mcu.add_config_cmd( self._mcu.add_config_cmd(
"config_end_stop oid=%d pin=%s pull_up=%d stepper_count=%d" % ( "config_end_stop oid=%d pin=%s pull_up=%d stepper_count=%d" % (
self._oid, self._pin, self._pullup, len(self._steppers))) self._oid, self._pin, self._pullup, len(self._steppers)))
@ -236,7 +236,8 @@ class MCU_endstop:
class MCU_digital_out: class MCU_digital_out:
def __init__(self, mcu, pin_params): def __init__(self, mcu, pin_params):
self._mcu = mcu self._mcu = mcu
self._oid = mcu.create_oid() self._oid = None
self._static_value = None
self._pin = pin_params['pin'] self._pin = pin_params['pin']
self._invert = pin_params['invert'] self._invert = pin_params['invert']
self._max_duration = 2. self._max_duration = 2.
@ -249,8 +250,15 @@ class MCU_digital_out:
self.system_to_mcu_time = mcu.system_to_mcu_time self.system_to_mcu_time = mcu.system_to_mcu_time
def setup_max_duration(self, max_duration): def setup_max_duration(self, max_duration):
self._max_duration = max_duration self._max_duration = max_duration
def setup_static(self):
self._static_value = not self._invert
def build_config(self): def build_config(self):
self._mcu_freq = self._mcu.get_mcu_freq() self._mcu_freq = self._mcu.get_mcu_freq()
if self._static_value is not None:
self._mcu.add_config_cmd("set_digital_out pin=%s value=%d" % (
self._pin, self._static_value))
return
self._oid = self._mcu.create_oid()
self._mcu.add_config_cmd( self._mcu.add_config_cmd(
"config_digital_out oid=%d pin=%s default_value=%d" "config_digital_out oid=%d pin=%s default_value=%d"
" max_duration=TICKS(%f)" % ( " max_duration=TICKS(%f)" % (
@ -278,7 +286,8 @@ class MCU_pwm:
self._hard_pwm = False self._hard_pwm = False
self._cycle_time = 0.100 self._cycle_time = 0.100
self._max_duration = 2. self._max_duration = 2.
self._oid = mcu.create_oid() self._oid = None
self._static_value = None
self._pin = pin_params['pin'] self._pin = pin_params['pin']
self._invert = pin_params['invert'] self._invert = pin_params['invert']
self._last_clock = 0 self._last_clock = 0
@ -298,26 +307,45 @@ class MCU_pwm:
return return
self._cycle_time = hard_cycle_ticks self._cycle_time = hard_cycle_ticks
self._hard_pwm = True self._hard_pwm = True
def setup_static_pwm(self, value):
if self._invert:
self._static_value = 1. - value
else:
self._static_value = value
def build_config(self): def build_config(self):
self._mcu_freq = self._mcu.get_mcu_freq() self._mcu_freq = self._mcu.get_mcu_freq()
if self._hard_pwm: if self._hard_pwm:
self._pwm_max = self._mcu.serial.msgparser.get_constant_float(
"PWM_MAX")
if self._static_value is not None:
value = int(self._static_value * self._pwm_max + 0.5)
self._mcu.add_config_cmd(
"set_pwm_out pin=%s cycle_ticks=%d value=%d" % (
self._pin, self._cycle_time, value))
return
self._oid = self._mcu.create_oid()
self._mcu.add_config_cmd( self._mcu.add_config_cmd(
"config_pwm_out oid=%d pin=%s cycle_ticks=%d default_value=%d" "config_pwm_out oid=%d pin=%s cycle_ticks=%d default_value=%d"
" max_duration=TICKS(%f)" % ( " max_duration=TICKS(%f)" % (
self._oid, self._pin, self._cycle_time, self._invert, self._oid, self._pin, self._cycle_time, self._invert,
self._max_duration)) self._max_duration))
self._pwm_max = self._mcu.serial.msgparser.get_constant_float(
"PWM_MAX")
self._set_cmd = self._mcu.lookup_command( self._set_cmd = self._mcu.lookup_command(
"schedule_pwm_out oid=%c clock=%u value=%hu") "schedule_pwm_out oid=%c clock=%u value=%hu")
else: else:
self._pwm_max = self._mcu.serial.msgparser.get_constant_float(
"SOFT_PWM_MAX")
if self._static_value is not None:
if self._static_value != 0. and self._static_value != 1.:
raise pins.error("static value on soft pwm not supported")
self._mcu.add_config_cmd("set_digital_out pin=%s value=%d" % (
self._pin, int(self._static_value)))
return
self._oid = self._mcu.create_oid()
self._mcu.add_config_cmd( self._mcu.add_config_cmd(
"config_soft_pwm_out oid=%d pin=%s cycle_ticks=TICKS(%f)" "config_soft_pwm_out oid=%d pin=%s cycle_ticks=TICKS(%f)"
" default_value=%d max_duration=TICKS(%f)" % ( " default_value=%d max_duration=TICKS(%f)" % (
self._oid, self._pin, self._cycle_time, self._invert, self._oid, self._pin, self._cycle_time, self._invert,
self._max_duration)) self._max_duration))
self._pwm_max = self._mcu.serial.msgparser.get_constant_float(
"SOFT_PWM_MAX")
self._set_cmd = self._mcu.lookup_command( self._set_cmd = self._mcu.lookup_command(
"schedule_soft_pwm_out oid=%c clock=%u value=%hu") "schedule_soft_pwm_out oid=%c clock=%u value=%hu")
def set_pwm(self, mcu_time, value): def set_pwm(self, mcu_time, value):
@ -334,12 +362,11 @@ class MCU_adc:
def __init__(self, mcu, pin_params): def __init__(self, mcu, pin_params):
self._mcu = mcu self._mcu = mcu
self._pin = pin_params['pin'] self._pin = pin_params['pin']
self._oid = mcu.create_oid()
self._min_sample = self._max_sample = 0. self._min_sample = self._max_sample = 0.
self._sample_time = self._report_time = 0. self._sample_time = self._report_time = 0.
self._sample_count = 0 self._sample_count = 0
self._report_clock = 0 self._report_clock = 0
self._callback = None self._oid = self._callback = None
self._inv_max_adc = 0. self._inv_max_adc = 0.
self._mcu_freq = 0. self._mcu_freq = 0.
self._cmd_queue = mcu.alloc_command_queue() self._cmd_queue = mcu.alloc_command_queue()
@ -355,6 +382,7 @@ class MCU_adc:
if not self._sample_count: if not self._sample_count:
return return
self._mcu_freq = self._mcu.get_mcu_freq() self._mcu_freq = self._mcu.get_mcu_freq()
self._oid = self._mcu.create_oid()
self._mcu.add_config_cmd("config_analog_in oid=%d pin=%s" % ( self._mcu.add_config_cmd("config_analog_in oid=%d pin=%s" % (
self._oid, self._pin)) self._oid, self._pin))
last_clock, last_clock_time = self._mcu.get_last_clock() last_clock, last_clock_time = self._mcu.get_last_clock()