Skip to content

Repository files navigation

txt2plot — інструменти для пен-плотера на GRBL

Vibe Coded

Набір Python-утиліт для керування пен-плотером на базі GRBL з текстових файлів. Повна підтримка кирилиці (українська мова).

Example

Яку проблему вирішує

Більшість інструментів для пен-плотерів розраховані на AxiDraw або платне ПО. Однолінійні шрифти («Hershey») — що дозволяють плотеру малювати літери одним безперервним рухом без заповнення контуру — майже виключно латинські. Безкоштовних Hershey-шрифтів з кирилицею практично немає.

Цей набір вирішує обидві проблеми:

  • centerline.py — конвертує будь-який контурний шрифт TTF/OTF в однолінійний Hershey SVG-шрифт. Саме так отримати кирилицю: взяти будь-який шрифт з підтримкою української (Caveat, Kobzar KS тощо) і конвертувати.
  • text_to_gcode.py — переводить вміст .txt-файлу безпосередньо в G-code посторінково: перенос слів, пагінація, портретна/ландшафтна орієнтація, точні відступи — все автоматично.
  • plot.py — стрімер G-code на плотер з оптимальним заповненням буфера GRBL (128 байт). Тримає буфер постійно повним → плавний рух без пауз між командами (bCNC не робить цього і плотер «заїкається»).
  • set_zero.py — інструмент для коригування нульової точки: переміщує перо в поточний (0, 0), дозволяє зберегти нову нульову точку та намалювати калібрувальні куточки для перевірки.

Обладнання

Протестовано з плотером на прошивці DrawCore V2.21 (GRBL 1.1h).

  • Підключення: USB serial (/dev/ttyACM0 на Linux, COM3 / COM4 на Windows — див. Налаштування)
  • Робоча область: 210 × 297 мм (A4)
  • Керування пером по осі Z: Z5 = перо вниз (малює), Z3 = перо вгору (перехід)

Встановлення

Linux

pip install vpype vpype-gcode pyserial

git clone https://github.com/your-username/txt2plot.git
cd txt2plot

Windows

  1. Встановіть Python 3.10+ — під час встановлення поставте галочку «Add Python to PATH».
  2. Відкрийте Command Prompt або PowerShell:
pip install vpype vpype-gcode pyserial
  1. Склонуйте або завантажте репозиторій і перейдіть у його папку.

Профіль vpype

Файл vpype.toml у цьому репозиторії — профіль G-code для DrawCore. text_to_gcode.py підхоплює його автоматично, якщо запущений з папки проєкту. Щоб використовувати глобально:

# Linux / macOS
cp vpype.toml ~/.config/vpype/vpype.toml

# Windows (PowerShell)
cp vpype.toml "$env:APPDATA\vpype\vpype.toml"

Налаштування

Відкрийте plot.py і set_zero.py та вкажіть правильний порт на початку кожного файлу:

# Linux
PORT = '/dev/ttyACM0'

# Windows — перевірте Диспетчер пристроїв → Порти (COM та LPT)
PORT = 'COM3'

Використання

1. Встановлення нульової точки (перший раз або після зміщення паперу)

python set_zero.py

При запуску перо автоматично переміщується в поточний (0, 0) — одразу видно де нуль фізично. Скоригуй положення паперу або каретки за потреби, потім:

Команда Дія
s Зберегти поточну позицію як нульову точку і вийти
c Намалювати калібрувальні куточки в кутах A4 для перевірки
Ctrl-C Вийти без збереження (перо підіймається)

2. Генерація G-code з тексту

# Портрет, стандартні налаштування (шрифт 5 мм, відступи 20 мм)
python text_to_gcode.py poem.txt --font fonts/myfont_centerline/myfont_centerline.svg

# Ландшафтна орієнтація
python text_to_gcode.py poem.txt --font fonts/myfont_centerline/myfont_centerline.svg \
    --orientation landscape \
    --margin-left 73 --margin-right 80 --margin-top 42 --margin-bottom 20 \
    --size 5 --line-height 7 --line-gap 2

# Попередній перегляд SVG без генерації G-code
python text_to_gcode.py poem.txt --font fonts/myfont_centerline/myfont_centerline.svg \
    --svg-only --output-dir ./preview

# Розмір шрифту і міжрядковий інтервал
python text_to_gcode.py poem.txt --font fonts/myfont_centerline/myfont_centerline.svg \
    --size 6 --line-height 9 --line-gap 1

# Зберегти в окрему папку з власним префіксом
python text_to_gcode.py poem.txt --font fonts/myfont_centerline/myfont_centerline.svg \
    --output-dir ./output --prefix poem

# Пропустити перші N рядків на першій сторінці (папір скінчився посередині)
python text_to_gcode.py poem.txt --font fonts/myfont_centerline/myfont_centerline.svg \
    --skip-lines 12

# Бічні мітки (дата, автор тощо) — див. розділ "Бічні мітки" нижче
python text_to_gcode.py poem.txt --font fonts/myfont_centerline/myfont_centerline.svg \
    --label дата:-32:60 --label автор:+5:70

Параметри:

Параметр За замовч. Опис
--orientation portrait portrait або landscape
--size MM 5.0 Em-розмір шрифту в мм (лише масштаб гліфів)
--line-height MM size × 1.5 Фіксована висота слоту на рядок (baseline-to-baseline), незалежно від вмісту
--line-gap MM 0 Додатковий відступ між рядками (leading). Повний крок = line-height + line-gap
--margin-top MM 20 Верхній відступ в орієнтації читання
--margin-bottom MM 20 Нижній відступ
--margin-left MM 20 Лівий відступ
--margin-right MM 20 Правий відступ
--page-width MM 210 Коротка сторона паперу (A4 = 210)
--page-height MM 297 Довга сторона паперу (A4 = 297)
--font PATH (обов'язковий) Шлях до Hershey SVG-шрифту
--output-dir DIR . Папка для файлів виводу
--prefix NAME page Префікс імен файлів
--skip-lines N 0 Пропустити перші N рядків на першій сторінці
--svg-only Тільки SVG, без G-code
--label NAME:OFFSET:WIDTH Оголосити бічну мітку (повторюваний прапорець). Див. "Бічні мітки" нижче

Ландшафт: папір лежить на плотері портретно як завжди. Скрипт повертає вміст на 90° проти годинникової стрілки всередині SVG. Щоб прочитати надрукований текст — поверни аркуш на 90° проти годинникової стрілки. Усі відступи вказуються в орієнтації читання.

Бічні мітки (дата, автор тощо)

Прапорець --label ІМ'Я:ЗМІЩЕННЯ:ШИРИНА (можна вказувати кілька разів) оголошує директиву --ІМ'Я ..., яку можна використовувати у вхідному текстовому файлі:

--дата 14.07.2026
--автор Іван Петренко

Цей рядок буде надруковано в основному тексті.
  • Директива вилучається з основного тексту; її вміст друкується збоку, прив'язаний до наступного змістовного рядка.
  • ЗМІЩЕННЯ (мм) — відступ від межі текстової області назовні, у поле сторінки: від'ємне значення рахується від --margin-left, додатне — від --margin-right.
  • ШИРИНА (мм) — ширина бічного блоку; якщо текст мітки не влазить в один рядок, він переноситься на наступні рядки (baseline-слоти), не залежно від того, скільки рядків займає сам основний текст.
  • Кілька міток підряд перед одним рядком — незалежні бічні колонки на тому самому якорі.
  • Директива для імені, яке не було оголошене через --label, лишається звичайним текстом.
python text_to_gcode.py poem.txt --font fonts/myfont_centerline/myfont_centerline.svg \
    --label дата:-32:60 --label автор:+5:70

3. Друк

python plot.py page_0001.gcode
python plot.py page_0002.gcode

Ctrl-C у будь-який момент — скрипт підніме перо і повернеться в домашню позицію.

Друк SVG-файлу

Якщо є готовий SVG з Inkscape або іншої програми:

# Конвертуй текст у шляхи (Inkscape CLI)
inkscape input.svg --export-text-to-path --export-plain-svg --export-filename=input_paths.svg

# Генерація G-code
vpype -c vpype.toml read input_paths.svg \
  linemerge --tolerance 0.5mm \
  linesort \
  gwrite --profile drawcore output.gcode

python plot.py output.gcode

editor/editor.py — веб-редактор з попереднім переглядом і друком

Flask-застосунок із браузерним інтерфейсом: зліва — поле введення тексту, справа — SVG-превʼю сторінки в реальному часі. Замінює ланцюжок text_to_gcode.py → plot.py для інтерактивної роботи.

Додаткові залежності

pip install flask

Запуск

python editor/editor.py --font fonts/myfont_centerline/myfont_centerline.svg

Відкрий у браузері: http://127.0.0.1:5000/

Усі параметри розмітки аналогічні text_to_gcode.py, включно з --label (див. "Бічні мітки" вище):

python editor/editor.py \
    --font fonts/myfont_centerline/myfont_centerline.svg \
    --orientation landscape \
    --size 5 --line-height 7 --line-gap 2 \
    --margin-left 73 --margin-right 80 --margin-top 42 --margin-bottom 20 \
    --label дата:-32:60 --label автор:+5:70 \
    --port 5000

Інтерфейс

Елемент Призначення
Ліва панель Введення тексту; текст зберігається в localStorage між сесіями
Права панель SVG-превʼю поточної сторінки (оновлюється через 400 мс після зупинки введення)
Start line Скільки рядків пропустити на першій сторінці (якщо папір уже частково надрукований)
Сітка Перемикає показ сітки-лінійки, контуру текстової області та боксів бічних міток (з --label) в прев'ю (не впливає на друк)
‹ / › / поле сторінки Навігація між сторінками; також Alt+← / Alt+→
Друкувати Генерує G-code через vpype і запускає plot.py для поточної сторінки
Пауза / Продовжити Надсилає Enter у stdin plot.py (пауза/відновлення між ходами)
Стоп Надсилає SIGINT процесу plot.py; перо піднімається і повертається додому

Ширина лівої панелі регулюється перетягуванням розділювача.


grbl_tune.py — перегляд і налаштування параметрів GRBL

Підключається до плотера, зчитує $$ і виводить параметри, що впливають на швидкість друку. З прапором --set дозволяє змінити їх прямо в терміналі.

# Тільки переглянути поточні значення
python grbl_tune.py

# Переглянути і змінити
python grbl_tune.py --set

Відображувані параметри:

Параметр Опис
$110 / $111 Максимальна швидкість X / Y (мм/хв)
$112 Максимальна швидкість Z (мм/хв)
$120 / $121 Прискорення X / Y (мм/с²)
$122 Прискорення Z (мм/с²)

Зміни зберігаються в EEPROM плотера і зберігаються після вимкнення.


centerline.py — конвертація будь-якого шрифту в однолінійний

Утиліта рендерить кожен гліф через FreeType, скелетонізує растр (алгоритм Чжан-Суена), трасує скелет в полілінії за алгоритмом Ейлера (мінімум підйомів пера), спрощує Рамером-Дугласом-Пекером, апроксимує кубічними кривими Без'є та записує результат як Hershey SVG-шрифт (сумісний з text_to_gcode.py і розширенням Hershey Text для Inkscape).

Навіщо вона потрібна

Безкоштовних однолінійних шрифтів з кирилицею практично не існує. centerline.py дозволяє взяти будь-який TTF/OTF-шрифт з підтримкою потрібної мови і отримати готовий однолінійний варіант для плотера.

Додаткові залежності

centerline.py потребує бібліотек, які не потрібні решті утиліт:

pip install freetype-py fonttools numpy scikit-image scipy

На Windows freetype-py зазвичай включає потрібну DLL, але якщо при імпорті виникає помилка — встановіть FreeType для Windows вручну.

Вихідні TTF/OTF-файли і результат конвертації можна зберігати в папці fonts/.

Використання

# Конвертувати шрифт (латиниця + кирилиця, всі друковані символи)
python centerline.py fonts/myfont.ttf

# Вища роздільна здатність рендеру для тонких або деталізованих шрифтів
python centerline.py fonts/myfont.ttf --render-size 400

# Тільки вказані символи
python centerline.py fonts/myfont.otf --glyphs "АБВГДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯабвгдеєжзиіїйклмнопрстуфхцчшщьюя"

# Тільки Hershey SVG-шрифт, без UFO і покрокових SVG
python centerline.py fonts/myfont.ttf --no-ufo --no-svg

Параметри:

Параметр За замовч. Опис
--render-size PX 300 Висота рендеру FreeType у пікселях. Збільш для тонких/декоративних шрифтів
--rdp-epsilon 1.5 Допуск спрощення Рамера-Дугласа-Пекера в пікселях
--spur-size N 12 Обрізати тупикові гілки скелету коротші за N пікселів (прибирає артефакти растеризації)
--min-component N 10 Видалити фрагменти скелету менші за N пікселів. Збільш для тонких/геометричних шрифтів
--glyphs STRING всі друковані ASCII + кирилиця Символи для обробки
--out-dir DIR поруч із шрифтом Папка виводу
--no-ufo Не записувати UFO 3-шрифт
--no-svg Не записувати SVG для кожного гліфа окремо
--no-hershey Не записувати Hershey SVG-шрифт

Результат (у папці fonts/<НазваШрифту>_centerline/):

  • <НазваШрифту>_centerline.svg — Hershey SVG-шрифт для text_to_gcode.py і Inkscape Hershey Text
  • <НазваШрифту>_centerline_specimen.svg — зведений огляд усіх гліфів
  • <НазваШрифту>_centerline.ufo — UFO 3-шрифт (відкривається у FontForge / RoboFont)
  • svg/ — SVG-файл для кожного гліфа окремо

Передати шрифт у text_to_gcode.py:

python text_to_gcode.py poem.txt --font fonts/myfont_centerline/myfont_centerline.svg

В Inkscape Hershey Text: Extensions → Text → Hershey Text → Font face: Other → вказати повний шлях до .svg-файлу.


Примітки

  • Це не інструмент для AxiDraw — axicli несумісний з DrawCore/GRBL-обладнанням.
  • plot.py тримає 128-байтний GRBL-буфер постійно заповненим → плавний рух з постійною швидкістю. bCNC надсилає команди по одній, через що плотер гальмує і смикається між ходами.
  • SVG має вісь Y вниз, GRBL — вгору; vertical_flip = true у профілі vpype компенсує це автоматично.

About

Набір Python-утиліт для керування пен-плотером на базі GRBL з текстових файлів. Повна підтримка кирилиці (українська мова).

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages