- Регистрация
- 26.03.2023
- Сообщения
- 12
- Реакции
- 31
- Баллы
- 83
Последнее редактирование:
Доброго времени суток.
Решил поделиться , вдруг кому пригодится. ( Тем, кто режет платы )
Напоминаю одну старую тему:
После того, как я устал бороться с различными кабелями, (то есть внезапными остановками станка) я стал делать так:
Cнимаю карту высот, ставлю галочку "use heightmap" после этого меню Candle появляется пункт "Save transformed as"
Я сохраняю получившийся G-код, пишу его на карточку, вставляю карточку в пульт и говорю пульту "File"
Всё работает отлично (нет) - "ни единого разрыва" (с)
А "нет" потому что Candle при сохранении такого вот "transformed" допускает кучу ошибок.
G1 вместо G01
G01 вместо G00
G00 вместо G01
теряет скорости F
итд итп.
Долгое время я проверял код руками, попутно вычисляя характерные ошибки Candle
Когда вычислил их все, попросил AI написать скрипт, который бы все эти ошибки правил.
Кроме того, скрипт, обнаруживая в коде глубокий рез ( глубже полмиллиметра ) принудительно меняет скорость на F5
Так же скрипт предохраняет втыкание фрезы в плату на полном ходу, то есть
G00 Z-** меняет на G00 Z0.5
Ну и вот - делюсь этим скриптом, вдруг кому пригодится:
Скрипт запускается в формате python reformat.py file.nc
Питон нужен не ниже 3-его, то есть на Win7 работать будет.
Так же обнаружилась ещё одна проблема - очень сложно откалибровать станок по оси Z так чтобы было совсем точно. Нужно ловить сотые доли миллиметра.
Если по осям X Y + - 0.1 - ерунда, то когда работаешь с фольгой, толщина которой 0.05 , это часто вызывает недорез или перерез.
И если небольшой перерез еще можно стерпеть, то недорез - это очень неприятно.
Я как то создавал дaже тему, что-то вроде "можно ли в процессе реза, сместить Z0 ?"
Для решения этой проблемы использую второй скрипт, которым можно изменить положение оси Z на любую величину вниз по всему коду.
строка запуска python deeper.py file.nc <число> <для кода Z-> <для кода Z+>
например python deeper.py file.nc 0.05 pozitive
все строчки типа G01 F15 X10 Y10 Z0.01 "углубит" на 0.05 то есть получится G01 F15 X10 Y10 Z-0.04
Решил поделиться , вдруг кому пригодится. ( Тем, кто режет платы )
Напоминаю одну старую тему:
После того, как я устал бороться с различными кабелями, (то есть внезапными остановками станка) я стал делать так:
Cнимаю карту высот, ставлю галочку "use heightmap" после этого меню Candle появляется пункт "Save transformed as"
Я сохраняю получившийся G-код, пишу его на карточку, вставляю карточку в пульт и говорю пульту "File"
Всё работает отлично (нет) - "ни единого разрыва" (с)
А "нет" потому что Candle при сохранении такого вот "transformed" допускает кучу ошибок.
G1 вместо G01
G01 вместо G00
G00 вместо G01
теряет скорости F
итд итп.
Долгое время я проверял код руками, попутно вычисляя характерные ошибки Candle
Когда вычислил их все, попросил AI написать скрипт, который бы все эти ошибки правил.
Кроме того, скрипт, обнаруживая в коде глубокий рез ( глубже полмиллиметра ) принудительно меняет скорость на F5
Так же скрипт предохраняет втыкание фрезы в плату на полном ходу, то есть
G00 Z-** меняет на G00 Z0.5
Ну и вот - делюсь этим скриптом, вдруг кому пригодится:
Код:
import re
import sys
import os
import argparse
import shutil
def detect_encoding(filename):
"""
Определяет кодировку файла
"""
encodings = ['utf-8', 'cp1251', 'cp1252', 'iso-8859-1', 'latin1', 'windows-1251']
for encoding in encodings:
try:
with open(filename, 'r', encoding=encoding) as file:
file.read()
return encoding
except UnicodeDecodeError:
continue
return 'cp1251' # дефолтная для CNC
def add_spaces_to_gcode(line):
"""
Добавляет пробелы перед F, Y, Z, X где их нет
"""
# Сначала добавляем пробелы между параметрами
# Ищем комбинации типа X10Y20Z30F100 и разбиваем их
line = re.sub(r'([XYZF])(?=[YZF])', r'\1 ', line)
# Добавляем пробелы после G-кодов
line = re.sub(r'(G0[01])(?=[XYZF])', r'\1 ', line)
# Добавляем пробелы между числами и следующими параметрами
line = re.sub(r'(\d)(?=[XYZF])', r'\1 ', line)
return line
def fix_x_position(line):
"""
Исправляет позицию X: если X не в начале строки и перед ним не пробел, добавляет пробел
"""
# Ищем X с числом, который не в начале строки и перед ним не пробел
pattern = r'(?<!\s)(?<!^)(X[-+]?\d*\.?\d+)'
line = re.sub(pattern, r' \1', line)
return line
def adjust_feedrate_for_deep_z(line):
"""
Если Z < -0.5, гарантированно устанавливаем F5 (удаляя все существующие F-параметры)
"""
original_line = line
# Ищем Z-параметр в строке
z_match = re.search(r'Z([-+]?\d*\.?\d+)', line)
if z_match:
try:
z_value = float(z_match.group(1))
# Если Z < -0.5, гарантируем что есть F5 (и только один)
if z_value < -0.5:
# Удаляем все существующие F-параметры
line = re.sub(r'F\d*\.?\d+\s*', '', line)
# Убираем возможные двойные пробелы после удаления
line = re.sub(r' +', ' ', line).strip()
# Добавляем F5 после G-кода
g_match = re.search(r'(G0[01])', line)
if g_match:
# Если G-код найден, добавляем F5 после него
line = line.replace(g_match.group(1), g_match.group(1) + ' F5', 1)
print(f"🔹 Установлен F5 (Z={z_value})")
else:
# Если G-кода нет, добавляем в начало
line = 'F5 ' + line
print(f"🔹 Добавлен F5 в начало (Z={z_value})")
except ValueError as e:
print(f"⚠️ Ошибка чтения Z-значения: {e}")
return line
def fix_negative_z_in_rapid_move(line):
"""
Исправляет отрицательный Z в быстрых перемещениях (G00) - меняет на Z0.5
"""
original_line = line
# Проверяем, что строка содержит G00 (быстрое перемещение)
if re.search(r'\bG00\b', line):
# Ищем Z с отрицательным значением
z_match = re.search(r'Z(-?\d*\.?\d+)', line)
if z_match:
try:
z_value = float(z_match.group(1))
# Если Z отрицательный, заменяем на Z0.5
if z_value < 0:
# Заменяем отрицательное Z на Z0.5
new_line = re.sub(r'Z-?\d*\.?\d+', 'Z0.5', line)
print(f"🔹 Исправлен отрицательный Z в G00: {z_value} -> 0.5")
return new_line
except ValueError as e:
print(f"⚠️ Ошибка чтения Z-значения в G00: {e}")
return line
def reformat_gcode(input_filename, output_filename=None):
"""
Улучшенная функция для реформатирования G-кода с созданием нового файла
"""
try:
# Проверяем существование файла
if not os.path.exists(input_filename):
print(f"❌ Ошибка: Файл '{input_filename}' не найден")
return False
# Определяем кодировку
encoding = detect_encoding(input_filename)
print(f"📖 Определена кодировка: {encoding}")
# Генерируем имя выходного файла если не указано
if output_filename is None:
name, ext = os.path.splitext(input_filename)
output_filename = f"{name}_formatted{ext}"
# Читаем файл с правильной кодировкой
with open(input_filename, 'r', encoding=encoding, errors='replace') as file:
lines = file.readlines()
processed_lines = []
changes_count = 0
for i, line in enumerate(lines, 1):
original_line = line.rstrip('\n\r')
processed_line = original_line
# Пропускаем пустые строки и комментарии
if not processed_line.strip() or processed_line.strip().startswith(('(', ';', '%', '#')):
processed_lines.append(processed_line)
continue
# 1) Сначала добавляем все необходимые пробелы
processed_line = add_spaces_to_gcode(processed_line)
# 2) Исправляем позицию X
processed_line = fix_x_position(processed_line)
# 3) Обработка строк, начинающихся с X
if re.match(r'^\s*X[-+]?\d', processed_line) and not re.search(r'\bG0[01]\b', processed_line):
# Ищем Z-параметр в строке
z_match = re.search(r'Z([-+]?\d*\.?\d+)', processed_line)
if z_match:
try:
z_value = float(z_match.group(1))
if z_value > 1:
# 6а) Добавляем G00 для Z > 1
processed_line = 'G00 ' + processed_line.lstrip()
changes_count += 1
print(f"🔹 Строка {i}: Добавлен G00 (Z={z_value})")
elif z_value < 1:
# 6б) Добавляем G01 F15 для Z < 1
processed_line = 'G01 F15 ' + processed_line.lstrip()
changes_count += 1
print(f"🔹 Строка {i}: Добавлен G01 F15 (Z={z_value})")
except ValueError as e:
print(f"⚠️ Предупреждение в строке {i}: {e}")
pass
# 4) Заменяем G1 на G01 (теперь пробелы уже добавлены)
processed_line = re.sub(r'\bG1\b', 'G01', processed_line)
# 5) Корректировка подачи для глубокого Z
processed_line = adjust_feedrate_for_deep_z(processed_line)
# 6) В САМЫЙ КОНЕЦ: Исправление отрицательного Z в быстрых перемещениях
processed_line = fix_negative_z_in_rapid_move(processed_line)
# Считаем изменения
if processed_line != original_line:
changes_count += 1
# Показываем изменения для отладки
if original_line != processed_line:
print(f"📝 Строка {i}:")
print(f" БЫЛО: {original_line}")
print(f" СТАЛО: {processed_line}")
processed_lines.append(processed_line)
# Записываем результат в НОВЫЙ файл
with open(output_filename, 'w', encoding='utf-8') as file:
file.write('\n'.join(processed_lines))
print(f"✅ Создан новый файл: '{output_filename}'")
print(f"📊 Внесено изменений: {changes_count}")
# Показываем пример изменений
print("\n🔍 Примеры изменений:")
example_count = 0
for i, (orig, new) in enumerate(zip(lines[:10], processed_lines[:10])):
if orig.strip() != new.strip() and example_count < 3:
print(f"Строка {i+1}:")
print(f" БЫЛО: {orig.strip()}")
print(f" СТАЛО: {new.strip()}")
print()
example_count += 1
return True
except Exception as e:
print(f"❌ Критическая ошибка при обработке файла: {e}")
import traceback
traceback.print_exc()
return False
def main():
"""
Главная функция
"""
parser = argparse.ArgumentParser(description='Реформатирование G-кода для фрезерного станка')
parser.add_argument('input_file', help='Путь к исходному файлу')
parser.add_argument('-o', '--output', help='Путь к выходному файлу (опционально)')
parser.add_argument('--inplace', action='store_true', help='Заменить исходный файл (с созданием backup)')
if len(sys.argv) == 1:
parser.print_help()
return
args = parser.parse_args()
print(f"🔧 Начинаем обработку файла: {args.input_file}")
if args.inplace:
# Создаем backup и заменяем исходный файл
backup_name = args.input_file + '.backup'
shutil.copy2(args.input_file, backup_name)
print(f"💾 Создан backup: {backup_name}")
success = reformat_gcode(args.input_file, args.input_file)
else:
# Создаем новый файл
success = reformat_gcode(args.input_file, args.output)
if success:
print("🎉 Обработка завершена успешно!")
else:
print("💥 Обработка завершена с ошибками!")
sys.exit(1)
if __name__ == "__main__":
main()
Скрипт запускается в формате python reformat.py file.nc
Питон нужен не ниже 3-его, то есть на Win7 работать будет.
Так же обнаружилась ещё одна проблема - очень сложно откалибровать станок по оси Z так чтобы было совсем точно. Нужно ловить сотые доли миллиметра.
Если по осям X Y + - 0.1 - ерунда, то когда работаешь с фольгой, толщина которой 0.05 , это часто вызывает недорез или перерез.
И если небольшой перерез еще можно стерпеть, то недорез - это очень неприятно.
Я как то создавал дaже тему, что-то вроде "можно ли в процессе реза, сместить Z0 ?"
Для решения этой проблемы использую второй скрипт, которым можно изменить положение оси Z на любую величину вниз по всему коду.
Код:
import re
import sys
def adjust_z_value(match, delta):
z_number = float(match.group(1))
new_z = z_number - delta
if abs(new_z) < 1e-9:
new_z = 0.0
decimals = len(match.group(1).split('.')[1]) if '.' in match.group(1) else 0
return f"Z{new_z:.{decimals}f}"
def process_file(input_file, output_file, delta, mode):
with open(input_file, 'r') as f:
content = f.read()
# Выбор шаблона в зависимости от режима
if mode == 'positive':
pattern = re.compile(r'Z(0\.\d+)') # Ищем Z0.xxx (без плюса!)
elif mode == 'negative':
pattern = re.compile(r'Z(-0\.\d+)') # Ищем Z-0.xxx
else:
pattern = re.compile(r'Z([+-]?0\.\d+)') # Все варианты
modified_content = pattern.sub(lambda m: adjust_z_value(m, delta), content)
with open(output_file, 'w') as f:
f.write(modified_content)
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Использование: python deeper.py <file.nc> <число> [режим]")
print("Режимы: 'positive' (только Z0.xxx), 'negative' (только Z-0.xxx), по умолчанию — все")
sys.exit(1)
input_file = sys.argv[1]
delta = float(sys.argv[2])
mode = sys.argv[3].lower() if len(sys.argv) > 3 else None # Регистронезависимо
output_file = input_file.replace('.nc', f'_deeped_{mode or "all"}.nc')
process_file(input_file, output_file, delta, mode)
print(f"Файл обработан в режиме '{mode or 'all'}'. Результат в {output_file}")
строка запуска python deeper.py file.nc <число> <для кода Z-> <для кода Z+>
например python deeper.py file.nc 0.05 pozitive
все строчки типа G01 F15 X10 Y10 Z0.01 "углубит" на 0.05 то есть получится G01 F15 X10 Y10 Z-0.04