Рисовалка на основе 2-ух DVD-ROM

gumeldiman
Offline
Зарегистрирован: 05.02.2020

Привет всем!

Хочу поделится опытом в создании одной забавной штуки:

 

Это мини ЧПУ-шка для рисования чего либо. Отлично подойдет в качестве демонстрации возможностей Arduino, работы шаговых двигателей и сервопривода.

Вот ссылка на ВИДЕО работы данного устройства.

 

Для изготовления вам понадобятся:

- привод DVD-ROM * 2 шт

- ARDUINO UNO * 1 шт

- мотор-шилд l293d * 1 шт

- серво привод * 1 шт

- А также ваша фантазия + всякая всячина ;)

 

Вариантов исполнения подобных рисовалок в сети множество, но я выбрал свой нестандартный путь.

Самое сложное было реализовать механическую часть. За перемещение карандаша отвечают приводы от старых DVD-ROM'ов:

С приводами все более-менее понятно, один отвечает за перемещение по оси X, второй за перемещение по оси Y. Реализация в исполнении, не должна вызвать трудностей. Самое сложное для меня было придумать механизм для поднятия и опускания карандаша. Сгодился старый телефон - слайдер:

Ну а дальше все собрал на куске ЛДСП, каких-то уголках и прочего. С обратной стороны закрепил Ардуину, в нее воткнул шилд, соединил проводами 

Вид поделки с обратной стороны:

И начал придумывать код. Ну как придумывать, сначала смотрел у других, разбирался в синтаксисе языка и т.д. Сначала научился крутить серво привод, потом пробовал шагать шаговыми движками. Шагать движками было несложно, но шагали они у меня отдельно друг от друга, а нужно было делать это параллельно. Помогли библиотеки. В этих библиотеках все реализовано, главное уметь правильно ими воспользоваться.

Изучая скетчи подобных рисовалок, зачастую люди писали трехэтажный код, в котором чёрт ногу сломает.. А я люблю когда код очень маленький и при этом все работает как надо. Правда я немного схитрил. Хитрость заключается в том, что на Ардуинку подается лишь нужная (готовая) информация, и она просто выполняет определенную работу. При этом с компьютером происходит некий "диалог". Компьютер говорит, - езжай туда-то. Рисовалка читает эту информацию, анализирует, выполняет и в ответ сообщает компьютеру, - готово, чё делать дальше? И компьютер выдает очередную координату. И так по кругу, до тех пор, пока не закончится рисунок. 

Собственно вот мой скетч:

/////////////////////////////////////////////////////////////.//////////////////////////////////////////////////
///                                                                                                          ///
///    Рисовалка собрана на базе двух DVD, микросервы и управлется мотор-шилдом l293d во главе Arduino UNO   ///
///                                                                                                          ///
///    Управление рисовалкой осуществляется через терминальное приложение, написанное на Delphi,             ///
///    данные поступают в виде текстовых строк в следующем формате:                                          ///
///    X100 - означает, что следущая координата X будет 100                                                  ///
///    Y200 - означает, что следущая координата Y будет 200                                                  ///
///    если в строке присутствет "-" (минус), координата будет отрицательной                                 ///
///    M - говорит о пуске двигателей, для перемещения карандаша                                             ///
///    U - поднять карандаш (холостой ход)                                                                   ///
///    D - опустить карандаш (рабочий ход)                                                                   ///
///    допускается использовать M, U, D d в одной строке с координатами, например                            ///
///    Y300DM - задаст координату Y, опустит карандаш и поедет в X,Y                                         ///
///    по завершении хода, в ком-порт отправляется "OK" - что говорит о готовности рисовалки                 ///
///    принять новые строки с информацией                                                                    ///
///                                                                                                          ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <AFMotor.h>
#include <AccelStepper.h>
#include <MultiStepper.h>
#include <Servo.h>

char STEP = SINGLE; // будем юзать этот способ "шагания"
//char STEP = DOUBLE;
//char STEP = INTERLEAVE;
//char STEP = MICROSTEP;

const int penZUp = 60;        // угол сервы для холостого хода
const int penZDown = 120;     // угол сервы для рабочего положения карандаша
const int penServoPin = 9;    // пин сервы
const int penDownDelay = 750; // время на опускание крандаша
const int penUpDelay = 250;   // время на поднятие крандаша
const int SpeedMotor = 150;   // скорость моторов

AF_Stepper motor1(20, 2); // мотор X, подключенный через мотор-шилд l293d
AF_Stepper motor2(20, 1); // мотор Y, подключенный через мотор-шилд l293d

void forwardstepX () { motor1.onestep(FORWARD,  STEP); } // такая заморока чтоб управлять моторами через AccelStepper
void backwardstepX() { motor1.onestep(BACKWARD, STEP); } // такая заморока чтоб управлять моторами через AccelStepper
void forwardstepY () { motor2.onestep(FORWARD,  STEP); } // такая заморока чтоб управлять моторами через AccelStepper
void backwardstepY() { motor2.onestep(BACKWARD, STEP); } // такая заморока чтоб управлять моторами через AccelStepper

// Motor shield has two motor ports, now we'll wrap them in an AccelStepper object
AccelStepper Xaxis(forwardstepX, backwardstepX); // мотор для X
AccelStepper Yaxis(forwardstepY, backwardstepY); // мотор для Y
MultiStepper steppers; // для согласованного управления движками
Servo PenServo;  // карандашная серва

void PenUp()   { PenServo.write(penZUp); delay(penUpDelay);     } // функция поднять карандаш
void PenDown() { PenServo.write(penZDown); delay(penDownDelay); } // функция опустить карандаш

void setup() 
{
  Serial.begin(9600); // для общения с иным миром
  Xaxis.setMaxSpeed(SpeedMotor); // скорость мотора по X
  Yaxis.setMaxSpeed(SpeedMotor); // скорость мотора по Y
  steppers.addStepper(Xaxis); // добавим мотор X
  steppers.addStepper(Yaxis); // добавим мотор Y
  PenServo.attach(penServoPin);  // подключим серву
  PenUp();
  Serial.println("Hellow world");
}

char a; // текущий символ
long b, X, Y, dir = 0; // текущее целое, и координаты X и Y, направление
long positions[2]; // для хранения координат моторов
boolean isMinus, isX, isY, isMove, isDown, isUp, isStep = false; // флаги для всякого

void loop() 
{  
  while (Serial.available()) // пока поступает информация, крутим цикл (хотя и if проканает..)
    {
      a = Serial.read(); // читаем символ и смотрим что там пришло
      if (a == '-') { isMinus = true; } // вдруг минус
      if (a == 'X') { isX = true; }     // данные для X
      if (a == 'Y') { isY = true; }     // данные для Y
      if (a == 'M') { isMove = true; }  // нужно ехать
      if (a == 'D') { isDown = true; }  // нужно опустить карандаш
      if (a == 'U') { isUp = true; }    // нужно поднять карандаш
      if (a == 'd') { isStep = true; }  // ручное управление
      if (a >= 48 && a <= 57){ b *= 10; b += a - 48; } // если цифра, сей хитрый алгоритм позволяет преобразовать строку в число посимвольно (!)
      if (a == 13) // если закончилась строка, то нужно что то сделать
        {          
          if (isDown) { PenDown(); } // подготовка к рабочему ходу
          if (isUp) { PenUp(); }     // подготовка к холостому ходу          
          if (isMinus) { b = -b; }   // если был минус 
          if (isX) { X = b; }        // если X
          if (isY) { Y = b; }        // если Y
          if (isMove)                // если нужно ехать, то
            {
              Serial.println("OK"); // напишем что все ништяк (предполагаем, что терминальная прога будет ждать эту информацию, чтобы отправить следущую)              
              positions[0] = X; // укажем X
              positions[1] = Y; // укажем Y
              steppers.moveTo(positions);    // указываем новую позицию 
              steppers.runSpeedToPosition(); // включаем оба движка и едем
            }   
          if (isStep) // если ручное управление
            {
              if (b > 0) {dir = FORWARD;} else {dir = BACKWARD;} // определим направление
              if (isX) { motor1.step(1, dir, STEP); } // шагаем по X
              if (isY) { motor2.step(1, dir, STEP); } // шагаем по Y
            }
          b = 0;           // обнулим текущее значение целого
          isX = false;     // обнулим признак X
          isY = false;     // обнулим признак Y
          isMove = false;  // обнулим необходимость движения
          isMinus = false; // обнулим минус
          isDown = false;  // обнулим необходимость вниз
          isUp = false;    // обнулим необходимость вверх
          isStep = false;  // обнулим необходимость ручного управления
        }
    }
}

Конечно, ввиду того что я начинающий писака, тут могут быть косячки. Но на самом деле вроде все нормально работает. )

А вот для управления этой рисовалкой пришлось сваять терминальное приложение. Исходный код я приводить не буду, он довольно большой. Программа писалась на Delphi 7. Посмотреть исходники и саму программу для управления рисовалкой можете по этой ссылке.

Программа позволяет управлять шаговыми двигателями с помощью стрелок на клавиатуре, поднимать либо опускать карандаш нажатием на PageUp/PageDown. При первом запуске, нужно подружить прогу с рисовалкой, для чего необходимо настроить номер порта, нажав на кнопку "настройки".

Чуть не забыл про самое главное. Откуда берется графическая информация. Для работы рисовалки нужно определенным образом подготовить файл формата *.plt. Я делаю его в графическом редакторе CorelDraw (версия может быть любой). В вышеуказанной ссылке вы найдете примеры plt-файлов. Самое главное, при создании такого файла сделать верными настройки, чтобы габарит векторного рисунка не выходил за пределы рабочей области этой рисовалки. Рабочая область ограничена физическими размерами DVD привода и составляет примерно 38х38 мм. Скорее всего это 1.5х1.5 дюйма. При этом, максимальные координаты которые передаются ардуинке должны находится в пределах 0..255, именно столько полных шагов делает DVD привод чтобы переместиться от начала до конца. Конечно это грубовато, но и размер рабочей области у нас не велик.

Короче говоря, я рекомендую делать plt-файлы, открывая файл "Пустой.cdr", в нем просто изменена рабочая область с формата А4 на 38х38 мм. Ваш рисунок должен быть в векторном виде и его вы просто экспортируете в формат *.plt

ВАЖНО в настройках экспорта поменять единицы измерения плоттера на 170 точек на дюйм. (при габарите в 1.5 дюйма это как раз 255):

Далее, полученный файл вы загружаете в окно терминального приложения:

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

Остальное все должно быть интуитивно понятно.

И еще крайне важно, чтобы карандаш в рисовалке, перед запуском рисования, находился в левой нижней точке (координаты 0,0).

 

*********************

Если что-то непонятно, спрашивайте, постараюсь ответить ))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Круто!

mykaida
mykaida аватар
Онлайн
Зарегистрирован: 12.07.2018

gumeldiman пишет:

С приводами все более-менее понятно, один отвечает за перемещение по оси X, второй за перемещение по оси Y. Реализация в исполнении, не должна вызвать трудностей. Самое сложное для меня было придумать механизм для поднятия и опускания карандаша. Сгодился старый телефон - слайдер

С софтом более - менее понятно, а вот с механикой не очень. Реально интересно. ДиВиДюхи есть, руки тоже. Понятка отсутсвует... А так - круто

RG22EM
Offline
Зарегистрирован: 27.08.2016

а CD-ROM пойдёт, у меня их полвагона

-NMi-
Offline
Зарегистрирован: 20.08.2018

ТС- слушай, а можно вот с таким "дэвайсом" промерять сверхтогные детали, заменим "карандаш" на микродатчик???

gumeldiman
Offline
Зарегистрирован: 05.02.2020

mykaida пишет:

gumeldiman пишет:

С приводами все более-менее понятно, один отвечает за перемещение по оси X, второй за перемещение по оси Y. Реализация в исполнении, не должна вызвать трудностей. Самое сложное для меня было придумать механизм для поднятия и опускания карандаша. Сгодился старый телефон - слайдер

С софтом более - менее понятно, а вот с механикой не очень. Реально интересно. ДиВиДюхи есть, руки тоже. Понятка отсутсвует... А так - круто

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

Один привод, который приручен к ЛДСП двигает площадку вверх/вниз, это ось Y. Второй привод расположен вертикально и перпендикулярно первому (на стойках), этот привод двигает площадку с подъемным механизмом влево/вправо, это ось X. В свою очередь подъемный механизм управляется сервоприводом и опускает и поднимает карандаш.

А вообще, картинок то в сети полно

gumeldiman
Offline
Зарегистрирован: 05.02.2020

-NMi- пишет:

ТС- слушай, а можно вот с таким "дэвайсом" промерять сверхтогные детали, заменим "карандаш" на микродатчик???

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

gumeldiman
Offline
Зарегистрирован: 05.02.2020

RG22EM пишет:

а CD-ROM пойдёт, у меня их полвагона

Думаю, что подойдет. 

trembo
trembo аватар
Онлайн
Зарегистрирован: 08.04.2011

Как только вижу что-то подобное - сразу руки тянутся к кнопке и ставят жирный плюс!
Ведь есть же ещё специалисты кроме эффективных менеджеров!