Очень давно хотелось сделать какой-нибудь проект на Ardoino, да такой, чтобы всё в нём двигалось и работало. И, спустя пару месяцев проектирования, программирования и сборки получился вот такой мини-принтер, с помощью которого можно печатать разнообразные картинки и текст на самых обычных стикерах. Если после просмотра видео Вы загорелись необъятным желанием сделать нечто подобное — прошу под кат.
Что нам понадобится
- Arduino Uno. Для этого проекта я использовал оригинальную итальянскую плату Arduino Uno. Не произойдет совершенно ничего страшного, если в этом проекте использовать её китайский аналог, который будет стоить в несколько раз дешевле.
- Сервоприводы sg-90 — 3 штуки. Это самые дешёвые и маленькие сервоприводы из ныне существующих.
- Любой стержень. Я использовал для этого алюминиевый пруток 5 мм, который можно купить в любом строительном магазине
- Клей. В этом проекте я использовал 3 вида клея: столярный для фанеры, супер-клей для соединения шестерней с осями, также мне понадобился термический клей для крепления сервоприводов. Можно так сильно не запариваться и собрать все на какой-нибудь универсальный клей «Момент».
- Наждачная бумага. Даже при очень точном изготовлении деталей им потребуется подгонка, поэтому без шлифовки — никуда.
- Станок для лазерной резки(опционально). Если за Вас все детали сделает машина — это хорошо, но вполне реально сделать этот проект дома на коленке, используя обычный ручной лобзик. Первую версию принтера я делал именно так.
- Фломастер. Можно использовать несколько фломастеров для печати цветных картинок
- Пружинка и оси с маленьким диаметром. Для этого идеально подойдет «щелкающая» ручка, из которой можно достать пружинку и использовать её стержень в качестве оси
- Фанера 4 мм. Можно найти в строительном или хобби-магазине. Возможно, подойдут и другие варианты, например, оргстекло.
- Чертежи. Ссылки на них я оставлю здесь:
Собственно реализация
Изготовление деталей
Этот этап зависит от вашего желания и ваших возможностей. Можете вырезать на станке или выпиливать все детали вручную. Главное, что здесь надо отметить — это то, что качество и работоспособность этого проекта напрямую будет зависеть от вашей аккуратности. Также надо учитывать такой момент: некоторые детали, которые Вы увидите на фотографиях могут немного отличаться от тех, что будут на чертежах.
Самое сложное здесь — это пазо-шиповое соединение деталей и изготовление шестеренок.
Алгоритм здесь такой. распечатываете чертежи, наклеиваете их на фанеру. Затем сверлите все необходимые отверстия в местах внутренних контуров. Контуры пазов следует выпиливать, отступая немного места внутрь, чтобы потом шипы (после небольшой обработка надфилем) вошли в них внатяг. После этого выпиливаем внутренние контуры, отрываем/сошкуриваем бумагу, которую наклеили и шлифуем. Ничего сложного в этом нет, главное — работать аккуратно и не торопиться.
Чтобы этот текст не казался таким сухим, разбавлю его этапами изготовления шестеренки:
Собираем боковые стенки
Пока всё просто: берете детали и склеиваете их. Следите за перпендикулярностью и за тем, чтобы на деталях не оставалось лишнего клея.
Приклеиваем ножки к основанию
Эти ножки представляют только эстетическую ценность. Если вы хотите сэкономить немного времени, то этот этап можно пропустить
Собираем корпус воедино
Текст на передней и задней табличках можете изменить на свой вкус.
Делаем площадку для бумаги
Этот этап требует особой аккуратности и тщательности выполнения работы. Особую сложность представляют «Г»-образные рельсы, на которых и будет держаться вся эта площадка.
Вам нужно аккуратно приклеить тонкие полоски точно по рискам, указанным в чертеже. Для лучшего эффекта я использовал такие необычные «прищепки», но можно спокойно обойтись и без них. Главное — убрать лишний клей и следить за тем, чтобы полоски никуда не съехали. Дальше на них сверху приклеиваем полоски пошире — технология здесь такая же.
После того, как клей высохнет (минимум 20 минут), попробуйте вставить площадку в корпус. Если она зайдет туда, как по маслу и сможет совершать четкие движения вперед-назад, то вам сильно повезло — это именно то, что надо. В противном случае — берём в руки наждачную бумагу и шкурим те места рельсов площадки, на которых она у нас клинит.
С приклеиванием зубчатых реек проблем быть не должно. Следите за тем, чтобы они приклеились перпендикулярно.
Переходим к сборке механизма, удерживающего бумагу. Проблемы не должны возникнуть если собирать всё в такой последовательности. Сначала приклеиваем стойки, на них закрепляем рычажки. Потом к ним приклеиваем полоску фанеры, которая будет удерживать лис бумаги. А уже потом приклеиваем ту часть, в которую будут упираться пружинки.
Если всё было сделано правильно, то Ваш принтер должен выглядеть примерно вот так:
Протяжный механизм
Вот мы наконец и добрались до шестеренок… Их нужно просто насадить на заранее подготовленный стержень длиной около 110 мм так, как показано на фото ниже и приклеить на супер-клей (его надо наносить равномерно на стенки центрового отверстия шестеренки). Следите за тем, чтобы зубья шестеренок подходили к зубчатой рейке.
После того, как клей высохнет, попробуйте аккуратно прокрутить стержень — площадка должна двигаться.
Устанавливаем первый сервопривод
Первым делом нужно подготовить шестеренку для моторчика. В комплекте с каждым серво идет несколько пластиковых качелек. Их надо обрезать и обточить так, как показано на рисунке ниже. А затем вклеить её в шестерню.
А теперь переходим к установке привода. Для начала задвиньте площадку для бумаги до конца в принтер и прокрутите Ваш серво против часовой стрелки до упора. Затем надо подобрать оптимальное положение привода, то есть закрепить сервопривод так, чтобы у шестеренок не было больших люфтов, но при этом они не упирались друг в друга.
А теперь можно проверить, всё ли у нас работает. Для этого подключите серво к Вашему Arduino через pin9 и загрузите скетч из Образцов: Servo > Sweep. Его код я, на всякий случай, привожу ниже.
#include <Servo.h> #define MIN_ANGLE 0 #define MAX_ANGLE 180 Servo servo; void setup() { servo.attach(9); } void loop() { for(int i=MIN_ANGLE; i<=MAX_ANGLE; ++i) { servo.write(i); delay(15); } for(int i=MAX_ANGLE; i>=MIN_ANGLE; --i) { servo.write(i); delay(15); } }
Если всё заработало — замечательно. Если нет — попробуйте поменять положение привода или значения MIN_ANGLE и MAX_ANGLE в коде.
Устанавливаем второй сервопривод
Здесь всё делается аналогично с первым мотором. Единственное отличие — понадобится небольшая ось длиной ~12 мм, чтобы закрепить две шестерни.
Ставим печатающую каретку
Если Вы сумели добраться до этого этапа, то особых трудностей у вас здесь быть не должно. Самое сложное здесь — аккуратно собрать каретку(чтобы она не болталась и не клинила), возможно, придется поработать наждачной бумагой. Следующая возможная проблема — неправильно приклеенная зубчатая рейка. Она должна идти строго параллельно основанию корпуса, клеить ее лучше, когда каретка находится в самом дальнем от сервопривода положении.
Проверяем эту сборку с помощью Arduino и вышеупомянутого скетча, если всё работает, как надо, то переходи к следующему этапу. Если нет, то проблема скорее всего связана с шестеренками или неправильно приклеенной зубчатой рейкой.
Последний сервопривод
На этом этапе собираем рычажок для фломастера. Нужно суметь просверлить сбоку отверстие для шурупа, которым мы будем поджимать винт. Постарайтесь, чтобы в состоянии, когда фломастер опущен, серво имел положение 90 градусов, тогда Вам не придется делать лишних исправлений в коде.
После установки мотора наш принтер будет уже почти готов. Рекомендую заклеить поверхность площадки для бумаги малярным скотчем, в процессе отладки принтера она может серьёзно испачкаться.
Первый запуск и отладка
Для начала мы подключаем серво к нашему Arduino Uno, не обязательно на данном этапе помещать его внутрь принтера, так будет неудобно работать. Первый мотор подключаем к pin2, второй — к pin4, третий — к pin6. Далее загружаем вот этот скетч (весь код я постарался подробно и понятно закомментировать, сильно в его подрробности вдаваться не буду):
#include <Servo.h> /* * MiniPrinter * Designed in May 2015 * By Alexandrow Yegor */ //Структура мотора, хранящая диапазон допустимых углов и экземпляр класса Servo struct Motor { int min_angle, max_angle; Servo servo; }; #define IMG_W 64 //Ширина изображения #define IMG_H 64 //Высота изображения int STEP = 2; //Градус поворота серво на 1 пиксель #define IDLING_MS 4 // Время, тербующееся на поворот в 1 градус #define WRITING_MS 8 struct Motor motor_x, motor_y, motor_p; byte img[IMG_W/8]; //Изображение передается построчно //Один пиксель = один бит struct Motor newMotor(int pin, int a1, int a2) { //Инициализация мотора struct Motor m; m.servo.attach(pin); m.min_angle = a1; m.max_angle = a2; return m; } void gotoStart() { motor_p.servo.write(motor_p.max_angle); //Поднятие фломастера delay(15); //Перемещение в точку (0; 0) motor_x.servo.write(motor_x.min_angle); motor_y.servo.write(motor_y.min_angle); delay(IDLING_MS * STEP * IMG_W + 150); } void finish() { //Закрыть принтер motor_p.servo.write(motor_p.max_angle); delay(15); motor_x.servo.write(motor_x.min_angle); motor_y.servo.write(motor_y.max_angle); delay(IDLING_MS * STEP * IMG_W + 150); } void setup() { //Инициализация Serial.begin(9600); motor_y = newMotor(2, 50, 180); motor_x = newMotor(4, 30, 160); motor_p = newMotor(6, 90, 99); gotoStart(); } //Проверяет, есть ли в строке черные пиксели, которые еще не были напечатаны boolean nextWayIsEmpty(int i) { for(; i<IMG_W; ++i) { if(!(img[i/8] & (1 << 7-(i%8)))) continue; else return false; } return true; } void printImg() { gotoStart(); int x = 0; for(int y=0; y<IMG_H; ++y) { for(int i=0; i<IMG_W/8; ++i) img[i] = Serial.read(); Serial.write(61);//Эта команда означает, что принтер принял строку с ПК и готов принимать новую for(int i=0; i<STEP; ++i) { //Каждый пиксель на бумаге имеет длину и ширину, равную STEP motor_x.servo.write(motor_x.min_angle); //Переход на новую строку motor_y.servo.write(motor_y.min_angle + y*STEP + i); delay(IDLING_MS * STEP * x + 30); for(x=0; x<IMG_W; ++x) { if(nextWayIsEmpty(x)) { motor_p.servo.write(motor_p.max_angle); delay(IDLING_MS * (motor_p.max_angle-motor_p.min_angle)); break; } //Определяет положение фломастера(нажат/поднят), исходя из цвеа пикселя motor_p.servo.write((img[x/8] & (1 << 7-(x%8))) ? motor_p.min_angle : motor_p.max_angle); delay(IDLING_MS * (motor_p.max_angle-motor_p.min_angle)); //Продвижение печатающей каретки по оси X motor_x.servo.write(motor_x.min_angle + x*STEP); delay(((img[x/8] & (1 << 7-(x%8))) ? WRITING_MS : IDLING_MS) * STEP); } //Поднять фломастер motor_p.servo.write(motor_p.max_angle); delay(IDLING_MS * (motor_p.max_angle-motor_p.min_angle)); } //Поднять фломастер motor_p.servo.write(motor_p.max_angle); delay(IDLING_MS * (motor_p.max_angle-motor_p.min_angle)); } gotoStart(); Serial.flush(); } //Проверка входящего сообщения //ПК может отправлять на принтер команды, состоящие из двух байтов //Некоторые команды требуют дополнительных параметров void checkMessage() { if(Serial.available()) { delay(10); byte msg[] = {Serial.read(), Serial.read()}; if(msg[0] == 'P' && msg[1] == 'R') printImg(); //Печать if(msg[0] == 'S' && msg[1] == 'T') gotoStart(); //Перейти в точку (0; 0) if(msg[0] == 'C' && msg[1] == 'L') finish(); //"Закрыть принтер" if(msg[0] == 'S' && msg[1] == 'Z') STEP = Serial.read(); //Определить размер пикселя на бумаге if(msg[0] == 'P' && msg[1] == 'T') { // Определить высоту поднятия фломастера (PT+1 - на градус выше, PT-2 на 2 градуса ниже) if(Serial.read() == '+') { byte b = Serial.read(); motor_p.min_angle += b-'0'; motor_p.max_angle += b-'0'; } else { byte b = Serial.read(); motor_p.min_angle -= b-'0'; motor_p.max_angle -= b-'0'; } } } } void loop() { checkMessage(); }
Если Вы до этого момента уже протестировали и отладили все системы, то проблем быть не должно: площадка для бумаги должна слегка дернуться, а печатающая каретка должна занять крайнее левое положение. Если что-то из вышеперечисленного не доходит до краев, или, напротив, упирается в стенки, попробуйте подобрать параметры в функции setup().
Если Вы столкнулись с проблемами посерьёзнее, рекомендую перечитать внимательно весь туториал еще раз, и проверить, все ли Вы сделали правильно. А еще будет неплохо в таком случае проверить каждый моторчик еще раз с помощью первого листинга(Servo sweep).
Далее мы подключаем наш принтер к компьютеру и запускаем вот эту программу (нужна установленная java).
Сначала мы выбираем тот последовательный порт, к которому подключен принтер и нажимаем кнопку «OK», после чего принтер должен слегка подёрнуть площадкой для бумаги. Затем нажимаем кнопку «Log». У нас открылось окно терминала. Далее вводим команду CL — принтер должен задвинуть площадку внутрь. Если ввести ST, то принтер вернется в исходное положение. Также можно отправлять несколько команд подряд, например: CLSTCL. Главное не использовать пробелов и других символов между командами.
Если с эти справились, идём дальше — устанавливаем рычажок с фломастером. Для начала закрепим фломастер на рычаге. расстояние от его кончика до нижней грани рычага должно составлять около 25 мм. После чего нужно вкрутить шуруп так, чтобы фломастер закрепился и никуда не делся. Теперь просто надеваем этот рычаг на ось сервопривода — расстояние от кончика фломастера до бумаги должно составлять около 7 мм. Более точно высоту можно отрегулировать с помощью команд PT+1 и PT-1. Они регулируют угол подъема фломастера, вместо 1 может быть любое число от 0 до 9.
А теперь настал самый ответственный момент — печать первого рисунка. Маленькие картинки разрешения 64×64 подходят лучше всего. Я рекомендую использовать вот этого Марио:
Сначала нужно открыть изображение:
С помощью ползунков справа можно настроить контрастность изображения на свой вкус. Стоит помнить, что чем больше чёрных пикселей — тем дольше будет печататься картинка.
Это всё. Потом Вы просто нажимаете кнопку «Print» и любуетесь тем, как работает ваше творение. Единственная возможная проблема на этом этапе — нажатия фломастера. Он будет либо давить слишком сильно, либо не давить совсем. Помимо управления высотой фломастера через терминал, можно попробовать подстроить высоту вручную.
Также вы можете на свой страх и риск поменять значения глобальных переменных в скетче: поиграть со скоростью и размерами печати.
Как только вы будете довольны качеством получаемой картинки, можете смело помещать Arduino в корпус принтера, прикрутив её винтами — на этом Ваш проект можно считать завершенным, можете хвастаться им перед всеми друзьями!
Заключение
На этом всё, надеюсь, вам был интересен этот проект. В нём, конечно есть свои недостатки особенности реализации, так что ещё есть куда стремиться, что совершенствовать и что развивать. Буду рад любым советам, вопросам и пожеланиям в комментариях.
ссылка на оригинал статьи http://geektimes.ru/post/262098/
Добавить комментарий