├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── READMEru.md ├── TODO ├── inc └── TorchHeightControl.h ├── lib ├── ADC │ ├── ADC.cpp │ └── ADC.h ├── MotorControl │ ├── MotorControl.cpp │ └── MotorControl.h ├── MotorDriver │ ├── MotorDriver.cpp │ └── MotorDriver.h └── readme.txt ├── platformio.ini ├── src └── TorchHeightControl.cpp ├── torch-height-control-uml.html └── torch-height-control-uml.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .clang_complete 3 | .gcc-flags.json 4 | .piolibdeps 5 | .DS_Store 6 | .pioenvs 7 | .piolibdeps 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Continuous Integration (CI) is the practice, in software 2 | # engineering, of merging all developer working copies with a shared mainline 3 | # several times a day < http://docs.platformio.org/page/ci/index.html > 4 | # 5 | # Documentation: 6 | # 7 | # * Travis CI Embedded Builds with PlatformIO 8 | # < https://docs.travis-ci.com/user/integration/platformio/ > 9 | # 10 | # * PlatformIO integration with Travis CI 11 | # < http://docs.platformio.org/page/ci/travis.html > 12 | # 13 | # * User Guide for `platformio ci` command 14 | # < http://docs.platformio.org/page/userguide/cmd_ci.html > 15 | # 16 | # 17 | # Please choice one of the following templates (proposed below) and uncomment 18 | # it (remove "# " before each line) or use own configuration according to the 19 | # Travis CI documentation (see above). 20 | # 21 | 22 | 23 | # 24 | # Template #1: General project. Test it using existing `platformio.ini`. 25 | # 26 | 27 | # language: python 28 | # python: 29 | # - "2.7" 30 | # 31 | # sudo: false 32 | # cache: 33 | # directories: 34 | # - "~/.platformio" 35 | # 36 | # install: 37 | # - pip install -U platformio 38 | # - platformio update 39 | # 40 | # script: 41 | # - platformio run 42 | 43 | 44 | # 45 | # Template #2: The project is intended to by used as a library with examples 46 | # 47 | 48 | # language: python 49 | # python: 50 | # - "2.7" 51 | # 52 | # sudo: false 53 | # cache: 54 | # directories: 55 | # - "~/.platformio" 56 | # 57 | # env: 58 | # - PLATFORMIO_CI_SRC=path/to/test/file.c 59 | # - PLATFORMIO_CI_SRC=examples/file.ino 60 | # - PLATFORMIO_CI_SRC=path/to/test/directory 61 | # 62 | # install: 63 | # - pip install -U platformio 64 | # - platformio update 65 | # 66 | # script: 67 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # torch-height-control 2 | CNC plugin for the plasma torch height controlling on the base of Arduino (ATmega328P MCU). Can be used to improve cutting quality of bent and distorted metal plates. Regulator intercepts Z-axis (vertical) movement of a torch. Bypass mode is provided for cases when control is unneeded. Main idea is to determine the current height by measuring a voltage of the plasma arc: the higher the voltage, the greater the distance. 3 | 4 | 5 | ## Features 6 | - Receiving signals from CNC for initial and manual positioning; 7 | - API for easy interfacing with any Z-axis actuator (2 drivers for stepper motor are already available out-of-the-box: 4-wire bipolar and 2-wire "smart" driver (STEP+DIR)); 8 | - Auto defining of the height to keep (setpoint) using only initial presetted distance value. It allows to abstract from such parameters as metal type, its thickness etc.; 9 | - Adjustable insensitivity hysteresis of setpoint; 10 | - Software filtering of an arc voltage reduces noise and spikes (recommended for usage alongside with hardware filter); 11 | - Displaying of a current arc voltage and measured setpoint value allows to evaluate control quality (required LCD (sort of HD44780)); 12 | - Detecting a touch of torch and metal at startup (no need to manually set the initial height at every cut, should do it only once in the settings); 13 | - Bypass mode (system only responds to the Up/Down signals); 14 | - Settings menu for all necessary parameters; 15 | - Preserving parameters after power off. 16 | 17 | 18 | ## Logic description 19 | 1. CNC or user performs initial positioning (e.g. motion to the entry point); 20 | 2. After Plasm signal presence torch going down until the Touch signal is appeared; 21 | 3. Torch immediately lifting to the pierce height (specified parameter); 22 | 4. Torch is holding on at this position for the entire pierce time (specified parameter); 23 | 5. After setpoint calculation, then main control algorithm starts; 24 | 6. System goes back to the Idle mode when the cutting is complete (Plasm signal is turning off). 25 | 26 | 27 | ## Connection 28 | To minimize effect of cross-talks and spikes there should be solid assembly and the plugin must not be located near any high-voltage or power circuits. Some installed shield (full case or just to wires) is also desirable. It's advised to galvanic isolate device as possible to protect low-current and logic circuits. 29 | 30 | ### Digital inputs 31 | All digital inputs are pulled-up to the high-level voltage by default (so they are triggered by 0). ATmega328P and Arduino pins notations are specified in the brackets. 32 | - **UP** (PB2, 10) and **DOWN** (PB3, 11) - Up and Down signals for Z-axis. Movement is performing for all time the signal is applying. These signals are ignored in the Working mode; 33 | - **PLASM** (PB4, 12) - signal of the plasma ignition. It must be directed both to the regulator and the torch (e.g. DPST relay); 34 | - **TOUCH** (PB1, 9) - signal propagating when a metal plate and a torch touch each other. There are variety of available implementations depends on the specific construction of Z-axis. There can be, for example, a capacitive sensor or some sort of connection directly to the torch nozzle (so when the torch touches the metal they both should have got the same electrical potential). 35 | - **SETTINGS BUTTON** (PB0, 8) - just button for the cyclic navigation through the menu. 36 | 37 | ### Analog inputs 38 | - **FEEDBACK** (PC1, A1) - arc voltage value that limited to the diapason of ADC input voltages (0-5 V, desirable with some gap). It can be done, in the simplest case, via basic voltage divisor. Additionally recommended to install any low-pass filter to reduce noise and spikes; 39 | - **SETTINGS ADC** (PC0, A0) - used to set parameters. Usually represented by a potentiometer (3-100K) connected between GND and 5V. 40 | 41 | ### Motor 42 | To actuating of Z-axis your driver should provide 5 functions: 43 | - `motor_init()`; 44 | - `motor_up()`; 45 | - `motor_down()`; 46 | - `motor_stop()`; 47 | - `motor_move(int16_t steps)` where the sign of `steps` indicates a direction of movement. 48 | 49 | Also, note that your custom pinout should not conflict with other signals. It's recommended to use PC2-5 (Arduino's A2-5) pins. 50 | 51 | There already 2 libraries in the `/lib` folder representing 2 different drivers for stepper motors' driven Z-axis. 52 | 53 | #### MotorControl 54 | Straightforward driver that uses Timer2 to manually switches corresponding phases of 4-wire bipolar stepper motors (wave (one-phase-on) mode). Plug in your motor to any switches (relays, discrete transistors, array of transistors, driver IC and so on). Correct order of phases' connection depends on your motor but generally is A-C-B-D, considering AB and CD as 2 coils. Other parameters that you should adjust are period and pulsewidth (we consider them as equal). 55 | 56 | #### MotorDriver 57 | Library for usage with "smart" drivers that controlled by 2 signals: STEP and DIRECTION. It also uses Timer2 to form STEP pulses sequence. Other parameters that you should adjust to match your driver are period and pulsewidth. 58 | 59 | ### Display 60 | THC uses Arduino's LiquidCrystal library to manage LCD (HD44780, its derivatives and other compatible ones). Timer1 is used for refreshing information on the screen when it's needed (e.g. in Working mode or in the settings menu). By default LCD is connected to PD1-7 pins with following pinout (Arduino notation in the brackets): 61 | - PD4 (4) - DB4; 62 | - PD5 (5) - DB5; 63 | - PD6 (6) - DB6; 64 | - PD7 (7) - PD7; 65 | - PD1 (1) - RS; 66 | - PD2 (2) - RW 67 | - PD3 (3) - E. 68 | 69 | 70 | ## User parameters 71 | Before flashing the firmware you can check and set some related parameters. Most of them are located in `TorchHeightControl.cpp/h` files: 72 | - I/Os and default signals' port state (in case of reassigning); 73 | - Cutting height is measured in steps of stepper motor (0-1023). EEMEM is the default value at the flash time. Actually, not so important because we can always change it at runtime; 74 | - Pierce time default EEMEM; 75 | - Bypass mode flag; 76 | - Number of values for setpoint definition; 77 | - Setpoint hysteresis offset EEMEM default value (setpoint ± setpoint_offset); 78 | - Interval of voltages for specifing setpoint offset in settings menus; 79 | - Prescaler for dividing frequency of algorithm' timer in its ISR; 80 | - Hysteresis for averaging only close results of ADC measurements; 81 | 82 | 83 | ## Build and flash 84 | It's recommended to use [PlatformIO](https://platformio.org) for building and flashing as all-in-one solution. 85 | 86 | ### CLI 87 | Change settings in `platformio.ini` file if needed (for example, specify whether use programming unit or not). Then in the same directory run: 88 | ```bash 89 | $ pio run # build 90 | 91 | $ pio run -t program # flash using usbasp 92 | or 93 | $ pio run -t upload # flash using on-board programmer 94 | 95 | $ pio run -t uploadeep # write EEPROM 96 | ``` 97 | 98 | 99 | ### IDE (Atom or VSCode) 100 | 1. Import project: `File` -> `Add Project Folder`; 101 | 2. Change settings in `platformio.ini` file if needed (for example, specify whether use programming unit or not); 102 | 3. Build: `PlatformIO` -> `Build`; 103 | 4. Open built-in terminal and run: 104 | ```bash 105 | $ pio run -t program; pio run -t uploadeep 106 | ``` 107 | or for Arduino board: 108 | ```sh 109 | $ pio run -t upload; pio run -t uploadeep 110 | ``` 111 | 112 | 113 | ## Usage 114 | After reset, LCD displays Idle mode. It contains current settings of setpoint hysteresis, the cutting height `lft` (in steps) and the pierce time `dlay`. Cycle through the settings menu by pressing settings button till you get back to the Idle mode. Current value of each parameter is indicated in the brackets. Use your potentiometer to adjust values. 115 | 116 | After Plasm ON signal, `start...` string is appears. After touching the metal, `pierce...` lasts entire pierce time. Then `define sp...` is appeared on short time during which setpoint is defining. Finally, working mode follows and the first LCD line displays measured setpoint and the second displays current averaged arc voltage. If the `define sp...` string lasts too long it means that whether the number of values for setpoint definition is too high or the offset for averaging is too small or an arc signal is just too noisy. 117 | 118 | After cutting completes, Idle mode will also display last measured setpoint. 119 | 120 | To enter (and to exit) Bypass mode press and hold Settings button for 8 seconds. LCD will display `regulation off` string. THC then will respond only to Up/Down signals. Bypass mode state is saved after resets and power offs. 121 | 122 | 123 | ## Notes 124 | See states diagram (UML) in `torch-height-control-uml.*` files (created with [draw.io](https://draw.io)). 125 | 126 | Behavior of THC when multiple signals are applied is undefined in general and depends on the order of corresponding handlers in the `PCINT0_vect` ISR. Because of the `if - else if` construction execution of multiple code blocks is impossible but such conditions are still not recommended. However, at normal operating, those cases are not met. 127 | -------------------------------------------------------------------------------- /READMEru.md: -------------------------------------------------------------------------------- 1 | # Регулятор высоты плазменной горелки 2 | Регулятор высоты плазменной горелки на базе Arduino (МК ATmega328P). Применим для улучшения качества реза неровных листов и заготовок металла методом плазменной резки. Регулятор полностью перехватывает на себя управление вертикальной осью от станка ЧПУ (т.е. включается "в разрыв"). На случай необходимости предусмотрен режим работы "в обход", при котором контроль высоты не активен. Текущая высоты горелки во время реза определяется из напряжении плазменной дуги: чем выше напряжение, тем больше высота, и наоборот. 3 | 4 | 5 | ## Функциональность 6 | - Прием сигналов от ЧПУ для начального позиционирования горелки по высоте, а также для ручного подъема/опускания; 7 | - API для подключения любого привода оси Z (уже реализованы 2 типа драйверов для шагового двигателя: биполярное 4-проводное включение и 2-проводный "умный" драйвер (STEP + DIRECTION)); 8 | - Автоматическое определение напряжения (высоты) удержания при заданной высоте прокола (позволяет абстрагироваться от толщины, материала металла и других параметров); 9 | - Регулируемый по ширине интервал нечувствительности регулятора (гистерезис); 10 | - Программная фильтрация шумов и скачков напряжения (рекомендуется к применению наряду с аппаратным фильтром); 11 | - Отображение текущего напряжения дуги, измеренного напряжения удержания (позволяет оценить процесс регулировки); 12 | - Детектирование касания металла при включении (не требуется предварительно выставлять начальную высоту, достаточно просто указать ее в настройках); 13 | - Режим работы "в обход", при котором система воспринимает только сигналы движения вверх/вниз; 14 | - Подробное меню для настройки необходимых параметров (стандартный двухстрочный ЖК дисплей типа HD44780); 15 | - Параметры сохраняются после выключения устройства. 16 | 17 | 18 | ## Алгоритм работы 19 | - ЧПУ либо пользователь совершают начальное позиционирование (например, переезд до точки начала реза); 20 | - После отправки станком ЧПУ сигнала на включение плазмы горелка опускается до касания с листом металла; 21 | - После касания горелка приподнимается на высоту прокола (параметр задается); 22 | - Горелка удерживается в данной позиции на время прокола (параметр задается); 23 | - Запускается регулировка по уровню напряжения. Начинается процесс непосредственного вырезания детали; 24 | - После подачи станком ЧПУ сигнала на отключение плазмы регулятор переходит в изначальное состояние (ждущий режим). 25 | 26 | 27 | ## Подключение 28 | Регулятор включается в разрыв текущей цепи управления и перехватывает на себя соответствующие сигналы. 29 | 30 | 31 | ### Входы 32 | В скобках указаны выводы ATmega328P и Arduino. 33 | - **UP** (PB2, 10) - сигнал подъема горелки. Подъем осуществляется все время, пока подается данный сигнал; 34 | - **DOWN** (PB3, 11) - сигнал опускания горелки. Опускание осуществляется все время, пока подается данный сигнал. Данные сигналы "Вверх" и "Вниз" игнорируются во время реза; 35 | - **PLASM** (PB4, 12) - сигнал включения плазмы. Сигнал должен поступать как в регулятор, так и непосредственно запускать плазму в горелке (можно использовать, например, реле с двумя группами контактов); 36 | - **TOUCH** (PB1, 9) - сигнал касания горелкой листа металла. Возможно несколько вариантов, в зависимости от конструкции горелки и оси Z. В частности, емкостный датчик (работает как кнопка), либо подключение к соплу горелки (при касании металла напряжение на сопле становится равно потенциалу листа металла); 37 | - **FEEDBACK** (PC1, A1) - аналоговый сигнал напряжения дуги, приведенный к интервалу входных напряжений АЦП ATmega328P (0-5 Вольт, желательно с запасом), например, резистивным делителем. Резкие скачки и перепады, а также шумы в сигнале крайне желательно устранить установкой фильтра; 38 | - **SETTINGS ADC** (PC0, A0) - аналоговый вход для настройки параметров. Обычно - потенциометр сопротивлением 3-100 кОм и размахом напряжений 0-5 В; 39 | - **SETTINGS BUTTON** (PB0, 8) - кнопка циклического выбора меню. 40 | Все цифровые входы по умолчанию - типа "активный ноль", и должны быть подтянуты к питанию (+5В DC - питание Arduino). Во избежание влияния наводок и помех необходимо осуществить качественный монтаж и не располагать устройство вблизи высоковольтных или силовых частей. При необходимости сделайте экранировку. Для безопасности компонентов также рекомендуется развязать все связи с остальными частями станка и использовать отдельный гальванически развязанный источник питания. 41 | 42 | 43 | ### Мотор 44 | В папке `/lib` находятся две версии драйвера для шагового мотора: для использования с набором ключей (MotorControl) и для "умных" драйверов с сигналами STEP-DIR (MotorDriver). Выберите один из них, подключив соответствующий заголовочный файл в `TorchHeightControl.h`. Также вы можете создать свой драйвер, реализовав 5 необходимых функций. 45 | 46 | #### MotorControl 47 | **MOTOR_PHASE_A**, **MOTOR_PHASE_B**, **MOTOR_PHASE_C**, **MOTOR_PHASE_D** - четыре вывода (фазы) шагового двигателя (A, B, C, D). Подключение через любые ключи: реле, дискретные полевые/биполярные транзисторы, сборки, драйверы и т.д. Правильный порядок включения фаз: A-C-B-D. По умолчанию настроены выводы PC2-PC5 (A2-A5): 48 | - PC2 (A2) - A; 49 | - PC3 (A3) - C; 50 | - PC4 (A4) - B; 51 | - PC5 (A5) - D. 52 | 53 | В то же время, существует путаница в обозначениях обмоток шаговых моторов, поэтому при отсутствии вращения можно попробовать изменить порядок подключения (прежде всего, B и C). 54 | 55 | Также для различных двигателей различные оптимальные длительности импульса и периода. 56 | 57 | 58 | ### Дисплей 59 | По умолчанию двухстрочный ЖК-дисплей типа HD44780 подключается к выводам порта D с PD1 по PD7 (Arduino 1-7): 60 | - PD4 (4) - DB4; 61 | - PD5 (5) - DB5; 62 | - PD6 (6) - DB6; 63 | - PD7 (7) - PD7; 64 | - PD1 (1) - RS; 65 | - PD2 (2) - RW 66 | - PD3 (3) - E. 67 | 68 | 69 | ## Настройка параметров программы 70 | Перед прошивкой микроконтроллера (МК) можно изменить некоторые параметры в основных файлах программы `TorchHeightControl.cpp/h` и заголовочных файлах соответствующих библиотек: 71 | - Порты ввода-вывода (если было установлено отличное от рекомендуемого подключение); 72 | - Значение по умолчанию петли гистерезиса регулировки (`setpoint_offset_EEPROM`), интервал допустимых для установки в меню значений (`SETPOINT_OFFSET_MIN/MAX_SET_VOLTAGE`); 73 | - Значение по умолчанию высоты прокола (`cutting_height_EEPROM`); 74 | - Значение по умолчанию времени прокола (`pierce_time_EEPROM`); 75 | - Режим "в обход" (`bypass_ON_flag_EEPROM`): ВКЛ (`1`) или ВЫКЛ (`0`); 76 | - Число значений для определения напряжения дуги, которое будет удерживать регулятор (`NUM_OF_VALUES_FOR_SETPOINT_DEFINITION`). Слишком маленькое значение не позволит точно определить нужное напряжение, а слишком большое будет занимать много времени (особенно при высокой зашумленности и неоднородности сигнала); 77 | - Число значений для усреднения при программном усреднении напряжения дуги (`PRESCALER_MAIN_ALGO`). Это значение также влияет на частоту алгоритма контроля и, следовательно, на скорость реакции системы: чем больше значений усредняется, тем ниже частота отклика; 78 | - Интервал нечувствительности при программном усреднении напряжения дуги (`OFFSET_FOR_AVRG`). 79 | 80 | 81 | ## Сборка программы и прошивка 82 | Для сборки рекомендуется использовать программу PlatformIO. 83 | 84 | 85 | ### Консольный режим 86 | При необходимости настройте параметры прошивки в файле `platformio.ini` (например, укажите, использовать для прошивки программатор или нет). Затем, в папке с проектом выполните: 87 | ```sh 88 | $ pio run # компиляция 89 | 90 | $ pio run -t program # загрузка через программатор 91 | или 92 | $ pio run -t upload # загрузка через встроенный программатор Arduino 93 | 94 | $ pio run -t uploadeep # загрузка в EEPROM значений по умолчанию 95 | ``` 96 | 97 | 98 | ### IDE (Atom или VScode) 99 | - Импортируйте папку репозитория: `File` -> `Add Project Folder`; 100 | - При необходимости настройте параметры прошивки в файле `platformio.ini` (например, укажите, использовать для прошивки программатор или нет); 101 | - Запустите сборку `PlatformIO` -> `Build`; 102 | - Откройте встроенный терминал и выполните команду (при загрузке через программатор): 103 | ```sh 104 | $ pio run -t program; pio run -t uploadeep 105 | ``` 106 | При загрузке через плату Arduino: 107 | ```sh 108 | $ pio run -t upload; pio run -t uploadeep 109 | ``` 110 | 111 | 112 | ## Использование 113 | После прошивки регулятора на дисплее отображается главное меню (ждущий режим). На нем отображаются текущие настройки интервала гистерезиса при регулировании, высоты (`lft`) и задержки (`dlay`) прокола. Нажатием кнопки меню перейдите к настройкам и задайте параметр с помощью потенциометра. В скобках указано текущее значение параметра. Нажимайте кнопку меню, пока не настроите все параметры и не вернетесь в главное меню. 114 | 115 | После замыкания реле плазмы отображается надпись `start...`. После касания горелкой листа металла надпись сменяется на `pierce...` и сохраняется все время прокола. Затем промаргивает надпись `define sp...`, во время которой система определяет напряжение дуги для удержания, и, наконец, дисплей переходит в рабочий режим: верхняя строчка отображает измеренное напряжение удержания, нижняя - текущее напряжение (усредненное). Если надпись `define sp...` сохраняется слишком долго, то это говорит о слишком большом количестве точек для определения уставки (`NUM_OF_VALUES_FOR_SETPOINT_DEFINITION`), либо слишком маленьком интервале усреднения (`OFFSET_FOR_AVRG`), либо сильно зашумленном сигнале. 116 | 117 | По возвращении в режим ожидания (после размыкания реле плазмы) в первой строчке будет отображаться последнее измеренное значение напряжения дуги. 118 | 119 | Для входа в режим обхода удерживайте нажатой кнопку меню около 8 секунд. На экране отобразится надпись `regulation off`. Регулятор будет реагировать только на сигналы подъема/опускания. Текущий режим сохраняется при сбросе и отключении питания. Для выхода из режима также удерживайте кнопку меню в течение 8 секунд. 120 | 121 | 122 | ## Замечания 123 | Поведение контроллера при подаче нескольких управляющих сигналов одновременно (например, сигнал зажигания плазмы и касания) в общем случае не определено и зависит от порядка их обработчиков в коде прерывания `PCINT0_vect`. Благодаря конструкции `if - else if` исключается выполнение нескольких блоков за один проход прерывания, однако все же данные ситуации крайне не рекомендуются. Впрочем, при работе в реальном устройстве подобные случаи не должны встречаться. 124 | 125 | Диаграмму переходов конечного автомата (UML), можно посмотреть в файлах `torch-height-control-uml.*` (создано с помощью [draw.io](https://github.com/jgraph/drawio)). 126 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - Convert Pierce height from steps to distance (but then it will be dependent on certain motor and mechanics); 2 | - Handle touches when cutting (reduce "pecks" into the metal); 3 | - Convert feedback ADC value to actual arc voltage; 4 | - Take out all platform-dependent parts and make the actual library generic. 5 | -------------------------------------------------------------------------------- /inc/TorchHeightControl.h: -------------------------------------------------------------------------------- 1 | #ifndef TORCHHEIGHTCONTROL_H_ 2 | #define TORCHHEIGHTCONTROL_H_ 3 | 4 | 5 | 6 | /* 7 | * Main libraries 8 | */ 9 | // already contains all necessary AVR's and C standard library functions 10 | #include 11 | 12 | /* 13 | * User libraries 14 | */ 15 | // We use custom ADC library instead of Arduino's analogRead() 16 | // because second takes some unwanted for us periphery (timer) 17 | // and it is actually quite simple to write your own lightweight version 18 | // of analogRead() so why not? 19 | #include 20 | // Abstraction layer for the way we rule the motor. There can be a driver 21 | // for a stepper motor plus set of switches, a stepper motor with 22 | // "intelligent" step-direction driver, simply DC motor or whatever you wants to. 23 | #include 24 | 25 | 26 | /* 27 | * Control signals definitions (all of them are inputs) 28 | * Free (unused) pins: 29 | * - PB5 (can be used as a test LED) 30 | * - PD0 31 | * - PD1 32 | */ 33 | #define SIGNALS_DDR DDRB 34 | #define SIGNALS_PIN PINB 35 | #define UP_SIGNAL_PIN PB2 36 | #define UP_SIGNAL_INT PCINT2 37 | #define DOWN_SIGNAL_PIN PB3 38 | #define DOWN_SIGNAL_INT PCINT3 39 | #define PLASM_SIGNAL_PIN PB4 40 | #define PLASM_SIGNAL_INT PCINT4 41 | #define TOUCH_SIGNAL_PIN PB1 42 | #define TOUCH_SIGNAL_INT PCINT1 43 | #define SETTINGS_BUTTON_PIN PB0 44 | #define SETTINGS_BUTTON_INT PCINT0 45 | // initial state: all signals are pulled up to Vcc 46 | uint8_t signals_port_history = 0xFF; 47 | 48 | 49 | /* 50 | * Menu definitions 51 | */ 52 | enum Menu { 53 | WORK_MENU, 54 | IDLE_MENU, 55 | cutting_height_MENU, 56 | SETPOINT_OFFSET_MENU, 57 | PIERCE_TIME_MENU, 58 | 59 | NUM_OF_MENUS 60 | }; 61 | uint8_t menu = IDLE_MENU; // initial state 62 | 63 | 64 | /* 65 | * LCD definitions. We use Arduino's standard library LiquidCrystal for this 66 | * because of its robustness and widespread 67 | */ 68 | #include 69 | // RS, RW (optional, faster in general), E, D4-7 70 | LiquidCrystal lcd(1, 2, 3, 4, 5, 6, 7); 71 | // we need slightly more than the length of a string (16 in our case) 72 | // due to the inner structure of the sprintf(). Otherwise, displayed 73 | // values can be corrupted 74 | #define BUFFER_SIZE 25 75 | char bufferA[BUFFER_SIZE]; // 1st raw of LCD 76 | char bufferB[BUFFER_SIZE]; // 2nd raw of LCD 77 | 78 | 79 | /* 80 | * LED for testing purposes. PB5 is built-in on UNO and NANO 81 | */ 82 | // #define TEST_LED 83 | #ifdef TEST_LED 84 | #define TEST_LED_DDR DDRB 85 | #define TEST_LED_PORT PORTB 86 | #define TEST_LED_PIN PB5 87 | #endif 88 | 89 | 90 | 91 | #endif /* TORCHHEIGHTCONTROL_H_ */ 92 | -------------------------------------------------------------------------------- /lib/ADC/ADC.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void adc_init(void) { 5 | // enable ADC, prescaler=128 6 | ADCSRA |= (1< 7 | 8 | // ADC pinout 9 | #define ADC_SETTINGS_PIN 0 // PC0 10 | #define ADC_FEEDBACK_PIN 1 // PC1 11 | 12 | // edit this value to match your voltage 13 | #define ADC_REFERENCE_VOLTAGE 5.00 14 | 15 | 16 | void adc_init(void); 17 | uint16_t adc_read(uint8_t adc_channel); 18 | 19 | 20 | 21 | #endif /* ADC_H_ */ 22 | -------------------------------------------------------------------------------- /lib/MotorControl/MotorControl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | static bool motor_up_flag; 5 | static int8_t last_step = 0; 6 | 7 | 8 | // Motor timer initialization. We use Timer2 for motor movement algorithm 9 | void motor_init(void) { 10 | MOTOR_DDR |= (1< 0) { 28 | for (steps_cnt=0; steps_cnt 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | /* 13 | * Motor definitions. We've used 42BYGHW208 stepper motor with such pinout: 14 | * First coil: 15 | * - A black 16 | * - C green 17 | * Second coil: 18 | * - B red 19 | * - D blue 20 | */ 21 | #define MOTOR_DDR DDRC 22 | #define MOTOR_PORT PORTC 23 | #define MOTOR_PHASE_A PC2 24 | #define MOTOR_PHASE_C PC3 25 | #define MOTOR_PHASE_B PC4 26 | #define MOTOR_PHASE_D PC5 27 | #define MOTOR_PINS_OFFSET 2 // 2 for PC2. Needed to iterate through the pins 28 | #define MOTOR_STOP MOTOR_PORT&=(~((1< 2 | 3 | 4 | // Motor timer initialization 5 | void motor_init(void) { 6 | MOTOR_DRIVER_DDR |= (1< 0) 41 | MOTOR_DRIVER_PORT |= (1< 7 | 8 | 9 | #define MOTOR_DRIVER_DDR DDRC 10 | #define MOTOR_DRIVER_PORT PORTC 11 | 12 | #define STEP_PIN PC3 13 | #define DIR_PIN PC2 14 | 15 | // in milliseconds 16 | #define PERIOD 1500 17 | #define PULSE 20 18 | 19 | // for internal usage 20 | #define MOTOR_STOP MOTOR_DRIVER_PORT&=(~((1< THIS FILE 21 | |- platformio.ini 22 | |--src 23 | |- main.c 24 | 25 | Then in `src/main.c` you should use: 26 | 27 | #include 28 | #include 29 | 30 | // rest H/C/CPP code 31 | 32 | PlatformIO will find your libraries automatically, configure preprocessor's 33 | include paths and build them. 34 | 35 | More information about PlatformIO Library Dependency Finder 36 | - http://docs.platformio.org/page/librarymanager/ldf.html 37 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; http://docs.platformio.org/page/projectconf.html 10 | 11 | [env:atmelavr_usbasp] 12 | platform = atmelavr 13 | framework = arduino 14 | board = uno 15 | build_flags = -Wl,-u,vfprintf -lprintf_flt -lm, -O3 16 | upload_protocol = usbasp 17 | upload_flags = -Pusb -B5 18 | 19 | [platformio] 20 | include_dir = Inc 21 | -------------------------------------------------------------------------------- /src/TorchHeightControl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | 5 | /* 6 | * Other settings 7 | */ 8 | // Lift before cut is measured in steps of stepper motor (0-1023). 9 | // EEMEM is the default value at the flash time. Actually, not so important 10 | // because we always can change it at runtime 11 | uint16_t cutting_height; // cutting_height 12 | uint16_t EEMEM cutting_height_EEPROM = 150; 13 | // Pierce time is measured in ELEMENTARY_DELAYs which in turn is measured in ms 14 | uint8_t pierce_time; 15 | #define PIERCE_TIME_ELEMENTARY_DELAY 100 // 100 ms 16 | #define PIERCE_TIME_MAX_TIME 50 // 50*ELEMENTARY_DELAY = 5s max 17 | uint8_t EEMEM pierce_time_EEPROM = 20; // 20*ELEMENTARY_DELAY = 2000ms 18 | // Flag of the "bypass mode" without regulation. We explicitly use uint8_t type 19 | // (instead of bool) because AVR's EEPROM driver has function for that 20 | uint8_t EEMEM bypass_ON_flag_EEPROM = 0; 21 | 22 | 23 | /* 24 | * Setpoint settings 25 | */ 26 | uint16_t setpoint = 0; 27 | // setpoint will be automatically defined at regulation start 28 | #define NUM_OF_VALUES_FOR_SETPOINT_DEFINITION 200 29 | bool setpoint_defined = false; 30 | // hysteresis for control algorithm (setpoint ± setpoint_offset) 31 | uint16_t setpoint_offset; 32 | uint16_t EEMEM setpoint_offset_EEPROM = 20; // 97mV 33 | // interval of voltages for specifing setpoint offset in settings menus, Volts 34 | #define SETPOINT_OFFSET_MIN_SET_VOLTAGE 0.010 35 | #define SETPOINT_OFFSET_MAX_SET_VOLTAGE 0.200 36 | 37 | 38 | /* 39 | * Signal from arc and control algorithm definitions. Note that we use shared 40 | * feedback variables first for setpoint defining and then for main regulation 41 | * algorithm itself 42 | */ 43 | uint16_t feedback = 0; // 10-bit ADC value 44 | uint16_t feedback_prev = 0; // previous ADC value 45 | uint32_t feedback_accum = 0; // accumulator for averaging 46 | uint16_t feedback_accum_cnt = 0; // counter of num of values for averaging 47 | uint16_t feedback_avrg = 0; 48 | // counter for manual dividing frequency of algo' timer in its ISR 49 | uint8_t prescaler_cnt = 0; 50 | #define PRESCALER_MAIN_ALGO 50 51 | // hysteresis for averaging only close results of ADC measurements 52 | #define OFFSET_FOR_AVRG 10 // ±48mV 53 | 54 | 55 | 56 | int main(void) { 57 | 58 | // disable all interrupts while setup 59 | cli(); 60 | 61 | /* 62 | * Debug LED 63 | */ 64 | #ifdef TEST_LED 65 | TEST_LED_DDR |= (1< (setpoint+setpoint_offset)) 210 | motor_down(); 211 | // otherwise stop 212 | else 213 | motor_stop(); 214 | } 215 | } 216 | 217 | // store previous value 218 | feedback_prev = feedback; 219 | } 220 | 221 | 222 | 223 | /* 224 | * Interrupt handler for LCD menu timer 225 | */ 226 | ISR (TIMER1_COMPA_vect) { 227 | 228 | // if bypass mode ON 229 | if ( eeprom_read_byte(&bypass_ON_flag_EEPROM) ) { 230 | // turn off LCD timer interrupt (i.e. this interrupt) 231 | LCD_ROUTINE_OFF; 232 | return; 233 | } 234 | 235 | switch (menu) { 236 | 237 | // print only second row - current voltage (averaged) 238 | case WORK_MENU: 239 | sprintf(bufferB, "%0.2f", ADC_REFERENCE_VOLTAGE*feedback_avrg/1023); 240 | break; 241 | 242 | // print only once, then turn off LCD timer interrupt 243 | case IDLE_MENU: 244 | sprintf(bufferA, "sp: %0.2fV+-%3umV", ADC_REFERENCE_VOLTAGE*setpoint/1023, 245 | (uint16_t)(1000*ADC_REFERENCE_VOLTAGE*setpoint_offset/1023)); 246 | sprintf(bufferB, "lft%u dlay%u", cutting_height, 247 | pierce_time*PIERCE_TIME_ELEMENTARY_DELAY); 248 | lcd.clear(); 249 | lcd.print(bufferA); 250 | // turn off LCD timer interrupt 251 | LCD_ROUTINE_OFF; 252 | break; 253 | 254 | // For the next 3 menu entries first string (bufferA) was printed outside this ISR 255 | // (at settings button ISR) so we only need to handle second row 256 | case cutting_height_MENU: 257 | // We don't map this, the default interval 0-1023 is OK for us 258 | // since ~200 steps is a one full revolution 259 | cutting_height = adc_read(ADC_SETTINGS_PIN); 260 | sprintf(bufferB, "%4u steps", cutting_height); 261 | break; 262 | 263 | case SETPOINT_OFFSET_MENU: 264 | setpoint_offset = map( adc_read(ADC_SETTINGS_PIN), 0, 1023, 265 | 1023*SETPOINT_OFFSET_MIN_SET_VOLTAGE/ADC_REFERENCE_VOLTAGE, 266 | 1023*SETPOINT_OFFSET_MAX_SET_VOLTAGE/ADC_REFERENCE_VOLTAGE ); 267 | sprintf(bufferB, "%3umV", (uint16_t)(1000*ADC_REFERENCE_VOLTAGE*setpoint_offset/1023)); 268 | break; 269 | 270 | case PIERCE_TIME_MENU: 271 | pierce_time = map(adc_read(ADC_SETTINGS_PIN), 0, 1023, 0, PIERCE_TIME_MAX_TIME); 272 | sprintf(bufferB, "%5ums", pierce_time*PIERCE_TIME_ELEMENTARY_DELAY); 273 | break; 274 | } 275 | 276 | // we always print second row of LCD here 277 | lcd.setCursor(0, 1); 278 | lcd.print(bufferB); 279 | } 280 | 281 | 282 | 283 | /* 284 | * Input signals interrupt 285 | */ 286 | ISR (PCINT0_vect) { 287 | 288 | // determine which bits have changed 289 | uint8_t changed_bits = SIGNALS_PIN ^ signals_port_history; 290 | // store current state as old one 291 | signals_port_history = SIGNALS_PIN; 292 | 293 | 294 | if ( changed_bits & (1< 75) { // 75*100ms = 7.5s 307 | toggle_bypass_cnt = 0; 308 | 309 | // write status in EEPROM 310 | eeprom_update_byte(&bypass_ON_flag_EEPROM, eeprom_read_byte(&bypass_ON_flag_EEPROM)^1); 311 | 312 | // toggle plasm interrupt 313 | PCMSK0 ^= (1< 2 | 3 | 4 | 5 | torch-height-control-uml.html 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /torch-height-control-uml.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ussserrr/torch-height-control/0b8c41afb78fc578ec8011ebd2d67da18a879fa6/torch-height-control-uml.pdf --------------------------------------------------------------------------------