Как стать автором
Обновить
390.96
FirstVDS
Виртуальные серверы в ДЦ в Москве и Амстердаме

Удалённый мониторинг 3D-принтера. Рассуждаем

Время на прочтение7 мин
Количество просмотров5.9K
Картинка: Mitch, r/3Dprinting

Так как я уже некоторое время являюсь владельцем 3D-принтера, меня всё чаще стала посещать интересная мысль: а ведь было бы очень полезно поставить систему на печать и удалённо её мониторить. Уверен, что эта идея терзала многих. Давайте порассуждаем, как этот вопрос можно было бы решить.

Тут следует сделать небольшое отступление и сказать вот что:

  • Мой 3d-принтер (AnycubicKossell Linear Plus) обладает встроенным портом UART, который позволяет много чего и сразу, но это же не так интересно! Гораздо интереснее было бы разработать некое универсальное решение, не привязанное к конкретному принтеру и его аппаратным особенностям.
  • Базируясь на собранном материале и проведённых экспериментах — создать своё решение вполне возможно. Остаётся только написать непосредственно сам код, который будет общаться с принтером. Однако, это удовольствие я решил оставить для вас. Напрягаться одному мне неохота :) К тому же — задача достаточно интересна сама по себе, что позволит вам прочувствовать сопричастность к классному проекту.

Это, как говорится, «была преамбула, а теперь начинается амбула».

Так как большинство принтеров соединяется с компьютером через USB, то мне видится достаточно разумным шагом использовать именно этот канал связи для создания универсальной системы мониторинга телеметрии принтера. Этот способ также хорош тем, что он не привязан к особенностям устройства принтера. USB, похоже, есть почти у всех, если не у всех.

Для начала постараемся дать полное определение самой задачи: необходимо мониторить телеметрию принтера удалённо, желательно не находясь с принтером даже в одной квартире (например, как часто бывает у меня — пошёл бегать рядом с домом в небольшом парке, а принтер оставил на печать. Да, «Риск — моё второе имя!», но, тем не менее — было бы интересно мониторить в процессе бега, что же там происходит).

Таким образом, понятно, что необходимо некое устройство, которое будет общаться с принтером и являться для него ведущим, так называемым USB-хостом. Он, в свою очередь, будет посылать на принтер соответствующие команды, на которые принтер будет отвечать и посылать в ответ телеметрию.

Теоретически, если «совсем-пресовсем» заморочиться, то можно изменить саму прошивку принтера таким образом, чтобы она выполняла, в том числе и функции USB-хоста, то есть ведущего устройства, а мы бы подключались в качестве ведомого. Однако я посчитал, что это задача будет чересчур замороченной, и решил её пока отложить.

Почему я так много говорю о USB-хосте и USB-клиенте? Всё это определено спецификациями USB-протокола, в рамках которого между собой общаются только ведущее и ведомые устройства. Таким образом, мы будем видоизменять подключённое к 3D-принтеру устройство, которое превратится в USB-хост, а принтер мы трогать не будем.

Процесс погружения в эту тему привёл меня к пониманию следующих вещей. Если мы используем Arduino USB Host Shield и будем строить своё устройство на базе платы Arduino — можно реализовать аппаратный USB-хост:

image
Картинка: docs.arduino.cc

Это аппаратное устройство позволяет превратить Arduino в USB-хост и подключать к нему любые HID-устройства (джойстики, мыши, клавиатуры) и много чего ещё — внешние накопители и т. д.

Всё это, конечно, очень интересно, но было бы гораздо лучше, если бы оно было в рамках того же ТРИЗа — «чтобы само устройство отсутствовало, а его функция — выполнялась».

И я стал искать некий программный USB-хост. Как выяснилось, подобного добра совсем негусто. Например, имеется USB-хост для Arduino Due, предоставляющий следующий API для общения с устройствами:

General

  • Task()

MouseController

  • mouseMoved()
  • mouseDragged()
  • mousePressed()
  • mouseReleased()
  • getXChange()
  • getYChange()
  • getButton()

Keyboard Controller

  • KeyboardController
  • keyPressed()
  • keyReleased()
  • getModifiers()
  • getKey()
  • getOemKey()

Где, например, Task() — это функция опроса подключённых устройств, по поводу их статуса:

#include <MouseController.h>

// Initialize USB Controller                                           
USBHost usb;

// Attach mouse controller to USB                                           
MouseController mouse(usb);

void setup(){
  Serial.begin(9600);
}

void loop(){
  usb.Task();
}

Так как Arduino Due — не слишком широко распространённая вещь (по сравнению с той же самой Uno, на основе которой построено много чего), то нельзя назвать это решение удачным выбором.

И тут я наткнулся на одну замечательную вещь, которая была разработана Дмитрием Самсоновым — чистый софтовый USB-хост, работающий через стандартные GPIO-выходы esp32 и поддерживающий до 4х устройств одновременно.

На базе этой библиотеки и уже другим разработчикам была создана библиотека-надстройка, с использованием операционной системы реального времени freeRTOS, демонстрационный пример которой выводит характеристики подключённого устройства:

Код примера
static void my_USB_DetectCB( uint8_t usbNum, void * dev )
{
  sDevDesc *device = (sDevDesc*)dev;
  printf("New device detected on USB#%d\n", usbNum);
  printf("desc.bcdUSB             = 0x%04x\n", device->bcdUSB);
  printf("desc.bDeviceClass       = 0x%02x\n", device->bDeviceClass);
  printf("desc.bDeviceSubClass    = 0x%02x\n", device->bDeviceSubClass);
  printf("desc.bDeviceProtocol    = 0x%02x\n", device->bDeviceProtocol);
  printf("desc.bMaxPacketSize0    = 0x%02x\n", device->bMaxPacketSize0);
  printf("desc.idVendor           = 0x%04x\n", device->idVendor);
  printf("desc.idProduct          = 0x%04x\n", device->idProduct);
  printf("desc.bcdDevice          = 0x%04x\n", device->bcdDevice);
  printf("desc.iManufacturer      = 0x%02x\n", device->iManufacturer);
  printf("desc.iProduct           = 0x%02x\n", device->iProduct);
  printf("desc.iSerialNumber      = 0x%02x\n", device->iSerialNumber);
  printf("desc.bNumConfigurations = 0x%02x\n", device->bNumConfigurations);
  // if( device->iProduct == mySupportedIdProduct && device->iManufacturer == mySupportedManufacturer ) {
  //   myListenUSBPort = usbNum;
  // }
}


static void my_USB_PrintCB(uint8_t usbNum, uint8_t byte_depth, uint8_t* data, uint8_t data_len)
{
  // if( myListenUSBPort != usbNum ) return;
  printf("in: ");
  for(int k=0;k<data_len;k++) {
    printf("0x%02x ", data[k] );
  }
  printf("\n");
}

usb_pins_config_t USB_Pins_Config =
{
  DP_P0, DM_P0,
  DP_P1, DM_P1,
  DP_P2, DM_P2,
  DP_P3, DM_P3
};


void setup()
{

  Serial.begin(115200);
  delay(200);
  Serial.printf("USB Soft Host Test for %s\n", PROFILE_NAME );
  delay(1000);

  USH.init( USB_Pins_Config, my_USB_DetectCB, my_USB_PrintCB );

}

void loop()
{
  vTaskDelete(NULL);
}


В принципе, это уже достаточно интересно, так как использование esp32 позволяет в полной мере реализовать удалённый мониторинг, не находясь непосредственно рядом с принтером.
Но что же сама компания Espressif — неужели у неё нет никакого решения для этого вопроса? Есть.

Полноценный API USB-хоста расположен здесь.

Однако, библиотека, предоставляемая компанией, даёт возможности не только использовать относительно высокоуровневые функции API, но и спускаться на более низкие уровни, если того требуют ресурсы/задержки.

Характеристики библиотеки приведены на картинке ниже.


Картинка: docs.espressif.com

Единственный минус этого решения заключается в том, что это API среды разработки ESP-IDF (Espressif IoT Development Framework). Например, я привык работать в Arduino IDE, и поэтому мне было неудобно, но вам, может, и «зайдёт» :).

А плюс, безусловно, в том, что всё очень хорошо документировано и собрано в одном месте.

То есть, вам придётся установить фирменную среду разработки от Espressif и работать в ней, и тогда вам станут доступны все функции её API. Но есть и лайфхак — эта среда в качестве модуля может быть встроена и в стандартную Arduino IDE! Как именно — написано тут.

Отправка команд на принтер


Теперь, когда нам более-менее понятно, каким образом в этом процессе USB-обмена сделать нашу подключаемую плату esp32 главной, нам, собственно, необходимо каким-то образом отдавать команды принтеру, чтобы он возвращал нам свою телеметрию.

Поначалу я даже хотел приспособить некое своё решение, но вовремя вспомнил, что в комплекте с моим принтером, который прошит прошивкой Marlin, шла стандартная программа для калибровки печатного стола, и через эту программу можно было отдавать текстовые команды в виде g-код команд (парковка головки и т.д.), то есть прошивка уже поддерживает отправку отчётов при поступлении запроса.

Так как прошивка Marlin является достаточно распространённой, итоговые решения будут интересными для очень широкого круга людей.

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

Отправку команд я протестировал через стандартный монитор порта Arduino IDE, настроив его следующим образом:



Например, можно запросить отчёт о текущей температуре:



Или отправить команду, которая позволит получать отчёт о текущем статусе печати с флешки, например, каждые 4 секунды:



ОК, с этим всё понятно — отправляя подобные команды на принтер, в ответ мы получаем отчёт в текстовом виде, из которого нам следует только спарсить необходимые нам числа.

К слову, команды отправляются в ASCII-формате и поэтому, если требуется отправить команду G28 («парковка головки»), в коде Arduino IDE это будет выглядеть как-то так (шлём коды из ASCII-таблицы + байт перевода строки LF (10) (почитать про него можно тут)):

Serial.write (71);      
Serial.write (50);  
Serial.write (56);
Serial.write (10);

Однако, возможно, потребуется учесть и ещё один нюанс — необходимость соединения USB-хоста и USB клиента с использованием OTG кабеля. Вполне вероятно, этот пункт и не понадобится, но знать о нём следует.

Подобный кабель в принципе можно и купить, он не является редкостью, однако вполне может быть изготовлен и самостоятельно.

Для этого всего лишь необходимо соединить на стороне мини USB разъёма четвёртый и пятый контакты, как рассказано здесь.

image
Картинка: pikabu.ru

Ну вот, допустим, отчёт уже имеется у нас на руках, и мы спарсили из него все необходимые значения.

После этого у нас останется нерешённым только последний вопрос — каким образом информировать человека о состоянии печати?

Для этого просто запрашивается отправка этих значений на MQTT-брокер, с которого эти значения впоследствии будут прочитаны приложением на смартфоне.

В качестве кода для отправки сообщений на MQTT-брокер, можно использовать следующий код из примера по ссылке. Там же подробно рассказано (и показано), что такое MQTT брокер.

В качестве примера приложения, которое мониторит соответствующий топик/топики брокера, я обычно пользуюсь MQTT Dash, хотя подойдёт и любое аналогичное.

Таким образом, на выходе должна получиться достаточно интересная вещь: плата esp32 с небольшим USB кабелем, который может подключаться к абсолютно любому 3D-принтеру и мониторить состояние его печати удалённо.

На самом деле, как вы могли видеть по ссылке выше, этих команд, которые могут отправляться на принтер — достаточно много, поэтому работа с принтером не ограничивается только мониторингом его состояния. Можно вполне попытаться реализовать и полноценное удалённое управление. Мне не кажется это излишним, а скорее даже, наоборот это необходимый элемент, если уж решили браться за реализацию всего этого.

Вот примерно такие мысли у меня по этому поводу. Надеюсь, кому-то будет интересно продолжить мои исследования и дописать код общения с принтером.


НЛО прилетело и оставило здесь промокод для читателей нашего блога:

15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.
Теги:
Хабы:
Всего голосов 11: ↑11 и ↓0+11
Комментарии9

Публикации

Информация

Сайт
firstvds.ru
Дата регистрации
Дата основания
Численность
51–100 человек
Местоположение
Россия
Представитель
FirstJohn