├── son └── beep.wav ├── i18n ├── cn5X.en.qm ├── cn5X.fr.qm ├── flags │ └── flag_fr.svg ├── Makefile ├── cn5X_locales.xsd ├── cn5X_locales.xml └── cn5X.pro ├── images ├── XYZAB-32.ico ├── XYZAB-48.ico ├── screenshots │ ├── cn5X_screenShot_00.png │ ├── cn5X_screenShot_01.png │ ├── cn5X_screenShot_02.png │ ├── cn5X_screenShot_03.png │ ├── cn5X_screenShot_04.png │ ├── cn5X_screenShot_05.png │ ├── cn5X_screenShot_06.png │ └── cn5X_screenShot_07.png ├── Vide-60x60.svg ├── Fleche00.svg ├── btnJogNone.svg ├── btnClose.svg ├── btnJogPlusX.svg ├── btnJogPlusY.svg ├── btnJogMoinsY.svg ├── btnJogMoinsC.svg ├── btnJogMoinsX.svg ├── btnJogPlusC.svg ├── btnJogMoinsZ.svg ├── btnJogPlusZ.svg ├── btnJogMoinsA.svg ├── btnJogPlusA.svg ├── btnJogPlusB.svg ├── btnJogMoinsB.svg ├── btnResetSpeed.svg ├── btnProbeInX-.svg ├── btnProbeInX+.svg ├── btnProbeOutX-.svg ├── btnProbeInY-.svg ├── btnProbeInY+.svg ├── btnProbeOutX+.svg ├── btnProbeOutY-.svg ├── btnProbeOutY+.svg ├── chkBoxDisabledUnChecked.svg ├── chkBoxUnChecked.svg ├── btnProbeOutCercle.svg ├── btnProbeZ-.svg ├── btnJogX.svg ├── btnJogY.svg ├── btnKillAlarm.svg ├── btnJogZ.svg ├── btnProbeInCercle.svg ├── btnJogC.svg ├── chkBoxDisabledChecked.svg ├── btnRefresh.svg ├── btnJogB.svg ├── ledBleuEteinte.svg ├── btnJogA.svg ├── ledVerteEteinte.svg ├── chkBoxChecked.svg ├── ledBleuAlumee.svg ├── ledRougeEteinte.svg ├── ledVerteAlumee.svg └── btnG28.svg ├── fonts ├── DSEG14Classic.ttf ├── LEDCalculator.ttf ├── DSEG14ClassicMini.ttf └── fontsRessources.qrc ├── .github └── FUNDING.yml ├── .gitignore ├── Makefile ├── gcodeQLineEdit.py ├── cn5X_beep.py ├── cnQLabel.py ├── setup.py ├── compilOptions.py ├── README.md ├── grblComStack.py ├── speedOverrides.py ├── cn5X_apropos.py ├── grblJog.py ├── qwHorloge.ui └── cnled.py /son/beep.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/son/beep.wav -------------------------------------------------------------------------------- /i18n/cn5X.en.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/i18n/cn5X.en.qm -------------------------------------------------------------------------------- /i18n/cn5X.fr.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/i18n/cn5X.fr.qm -------------------------------------------------------------------------------- /images/XYZAB-32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/images/XYZAB-32.ico -------------------------------------------------------------------------------- /images/XYZAB-48.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/images/XYZAB-48.ico -------------------------------------------------------------------------------- /fonts/DSEG14Classic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/fonts/DSEG14Classic.ttf -------------------------------------------------------------------------------- /fonts/LEDCalculator.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/fonts/LEDCalculator.ttf -------------------------------------------------------------------------------- /fonts/DSEG14ClassicMini.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/fonts/DSEG14ClassicMini.ttf -------------------------------------------------------------------------------- /images/screenshots/cn5X_screenShot_00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/images/screenshots/cn5X_screenShot_00.png -------------------------------------------------------------------------------- /images/screenshots/cn5X_screenShot_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/images/screenshots/cn5X_screenShot_01.png -------------------------------------------------------------------------------- /images/screenshots/cn5X_screenShot_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/images/screenshots/cn5X_screenShot_02.png -------------------------------------------------------------------------------- /images/screenshots/cn5X_screenShot_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/images/screenshots/cn5X_screenShot_03.png -------------------------------------------------------------------------------- /images/screenshots/cn5X_screenShot_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/images/screenshots/cn5X_screenShot_04.png -------------------------------------------------------------------------------- /images/screenshots/cn5X_screenShot_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/images/screenshots/cn5X_screenShot_05.png -------------------------------------------------------------------------------- /images/screenshots/cn5X_screenShot_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/images/screenshots/cn5X_screenShot_06.png -------------------------------------------------------------------------------- /images/screenshots/cn5X_screenShot_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fra589/cn5X/HEAD/images/screenshots/cn5X_screenShot_07.png -------------------------------------------------------------------------------- /fonts/fontsRessources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | LEDCalculator.ttf 4 | DSEG14Classic.ttf 5 | DSEG14ClassicMini.ttf 6 | 7 | 8 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: Gauthier 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | build*/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.cover 48 | .hypothesis/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | 58 | # Flask stuff: 59 | instance/ 60 | .webassets-cache 61 | 62 | # Scrapy stuff: 63 | .scrapy 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | 71 | # Jupyter Notebook 72 | .ipynb_checkpoints 73 | 74 | # pyenv 75 | .python-version 76 | 77 | # celery beat schedule file 78 | celerybeat-schedule 79 | 80 | # SageMath parsed files 81 | *.sage.py 82 | 83 | # dotenv 84 | .env 85 | 86 | # virtualenv 87 | .venv 88 | venv/ 89 | ENV/ 90 | 91 | # Spyder project settings 92 | .spyderproject 93 | .spyproject 94 | 95 | # Rope project settings 96 | .ropeproject 97 | 98 | # mkdocs documentation 99 | /site 100 | 101 | # mypy 102 | .mypy_cache/ 103 | 104 | # Geany project file 105 | cn5X.geany 106 | 107 | # old files 108 | *.old 109 | 110 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for cn5X++ 2 | 3 | #'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | # ' 5 | # Copyright 2018 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | # ' 7 | # This file is part of cn5X++ ' 8 | # ' 9 | # cn5X++ is free software: you can redistribute it and/or modify it ' 10 | # under the terms of the GNU General Public License as published by ' 11 | # the Free Software Foundation, either version 3 of the License, or ' 12 | # (at your option) any later version. ' 13 | # ' 14 | # cn5X++ is distributed in the hope that it will be useful, but ' 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | # GNU General Public License for more details. ' 18 | # ' 19 | # You should have received a copy of the GNU General Public License ' 20 | # along with this program. If not, see . ' 21 | # ' 22 | #'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | #----------------------------------------------------------------------- 25 | # Compile les fichiers de langue 26 | #----------------------------------------------------------------------- 27 | 28 | LANG_DIR=i18n 29 | 30 | all: lang 31 | 32 | lang: $(LANG_DIR)/*.qm $(LANG_DIR)/cn5X_locales.xml 33 | @(cd $(LANG_DIR) && $(MAKE)) 34 | 35 | %.qm: %.ts cn5X.pro 36 | -------------------------------------------------------------------------------- /images/Vide-60x60.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | 62 | -------------------------------------------------------------------------------- /i18n/flags/flag_fr.svg: -------------------------------------------------------------------------------- 1 | 2 | 16 | 18 | 19 | 21 | image/svg+xml 22 | 24 | 25 | 26 | 27 | 29 | 46 | 53 | 60 | 66 | 67 | -------------------------------------------------------------------------------- /i18n/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for cn5X++ 2 | 3 | #'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | # ' 5 | # Copyright 2018 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | # ' 7 | # This file is part of cn5X++ ' 8 | # ' 9 | # cn5X++ is free software: you can redistribute it and/or modify it ' 10 | # under the terms of the GNU General Public License as published by ' 11 | # the Free Software Foundation, either version 3 of the License, or ' 12 | # (at your option) any later version. ' 13 | # ' 14 | # cn5X++ is distributed in the hope that it will be useful, but ' 15 | # WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | # GNU General Public License for more details. ' 18 | # ' 19 | # You should have received a copy of the GNU General Public License ' 20 | # along with this program. If not, see . ' 21 | # ' 22 | #'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | #----------------------------------------------------------------------- 25 | # Compile les fichiers .ui de QT Designer vers scripts Python 26 | # Compile les fichiers de ressources vers scripts Python 27 | #----------------------------------------------------------------------- 28 | 29 | SRC=$(wildcard *.ts) 30 | QMFILES=$(SRC:.ts=.qm) 31 | 32 | all: $(QMFILES) 33 | 34 | %.qm: %.ts 35 | lrelease cn5X.pro 36 | 37 | %.ts: ../*.py cn5X.pro 38 | lupdate cn5X.pro 39 | 40 | -------------------------------------------------------------------------------- /gcodeQLineEdit.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | ' ' 5 | ' Copyright 2018-2024 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | ' ' 7 | ' This file is part of cn5X++ ' 8 | ' ' 9 | ' cn5X++ is free software: you can redistribute it and/or modify it ' 10 | ' under the terms of the GNU General Public License as published by ' 11 | ' the Free Software Foundation, either version 3 of the License, or ' 12 | ' (at your option) any later version. ' 13 | ' ' 14 | ' cn5X++ is distributed in the hope that it will be useful, but ' 15 | ' WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | ' GNU General Public License for more details. ' 18 | ' ' 19 | ' You should have received a copy of the GNU General Public License ' 20 | ' along with this program. If not, see . ' 21 | ' ' 22 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | from PyQt6 import QtCore, QtGui, QtWidgets 25 | from PyQt6.QtCore import pyqtSignal 26 | 27 | 28 | class gcodeQLineEdit(QtWidgets.QLineEdit): 29 | ''' QlineEdit avec ajout de l'envoi d'evennement KeyPressed 30 | ''' 31 | keyPressed = pyqtSignal(QtGui.QKeyEvent) 32 | 33 | 34 | def __init__(self, parent=None): 35 | super().__init__(parent) 36 | 37 | 38 | def keyPressEvent(self, event): 39 | self.keyPressed.emit(event) 40 | return super().keyPressEvent(event) 41 | 42 | -------------------------------------------------------------------------------- /cn5X_beep.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | ' ' 5 | ' Copyright 2018-2024 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | ' ' 7 | ' This file: cn5X_beep.py, is part of cn5X++ ' 8 | ' ' 9 | ' cn5X++ is free software: you can redistribute it and/or modify it ' 10 | ' under the terms of the GNU General Public License as published by ' 11 | ' the Free Software Foundation, either version 3 of the License, or ' 12 | ' (at your option) any later version. ' 13 | ' ' 14 | ' cn5X++ is distributed in the hope that it will be useful, but ' 15 | ' WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | ' GNU General Public License for more details. ' 18 | ' ' 19 | ' You should have received a copy of the GNU General Public License ' 20 | ' along with this program. If not, see . ' 21 | ' ' 22 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | import os 25 | from platform import system 26 | from playsound import playsound 27 | 28 | class cn5XBeeper(): 29 | ''' 30 | Emissions de bip sonores 31 | ''' 32 | def __init__(self): 33 | super().__init__() 34 | 35 | self.__beepFile = os.path.join(os.path.dirname(__file__), "son/beep.wav") 36 | 37 | 38 | def beep(self, volume: float): 39 | ''' 40 | Emission d'un beep sonore depuis le fichier beep.wav 41 | ''' 42 | if system() == 'Windows': 43 | playsound(self.__beepFile, True) 44 | else: 45 | playsound(self.__beepFile, False) 46 | 47 | -------------------------------------------------------------------------------- /i18n/cn5X_locales.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /images/Fleche00.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /cnQLabel.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | ' ' 5 | ' Copyright 2018-2024 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | ' ' 7 | ' This file is part of cn5X++ ' 8 | ' ' 9 | ' cn5X++ is free software: you can redistribute it and/or modify it ' 10 | ' under the terms of the GNU General Public License as published by ' 11 | ' the Free Software Foundation, either version 3 of the License, or ' 12 | ' (at your option) any later version. ' 13 | ' ' 14 | ' cn5X++ is distributed in the hope that it will be useful, but ' 15 | ' WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | ' GNU General Public License for more details. ' 18 | ' ' 19 | ' You should have received a copy of the GNU General Public License ' 20 | ' along with this program. If not, see . ' 21 | ' ' 22 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | import sys, os 25 | from PyQt6 import QtCore, QtGui, QtWidgets 26 | from PyQt6.QtCore import pyqtSignal 27 | 28 | 29 | class cnQLabel(QtWidgets.QLabel): 30 | ''' 31 | QLabel avec gestion de click 32 | ''' 33 | 34 | clicked = pyqtSignal(str, QtGui.QMouseEvent) 35 | doubleClick = pyqtSignal(str, QtGui.QMouseEvent) 36 | 37 | def __init__(self, parent=None): 38 | super(cnQLabel, self).__init__(parent=parent) 39 | 40 | def mouseReleaseEvent(self, e): 41 | super(cnQLabel, self).mouseReleaseEvent(e) 42 | self.clicked.emit(self.text(), e) 43 | 44 | def mouseDoubleClickEvent(self, e): 45 | super(cnQLabel, self).mouseDoubleClickEvent(e) 46 | self.doubleClick.emit(self.text(), e) 47 | -------------------------------------------------------------------------------- /images/btnJogNone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 5 | ' ' 6 | ' Copyright 2018-2024 Gauthier Brière (gauthier.briere "at" gmail.com) ' 7 | ' ' 8 | ' This file is part of cn5X++ ' 9 | ' ' 10 | ' cn5X++ is free software: you can redistribute it and/or modify it ' 11 | ' under the terms of the GNU General Public License as published by ' 12 | ' the Free Software Foundation, either version 3 of the License, or ' 13 | ' (at your option) any later version. ' 14 | ' ' 15 | ' cn5X++ is distributed in the hope that it will be useful, but ' 16 | ' WITHOUT ANY WARRANTY; without even the implied warranty of ' 17 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 18 | ' GNU General Public License for more details. ' 19 | ' ' 20 | ' You should have received a copy of the GNU General Public License ' 21 | ' along with this program. If not, see . ' 22 | ' ' 23 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 24 | 25 | from cn5X_config import * 26 | from cx_Freeze import setup, Executable 27 | 28 | # Dependencies are automatically detected, but it might need 29 | # fine tuning. 30 | buildOptions = dict(packages = [], excludes = [], 31 | include_files = ['COPYING'] 32 | ) 33 | 34 | import sys 35 | base = 'Win32GUI' if sys.platform=='win32' else None 36 | 37 | 38 | 39 | executables = [ 40 | Executable('cn5X.py', base=base) 41 | ] 42 | 43 | setup(name='cn5X++', 44 | version = APP_VERSION_STRING, 45 | description = '5/6 axis Grbl control panel for grbl-Mega-5X', 46 | author = 'Gauthier Brière', 47 | install_requires = [ 48 | 'pyqt6', 49 | 'pyserial', 50 | ], 51 | options = dict(build_exe = buildOptions), 52 | executables = executables 53 | ) 54 | -------------------------------------------------------------------------------- /compilOptions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | ' ' 5 | ' Copyright 2018-2024 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | ' ' 7 | ' This file is part of cn5X++ ' 8 | ' ' 9 | ' cn5X++ is free software: you can redistribute it and/or modify it ' 10 | ' under the terms of the GNU General Public License as published by ' 11 | ' the Free Software Foundation, either version 3 of the License, or ' 12 | ' (at your option) any later version. ' 13 | ' ' 14 | ' cn5X++ is distributed in the hope that it will be useful, but ' 15 | ' WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | ' GNU General Public License for more details. ' 18 | ' ' 19 | ' You should have received a copy of the GNU General Public License ' 20 | ' along with this program. If not, see . ' 21 | ' ' 22 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | grblCompilOptions = { 25 | 'V': ["Variable spindle enabled"], 26 | 'N': ["Line numbers enabled"], 27 | 'M': ["Mist coolant enabled"], 28 | 'G': ["Safety door support standard"], 29 | 'C': ["CoreXY enabled"], 30 | 'P': ["Parking motion enabled"], 31 | 'Z': ["Homing force origin enabled"], 32 | 'H': ["Homing single axis enabled"], 33 | 'T': ["Two limit switches on axis enabled"], 34 | 'A': ["Allow feed rate overrides in probe cycles"], 35 | '*': ["Restore all EEPROM disabled"], 36 | '$': ["Restore EEPROM $ settings disabled"], 37 | '#': ["Restore EEPROM parameter data disabled"], 38 | 'I': ["Build info write user string disabled"], 39 | 'E': ["Force sync upon EEPROM write disabled"], 40 | 'W': ["Force sync upon work coordinate offset change disabled"], 41 | 'L': ["Homing init lock sets Grbl into an alarm state upon power up"], 42 | 'D': ["Use digital input pins"] 43 | } 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cn5X++ 5X++ Logo 2 | 3 |

4 | 5 | 5X++ Screenshot 6 | 7 |

8 | 9 | Panneau de contrôle Grbl 5/6 axes avec pour but d'implémenter toutes les fonctionalités de grbl-Mega-5X... 10 | *5/6 axis Grbl control panel to implement all the grbl-Mega-5X capabilities...* 11 | 12 | | *cn5X++ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.* | 13 | | :--- | 14 | 15 | 16 | ## Prérequis : 17 | cn5X++ est basé sur Python3, python-serial, PyQt6 et Qt6-SVG. 18 | Pour installer les prérequis sur un système Linux type Debian : 19 | ``` 20 | sudo apt install python3-pyqt6 libqt6svg6 pyqt6-dev-tools 21 | ``` 22 | En utilisation sous Linux, l'utilisateur doit faire partie du groupe Unix dialout pour pouvoir utiliser les ports série : 23 | ``` 24 | sudo adduser dialout 25 | ``` 26 | 27 | Après avoir installé les prérequis, copiez l'ensemble du dépôt cn5X++ (avec tous ses sous-répertoires) sur votre ordinateur puis, "exécutez" le script principal "`cn5x.py`" 28 | 29 | ## *prerequisite :* 30 | *cn5X ++ is based on Python3, python-serial, PyQt6 and Qt6-SVG.* 31 | *To install the prerequisites on a Linux system such as Debian:* 32 | ``` 33 | sudo apt install python3-pyqt6 libqt6svg6 pyqt6-dev-tools 34 | ``` 35 | *When using under Linux, the user must be part of the Unix dialout group to be able to use the serial ports:* 36 | ``` 37 | sudo adduser dialout 38 | ``` 39 | 40 | After installing the prerequisites, copy the entire cn5X++ repository (with all its subdirectories) to your computer and then "run" the main script "`cn5x.py`" 41 | 42 | ------------- 43 | cn5X++ is an open-source project and fueled by the free-time of our intrepid administrators and altruistic users. If you'd like to donate, all proceeds will be used to help fund supporting hardware and testing equipment. Thank you! [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/donate/?business=CZZN52UPPVHCW&no_recurring=0&item_name=Grbl-Mega-5X+%26+cn5X%2B%2B+donations¤cy_code=EUR) 44 | -------------------------------------------------------------------------------- /i18n/cn5X_locales.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 25 | 26 | 27 | 28 | fr 29 | 30 | cn5X.fr.qm 31 | i18n/flags/flag_fr.svg 32 | 33 | 34 | en 35 | 36 | cn5X.en.qm 37 | i18n/flags/flag_en.svg 38 | 39 | 40 | es 41 | 42 | cn5X.es.qm 43 | i18n/flags/flag_es.svg 44 | 45 | 46 | pt 47 | 48 | cn5X.pt.qm 49 | i18n/flags/flag_pt.svg 50 | 51 | 52 | -------------------------------------------------------------------------------- /i18n/cn5X.pro: -------------------------------------------------------------------------------- 1 | # cn5X.pro 2 | # QT Linguist translation project 3 | #''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | #' ' 5 | #' Copyright 2018 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | #' ' 7 | #' This file is part of cn5X++ ' 8 | #' ' 9 | #' cn5X++ is free software: you can redistribute it and/or modify it ' 10 | #' under the terms of the GNU General Public License as published by ' 11 | #' the Free Software Foundation, either version 3 of the License, or ' 12 | #' (at your option) any later version. ' 13 | #' ' 14 | #' cn5X++ is distributed in the hope that it will be useful, but ' 15 | #' WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | #' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | #' GNU General Public License for more details. ' 18 | #' ' 19 | #' You should have received a copy of the GNU General Public License ' 20 | #' along with this program. If not, see . ' 21 | #' ' 22 | #''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | # Utiliser : 24 | ## cd $HOME/src/cn5X/i18n 25 | ## pylupdate5 cn5X.pro 26 | # Pour mettre à jour les sources de traduction. 27 | 28 | SOURCES = ../cn5X.py \ 29 | ../cn5X_apropos.py \ 30 | ../cn5X_config.py \ 31 | ../cn5X_gcodeFile.py \ 32 | ../cn5X_gcodeParser.py \ 33 | ../cn5X_helpProbe.py \ 34 | ../cn5X_jog.py \ 35 | ../cn5X_toolChange.py \ 36 | ../grblCom.py \ 37 | ../grblComSerial.py \ 38 | ../grblConfig.py \ 39 | ../grblDecode.py \ 40 | ../grblG28_30_1.py \ 41 | ../grblG92.py \ 42 | ../grblProbe.py \ 43 | ../msgbox.py \ 44 | ../qweditmask.py \ 45 | ../qwprogressbox.py \ 46 | ../speedOverrides.py 47 | 48 | FORMS = ../mainWindow.ui 49 | ../dlgAPropos.ui \ 50 | ../dlgConfig.ui \ 51 | ../dlgG28_30_1.ui \ 52 | ../dlgG92.ui \ 53 | ../dlgHelpProbe.ui \ 54 | ../dlgJog.ui \ 55 | ../dlgToolChange.ui \ 56 | ../qwHorloge.ui \ 57 | ../qwKeyboard_ui.ui \ 58 | ../qwKeyNum_ui.ui \ 59 | 60 | TRANSLATIONS = cn5X.fr.ts \ 61 | cn5X.en.ts 62 | 63 | 64 | -------------------------------------------------------------------------------- /images/btnClose.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 59 | 65 | 75 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /images/btnJogPlusX.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | +X 72 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /images/btnJogPlusY.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | +Y 72 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /images/btnJogMoinsY.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | -Y 72 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /images/btnJogMoinsC.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | -C 72 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /images/btnJogMoinsX.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | -X 72 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /images/btnJogPlusC.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | +C 72 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /grblComStack.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | ' ' 5 | ' Copyright 2018-2024 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | ' ' 7 | ' This file is part of cn5X++ ' 8 | ' ' 9 | ' cn5X++ is free software: you can redistribute it and/or modify it ' 10 | ' under the terms of the GNU General Public License as published by ' 11 | ' the Free Software Foundation, either version 3 of the License, or ' 12 | ' (at your option) any later version. ' 13 | ' ' 14 | ' cn5X++ is distributed in the hope that it will be useful, but ' 15 | ' WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | ' GNU General Public License for more details. ' 18 | ' ' 19 | ' You should have received a copy of the GNU General Public License ' 20 | ' along with this program. If not, see . ' 21 | ' ' 22 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | from PyQt6.QtCore import QObject, QThread, QEventLoop, pyqtSignal, pyqtSlot 25 | from cn5X_config import * 26 | 27 | class grblStack(): 28 | ''' 29 | Gestionnaire de file d'attente du port serie. 30 | Stocke des couples (CommandeGrbl, flag), soit en mode FiFo (addFiFo()), soit en mode LiFo (addLiFo()) 31 | et les renvoie dans l'ordre choisi avec la fonction pop(). 32 | ''' 33 | 34 | def __init__(self): 35 | self.__data = [] 36 | 37 | def isEmpty(self): 38 | return len(self.__data) == 0 39 | 40 | def count(self): 41 | return len(self.__data) 42 | 43 | def addFiFo(self, item, flag = COM_FLAG_NO_FLAG): 44 | ''' Ajoute un element en mode FiFO, l'element ajoute sera le dernier a sortir 45 | ''' 46 | self.__data.append((item, flag)) 47 | 48 | def addLiFo(self, item, flag = COM_FLAG_NO_FLAG): 49 | ''' Ajoute un element en mode LiFO, l'element ajoute sera le premier a sortir 50 | ''' 51 | self.__data.insert(0, (item, flag)) 52 | 53 | def next(self): 54 | ''' Renvoie le prochain element de la Queue sans depiler (le supprimer) ou None si la liste est vide. 55 | ''' 56 | if len(self.__data) > 0: 57 | return self.__data[0] 58 | else: 59 | return None 60 | 61 | def pop(self): 62 | ''' Depile et renvoie le premier element de la liste ou None si la liste est vide. 63 | ''' 64 | if len(self.__data) > 0: 65 | return self.__data.pop(0) 66 | else: 67 | return None 68 | 69 | def clear(self): 70 | ''' Vide toute la pile 71 | ''' 72 | self.__data.clear() 73 | -------------------------------------------------------------------------------- /images/btnJogMoinsZ.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 66 | -Z 78 | 79 | 80 | -------------------------------------------------------------------------------- /images/btnJogPlusZ.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 66 | +Z 78 | 79 | 80 | -------------------------------------------------------------------------------- /speedOverrides.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | ' ' 5 | ' Copyright 2018-2024 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | ' ' 7 | ' This file is part of cn5X++ ' 8 | ' ' 9 | ' cn5X++ is free software: you can redistribute it and/or modify it ' 10 | ' under the terms of the GNU General Public License as published by ' 11 | ' the Free Software Foundation, either version 3 of the License, or ' 12 | ' (at your option) any later version. ' 13 | ' ' 14 | ' cn5X++ is distributed in the hope that it will be useful, but ' 15 | ' WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | ' GNU General Public License for more details. ' 18 | ' ' 19 | ' You should have received a copy of the GNU General Public License ' 20 | ' along with this program. If not, see . ' 21 | ' ' 22 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | from cn5X_config import * 25 | from grblCom import grblCom 26 | 27 | def adjustFeedOverride(valeurDepart: int, valeurArrivee: int, grbl: grblCom): 28 | valeurCourante = valeurDepart 29 | while valeurCourante != valeurArrivee: 30 | if valeurCourante <= valeurArrivee - 10: 31 | grbl.realTimePush(REAL_TIME_FEED_PLUS_10, COM_FLAG_NO_OK) 32 | valeurCourante += 10 33 | elif valeurCourante < valeurArrivee: 34 | grbl.realTimePush(REAL_TIME_FEED_PLUS_1, COM_FLAG_NO_OK) 35 | valeurCourante += 1 36 | elif valeurCourante >= valeurArrivee + 10: 37 | grbl.realTimePush(REAL_TIME_FEED_MOINS_10, COM_FLAG_NO_OK) 38 | valeurCourante -= 10 39 | elif valeurCourante > valeurArrivee: 40 | grbl.realTimePush(REAL_TIME_FEED_MOINS_1, COM_FLAG_NO_OK) 41 | valeurCourante -= 1 42 | 43 | 44 | def adjustSpindleOverride(valeurDepart: int, valeurArrivee: int, grbl: grblCom): 45 | valeurCourante = valeurDepart 46 | while valeurCourante != valeurArrivee: 47 | if valeurCourante <= valeurArrivee - 10: 48 | grbl.realTimePush(REAL_TIME_SPINDLE_PLUS_10, COM_FLAG_NO_OK) 49 | valeurCourante += 10 50 | elif valeurCourante < valeurArrivee: 51 | grbl.realTimePush(REAL_TIME_SPINDLE_PLUS_1, COM_FLAG_NO_OK) 52 | valeurCourante += 1 53 | elif valeurCourante >= valeurArrivee + 10: 54 | grbl.realTimePush(REAL_TIME_SPINDLE_MOINS_10, COM_FLAG_NO_OK) 55 | valeurCourante -= 10 56 | elif valeurCourante > valeurArrivee: 57 | grbl.realTimePush(REAL_TIME_SPINDLE_MOINS_1, COM_FLAG_NO_OK) 58 | valeurCourante -= 1 59 | 60 | -------------------------------------------------------------------------------- /images/btnJogMoinsA.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 64 | -A 76 | 77 | 78 | -------------------------------------------------------------------------------- /images/btnJogPlusA.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 64 | +A 76 | 77 | 78 | -------------------------------------------------------------------------------- /images/btnJogPlusB.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 64 | +B 76 | 77 | 78 | -------------------------------------------------------------------------------- /images/btnJogMoinsB.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 64 | -B 76 | 77 | 78 | -------------------------------------------------------------------------------- /cn5X_apropos.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | ' ' 5 | ' Copyright 2018-2024 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | ' ' 7 | ' This file is part of cn5X++ ' 8 | ' ' 9 | ' cn5X++ is free software: you can redistribute it and/or modify it ' 10 | ' under the terms of the GNU General Public License as published by ' 11 | ' the Free Software Foundation, either version 3 of the License, or ' 12 | ' (at your option) any later version. ' 13 | ' ' 14 | ' cn5X++ is distributed in the hope that it will be useful, but ' 15 | ' WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | ' GNU General Public License for more details. ' 18 | ' ' 19 | ' You should have received a copy of the GNU General Public License ' 20 | ' along with this program. If not, see . ' 21 | ' ' 22 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | import os 25 | from PyQt6 import QtCore, QtGui, QtWidgets, uic 26 | from PyQt6.QtCore import Qt, QObject, pyqtSignal, pyqtSlot 27 | from PyQt6.QtWidgets import QDialog, QAbstractButton, QDialogButtonBox, QCheckBox, QSpinBox, QDoubleSpinBox, QLineEdit 28 | from PyQt6.QtGui import QStandardItemModel, QStandardItem, QValidator 29 | from cn5X_config import * 30 | from grblCom import grblCom 31 | from msgbox import * 32 | 33 | 34 | class cn5XAPropos(QDialog): 35 | ''' Classe assurant la gestion de la boite de dialogue A Propos ''' 36 | 37 | def __init__(self, versionString: str, licenceFile: str): 38 | super().__init__() 39 | self.__di = uic.loadUi(os.path.join(os.path.dirname(__file__), "dlgAPropos.ui"), self) 40 | 41 | self.__di.lblVersion.setText(versionString + '\t' + "(Qt version " + QtCore.PYQT_VERSION_STR + ")") 42 | 43 | text=open(licenceFile).read() 44 | self.__di.qptLicence.setPlainText(text) 45 | 46 | def showDialog(self): 47 | # Centrage de la boite de dialogue sur la fenetre principale 48 | ParentX = self.parent().geometry().x() 49 | ParentY = self.parent().geometry().y() 50 | ParentWidth = self.parent().geometry().width() 51 | ParentHeight = self.parent().geometry().height() 52 | myWidth = self.geometry().width() 53 | myHeight = self.geometry().height() 54 | self.setFixedSize(self.geometry().width(),self.geometry().height()) 55 | self.move(ParentX + int((ParentWidth - myWidth) / 2),ParentY + int((ParentHeight - myHeight) / 2),) 56 | self.setWindowFlags(Qt.WindowType.Window | Qt.WindowType.Dialog) 57 | 58 | RC = self.exec() 59 | return RC 60 | 61 | -------------------------------------------------------------------------------- /images/btnResetSpeed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /images/btnProbeInX-.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | X- 73 | 76 | 82 | 89 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /images/btnProbeInX+.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | X+ 73 | 76 | 82 | 89 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /images/btnProbeOutX-.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | X- 73 | 76 | 82 | 89 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /images/btnProbeInY-.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | Y- 73 | 76 | 82 | 89 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /images/btnProbeInY+.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | Y+ 73 | 76 | 82 | 89 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /images/btnProbeOutX+.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | X+ 73 | 76 | 82 | 89 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /images/btnProbeOutY-.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | Y- 73 | 76 | 82 | 89 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /images/btnProbeOutY+.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | Y+ 73 | 76 | 82 | 89 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /images/chkBoxDisabledUnChecked.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 44 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 71 | 75 | 89 | 95 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /grblJog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | ' ' 5 | ' Copyright 2018-2024 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | ' ' 7 | ' This file is part of cn5X++ ' 8 | ' ' 9 | ' cn5X++ is free software: you can redistribute it and/or modify it ' 10 | ' under the terms of the GNU General Public License as published by ' 11 | ' the Free Software Foundation, either version 3 of the License, or ' 12 | ' (at your option) any later version. ' 13 | ' ' 14 | ' cn5X++ is distributed in the hope that it will be useful, but ' 15 | ' WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | ' GNU General Public License for more details. ' 18 | ' ' 19 | ' You should have received a copy of the GNU General Public License ' 20 | ' along with this program. If not, see . ' 21 | ' ' 22 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | import sys, os, time #, datetime 25 | from PyQt6 import QtGui # QtCore, , QtWidgets 26 | from PyQt6.QtCore import QCoreApplication, QObject, QThread, QTimer, QEventLoop, pyqtSignal, pyqtSlot, QIODevice 27 | from cn5X_config import * 28 | from cnQPushButton import cnQPushButton 29 | from grblCom import grblCom 30 | 31 | class grblJog(): 32 | ''' 33 | Envoie les ordres de mouvements de Jogging 34 | A jog command will only be accepted when Grbl is in either the 'Idle' or 'Jog' states. 35 | ''' 36 | def __init__(self, comm: grblCom): 37 | super().__init__() 38 | self.__grblCom = comm 39 | self.__jogSpeed = DEFAULT_JOG_SPEED 40 | 41 | 42 | @pyqtSlot(cnQPushButton, QtGui.QMouseEvent, float) 43 | @pyqtSlot(cnQPushButton, QtGui.QMouseEvent, float, float) 44 | def on_jog(self, cnButton, e, jogDistance, maxTravel=0): 45 | ''' 46 | Deplacement relatif (G91) de "jogDistance" mm (G21) sur axe defini par le nom du bouton 47 | si jogDistance != 0, si jogDistance = 0, déplacement en coordonnées machine jusqu'à 48 | la course maxi. 49 | ''' 50 | axis = cnButton.name()[-1] # L'axe est definit par le dernier caractere du nom du Bouton 51 | 52 | if jogDistance != 0: 53 | if cnButton.name()[-5:-1] == "Plus": 54 | value = jogDistance 55 | else: 56 | value = -jogDistance 57 | if self.__grblCom.grblStatus() in ['Idle', 'Jog']: 58 | cmdJog = CMD_GRBL_JOG + "G91G21F{}{}{}".format(self.__jogSpeed, axis, value) 59 | self.__grblCom.gcodePush(cmdJog, COM_FLAG_NO_OK) 60 | 61 | elif maxTravel != 0: # jogDistance == 0 & maxTravel !=0 62 | if cnButton.name()[-5:-1] == "Plus": 63 | value = 0 64 | else: 65 | value = -maxTravel 66 | if self.__grblCom.grblStatus() in ['Idle', 'Jog']: 67 | cmdJog = CMD_GRBL_JOG + "G53F{}{}{}".format(self.__jogSpeed, axis, value) 68 | self.__grblCom.gcodePush(cmdJog, COM_FLAG_NO_OK) 69 | 70 | 71 | def jogCancel(self): 72 | self.__grblCom.clearCom() 73 | self.__grblCom.realTimePush(REAL_TIME_JOG_CANCEL) # Commande realtime Jog Cancel 74 | 75 | 76 | def setJogSpeed(self, speed: float): 77 | if speed > 0: 78 | self.__jogSpeed = speed 79 | else: 80 | self.__jogSpeed = DEFAULT_JOG_SPEED 81 | 82 | -------------------------------------------------------------------------------- /images/chkBoxUnChecked.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 40 | 45 | 46 | 48 | 49 | 51 | image/svg+xml 52 | 54 | 55 | 56 | 57 | 58 | 63 | 72 | 76 | 90 | 96 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /qwHorloge.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | qwHorloge 4 | 5 | 6 | 7 | 0 8 | 0 9 | 411 10 | 101 11 | 12 | 13 | 14 | 15 | 16 | 0 17 | 0 18 | 331 19 | 101 20 | 21 | 22 | 23 | 24 | DSEG14 Classic 25 | 72 26 | true 27 | 28 | 29 | 30 | color: rgb(24, 40, 24); 31 | background-color: None; 32 | 33 | 34 | ~~:~~ 35 | 36 | 37 | Qt::PlainText 38 | 39 | 40 | Qt::AlignCenter 41 | 42 | 43 | 44 | 45 | 46 | 0 47 | 0 48 | 331 49 | 101 50 | 51 | 52 | 53 | 54 | DSEG14 Classic 55 | 72 56 | 50 57 | true 58 | false 59 | 60 | 61 | 62 | color: rgb(127, 255, 127); 63 | background-color: None; 64 | 65 | 66 | 23:59 67 | 68 | 69 | Qt::PlainText 70 | 71 | 72 | Qt::AlignCenter 73 | 74 | 75 | 76 | 77 | 78 | 330 79 | 47 80 | 81 81 | 55 82 | 83 | 84 | 85 | 86 | DSEG14 Classic 87 | 36 88 | true 89 | 90 | 91 | 92 | color: rgb(24, 40, 24); 93 | background-color: None; 94 | 95 | 96 | ~~ 97 | 98 | 99 | Qt::PlainText 100 | 101 | 102 | Qt::AlignCenter 103 | 104 | 105 | 106 | 107 | 108 | 330 109 | 47 110 | 81 111 | 55 112 | 113 | 114 | 115 | 116 | DSEG14 Classic Mini 117 | 36 118 | true 119 | 120 | 121 | 122 | color: rgb(127, 255, 127); 123 | background-color: None; 124 | 125 | 126 | 59 127 | 128 | 129 | Qt::PlainText 130 | 131 | 132 | Qt::AlignCenter 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /cnled.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 4 | ' ' 5 | ' Copyright 2018-2024 Gauthier Brière (gauthier.briere "at" gmail.com) ' 6 | ' ' 7 | ' This file is part of cn5X++ ' 8 | ' ' 9 | ' cn5X++ is free software: you can redistribute it and/or modify it ' 10 | ' under the terms of the GNU General Public License as published by ' 11 | ' the Free Software Foundation, either version 3 of the License, or ' 12 | ' (at your option) any later version. ' 13 | ' ' 14 | ' cn5X++ is distributed in the hope that it will be useful, but ' 15 | ' WITHOUT ANY WARRANTY; without even the implied warranty of ' 16 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ' 17 | ' GNU General Public License for more details. ' 18 | ' ' 19 | ' You should have received a copy of the GNU General Public License ' 20 | ' along with this program. If not, see . ' 21 | ' ' 22 | ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 23 | 24 | import sys, os 25 | from PyQt6 import QtCore, QtGui, QtWidgets 26 | from PyQt6.QtCore import pyqtSignal, pyqtSlot, QSize, pyqtProperty 27 | 28 | class cnLed(QtWidgets.QLabel): 29 | ''' QLabel affichant une image de Led eteinte ou allumee ''' 30 | 31 | statusChanged = pyqtSignal(bool) # signal emis a chaque changement de valeur 32 | 33 | def __init__(self, parent=None): 34 | super(cnLed, self).__init__(parent=parent) 35 | 36 | self.__couleur = "Rouge" # Rouge ou Verte 37 | 38 | # Chemin des images dans le fichier de resources 39 | self.__imagePath = os.path.join(os.path.dirname(__file__), "images/") 40 | self.iconOff = QtGui.QPixmap(self.__imagePath + "led" + self.__couleur + "Eteinte.svg") 41 | self.iconOn = QtGui.QPixmap(self.__imagePath + "led" + self.__couleur + "Alumee.svg") 42 | 43 | # Proprietes du label 44 | self.setMaximumSize(QSize(20, 20)) 45 | self.setText("") 46 | self.setPixmap(self.iconOff) 47 | self.setScaledContents(True) 48 | 49 | self.__ledStatus = False # led eteinte a l'initialisation 50 | 51 | 52 | @pyqtSlot() 53 | def Couleur(self): 54 | return self.__couleur 55 | 56 | 57 | @pyqtSlot() 58 | def setCouleur(self, couleur): 59 | if self.__couleur != couleur: 60 | self.__couleur = couleur 61 | self.iconOff = QtGui.QPixmap(self.__imagePath + "led" + self.__couleur + "Eteinte.svg") 62 | self.iconOn = QtGui.QPixmap(self.__imagePath + "led" + self.__couleur + "Alumee.svg") 63 | if self.__ledStatus: 64 | self.setPixmap(self.iconOn) 65 | else: 66 | self.setPixmap(self.iconOff) 67 | 68 | 69 | @pyqtSlot() 70 | def ledStatus(self): 71 | ''' Renvoie le status de la Led ''' 72 | return self.__ledStatus 73 | 74 | 75 | @pyqtSlot(bool) 76 | def setLedStatus(self, s: bool): 77 | ''' Allume (s=True) ou eteind (s=False) la Led ''' 78 | if self.__ledStatus != s: 79 | if s: 80 | self.setPixmap(self.iconOn) 81 | else: 82 | self.setPixmap(self.iconOff) 83 | self.__ledStatus = s 84 | self.statusChanged.emit(s) 85 | 86 | 87 | # Definie les propriétés pour permettre la configuration par Designer 88 | ledStatus = pyqtProperty("bool", fget=ledStatus, fset=setLedStatus) 89 | Couleur = pyqtProperty("QString", fget=Couleur, fset=setCouleur) 90 | -------------------------------------------------------------------------------- /images/btnProbeOutCercle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | 67 | 73 | 79 | 85 | 91 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /images/btnProbeZ-.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | Z- 73 | 76 | 79 | 85 | 92 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /images/btnJogX.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | +X 72 | 76 | -X 88 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /images/btnJogY.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | -Y 72 | 76 | +Y 88 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /images/btnKillAlarm.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | 78 | 80 | 85 | 91 | 92 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /images/btnJogZ.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 66 | -Z 78 | 84 | +Z 96 | 97 | 98 | -------------------------------------------------------------------------------- /images/btnProbeInCercle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 61 | 63 | 69 | 75 | 81 | 82 | 88 | 94 | 100 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /images/btnJogC.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | -C 72 | +C 84 | 88 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /images/chkBoxDisabledChecked.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 44 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 71 | 75 | 89 | 95 | 101 | 102 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /images/btnRefresh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 41 | 44 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 74 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /images/btnJogB.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 64 | -B 76 | 80 | +B 92 | 93 | 94 | -------------------------------------------------------------------------------- /images/ledBleuEteinte.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 23 | 27 | 31 | 32 | 35 | 39 | 43 | 44 | 53 | 63 | 64 | 84 | 87 | 88 | 90 | 91 | 93 | image/svg+xml 94 | 96 | 97 | 98 | 99 | 100 | 105 | 111 | 117 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /images/btnJogA.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 42 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 64 | -A 76 | 80 | +A 92 | 93 | 94 | -------------------------------------------------------------------------------- /images/ledVerteEteinte.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 23 | 27 | 31 | 32 | 35 | 39 | 43 | 44 | 53 | 63 | 64 | 84 | 87 | 88 | 90 | 91 | 93 | image/svg+xml 94 | 96 | 97 | 98 | 99 | 100 | 105 | 111 | 117 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /images/chkBoxChecked.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 40 | 45 | 46 | 48 | 49 | 51 | image/svg+xml 52 | 54 | 55 | 56 | 57 | 58 | 63 | 72 | 78 | 82 | 96 | 102 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /images/ledBleuAlumee.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 23 | 27 | 31 | 32 | 35 | 39 | 43 | 44 | 53 | 63 | 64 | 84 | 87 | 88 | 90 | 91 | 93 | image/svg+xml 94 | 96 | 97 | 98 | 99 | 100 | 105 | 111 | 117 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /images/ledRougeEteinte.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 25 | 29 | 33 | 34 | 37 | 41 | 45 | 46 | 55 | 65 | 66 | 85 | 88 | 89 | 91 | 92 | 94 | image/svg+xml 95 | 97 | 98 | 99 | 100 | 101 | 106 | 112 | 118 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /images/ledVerteAlumee.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 23 | 27 | 31 | 32 | 35 | 39 | 43 | 44 | 53 | 63 | 64 | 84 | 87 | 88 | 90 | 91 | 93 | image/svg+xml 94 | 96 | 97 | 98 | 99 | 100 | 105 | 111 | 117 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /images/btnG28.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | 60 | 68 | 76 | 80 | 84 | 92 | G28 103 | 104 | 105 | --------------------------------------------------------------------------------