Programming, robotics, traveling

21 Sep 2021

CNCjs + ESP-Link


Навигация по проекту:

  1. Покупка и разбор фрезерного станка Cutmaster CM-1500
  2. Модернизация Cutmaster CM-1500
  3. Установка и настройка Grbl
  4. CNCjs + ESP-Link
  5. Grbl + ESC & Brushless motor

Зачем нужен CNCjs?

После замены компьютера на котором был Mach3 на Arduino, у станка не стало оконного интерфейса, взамен появился UART-интерфейс способный исполнять gcode-команды. Однако использовать терминал для управления станком не удобно. Нужен какой-то интерфейс, который позволит выполнять ручное управление станком (как пультом), а также позволит производить запуск управляющих программ.

Дополнительный фактором, который для меня был критичен – я не хотел запускать программу для управления станком локально, а хотел использовать веб-приложение запускаемое на стороне станка. К которому я подключался бы через Wi-Fi сеть развернутую на Raspberry Pi.

Собственно, достаточно-известных проектов предстовляющих веб-интерфейс для управления CNC машиной всего пару штук:

  1. Octoprint
  2. CNCjs

И тогда как Octoprint заточен под 3D печать, CNCjs как раз наоборот под milling / cutting machine.

image

Создание Docker образа CNCjs

Впервые я узнал о CNCjs из статьи компании Balena. Данное решение предназначено для использования в среде balenaCloud. В кратце этот сервис предоставялет экосистему состоящую из:

  • преднастроенных образов ОС для разных видов однопланных компьютеров (SBC)
  • облака с веб интерфейсом

После скачивания и установки образа, SBC автоматически подключается к облаку через выбранный вами вариант подключение к интернету. Затем с помощью облачного интерфейса можно управлять приложениями на ваших одноплатных компьютерах. Запуск нескольких приложений осуществляется с помощью немного дополненного docker-compose файла и шаблонизатора на стороне сервиса.

Я решил не использовать balenaCloud, тк собрал собственное облако. А сборку преднастроенных ОС для Raspberry Pi делаю с помощью img-builder. К сожалению в репозитории Balena не было готовой версии для arm64 и они не публикуют свои docker-образы, а также в сборке уже поломались зависимости.

Собрать CNCjs из исходников мне никак не удавалось, и я решил пойти другим путём. Тк CNCjs поставляется в виде NodeJS пакета я решил его так и установить. Однако и тут тоже возникли сложности, например я хотел использовать за основу образ Alpine, но из-за отсуствующих зависимостей удалось все завести только на Debian.

Взяв за основу Dockerfile от Balena, я сделал свою реализацию. Затем собрал образ для arm64 и выгрузил на Docker Hub.

Запускаю я своё решение через docker run тк это всего один контейнер. Для хранения настроек использую внешний docker volume. Подробнее вы можете прочитать об этом в моём репозитории.

Изначально я планировал разместить Raspberry Pi внутри станка, так и сделал. Я ожидал, что после закрытия крышки сигнал будет слабый, но достаточный для работы на расстоянии пары метров. Однако сигнал пропадал вовсе.

Было три варианта:

  1. Распаять коннектор на Raspberry Pi 3B+
  2. Использовать внешний Wi-Fi адаптер со съёмной антенной который вывести за корпус
  3. Вытащить Raspberry Pi из станка, а к Arduino подключить ESP8266 в качестве модема UART в Wi-Fi

Я выбрал 3й вариант.

С счатью задача передачи UART интерфейса по сети достаточно широко-используется. Поэтому я с легкостью нашел проект – ESP-Link.

image

У него есть как минусы:

  1. Передача gcode-команд осуществялется по воздуху и возможна как потеря команд, так и задержки при их передаче. Однако как показали тесты, проблем с этим замечено не было, тк Raspberry Pi находится буквально в метре от антенны ESP8266.
  2. Отсуствует линия DTR, а значит перепрошивка Arduino по воздуху невозможна. Хотя думаю, что в ESP-Link всё таки есть такая функция, просто я её не искал.
  3. Нужно придумать как создать виртуальный интерфейс на Raspberry Pi для работы с CNCjs.

Так и плюсы:

  1. Raspberry Pi у меня также используется в качестве роутера с сотовым модемом и сама раздает интернет и подключается в моё облако.
  2. ESP8266 с ESP-Link очень быстро загружается и подключается к Wi-Fi сети, таким образом не приходится ждать пока загрузиться ОС на Raspberry Pi.
  3. Очень упростилась отладка ввиду того, что больше не нужно проверять соединение между Arduino и Raspberry Pi. А также доступ к Raspberry Pi намного удобнее.
  4. Есть возможность использовать Raspberry Pi для подключения камеры или других устройств, например 3D принтера стоящего на столе.

Описывать прошивку и настройку ESP-Link я не стану, все достаточно легко гуглится. Единственное, покажу очень удобную для этих целей плату:

image

Виртуальный UART интерфейс

Собственно единственным реальным затыком было придумать как подключить CNCjs к сокету в который публикует байты ESP-Link. Путей два:

  1. Дописать прошивку CNCjs и добавить возможность работы с сокетами напрямую
  2. Виртуализировать UART интерфейс

Я выбрал второй путь, тк он мне представляется как более лёгкий, хоть мб и не такой изящный и правильный.

Немного погуглив, я нашел утилиту socat которая умеет делать link сокета к файлу. Можно, конечно, заморочиться и использовать напрямую nc, но в данном контексте, думаю, что socat – идеальное решение.

Изначально я планировал сделать два контейнера CNCjs и socat. Однако несмотря на то, что в linux есть файловая абстракция, мне не удалось прокинуть файл сокета из одного в контейнер в другой средствами Docker. Не найдя решения, я решил разместить оба процесса в одном контейнере.

Для управления их состоянием добавил мастер-процесс – supervisor. Однако это решение работало нестабильно и иногда после отключения станка, приходилось перезагружать весь контейнер. Ну или ставить WebUI для supervisor. А еще весь лог был переполнен, тем как socat пытается подключиться к станку, естественно у меня станок включен далеко не всегда. В итоге я решил вопсользоваться встроенные в cncjs функционалом команд.

{
    "ports": [
        {
            "comName": "/dev/tty.esplink",
            "manufacturer": "ESP LINK"
        }
    ],
    "commands": [
        {
            "title": "Start socat",
            "commands": "/usr/bin/socat pty,link=/dev/tty.esplink,raw,echo=0 tcp:${ESPLINK}"
        },
        {
            "title": "Stop socat",
            "commands": "pkill -f socat"
        },
        {
            "title": "Restart CNCjs",
            "commands": "pkill -f cncjs"
        }
    ]
}

Также я собрал Docker образ с cncjs под arm64 с предустановленным socat (репозиторий / докер образ).

Результат

  • Собственно была проделана работа по созданию своего образа с CNCjs для arm64
  • Выбрано решение для UART Wi-Fi линка
  • Добавлена реализация создания виртуального интерфейса внутри docker контейнера