Автор оригинала: FreeCodeCapm Team.
Николай Хабарова
В этой статье обсуждается процесс, который я использовал для создания первого в истории реализации машинного контроллера CNC на Pure Python.
Компьютерные численные контрольные (CNC) машинные контроллеры обычно реализуются с использованием языка программирования C или C ++. Они работают на операционных системах меньше или в режиме реального времени с простыми микроконтроллерами.
В этой статье я опишу, как создать контроллер CNC – 3D-принтер, в частности – используя современные доски ARM (Raspberry Pi) с современным языком высокого уровня (Python).
Такой современный подход открывает широкий спектр вариантов интеграции с другими передовыми технологиями, решениями и инфраструктами. Это делает весь разработчик проекта.
О проекте
Современные доски ARM обычно используют Linux в качестве эталонной операционной системы. Это дает нам доступ ко всей инфраструктуре Linux со всеми программными пакетами Linux. Мы можем разместить веб-сервер на доске, используйте Bluetooth Connectivity, используйте Opencv Для распознавания изображений и построить скопление досок, среди прочего.
Это известные задачи, которые могут быть реализованы на досках ARM, и они могут быть действительно полезны для пользовательских машин с ЧПУ. Например, автоматическое позиционирование с использованием Compuvision может быть очень удобным для некоторых машин.
Linux не является операционной системой в реальном времени. Это означает, что мы не можем генерировать импульсы с необходимыми временными моментами для управления шаговыми двигателями непосредственно из контактов платы с запущенным программным обеспечением, даже в виде модуля ядра. Итак, как мы можем использовать степцы и высокоуровневые функции Linux? Мы можем использовать две чипы – один микроконтроллер с классической реализацией ЧПУ и доске ARM, подключенную к этому микроконтроллеру через UART (универсальный асинхронный приемник-передатчик).
Что если нет подходящих функций прошивки для этого микроконтроллера? Что, если нам нужно контролировать дополнительные оси, которые не реализованы в микроконтроллере? Любые модификации существующей прошивки C/C ++ потребуют много времени разработки и усилий. Посмотрим, сможем ли мы сделать это проще и даже сэкономить на микроконтроллерах, просто удаляя их.
Pycnc.
Pycnc Бесплатный открытый источник высокопроизводительный G-код переводчика G-кода и контроллером CNC/3D-принтера. Он может работать на различных лодках на основе Linux, на основе ARM, таких как Raspberry Pi, Odroid, Beaglebone и другие. Это дает вам гибкость, чтобы выбрать любую доску и использовать все, что предлагает Linux. И вы можете сохранить время выполнения G-кода на одной доске без необходимости в отдельном микроконтроллере для операции в реальном времени.
Выбор Python в качестве основного языка программирования значительно снижает базу кода по сравнению с проектами C/C ++. Он также уменьшает код Boeterplate и Microcontroller, и делает проект доступным для более широкой аудитории.
Как это работает
Проект использует DMA (прямой доступ к памяти) на аппаратном модуле чип. Он просто копирует GPIO (GPIO (общего назначения ввода ввода) буфер, выделенный в оперативной памяти в реальные регистры GPIO. Этот процесс копирования синхронизируется системными часами и работает полностью независимо от сердечников ЦП. Таким образом, последовательность импульсов для оси шагостата генерируется в память, а затем DMA точно отправляет их.
Давайте рассмотрим глубже в код, чтобы понять основы и как получить доступ к аппаратным модулям из Python.
GPIO
Модуль ввода ввода общего назначения управляет состояниями PIN. Каждый контакт может иметь низкое или высокое состояние. Когда мы программируем микроконтроллер, мы обычно используем SDK (комплект разработки программного обеспечения), определяемые переменными для записи на этот PIN-код. Например, чтобы включить высокое состояние для контактов 1 и 3:
PORTA = (1 << PIN1) | (1 << PIN3)
Если вы посмотрите в SDK, вы найдете объявление этой переменной, и она будет выглядеть как:
#define PORTA (*(volatile uint8_t *)(0x12345678))
Это просто указатель. Это не указывает на местоположение в оперативной памяти, а по адресу физического процессора. Фактический модуль GPIO расположен по этому адресу.
Чтобы управлять контактами, мы можем написать и читать данные. Процессор ARM Raspberry PI не является исключением, и он имеет тот же модуль. Чтобы контролировать контакты, мы можем написать/чтение данных. Мы можем найти адреса и структуры данных в Официальная документация Для периферийных устройств процессора.
Когда мы запускаем процесс выполнения пользователя, процесс запускается в виртуальном адресном пространстве. Фактический периферийный файл доступен напрямую. Но мы все еще можем получить доступ к реальным физическим адресам с ‘/dev/mem’ устройство.
Вот несколько простых кодов в Python, который контролирует состояние PIN, используя этот подход:
Давайте сломаемся линейкой по линии:
Линии 1-6 : заголовки, импорт.
Линия 7 : Открыть ‘/dev/mem’ Устройство доступа к физическому адресу.
Линия 8 : Мы используем mmap Системный вызов для отображения файла (хотя в нашем случае этот файл представляет физическую память) в виртуальную память процесса. Мы указываем длину и смещение области карты. В течение длины мы берем размер страницы. И смещение – 0x3f200000
Отказ
Документация говорит, что Автобус Адрес 0x7e200000
Содержит регистры GPIO, и нам нужно указать Физический адрес. Документация говорит (страница 6, пункт 1.2.3), что 0x7e000000
Адрес автобуса сопоставлен на 0x20000000
Физический адрес, но эта документация для малины 1. Обратите внимание, что все адреса шины модуля одинаковы для Raspberry Pi 1-3, но эта карта была изменена на 0x3f000000
для RPI 2 и 3. Итак, адрес здесь 0x3f200000
Отказ Для Raspberry Pi 1 измените его на 0x20200000
Отказ
После этого мы можем написать на виртуальную память нашего процесса, но на самом деле она пишет в модуль GPIO.
Линия 9 : Закройте ручку файла, так как нам не нужно хранить его.
Линии 11-14 : Мы читаем и пишу на нашу карту с 0x08
компенсировать. Согласно документации, это функция GPFEL2 GPIO Select 2 Register. И этот регистр контролирует функции PIN.
Мы устанавливаем (очистить все, затем установить с оператором) 3 бита с 3-х бита, установленным на 001
Отказ Это значение означает, что PIN-код работает как выход. Для них много булавок и возможных режимов. Вот почему реестр для режимов разделен на несколько регистров, где каждый содержит режимы для 10 контактов.
Линии 16 и 22 : Установите обработчик прерывания «Ctrl + C».
Линия 17 : бесконечная петля.
Линия 18 : Установите PIN-код на Высокий Состояние, написав в регистр GPSET0.
Обратите внимание, что Raspberry Pi не имеет регистрации, таких как Porta (микроконтроллеры AVR). Мы не можем написать все состояние GPIO всех булавок. Есть только Установить и ясно Регистрации, которые используются для установки и очистки, указанные с помощью битовой маски.
Линии 19 и 21 : задерживать
Линия 20 : Установите PIN-код в низкое состояние с регистром GPCLR0.
Линии 25 и 26 : Переключите PIN-код по умолчанию, входное состояние. Закройте карту памяти.
Этот код должен работать с привилегиями суперпользователя. Назовите файл 'gpio.py'
и запустить его с 'sudo python gpio.py'
Отказ Если у вас есть светодиод подключен к контакту 21, он будет мигать.
DMA
Прямой доступ к памяти – это специальный модуль, который предназначен для копирования блоков памяти из одной области на другую. Мы будем копировать данные из буфера памяти в модуль GPIO. Прежде всего, нам нужна прочная область в физической памяти, которая будет скопирована.
Есть несколько возможных решений:
- Мы можем создать простой драйвер ядра, который выделит, заблокируйте и сообщают нам адрес этой памяти.
- В некоторых реализациях виртуальная память выделяется и использует
'/proc/self/pagemap'
преобразовать адрес в физический. Я бы не рекомендовал этот подход, особенно когда нам нужно выделить большую область. Любая практически выделенная память (даже заблокирована, см. Документация Документация ядра ) Может быть перемещена в физическую область. - Все Raspberry Pi имеют
'/dev/vcio'
Устройство, которое является частью графического драйвера и может выделить физическую память для нас. Официальный Пример показывает, как это сделать. И мы можем использовать его вместо того, чтобы создавать нашего собственного.
Сам модуль DMA – это просто набор регистров, которые расположены где-то на физическом адресе. Мы можем контролировать этот модуль через эти регистры. По сути, есть источник, назначения и регистры управления. Давайте проверим какой-то простой код, который показывает, как использовать модули DMA для управления GPIO.
Поскольку дополнительный код требуется для выделения физической памяти с '/dev/vcio'
мы будем использовать Файл с существующей реализацией класса CMA FindMemory. Мы также будем использовать класс FindMemory, который выполняет трюк с MEMAP из предыдущего образца.
Давайте сломаемся линейкой по линии:
Линии 1-3 : заголовки, импорт.
Линии 5-6 : Константы с номером канала DMA и PIN-код GPIO, которые мы будем использовать.
Линии 8-15 : Инициализируйте указанный PIN-код GPIO в качестве вывода и зажигайте его на полторы для визуального управления. На самом деле, это то же самое, что мы сделали в предыдущем примере, написанные более питонным способом.
Линия 17 : распределяет 64
байты в физической памяти.
Линия 18 : Создает специальные структуры – блоки управления для модуля DMA. Следующие линии нарушают структуру этого блока. Каждое поле имеет длину 32
немного.
Линия 19 : передает информационные флаги. Вы можете найти полное описание каждого флага на странице 50 официальной документации.
Линия 20 : адрес источника. Этот адрес должен быть автономным адресом, поэтому мы называем get_bus_address () Отказ Блок управления DMA должен быть выровнен на 32 байтах, но размер Этот блок это 24
байты. Таким образом, у нас есть 8 байтов, которые мы используем в качестве хранения.
Линия 21 : адрес назначения. В нашем случае это адрес заданного реестра модуля GPIO.
Линия 22 : Длина коробки передач – 4
байты.
Линия 23 : шаг. Мы не используем эту функцию, набор 0
Отказ
Линия 24 : Адрес следующего блока управления, в нашем случае, следующие 32 байта.
Линия 25 : прокладка. Но так как мы использовали этот адрес в качестве источника данных, поставьте немного, что должно вызвать GPIO.
Линия 26 : прокладка.
Линии 28-37 : Заполните второй блок управления DMA. Разница в том, что мы пишем, чтобы очистить реестр GPIO и установить наш первый блок в качестве следующего блока управления для петли передачу.
Линии 38-39 : Пишите блоки управления на физическую память.
Линия 41 : Получите объект модуля DMA с выбранным каналом.
Линии 42-43 : Сбросьте модуль DMA.
Линия 44 : Укажите адрес первого блока.
Линия 45 : Запустите модуль DMA.
Линии 49-52 : убирать. Остановите модуль DMA и переключите PIN-код GPIO в состояние по умолчанию.
Давайте подключите осциллограф к указанному контакту и запустите это приложение (не забывайте о привилегиях Sudo). Мы будем наблюдать ~ 1,5 МГц квадратных импульсов:
Проблемы DMA
Есть несколько вещей, которые вы должны учитывать, прежде чем создавать реальный компьютер с ЧПУ.
Во-первых, размер буфера DMA может быть сотнями мегабайт.
Во-вторых, модуль DMA предназначен для быстрого копирования данных. Если несколько каналов DMA работают, мы можем выйти за пределы пропускной способности памяти, а буфер будет скопирован с задержками, которые могут привести к тому, что джиттеры в выходных импульсах. Итак, лучше иметь механизм синхронизации.
Чтобы преодолеть это, я создал специальный дизайн для блоков управления:
Осциллограмма в верхней части изображения показывает желаемые состояния GPIO. Блоки ниже представляют собой блоки управления DMA, которые генерируют эту форму волны. «Задержка 1» указывает длину импульсов, а «задержка 2» – длина паузы между импульсами. С помощью этого подхода размер буфера зависит только от количества импульсов.
Например, для машины с длиной перемещения 200 мм и 400 импульсов на мм каждый импульс взял бы 128 байт (4 блока управления на 32 байта), а общий размер будет ~ 9,8 МБ. У нас было бы более одной оси, но большинство импульсов произойдут одновременно. И это было бы десятки мегабайт, а не сотни.
Я решил вторую проблему, связанную с синхронизацией, введя временные задержки через блоки управления. Модуль DMA имеет специальную функцию: она может дождаться специального готового сигнала от модуля, где он пишет данные. Наиболее подходящим модулем для нас является модуль модуляции ШИМ (импульсных шириной), который также поможет нам при синхронизации.
Модуль PWM может сериализовать данные и отправлять его с фиксированной скоростью. В этом режиме он генерирует готовый сигнал для FIFO (First In, First Out) буфера модуля PWM. Итак, давайте напишем данные в модуль PWM и используйте его только для синхронизации.
По сути, нам нужно было бы включить специальный флаг в сопоставлении восприятия флага информации о передаче, а затем запустить модуль PWM с помощью нужной частоты. Реализация довольно длинная – вы можете Исследование Это сам.
Вместо этого давайте создадим какой-то простой код, который может использовать существующий модуль для генерации точных импульсов.
import rpgpio
PIN=21PINMASK = 1 << PINPULSE_LENGTH_US = 1000PULSE_DELAY_US = 1000DELAY_US = 2000 g = rpgpio.GPIO()g.init(PIN, rpgpio.GPIO.MODE_OUTPUT) dma = rpgpio.DMAGPIO()for i in range(1, 6): for i in range(0, i): dma.add_pulse(PINMASK, PULSE_LENGTH_US) dma.add_delay(PULSE_DELAY_US) dma.add_delay(DELAY_US)dma.run(True) raw_input("Press Enter to stop")dma.stop()g.init(PIN, rpgpio.GPIO.MODE_INPUT_NOPULL)
Код довольно прост, и нет необходимости разбивать его. Если вы запускаете этот код и подключите осциллограф, вы увидите:
И теперь мы можем создать реальный интерпретатор G-кода и контроль шаговых двигателей. Но ждать! Это уже реализовано здесь Отказ Вы можете использовать этот проект, так как он распространяется под лицензией MIT.
Аппаратное обеспечение
Проект Python может быть принят для ваших целей. Но для того, чтобы вдохновить вас, я опишу оригинальный аппаратный реализацию этого проекта – 3D-принтер. Он в основном содержит следующие компоненты:
- Raspberry Pi 3.
- Пандусы 1.4 доска
- 4 модуль A4988 или DRV8825
- Перепроектируйте рамку Prusa i3 с оборудованием (конечные остановки, двигатели, обогреватели и датчики)
- 12V 15A блок питания
- Модуль преобразователя DC-DC DC-DC
- Макс4420 Чип
- ADS1115 аналог модуля цифрового преобразователя
- Udma133 ленточный кабель IDE
- Акриловое стекло
- Стенды PCB
- Набор разъемов с шагом 2,54 мм
40-контактный ленточный кабель IDE подходит для разъема PI 40 Raspberry Pi 40, но противоположный конец требует некоторой работы. Отрежьте существующий разъем с противоположных концов и разъемов обжима к кабельным проводам.
Правление Rampsv1.4 была первоначально разработана для подключения к Arduino Mega Connector, поэтому нет простого способа подключения этой доски к Raspberry Pi. Следующий метод позволяет упростить подключение досок. Вам нужно будет подключиться менее 40 проводов.
Я надеюсь, что эта диаграмма подключения довольно проста и легко продумала. Лучше подключить некоторые контакты (2-й экструдер, сервопривод) для будущего использования, даже если они в настоящее время не требуются.
Вам может быть интересно – почему нам нужен чип Max4420? PI PI Raspberry PI обеспечивает 3,3 В для выходов GPIO, а контакты могут обеспечить очень маленький ток. Недостаточно для переключения MOSFET (транзистор полей эффекта эффекта эффекта полевого оксида металла). Кроме того, один из MOSFETS работает под 10А нагрузкой на утеплитель. В результате с прямым подключением к Raspberry Pi этот транзистор перегреется. Следовательно, лучше подключить специальный драйвер MOSFET между высокогруженным MOSFET и Raspberry Pi. Он может эффективным образом переключать MOSFET и уменьшить его нагрев.
ADS1115 – это аналог цифрового преобразователя (ADC). Поскольку Raspberry Pi не имеет встроенного модуля ADC, я использовал внешний для измерения температуры от термисторов 100K OHM. Модуль RAMPSV1.4 уже имеет разделитель напряжения для термисторов. Шагной преобразователь LM2596S должен быть отрегулирован до выхода 5 В, и он используется для питания самой платы PI Raspberry Pi.
Теперь он может быть установлен на кадре 3D принтера, а доски в рампах 1.4 должны быть подключены к оборудованной раме.
Вот и все. 3D-принтер собирается, и вы можете скопировать исходный код в Raspberry Pi и запустить его. sudo ./pycnc
Запустит его в интерактивной оболочке G-кода. sudo ./pycnc filename.gcode
Запустит файл кода G. Проверьте Готовый конфигурацию для SLIC3R Отказ
И в Это видео , вы можете увидеть, как это на самом деле работает.
Если вы нашли эту статью полезную, пожалуйста, дайте мне несколько хлопья, чтобы все больше людей видят это. Спасибо!
IoT – это все о прототипированных идеях быстро. Чтобы сделать это возможным, мы разработали Устройство , платформа с открытым исходным кодом IOT/M2M. DeviceHive обеспечивает прочный фундамент и строительные блоки для создания любого решения IOT/M2M, соединяя разрыв между встроенным разработкой, облачными платформами, большими данными и клиентскими приложениями.