Кремень FMZ Реклама
Kremen FMHM Реклама

32 бита для самых маленьких

jmz
Идет загрузка
Загрузка
18.08.2018
18623
57
Техничка

Подпишитесь на автора

Подпишитесь на автора, если вам нравятся его публикации. Тогда вы будете получать уведомления о его новых статьях.

Отписаться от уведомлений вы всегда сможете в профиле автора.

98
32 бита для самых маленьких
История о непростой дружбе Marlin 2.0 и микроконтроллера STM32F103C8T6.

Часть первая - аппаратная.

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

Ждать еще месяц не хотелось, равно как и покупать электронику по локализованным ценам, поэтому был приобретен пустой CNC shield v3, а роль UNO взяла на себя синяя таблетка - минималистичная отладочная плата с микроконтроллером STM32F103C8T6.



В процессе проектирования платы переходника аппетиты росли - ног у отладочной платы больше, чем нужно для CNC shield’а. На свободные ноги были назначены дисплей 2004, энкодер, два аналоговых входа для термисторов и четыре полевых транзистора. Потом захотелось добавить SD карту, для возможности автономной печати, но выводов микроконтроллера для такой роскоши уже не хватало. Для решения этой проблемы дисплей пришлось перевести с параллельной шины на I2C, а после заменить на I2C вариант OLED 128x64.



Конечный набор периферии выглядел так:
  • 4 шаговых двигателя с общей сигнальной линией enable
  • 3 концевых выключателя
  • 2 аналоговых входа для термисторов
  • 4 аппаратных ШИМ канала для управления 4 полевыми транзисторами или 3 транзисторами и сервоприводом
  • I2C шина для подключения OLED дисплея 12864
  • энкодер
  • SPI шина для SD карты
  • USB порт для подключения к компьютеру



Изначально планировалась выделенная линия enable для двигателя экструдера, но оказалось, что на CNC shield все линии enable сведены вместе.



После разводки получилась вот такая плата.
32 бита для самых маленьких
Ну или почти такая. Опыта нанесения паяльной маски у меня кот наплакал, поэтому без дефектов не обошлось.
32 бита для самых маленьких
Часть вторая - программная.

Первопроходцем в портировании Marlin на STM32 является Victor Perez.

Топик на reprap.org Топик на github.comДля сборки Marlin 2.0.x с HAL STM32F1 я использовал PlatformIO.

В platformio.ini было несколько вариантов для STM32 - F103RE, F407VG и некая плата Malyan M200 построенная на F103CB. Добавил новое окружение, свою MOTHERBOARD, написал к ней распиновку и запустил компиляцию.

Результат получился неожиданный - компиляция прошла на ура, а вот линковка не задалась. В минимальной конфигурации Marlin занимает больше 90КБ, а флеш памяти у F103C8 только 64КБ.

По счастью даже в даташите не всегда отражено истинное положение вещей и у имеющихся у меня F103C8 не флеш 64КБ, а очень даже 128KБ. То есть по факту у меня на руках микроконтроллер F103CB, который промаркирован и определяется как F103C8.

После замены в platformio.ini 'board = genericSTM32F103C8' на 'board = genericSTM32F103CB' линковка и прошивка прошли успешно.

Подключенная по USB плата определилась как LibMaple COM порт и Repetier Host успешно к ней подключился.

Осталась ерунда - сконфигурировать периферию и пересобрать. Какими граблями был засеян этот путь я тогда даже не догадывался.

Сразу заработали: UBS порт, шаговые двигатели, концевики, термисторы, нагреватели и энкодер. Вентиляторы включались и выключались, но, как выяснилось позже, не имели плавной регулировки оборотов.

Первая проблема была почти тривиальна - SD карта прекрасно читалась из тестовой программы, но не из Marlin.

Логический анализатор показывает, что несмотря на схожесть процедур инициализации, в SPI шину уходят совершенно разные импульсы.

Причина крылась в некорректной инициализации аппаратного SPI и линии SS (slave select) для SD карты.

Следующим был неработающий через I2C переходник дисплей LCD 2004. Логический анализатор показывал что в I2C шины данные уходят, но отклика в кремниевом сердце переходника на вызывают.

Причиной такой черствости стала банальная экономия - вместо микросхемы PCA8574 в переходнике использовалась более дешевая ее версия PCF8574, работавшая только с частотой шины 100КГц . Библиотека LiquidTWI2 такую экономию не приветствовала и инициализировала I2C шину на 400КГц. После внесения правок в LiquidTWI2.cpp дисплей заработал.

Борьба за пиксели.

На смену LCD 2004, вернувшемуся на свое законное место на передней панели моего принтера, пришел миниатюрный OLED дисплей 128x64. И на этот раз проблема была куда более серьезной - библиотека U8glib-HAL, необходимая для работы с графическими дисплеями, вызвала множественные ошибки компиляции. Адаптированная под ARM версия U8glib не дружила с stm32duinо, на котором построен весь HAL для STM32F1.

Недружила весьма серьезно: одна из ошибок компиляции была вызвана конфликтом в определении констант - одни и те же константы в stm32duino определялись через enum, а в U8glib-HAL - через #define.

Единственной платформой, на которой U8glib-HAL использовалась и компилировалась была LPC1768, но разница в устройстве HAL для STM32F1 и LPC1768 не позволяла воспользоваться кодом из LPC1768 без полной переработки HAL для STM32F1.

Высокие материи C++ никогда не были моей сильной стороной, поэтому был выбран обходной путь. Из библиотеки были надерганы файлы с функционалом, необходимым для компиляции, проблемный файл u8g_delay.c заменил u8g_delay.cpp с альтернативной реализацией u8g_Delay(), а из u8g.h были удалены все упоминания о неиспользуемых функциях.

Результатом стала успешная компиляция и до получения картинки на экране оставался всего один шаг - замена коммуникационной функции u8g_com_null_fn() на что-то более осмысленное.

Аналогичная коммуникационная функция у меня уже была в тестовом проекте, и все, что оставалось сделать, это заменить прямое обращение в аппаратной I2C периферии на вызовы библиотеки Wire.

Объем кода в этой функции пустяковый, так что уже через 15 минут экран озарился черным прямоугольником заботливо прикопанных граблей.

Верный логический анализатор показал, что управляющие команды в шину передаются, а данные - нет. Причиной тому стало переполнение буфера библиотеки Wire. U8glib передает блок в ~130 байт, а под буфер в библиотеке Wire выделено всего 32 байта. Вариантов решения было всего два - увеличить размер буфера в stm32duino до 144 байт или добавить в коммуникационную функцию проверку на переполнение буфера и отправку блока в несколько приемов. Для личного использования больше подходит первый вариант, но ручная правка библиотеки в stm32duino не самое переносимое решение.

В итоге в коде появилась константа, определяемая через #define. Если она определена - используется кусочная отправка, если нет - отправляем все и сразу, экономя на этом несколько байт лишних проверок.

Для обратного портирования кода в библиотеку U8glib-HAL все конфликтующие модули были отключены через #ifdef.
  • Для подключения обновленной библиотеки в platformio.ini нужно добавить https://github.com/jmz52/U8glib-HAL/archive/stm32duino.zip в список lib_deps.



После того, как графический дисплей заработал, настал момент переехать с макетки на полноценную печатную плату, а заодно и опробовать в деле новенькие драйвера LV8729.

Переезд прошел успешно и уровень шума от новых драйверов порадовал.

Война с таймерами и подключение сервопривода.



У F103C8 есть 4 таймера с возможностью генерации ШИМ. Еще во время использования макетной платы я заметил, что вентиляторы подключенные к ШИМ каналам таймеров 1 и 3 противно пищат, поэтому при проектировании платы управление полевыми транзисторами вентиляторов и сервоприводом было повешено на выходы таймера 4.

Какой ошибкой это было я узнал только подключив сервопривод, который, разумеется, не заработал.

В Marlin используется два таймера для генерации прерываний - STEP_TIMER для управления шаговыми двигателями и TEMP_TIMER для контроля температуры и прочих операций. На время обработки прерывания таймер останавливается, что делает невозможным использование этих таймеров для генерации ШИМ.

Для F103С8 TEMP_TIMER - это таймер 2, а STEP_TIMER - это таймер 4, на который и были повешены вентиляторы и сервопривод.

Противный писк вентиляторов, который мне так не понравился, вызван особенностью реализации analogWrite() в stm32duino. Таймеры используются с максимальным разрешением (16-бит) и без понижения частоты (prescale), а функция analogWrite() умножает 8-ми битное значение на 257, для получения 16-битного значения для генерации ШИМ.

При тактовой частоте микроконтроллера в 72 МГц, 16-ти битный таймер генерирует ШИМ с частотой 1.1 КГц. Противный писк вентиляторов был индикатором работающего аппаратного генератора ШИМ.

По счастью решить эту проблему можно было программным образом, назначив в HAL_timers_Stm32f1.h таймер 3 на роль STEP_TIMER_NUM.

Это освободило таймер 4 для генерации ШИМ, но не решило проблему с сервоприводом.

Сервопривод управляется ШИМ импульсами. Частота импульсов 50Гц, а ширина задает угол поворота сервопривода.

Инициализация сервопривода устанавливает предделитель таймера (prescaler), снижая его частоту до 50Гц. Писк вентилятора, управляемого другим каналом того же таймера сменился негромким жужжанием, из чего можно было сделать вывод, что инициализация отработала корректно. К сожалению на этом все и заканчивалось, так как код управления сервоприводом оказался нерабочим.

Код выглядит похожим на аналогичный код в HAL_TEENSY35_36, но без некоторых частей, от наличия которых зависит логика работы присутствующего кода.

Кроме этого был очередной конфликт между кодом Marlin и фреймворком stm32duino - moduleservo.h из Marlin и librariesServosrcServo.h из stm32duino используют одну и ту же константу _SERVO_H_ для исключения повторной обработки файла. Это приводит к тому, что файл из библиотеки stm32duino фактически не используется при компиляции и класс libServo, наследуемый от библиотечного класса Servo вызывает ошибку при линковке.

В итоге я переписал управление сервоприводом, убрав зависимость от библиотеки Servo и удалив весь неиспользуемый в Marlin код.

Часть третья - пробный запуск и разбор полетов.

Хотя на плате и заработала вся периферия, удачный решением ее назвать нельзя.

Список ошибок, проблем и особенностей получился немаленьким.
  • Неправильный размер отверстий для сверловки. В 0.8мм не проходят выводы большинства элементов. Почти все отверстия пришлось рассверливать до 1.0мм.
  • Отсутствует диод на входе стабилизатора 5В. При подключении USB на линии +12В оказывается ~4.9В, просочившиеся через стабилизатор в обратном направлении.
  • Отсутствует диод на входе стабилизатора 3.3В. Не является проблемой, так как сам стабилизатор не установлен - используется стабилизатор отладочной платы.
  • Отсутствуют подтягивающие резисторы на шине I2C. Не является большой проблемой, т.к. подтягивающие резисторы есть в модуле OLED дисплея.
  • Смазанные фронты на SPI шине. SD карта не проходит инициализацию, если на линиях SCK и MISO не висит по дополнительному проводу.
  • Неудачный выбор полевых транзисторов (IRL530). Высокое сопротивление в открытом состоянии не позволяет управлять нагревателем стола без использования внешнего реле. Нагреватель хотенда и вентиляторы могут подключаться непосредственно к клеммам платы. Стоит посмотреть в сторону решения ST Microelectronics - на плате STEVAL-3DP001V1 используется преобразователь логических уровней для управления полевыми транзисторами.

  • При установке драйвера A4988 линия ‘еnable’ подтягивается к земле, принудительно включая все шаговые двигатели. С драйверами LV8729 такой проблемы нет.

  • OLED дисплей должен быть подключен, иначе контроллер подвисает в процессе загрузки.
  • Кнопка “Emergency Stop” в Repetier-Host не вызывает перезагрузки контроллера и не отключает нагреватели.
  • 128КБ флеш памяти - это очень мало. Этого более-менее хватает для cartesian и coreXY кинематик, но математика для delta принтера поместится только если отказаться от идеи автономной печати.



Оргвыводы
  • Было интересно.Очень понравились драйвера LV8729.
  • Возможностей STM32F103C8T6 достаточно для построения 3d принтера.
  • Для полнофункционального контроллера 3d принтера нужно брать более серьезный микроконтроллер.
  • Плату стоит перепроектировать на два слоя и в размере 100x100мм.



Ссылки на GitHub Исходники печатной платы не выкладываю из-за большого количества ошибок в проектировании. Если кому-то понадобятся - напишите в личку.

В качестве бонуса - 32-х битный сапог Марго

32 бита для самых маленьких

Подпишитесь на автора

Подпишитесь на автора, если вам нравятся его публикации. Тогда вы будете получать уведомления о его новых статьях.

Отписаться от уведомлений вы всегда сможете в профиле автора.

98
Комментарии к статье