diff --git a/README.md b/README.md index 9665766..65f56a2 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ _Note: Current Raspberry Pi implementation uses the same resources as on board 3.5 mm jack(PWM module), so do not use it. HDMI audio works._ # Config -All configs are stored in [config.py](./cnc/config.py) and contain hardware +All configs are stored in /etc/pycnc.conf and contain hardware properties, limitations and pin names for hardware control. Raspberry Pi implementation should be connected to A4988, DRV8825 or any other stepper motor drivers with DIR and STEP pin inputs. @@ -112,12 +112,12 @@ interactive terminal mode where gcode commands can be entered manually. To run file with gcode commands, just run `./pycnc filename`. Optionally, `pycnc` can be installed. Run ```bash -sudo pip install . +sudo sudo pip3 install . ``` in repo root directory to install it. After than, `pycnc` command will be added to system path. To remove installation, just run: ```bash -sudo pip remove pycnc +sudo pip3 uninstall pycnc ``` # Performance notice @@ -160,3 +160,4 @@ see [LICENSE](./LICENSE) file. # Author Nikolay Khabarov +Jairo Moreno - added configuration file diff --git a/cnc/config.py b/cnc/config.py old mode 100644 new mode 100755 index 15668a5..019a272 --- a/cnc/config.py +++ b/cnc/config.py @@ -1,79 +1,94 @@ # ----------------------------------------------------------------------------- # Hardware config. +import configparser + +configFilePath = '/etc/pycnc.conf' + + +configParser = configparser.RawConfigParser() +configParser.read(configFilePath) + +# Mixed settings. +STEPPER_PULSE_LENGTH_US = configParser.getint('control', 'stepper_pulse_length_us') +STEPPER_MAX_ACCELERATION_MM_PER_S2 = configParser.getint('control', 'stepper_max_acceleration_mm_per_s2') +SPINDLE_MAX_RPM = configParser.getint('control', 'spindle_max_rpm') + + +# Workplace physical size. +TABLE_SIZE_X_MM = configParser.getint('workplace', 'table_size_x_mm') +TABLE_SIZE_Y_MM = configParser.getint('workplace', 'table_size_y_mm') +TABLE_SIZE_Z_MM = configParser.getint('workplace', 'table_size_z_mm') +TABLE_SIZE_E_MM = configParser.getint('workplace', 'table_size_e_mm') + +TABLE_SIZE_X_MIN_MM = configParser.getint('workplace', 'table_size_x_min_mm') +TABLE_SIZE_Y_MIN_MM = configParser.getint('workplace', 'table_size_y_min_mm') +TABLE_SIZE_Z_MIN_MM = configParser.getint('workplace', 'table_size_z_min_mm') +TABLE_SIZE_E_MIN_MM = configParser.getint('workplace', 'table_size_e_min_mm') + # Maximum velocity for each axis in millimeter per minute. -MAX_VELOCITY_MM_PER_MIN_X = 24000 -MAX_VELOCITY_MM_PER_MIN_Y = 12000 -MAX_VELOCITY_MM_PER_MIN_Z = 600 -MAX_VELOCITY_MM_PER_MIN_E = 1500 -MIN_VELOCITY_MM_PER_MIN = 1 +MAX_VELOCITY_MM_PER_MIN_X = configParser.getint('axis', 'max_velocity_mm_per_min_x') +MAX_VELOCITY_MM_PER_MIN_Y = configParser.getint('axis', 'max_velocity_mm_per_min_y') +MAX_VELOCITY_MM_PER_MIN_Z = configParser.getint('axis', 'max_velocity_mm_per_min_z') +MAX_VELOCITY_MM_PER_MIN_E = configParser.getint('axis', 'max_velocity_mm_per_min_e') +MIN_VELOCITY_MM_PER_MIN = configParser.getint('axis', 'min_velocity_mm_per_min') + # Average velocity for endstop calibration procedure -CALIBRATION_VELOCITY_MM_PER_MIN = 300 +CALIBRATION_VELOCITY_MM_PER_MIN = configParser.getint('axis', 'calibration_velocity_mm_per_min') # Stepper motors steps per millimeter for each axis. -STEPPER_PULSES_PER_MM_X = 100 -STEPPER_PULSES_PER_MM_Y = 100 -STEPPER_PULSES_PER_MM_Z = 400 -STEPPER_PULSES_PER_MM_E = 150 +STEPPER_PULSES_PER_MM_X = configParser.getint('axis', 'stepper_pulses_per_mm_x') +STEPPER_PULSES_PER_MM_Y = configParser.getint('axis', 'stepper_pulses_per_mm_y') +STEPPER_PULSES_PER_MM_Z = configParser.getint('axis', 'stepper_pulses_per_mm_z') +STEPPER_PULSES_PER_MM_E = configParser.getint('axis', 'stepper_pulses_per_mm_e') # Invert axises direction, by default(False) high level means increase of # position. For inverted(True) axis, high level means decrease of position. -STEPPER_INVERTED_X = True -STEPPER_INVERTED_Y = False -STEPPER_INVERTED_Z = False -STEPPER_INVERTED_E = True +STEPPER_INVERTED_X = configParser.getboolean('axis', 'stepper_inverted_x') +STEPPER_INVERTED_Y = configParser.getboolean('axis', 'stepper_inverted_y') +STEPPER_INVERTED_Z = configParser.getboolean('axis', 'stepper_inverted_z') +STEPPER_INVERTED_E = configParser.getboolean('axis', 'stepper_inverted_e') # Invert zero end stops switches. By default(False) low level on input pin # means that axis in zero position. For inverted(True) end stops, high level # means zero position. -ENDSTOP_INVERTED_X = True -ENDSTOP_INVERTED_Y = True -ENDSTOP_INVERTED_Z = False # Auto leveler +ENDSTOP_INVERTED_X = configParser.getboolean('axis', 'endstop_inverted_x') +ENDSTOP_INVERTED_Y = configParser.getboolean('axis', 'endstop_inverted_y') +ENDSTOP_INVERTED_Z = configParser.getboolean('axis', 'endstop_inverted_z') -# Workplace physical size. -TABLE_SIZE_X_MM = 200 -TABLE_SIZE_Y_MM = 200 -TABLE_SIZE_Z_MM = 220 +EXTRUDER_MAX_TEMPERATURE = configParser.getint('temperature', 'extruder_max_temperature') +BED_MAX_TEMPERATURE = configParser.getint('temperature', 'bed_max_temperature') +MIN_TEMPERATURE = configParser.getint('temperature', 'min_temperature') -# Mixed settings. -STEPPER_PULSE_LENGTH_US = 2 -STEPPER_MAX_ACCELERATION_MM_PER_S2 = 3000 # for all axis, mm per sec^2 -SPINDLE_MAX_RPM = 10000 -EXTRUDER_MAX_TEMPERATURE = 250 -BED_MAX_TEMPERATURE = 100 -MIN_TEMPERATURE = 40 -EXTRUDER_PID = {"P": 0.059161177519, - "I": 0.00206217171374, - "D": 0.206217171374} -BED_PID = {"P": 0.226740848076, - "I": 0.00323956215053, - "D": 0.323956215053} # ----------------------------------------------------------------------------- # Pins configuration. - # Enable pin for all steppers, low level is enabled. -STEPPERS_ENABLE_PIN = 26 -STEPPER_STEP_PIN_X = 21 -STEPPER_STEP_PIN_Y = 16 -STEPPER_STEP_PIN_Z = 12 -STEPPER_STEP_PIN_E = 8 - -STEPPER_DIR_PIN_X = 20 -STEPPER_DIR_PIN_Y = 19 -STEPPER_DIR_PIN_Z = 13 -STEPPER_DIR_PIN_E = 7 - -SPINDLE_PWM_PIN = 4 -FAN_PIN = 27 -EXTRUDER_HEATER_PIN = 18 -BED_HEATER_PIN = 22 -EXTRUDER_TEMPERATURE_SENSOR_CHANNEL = 2 -BED_TEMPERATURE_SENSOR_CHANNEL = 1 - -ENDSTOP_PIN_X = 23 -ENDSTOP_PIN_Y = 10 -ENDSTOP_PIN_Z = 25 +STEPPERS_ENABLE_PIN = configParser.getint('control', 'steppers_enable_pin') + +STEPPER_STEP_PIN_X = configParser.getint('axis', 'stepper_step_pin_x') +STEPPER_DIR_PIN_X = configParser.getint('axis', 'stepper_dir_pin_x') +ENDSTOP_PIN_X = configParser.getint('axis', 'endstop_pin_x') + +STEPPER_STEP_PIN_Y = configParser.getint('axis', 'stepper_step_pin_y') +STEPPER_DIR_PIN_Y = configParser.getint('axis', 'stepper_dir_pin_y') +ENDSTOP_PIN_Y = configParser.getint('axis', 'endstop_pin_y') + +STEPPER_STEP_PIN_Z = configParser.getint('axis', 'stepper_step_pin_z') +STEPPER_DIR_PIN_Z = configParser.getint('axis', 'stepper_dir_pin_z') +ENDSTOP_PIN_Z = configParser.getint('axis', 'endstop_pin_z') + +STEPPER_STEP_PIN_E = configParser.getint('axis', 'stepper_step_pin_e') +STEPPER_DIR_PIN_E = configParser.getint('axis', 'stepper_dir_pin_e') + +SPINDLE_PWM_PIN = configParser.getint('control', 'spindle_pwm_pin') +FAN_PIN = configParser.getint('control', 'fan_pin') +EXTRUDER_HEATER_PIN = configParser.getint('control', 'extruder_heater_pin') +BED_HEATER_PIN = configParser.getint('control', 'bed_heater_pin') + +EXTRUDER_TEMPERATURE_SENSOR_CHANNEL = configParser.getint('control', 'extruder_temperature_sensor_channel') +BED_TEMPERATURE_SENSOR_CHANNEL = configParser.getint('control', 'bed_temperature_sensor_channel') + # ----------------------------------------------------------------------------- # Behavior config @@ -82,13 +97,20 @@ # buffer will be prepared firstly and then command will run. # Before enabling this feature, please make sure that board performance is # enough for streaming pulses(faster then real time). -INSTANT_RUN = True +INSTANT_RUN = configParser.getboolean('control', 'instant_run') # If this parameter is False, error will be raised on command with velocity # more than maximum velocity specified here. If this parameter is True, # velocity would be decreased(proportional for all axises) to fit the maximum # velocity. -AUTO_VELOCITY_ADJUSTMENT = True +AUTO_VELOCITY_ADJUSTMENT = configParser.getboolean('control', 'auto_velocity_adjustment') # Automatically turn on fan when extruder is heating, boolean value. -AUTO_FAN_ON = True +AUTO_FAN_ON = configParser.getboolean('control', 'auto_fan_on') + +EXTRUDER_PID = {"P": 0.059161177519, + "I": 0.00206217171374, + "D": 0.206217171374} +BED_PID = {"P": 0.226740848076, + "I": 0.00323956215053, + "D": 0.323956215053} diff --git a/cnc/coordinates.py b/cnc/coordinates.py old mode 100644 new mode 100755 index 3cc18a3..f868c0e --- a/cnc/coordinates.py +++ b/cnc/coordinates.py @@ -24,6 +24,12 @@ def is_zero(self): return (self.x == 0.0 and self.y == 0.0 and self.z == 0.0 and self.e == 0.0) + def values(self): + """ return all values + :return: array. + """ + return [self.x , self.y , self.z , self.e] + def is_in_aabb(self, p1, p2): """ Check coordinates are in aabb(Axis-Aligned Bounding Box). aabb is specified with two points. E is ignored. diff --git a/cnc/enums.py b/cnc/enums.py old mode 100644 new mode 100755 diff --git a/cnc/gcode.py b/cnc/gcode.py old mode 100644 new mode 100755 diff --git a/cnc/gmachine.py b/cnc/gmachine.py old mode 100644 new mode 100755 index 776db32..ddd6094 --- a/cnc/gmachine.py +++ b/cnc/gmachine.py @@ -38,6 +38,16 @@ def __init__(self): hal.init() self.watchdog = HardwareWatchdog() + def reloadconfig(self): + self.release() + self.config() + + def config(self): + self.__init__() + + def coordinates(self): + return self._position.values() + def release(self): """ Free all resources. """ @@ -98,7 +108,7 @@ def _heat(self, heater, temperature, wait): def __check_delta(self, delta): pos = self._position + delta - if not pos.is_in_aabb(Coordinates(0.0, 0.0, 0.0, 0.0), + if not pos.is_in_aabb(Coordinates(TABLE_SIZE_X_MIN_MM, TABLE_SIZE_Y_MIN_MM, TABLE_SIZE_Z_MIN_MM, TABLE_SIZE_E_MIN_MM), Coordinates(TABLE_SIZE_X_MM, TABLE_SIZE_Y_MM, TABLE_SIZE_Z_MM, 0)): raise GMachineException("out of effective area") diff --git a/cnc/hal.py b/cnc/hal.py old mode 100644 new mode 100755 diff --git a/cnc/hal_raspberry/hal.py b/cnc/hal_raspberry/hal.py old mode 100644 new mode 100755 diff --git a/cnc/hal_raspberry/rpgpio_private.py b/cnc/hal_raspberry/rpgpio_private.py old mode 100644 new mode 100755 diff --git a/cnc/hal_virtual.py b/cnc/hal_virtual.py old mode 100644 new mode 100755 diff --git a/cnc/heater.py b/cnc/heater.py old mode 100644 new mode 100755 diff --git a/cnc/logging_config.py b/cnc/logging_config.py old mode 100644 new mode 100755 diff --git a/cnc/pid.py b/cnc/pid.py old mode 100644 new mode 100755 diff --git a/cnc/pulses.py b/cnc/pulses.py old mode 100644 new mode 100755 diff --git a/cnc/sensors/__init__.py b/cnc/sensors/__init__.py old mode 100644 new mode 100755 diff --git a/cnc/sensors/ads111x.py b/cnc/sensors/ads111x.py old mode 100644 new mode 100755 diff --git a/cnc/sensors/thermistor.py b/cnc/sensors/thermistor.py old mode 100644 new mode 100755 diff --git a/cnc/watchdog.py b/cnc/watchdog.py old mode 100644 new mode 100755 diff --git a/extra/pycnc.conf b/extra/pycnc.conf new file mode 100644 index 0000000..2e68624 --- /dev/null +++ b/extra/pycnc.conf @@ -0,0 +1,107 @@ +#/etc/pycnc.conf + +[control] +spindle_pwm_pin = 4 +fan_pin = 27 +extruder_heater_pin = 18 +bed_heater_pin = 22 +extruder_temperature_sensor_channel = 2 +bed_temperature_sensor_channel = 1 +steppers_enable_pin = 26 +led=17 + + +# if this parameter is false, error will be raised on command with velocity +# more than maximum velocity specified here. if this parameter is true, +# velocity would be decreased(proportional for all axises) to fit the maximum +# velocity. +auto_velocity_adjustment = true + +# automatically turn on fan when extruder is heating, boolean value. +auto_fan_on = true + +# run command immediately after receiving and stream new pulses, otherwise +# buffer will be prepared firstly and then command will run. +# before enabling this feature, please make sure that board performance is +# enough for streaming pulses(faster then real time). +instant_run = true + + +# mixed settings. +#2 >55us +stepper_pulse_length_us = 55 +#3000 # for all axis, mm per sec^2 +stepper_max_acceleration_mm_per_s2 = 2000 +spindle_max_rpm = 10000 + + +[axis] +# average velocity for endstop calibration procedure +calibration_velocity_mm_per_min = 300 + +stepper_step_pin_x = 21 +stepper_dir_pin_x = 20 + +stepper_step_pin_y = 16 +stepper_dir_pin_y = 19 + +stepper_step_pin_z = 13 +stepper_dir_pin_z = 12 + +stepper_step_pin_e = 6 +stepper_dir_pin_e = 5 + +endstop_pin_x = 24 +endstop_pin_y = 9 +endstop_pin_z = 11 + +# invert zero end stops switches. by default(false) low level on input pin +# means that axis in zero position. for inverted(true) end stops, high level +# means zero position. +endstop_inverted_x = false +endstop_inverted_y = false +# auto leveler +endstop_inverted_z = true + +# maximum velocity for each axis in millimeter per minute. +#funcionou com 1600 na diagonal y50z50 +max_velocity_mm_per_min_x = 1500 +max_velocity_mm_per_min_y = 1500 +max_velocity_mm_per_min_z = 1500 +max_velocity_mm_per_min_e = 1500 +min_velocity_mm_per_min = 1 + + +# invert axises direction, by default(false) high level means increase of +# position. for inverted(true) axis, high level means decrease of position. +stepper_inverted_x = false +stepper_inverted_y = false +stepper_inverted_z = true +stepper_inverted_e = true + +# stepper motors steps per millimeter for each axis. +#6400 #int(3200/5)*10 -> mm +#int(3200/5) +stepper_pulses_per_mm_x = 640 +stepper_pulses_per_mm_y = 640 +stepper_pulses_per_mm_z = 640 +stepper_pulses_per_mm_e = 640 + + +[workplace] +# workplace physical size. +table_size_x_mm = 200 +table_size_y_mm = 300 +table_size_z_mm = 200 +table_size_e_mm = 200 + +# workplace physical size. +table_size_x_min_mm = 0 +table_size_y_min_mm = 0 +table_size_z_min_mm = 0 +table_size_e_min_mm = 0 + +[temperature] +extruder_max_temperature = 250 +bed_max_temperature = 100 +min_temperature = 40 diff --git a/setup.py b/setup.py index 47d1bab..6410b29 100755 --- a/setup.py +++ b/setup.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +import os.path + try: import pypandoc long_description = pypandoc.convert('README.md', 'rst') @@ -12,6 +14,16 @@ version="1.1.0", packages=find_packages(), scripts=['pycnc'], + include_package_data=True, + + package_data = { + # If any package contains *.txt or *.rst files, include them: + '': ['.conf'], + }, + + data_files=[ + ('/cnc/etc/', [os.path.join('extra', 'pycnc.conf')]) + ], # metadata for upload to PyPI author="Nikolay Khabarov", diff --git a/tests/__init__.py b/tests/__init__.py old mode 100644 new mode 100755 diff --git a/tests/circles.gcode b/tests/circles.gcode old mode 100644 new mode 100755 diff --git a/tests/rects.gcode b/tests/rects.gcode old mode 100644 new mode 100755 diff --git a/tests/test_coordinates.py b/tests/test_coordinates.py old mode 100644 new mode 100755 diff --git a/tests/test_gcode.py b/tests/test_gcode.py old mode 100644 new mode 100755 diff --git a/tests/test_gmachine.py b/tests/test_gmachine.py old mode 100644 new mode 100755 diff --git a/tests/test_heater.py b/tests/test_heater.py old mode 100644 new mode 100755 diff --git a/tests/test_parser.gcode b/tests/test_parser.gcode old mode 100644 new mode 100755 diff --git a/tests/test_pid.py b/tests/test_pid.py old mode 100644 new mode 100755 diff --git a/tests/test_pulses.py b/tests/test_pulses.py old mode 100644 new mode 100755