Моя история постройки чпу-станка своими руками
Приветствую всех жителей Geektimes! Сегодня я хочу вам рассказать свою историю постройки бюджетного классического портального фрезерного станка.

Хочу начать с истории, которая началась в конце 2022 года. Встретившись тогда с другом, он предложил мне сделать фрезерный чпу-станок для раскройки фанеры и пластика. Недолго подумав, я сказал ему, что для вырезания различных слов, рамочек и прочего станок не окупит себя и станет убыточным, на что он мне ответил «придумай что-нибудь»…
Так как в основе проекта был положен интерес я, конечно же, взялся за него. Но все бы ничего, но на предложенный проект не было денег, да и свободного времени тоже. Тогда, исходя из задач, возложенных на станок, было спроектировано следующее:
В итоге на весь станок выделили 20 т.р. Рабочее поле — 550х950 мм. В качестве управления выбрал китайскую синюю плату на драйверах TB6560 на 4 оси, в комплект еще входит 4 двигателя, блок питания, диск с ПО и провод для подключения к ПК, на тот момент она обошлась мне в 14 с копейками т.р.
Так как планировалось сделать что-то вроде конструктора, и не прибегая к фрезерным, расточным, шлифовальным работам, вся конструкция изготовлялась из конструкционной листовой стали толщиной 8мм, раскроенной на лазерным ЧПУ станке. Но без токарной обработки не обошлось, так как надо точить подшипниковые опоры, втулки скольжения, обтачивать концы винтов и в этом помогла наша дочерняя фирма. И вообще то, что касается металлообработки в России, я постарался, высказать свои мысли в блоге, чтобы здесь не флудить.

Подшипниковая опора.
В итоге раскрой всех деталей к станку из металлического листа вышло в 1,5т.р., еще 2т.р. отдал за токарную обработку, остальное потратилось на крепеж, подшипники и прочие невспомненные мной моменты.
Далее хотелось бы продемонстрировать несколько видео о процессе сборки и работы станка, а также фото того, что пробовал вырезать я.
И еще один момент: в качестве шпинделя решил использовать обыкновенную дрель, ввиду невысокой скорости работы станка.

Попробовали выжигать


По итогам сборки наладки и проверки можно сказать, что станок оказался работоспособным, но достаточно «жидким», но это и так было понятно по закладываемому бюджету. И свои задачи он выполнял отлично… Станок был собран к концу февраля и окупился у друга до лета, после чего он успешно его продал за 30 т.р. Продал по причине – надоело, пропал интерес, и нежелание работать.
Я, возможно, что-то упустил и не описал, надеюсь, что на видео найдётся вся отсутствующая здесь информация. В другом же случае оставляйте комментарии.
От идеи до станка. фрезерный станок чпу своими руками
Всем привет!
Как и обещал, делаю подробный пост о создании станка с ЧПУ.
Начну с самого распространенного вопроса: а зачемчто он будет делать?
Ответ на этот вопрос не такой простой: всегда есть какие-либо детали, которые нужно сделать довольно точно и нет возможности просто распечатать их на 3d принтере. Так же иногда хочется делать самому печатные платы, быстро размечать детали. Ну и конечно же на этом можно зарабатывать 🙂 начиная от сувенирной продукции и заканчивая изготовлением деталей на заказ.
Сам процесс постройки уже затянулся на пол года, но на то были веские причины 🙂
Процесс проектирования и расчетов занял около 2 месяцев. Остановился на схеме портального фрезерного станка с подвижным столом, благо опыта расчета таких станков достаточно ( привет дипломной работе — рассчитывал стол фрезерного станка с длиной хода что-то около 4 метров, примерно как на фото).
С размерами рабочего поля определился довольно быстро: делать двери и прочую деревянную фурнитуру у меня никакого желание нет ( только металл, только хардкор).
В 80% задач габариты деталей не превышают 400х300 мм. От этого размера и был рассчитан станок.
После предварительного расчет всех передач приступил к процессу моделирования в CAD системе.
Покрутив и так и этак, остановился пока на таком решении:
А дальше началось самое интересное — превратить электронный вариант в осязаемый металлический.
На каждую деталь составил программу изготовления для станка ЧПУ из станочного алюминиевого профиля ( почему не стоит делать станки из профиля и в чем подводные камни — нужно делать отдельный пост с наглядными видео. А моое отношение к станкам из профиля хорошо отражает фото ниже ^____^ )
Готовые программы для изготовления деталей выглядят примерно так:
По поводу стружки: ее много. нет, ее даже ОЧЕНЬ МНОГО. Боевой пылесос забивался буквально за день 🙂 ох, сколько взрыв-пактов я бы сделал из этой стружки в детстве
Дальше шла самая ответственная часть — сборка. Скажу сразу, без друзей и матерных слов не обошлось, спасибо @mankxD за непосредственное участие в нарезание резьб 🙂 ну и конечно что же Маше за теплый чаек на холодном складе зимой.
Убедился, что все собирается на ура, отдал на аннодацию детали. Остановился на черном цвете, Batman меня поймет 🙂
Ну а дальше была финальная сборка механики и пайка электроники. Думаю, электронике уделить отдельный пост, ровно как и с первым запуском станка. На данном этапе он выглядит вот так.
Всем кому интересна данная тема — обращайтесь, буду рад помочь.
Будет рейтинг, буду кидать Вам всякие видосики с нюансами по эксплуатации и сборке таких машин в домашних условиях.
Всем спасибо за просмотр и хорошего дня 🙂
Приступаем к сборке оборудования
Основой самодельного фрезерного оборудования с ЧПУ может стать балка прямоугольного сечения, которую надо надежно зафиксировать на направляющих.
Несущая конструкция станка должна обладать высокой жесткостью, при ее монтаже лучше не использовать сварных соединений, а соединять все элементы нужно только при помощи винтов.
Объясняется это требование тем, что сварные швы очень плохо переносят вибрационные нагрузки, которым в обязательном порядке будет подвергаться несущая конструкция оборудования. Такие нагрузки в итоге приведут к тому, что рама станка начнет разрушаться со временем, и в ней произойдут изменения в геометрических размерах, что скажется на точности настройки оборудования и его работоспособности.
Сварные швы при монтаже рамы самодельного фрезерного станка часто провоцируют развитие люфта в его узлах, а также прогиб направляющих, образующийся при серьезных нагрузках.
Во фрезерном станке, который вы будете собирать своими руками, должен быть предусмотрен механизм, обеспечивающий перемещение рабочего инструмента в вертикальном направлении. Лучше всего использовать для этого винтовую передачу, вращение на которую будет передаваться при помощи зубчатого ремня.
Важная деталь фрезерного станка – его вертикальная ось, которую для самодельного устройства можно изготовить из алюминиевой плиты. Очень важно, чтобы размеры этой оси были точно подогнаны под габариты собираемого устройства. Если в вашем распоряжении есть муфельная печь, то изготовить вертикальную ось станка можно своими руками, отлив ее из алюминия по размерам, указанным в готовом чертеже.
После того как все комплектующие вашего самодельного фрезерного станка подготовлены, можно приступать к его сборке. Начинается данный процесс с монтажа двух шаговых электродвигателей, которые крепятся на корпус оборудования за его вертикальной осью. Один из таких электродвигателей будет отвечать за перемещение фрезерной головки в горизонтальной плоскости, а второй — за перемещение головки, соответственно, в вертикальной. После этого монтируются остальные узлы и агрегаты самодельного оборудования.
Вращение на все узлы самодельного оборудования с ЧПУ должно передаваться только посредством ременных передач. Прежде чем подключать к собранному станку систему программного управления, следует проверить его работоспособность в ручном режиме и сразу устранить все выявленные недостатки в его работе.
Посмотреть процесс сборки фрезерного станка своими руками можно на видео, которое несложно найти в интернете.
Самопальный чпу — бюджетный вариант / 3d-принтеры, станки и аксессуары / ixbt live
Самодельные ЧПУ станки — это способ получить возможность обрабатывать дома или в гараже дерево/пластик/легкие металлы. Для кого-то это способ начать свой бизнес, для кого-то это дешевый способ реализовать свое хобби.

Небольшая статья на тему о самостоятельной сборке простого ЧПУ станка.
Предыдущие посты по теме:
Комплектующие для самодельного ЧПУ с Таобао
Комплектующие для ЧПУ с Таобао
Частотный преобразователь для однофазной сети Delta VFD-M VFD015M21A
Это наверное самый простой способ собрать ЧПУ станок. И один из самых недорогих. Софт простой в освоении (достаточно закинуть файл-2D-рисунок для простейшей фрезеровки).
Стоимость самой станины не велика (профиль Соберизавод), в зависимости от размеров это от тысячи рублей для небольшого станка до нескольких тысяч для мощного профиля большого размера (с учетом уголков и метизов).
Станок не претендует на самую оптимальную конструкцию, но наверняка один из самых недорогих и простых в сборке.
Идея взята из похожего станка CNC2417

В попытках исправить косяки китайских разработчиков были переделаны боковые пластины для рамы и держатели моторов. Прикладываю ссылку на Чертежи пластин для самостоятельной сборки подобного станка (под двигатели Nema17, направляющие цилиндрические 8 мм).
Для потребуется алюминиевый профиль, фурнитура для сборки (уголки) и метизы. Размеры станка могут быть любые, в разумных пределах. Я использовал 7 отрезков по 260 мм и два на 300 мм. Длинные отрезки идут для увеличенного хода стола по Y. В результате рабочая область будет чуть больше, чем у 2418.
В каталоге Соберизавод ищем нужный тип профиля и кликаем «купить»

Режем в размер (размеры можно примерно прикинуть исходя из ваших потребностей

Нарезаем сразу нужный профиль, в нужном количестве для рамы.

Подтверждаем.

Плюс не забываем уголки и метизы для сборки. Опционально можно докупить и пластины для крепления.
В части сборки рамы все просто — свинчиваем профили с помощью уголков и закладных гаек.

Устанавливаем боковые пластины и держатели двигателей.

Далее нужно будет установить на раму остальные комплектующие.


Помимо рамы, для сборки потребуются другие комплектующие: «мозги», направляющие, ходовая часть, шпиндель, блок питания и т.п.
Большинство запчастей заказывал на площадке Таобао, так как получается дешевле при покупке комплекта (из-за одной запчасти нет смысла там заказывать, а если подбираете комплект — тогда да, удобно и выгодно).
Для доставки большой сборной посылки пользовался услугами посредника Yoybuy, воспользовался скидкой $10 для доставки (этот купон на скидку $10 то $20 дают всем вновь зарегистрированным пользователям).
В качестве платы управления используется простая МК1. Это самый бюджетный вариант с таким функционалом. Существуют «детские варианты» на Arduino Uno (Nano) CNC Shield с прошивкой GRBL, которые могут подойти для ознакомления с ЧПУ, но для серьезной работы малопригодны, хотя бы из-за ограниченных возможностей прошивки.
Купить плату управления МК1
(Не всегда ссылки корректно работают — я дублирую прямые ссылки на Таобао.)

Плата МК1 построена на основе PICmicro, имеет силовые выходы, входы для концевиков и датчика калибровки, а также возможность подключения ручного пульта управления.

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

Кстати, можно сделать ход конем, и прикупить полноценный пульт типа DDCSV — альтернативный вариант управления станком, хотя больше подходит для больших ЧПУ. Это наиболее бюджетный вариант автономного (без компьютера) управления станком, можно купить «навырост» — изготовив на маленьком станке детали для сборки большого ЧПУ фрезера. Пульт представляет собой автономный контроллер станка ЧПУ на 3 оси и имеет огромный функционал.
Ссылка на пульт DDCSV

В качестве направляющих рекомендую рельсы SBR10. Можно взять 12-16, хотя 16 мм явно будет перебор.
Размер берите исходя их ваших хотелок (размеры хода по XY). В моем случае используются простые полированные валы 8 мм, это эконом-вариант направляющих. Но рекомендую именно рельсы.
Купить рельсы SBR10-12-16-20 для станка ЧПУ.

Для обработки материалов потребуется шпиндель.
На Таобао есть неплохие варианты на 1,5кВт с воздушным охлаждением (до 24000 об/мин, диаметр 80 мм, цанга ER11, 400Гц).
Купить шпиндель 1,5 кВт

Если размер станка 2418 для вас маловат, можно собрать что-то подобное, но на раме из профиля 6060 (6090) и рельсах SBR16. Для перемещения осей потребуются мощные двигатели типа 57BYG78 (57H2P7842A4) с током до 4.2A и усилием 2.1Nm. Это как раз мощный вариант, у меня используются простые Nema17 42HS8404.
Купить шаговые двигатели 57BYG78

Для управления шпинделем потребуется частотный преобразователь (ЧП, Vector Frequency Converter — VFD для поиска).
Это устройство, вырабатывающее три фазы 220В с частотой до 400Гц и имеющее множество настраиваемых параметров.
Простой и недорогой ЧП, имеющий вход бытовой сети (220В/50Гц, одна фаза L ноль N).
Купить частотный преобразователь (однофазный)

Если размеры позволяет и есть доступ к трехфазной промышленной сети, можно выбрать вот такой недорогой ЧП.
Купить частотный преобразователь для трехфазной сети 1,5kw-5.5kw-7.5kw

По комплектующим все, многое было рассмотрено в предыдущих обзорах. При наличии некоторого навыка собирается все достаточно быстро, если опыта нет — может занять некоторое время. Если есть вопросы — спрашивайте))).
Скриншот управляющей программы для станка.

Проба хода по осям собранного станка.
В целом все, станок собирал для своего друга, он только начинает осваивать технологии с ЧПУ, и настольный вариант ему очень удобен. Профиль приобретался в компании Соберизавод, остальные комплектующие на Таобао через посредника Yoybuy. Прикинул сразу что нужно, сформировал одну большую сборную посылку. Получилось дешевле, чем покупать на Али или в оффлайне. Не забывайте про скидку — купон на $10 для доставки посылок от $20. Средняя посылка до 3 кг можно привезти за $20 с этим купоном.

Создание станка с чпу из доступных деталей с минимум слесарной работы
Продолжаем обзор деятельности нашего
Хакспейс-клуба
.
Мы давно мечтали купить в наш клуб ЧПУ станок. Но решили его сделать сами. С нуля, начиная от железа и кончая программного обеспечение (прошивка контроллера и управляющая программа). И у нас это получилось.
Детали для станка старались выбирать из доступных в свободной продаже, многие из которых даже не требуют дополнительной слесарной обработки.

Контроллер мы выбрали Arduino Mega 2560 и что бы много не думать, драйвер шаговых двигателей использовали RAMPS 1.4 (как у RepRap 3D принтера).

Программу контроллера писали по алгоритму метода конечных автоматов. Последний раз я о нем слышал лет 20 назад в институте, не помню по какому предмету изучали. Это была очень удачная идея. Код получился маленький и легко расширяемый без потери читабельности (если в дальнейшем понадобится не только оси XYZ, или использовать другой G-код). Программа контроллера принимает с USB порта G-код и, собственно, дает команду двигателям осей XYZ двигаться в заданном направлении. Кто не знает, G-код — это последовательность конструкций типа G1X10Y20Z10, которая говорит станку переместится по оси X на 10 мм, Y на 20 мм и Z на 10 мм. На самом деле, в G-коде много различных конструкций (например, G90 — используется абсолютная система координат, G91 — относительная) и много модификаций самого кода. В интернете много о нем описано.
Подробнее остановлюсь на описание скетча (прошивка контроллера).
Вначале в описании переменных прописываем, к какому выходу контроллера будет подключены двигатели и концевые выключатели.
В этом коде метода конечных автоматов переменная принимает значение ждать с USB порта первый байт, во второй конструкции case производится проверка наличия данных и переменная _s принимает значение get_cmd. Т.е считать данные с порта.
switch(_s){
case begin_cmd: Serial.println("&"); //038
//to_begin_coord();
n_t=0;
_s=wait_first_byte;
len=0;
break;
case wait_first_byte: if(Serial.available()){
Serial.print(">");
_s=get_cmd;
c_i=0;
}
break;
Далее считываем все, что есть в порту, переменная _s устанавливается в get_tag; т.е. переходим на прием буквенного значение G – кода.
case get_cmd: c=Serial.read();
if(c!=-1){
if(c=='~'){
_s=get_tag;
c_i=0;
n_t=0;
break;
}
Serial.print(c);
if((c>=97)&&(c<=122))
c-=32;
if( (c==32)||(c==45)||(c==46)||((c>=48)&&(c<=57))||((c>=65)&&(c<=90)) ){
cmd[c_i ]=c;
len ;
}
}
break;
Ну и так далее.
#include <Stepper.h>
#define STEPS 48
//#define SHAG 3.298701
#define STEP_MOTOR 1
double koefx = 1.333333;
double koefy = 1.694915;
Stepper stepper0(STEPS, 5, 4, 6, 3);
Stepper stepper1(STEPS, 8, 9, 10, 11);
Stepper stepper2(STEPS, 13, 12, 7, 2);
int x,y,x1,m;
int motor;
int inPinX = 15; // кнопка на входе 22
int inPinY = 14; // кнопка на входе 23
int inPinZ = 24; // кнопка на входе 24
int x_en = 62;
int x_dir = 48;
int x_step = 46;
int y_en = 56;
int y_dir = 61;
int y_step = 60;
const int begin_cmd=1;
const int wait_first_byte=2;
const int wait_cmd=3;
const int get_cmd=4;
const int test_cmd=5;
const int get_word=6;
const int get_tag=7;
const int get_val=8;
const int compilation_cmd=9;
const int run_cmd=10;
int abs_coord=1;
const int _X=1;
const int _Y=2;
//const int =10;
//const int =11;
//const int =12;
int _s=begin_cmd;
const int max_len_cmd=500;
char cmd[max_len_cmd];
char tag[100][20];
char val[100][20];
int n_t=0;
int c_i=0;
char c;
int i,j;
int amount_G=0;
int len=0;
char*trash;
int n_run_cmd=0;
int g_cmd_prev; //ya предыдущее значение G
class _g_cmd{
public:
_g_cmd(){
reset();
}
int n; //ya
int g;
double x;
double y;
double z;
void reset(void){
n=g=x=y=z=99999;
}
};
double _x,_y,_z;
double cur_abs_x,cur_abs_y,cur_abs_z; //ya stoyalo int
int f_abs_coord=1;
_g_cmd g_cmd[100];
void setup()
{
stepper0.setSpeed(150);
stepper1.setSpeed(150);
stepper2.setSpeed(1000);
Serial.begin(9600);
pinMode(inPinX, INPUT);
pinMode(inPinY, INPUT);
pinMode(inPinZ, INPUT);
pinMode(x_en, OUTPUT);
pinMode(x_dir, OUTPUT);
pinMode(x_step, OUTPUT);
pinMode(y_en, OUTPUT);
pinMode(y_dir, OUTPUT);
pinMode(y_step, OUTPUT);
digitalWrite(x_en, 1);
digitalWrite(y_en, 1);
to_begin_coord();
//UNIimpstep(12,13,2,7,3,1000);
//UNIimpstep(12,13,2,7,3,-1000);
}
void to_begin_coord(void)
{
impstep(_X,-10000,1);
impstep(_Y,-10000,1);
cur_abs_x=cur_abs_y=cur_abs_z=0;
}
void loop()
{
switch(_s){
case begin_cmd: Serial.println("&"); //038
//to_begin_coord();
n_t=0;
_s=wait_first_byte;
len=0;
break;
case wait_first_byte: if(Serial.available()){
Serial.print(">");
_s=get_cmd;
c_i=0;
}
break;
case get_cmd: c=Serial.read();
if(c!=-1){
if(c=='~'){
_s=get_tag;
c_i=0;
n_t=0;
break;
}
Serial.print(c);
if((c>=97)&&(c<=122))
c-=32;
if( (c==32)||(c==45)||(c==46)||((c>=48)&&(c<=57))||((c>=65)&&(c<=90)) ){
cmd[c_i ]=c;
len ;
}
}
break;
case get_tag: while((c_i<len)&&(cmd[c_i]<=32)) c_i ;
i=0;
while((c_i<len)&&(cmd[c_i]>=65)){
tag[n_t][i]=cmd[c_i];
i ;
c_i ;
while((c_i<len)&&(cmd[c_i]<=32)) c_i ;
}
if(i==0){
Serial.println("er2 cmd - 'no tag'");
_s=begin_cmd;
break;
}
tag[n_t][i]=0;
_s=get_val;
break;
case get_val: while((c_i<len)&&(cmd[c_i]<=32)) c_i ;
i=0;
while((c_i<len)&& ( (cmd[c_i]=='.')||(cmd[c_i]=='-')||((cmd[c_i]>=48)&&(cmd[c_i]<=57)) ) ){
val[n_t][i]=cmd[c_i];
i ;
c_i ;
while((c_i<len)&&(cmd[c_i]<=32)) c_i ;
}
if(i==0){
Serial.println("er3 cmd - 'no val'");
_s=begin_cmd;
break;
}
val[n_t][i]=0;
n_t ;
_s=get_tag;
if(c_i>=len)
_s=compilation_cmd;
break;
case compilation_cmd: Serial.println("");
Serial.print("compilation cmd,input (");
Serial.print(n_t);
Serial.println("): ");
for(i=0;i<n_t;i ){
Serial.print(i);
Serial.print("=");
Serial.print(tag[i]);
Serial.print("(");
Serial.print(val[i]);
Serial.println(")");
}
for (int k=0; k<=j; k )
{
g_cmd[k].reset();
}
j=0;
i=0;
while(i<n_t){
if(tag[i][0]=='N'){
g_cmd[j].n=(int)strtod(val[i],&trash);
i ;
while((i<n_t)&&(tag[i][0]!='N')){ //(g_cmd[j].g==1)&&
if(tag[i][0]=='G'){
g_cmd[j].g=(int)strtod(val[i],&trash);
g_cmd_prev = g_cmd[j].g;
}
else { g_cmd[j].g = g_cmd_prev;
}
if(tag[i][0]=='X')
g_cmd[j].x=(double)strtod(val[i],&trash);
if(tag[i][0]=='Y')
g_cmd[j].y=(double)strtod(val[i],&trash);
if(tag[i][0]=='Z')
g_cmd[j].z=(double)strtod(val[i],&trash);
i ;
}//while((i<n_t)&&(tag[i]!="G"))
j ;
}//if(tag[i]=="G")
else i ;
}//while(i<n_t)
amount_G=j;
Serial.print("compilation cmd,output (");
Serial.print(amount_G);
Serial.println("): ");
for(j=0;j<amount_G;j ){
Serial.print(j);
Serial.print("=");
Serial.print("N");Serial.print(g_cmd[j].n);Serial.print(" ");
Serial.print("G");Serial.print(g_cmd[j].g);Serial.print(" ");
Serial.print("X");Serial.print(g_cmd[j].x);Serial.print(" ");
Serial.print("Y");Serial.print(g_cmd[j].y);Serial.print(" ");
Serial.print("Z");Serial.print(g_cmd[j].z);Serial.println(" ");
}
n_run_cmd=0;
_s=run_cmd;
break;
case run_cmd:
Serial.print("run cmd [");
Serial.print("N");Serial.print(g_cmd[n_run_cmd].n);Serial.print(" ");
Serial.print("G");Serial.print(g_cmd[n_run_cmd].g);Serial.print(" ");
Serial.print("X");Serial.print(g_cmd[n_run_cmd].x);Serial.print(" ");
Serial.print("Y");Serial.print(g_cmd[n_run_cmd].y);Serial.print(" ");
Serial.print("Z");Serial.print(g_cmd[n_run_cmd].z);Serial.print(" ");
Serial.println("]");
int f_cmd_coord=0;
if(g_cmd[n_run_cmd].g==90){
f_abs_coord=1;
f_cmd_coord=1;
Serial.println("change to ABS coord");
}
if(g_cmd[n_run_cmd].g==91){
f_abs_coord=0;
f_cmd_coord=1;
Serial.println("change to REL coord");
}
Serial.print("cur_abs(");Serial.print(cur_abs_x);Serial.print(",");Serial.print(cur_abs_y);Serial.print(",");Serial.print(cur_abs_z);Serial.println(")");
if(f_cmd_coord){if( n_run_cmd>=amount_G) _s=begin_cmd; break;}
if(f_abs_coord){
Serial.println("zdes kosjak G90 ABS");
if (g_cmd[n_run_cmd].x==99999)
_x=0;
else
_x=g_cmd[n_run_cmd].x-cur_abs_x;
if (g_cmd[n_run_cmd].y==99999)
_y=0;
else
_y=g_cmd[n_run_cmd].y-cur_abs_y;
if (g_cmd[n_run_cmd].z==99999)
_z=0;
else
_z=g_cmd[n_run_cmd].z-cur_abs_z;
}else{
Serial.println("normalno G91 REL");
_x=g_cmd[n_run_cmd].x;
_y=g_cmd[n_run_cmd].y;
_z=g_cmd[n_run_cmd].z;
}
if((_x==0)&&(_y==0)&&(_z==0)){
Serial.println("exit: _x=0,_y=0,_z=0");
if( n_run_cmd>=amount_G) _s=begin_cmd; break;
}
// _x=_x*koefx;
// _y=_y*koefy;
//_z=_z*koef;
double max_l=abs(_x); //ya
if(abs(_y)>max_l)
max_l=abs(_y);
if(abs(_z)>max_l)
max_l=abs(_z);
double unit_scale=90; // steps in 1.0
double unit_len=max_l*unit_scale,unit_step;
double px=0,py=0,pz=0,x=0,y=0,z=0,kx,ky,kz;
int all_x_steps=0,all_y_steps=0,all_z_steps=0;
kx=_x/unit_len;
ky=_y/unit_len;
kz=_z/unit_len;
// Serial.print("unit_len - "); Serial.print(unit_len); Serial.print(" _x- "); Serial.print(_x); Serial.print(" max_l- "); Serial.println(max_l);
// Serial.print("kx=");Serial.print(kx);Serial.print(" ky=");Serial.print(ky);Serial.print(" kz=");Serial.println(kz);
if((kx==0)&&(ky==0)&&(kz==0)){if( n_run_cmd>=amount_G) _s=begin_cmd; break;}
for(unit_step=0;unit_step<unit_len;unit_step ){
if((abs(x-px)*unit_scale)>=1){
impstep(_X,STEP_MOTOR*kx/abs(kx),1); //stepper0.step(STEP_MOTOR*kx/abs(kx));
//Serial.print("x_step ");Serial.println(kx/abs(kx));
all_x_steps ;
px=x;
}
if((abs(y-py)*unit_scale)>=1){
impstep(_Y,STEP_MOTOR*ky/abs(ky),1); //stepper1.step(STEP_MOTOR*ky/abs(ky));
//Serial.print("y_step ");Serial.println(ky/abs(ky));
all_y_steps ;
py=y;
}
if((abs(z-pz)*unit_scale)>=1){
UNIimpstep(12,13,2,7,3,10*kz/abs(kz)); //stepper2.step(STEP_MOTOR*kz/abs(kz));
//Serial.print("z_step ");Serial.println(kz/abs(kz));
all_z_steps ;
pz=z;
}
x =kx; y =ky; z =kz;
// Serial.print(unit_step);Serial.print(" : ");
// Serial.print(x);Serial.print(" | ");Serial.print(y);Serial.print(" | ");Serial.println(z);
}
Serial.println("-----------------------------------------");
Serial.print("all_steps(");Serial.print(all_x_steps);Serial.print(",");Serial.print(all_y_steps);Serial.print(",");Serial.print(all_z_steps);Serial.print(")");
cur_abs_x =_x; cur_abs_y =_y; cur_abs_z =_z;
Serial.print("cur_abs(");Serial.print(cur_abs_x);Serial.print(",");Serial.print(cur_abs_y);Serial.print(",");Serial.print(cur_abs_z);Serial.println(")");
Serial.println("-----------------------------------------");
if( n_run_cmd>=amount_G) _s=begin_cmd;
}//switch(_s)
}
char end_button(int coord)
{
int but=0;
if(coord==_X)
but=digitalRead(inPinX);
if(coord==_Y)
but=digitalRead(inPinY);
if(but){
if(coord==_X)
Serial.println("[ X out of range ]");
if(coord==_Y)
Serial.println("[ Y out of range ]");
}
return but;
}
char impstep(int coord,int kol,int f_test_coord)
{
int IN_en,IN_dir,IN_step,pause;
pause=2; //35
switch(coord){
case _X: IN_en=x_en; IN_dir=x_dir; IN_step=x_step;
digitalWrite(IN_en, 0);
break;
case _Y: IN_en=y_en; IN_dir=y_dir; IN_step=y_step;
digitalWrite(IN_en, 0);
break;
}
if(!f_test_coord)
Serial.println("[ break step ]");
//delay(100);
if (kol<0)
for (int i=0; i<=abs(kol); i ){
if(f_test_coord&&end_button(coord)){
impstep(coord,200,0);
return 0;
}
digitalWrite(IN_dir, LOW);
digitalWrite(IN_step, HIGH);
delay(pause);
digitalWrite(IN_step, LOW);
delay(pause);
}else
for (int i=0; i <= kol; i ){
if(f_test_coord&&end_button(coord)){
impstep(coord,200,0);
return 0;
}
digitalWrite(IN_dir, HIGH);
digitalWrite(IN_step, HIGH);
delay(pause);
digitalWrite(IN_step, LOW);
delay(pause);
}
digitalWrite(IN_en, 1);
return 1;
}
void UNIimpstep(int IN1,int IN2,int IN3,int IN4,int pause,int kol)
{
//delay(100);
if (kol<0)
for (int i=0; i<=abs(kol); i ){
digitalWrite(IN1, 0);
digitalWrite(IN2, 1);
digitalWrite(IN3, 0);
digitalWrite(IN4, 0);
delay(pause);
digitalWrite(IN1, 1);
digitalWrite(IN2, 0);
digitalWrite(IN3, 0);
digitalWrite(IN4, 0);
delay(pause);
digitalWrite(IN1, 0);
digitalWrite(IN2, 0);
digitalWrite(IN3, 0);
digitalWrite(IN4, 1);
delay(pause);
digitalWrite(IN1, 0);
digitalWrite(IN2, 0);
digitalWrite(IN3, 1);
digitalWrite(IN4, 0);
delay(pause);
}
else
for (int i=0; i <= kol; i ){
digitalWrite(IN1, 1);
digitalWrite(IN2, 0);
digitalWrite(IN3, 0);
digitalWrite(IN4, 0);
delay(pause);
digitalWrite(IN1, 0);
digitalWrite(IN2, 1);
digitalWrite(IN3, 0);
digitalWrite(IN4, 0);
delay(pause);
digitalWrite(IN1, 0);
digitalWrite(IN2, 0);
digitalWrite(IN3, 1);
digitalWrite(IN4, 0);
delay(pause);
digitalWrite(IN1, 0);
digitalWrite(IN2, 0);
digitalWrite(IN3, 0);
digitalWrite(IN4, 1);
delay(pause);
}
}
Завершается конечный автомат конструкцией case run_cmd: где собственно и подается управляющий сигнал на двигатель. Управлением двигателем можно было бы использовать библиотеку #include <Stepper.h> но мы написали свою функцию(char impstep -для биполярного двигателя, void UNIimpstep — униполярного ), что бы можно было не ждать пока один двигатель отработает, что бы послать сигнал другому. Ну и на будущее, отдельная процедура позволит гибче использовать возможностями шагового двигателя. Например, если будем использовать другой драйвер двигателя программно задавать полушаг или шаг двигателя. В нынешнем исполнении с RAMPS получается 1/16 шага. Если кому интересно, про управление шаговыми двигателями можно отдельную статью часами писать.
Теперь немного о железе.

Двигатели использовали 17HS8401, самые мощные из NEMA17, которые смогли на ebay найти. Там же купили подшипники и оптические концевики.

Все остальное отечественное, родное. Оригинальная идея с направляющими, сделали их из длинных хромированных ручек для мебели, они как раз диаметром 12 мм под подшипники, длиной они продаются до метра, и прочности вполне хватает. В торцах ручек просверлили отверстия и метчиком нарезали резьбу. Это позволило просто болтом надежно соединить направляющие с несущим конструктивом. Для оси Z так вообще ручку прикрепили к пластине конструктива целиком, Вал продается в любом строительном магазине как шпилька с резьбой любого диаметра. Мы использовали на 8 мм. Соответственно и гайки 8 мм. Гайку с подшипником и несущим конструктивом оси Y соединили с помощью соединительной скобы. Скобы купили в специализированном магазине для витрин. Видели наверно такие хромированные конструкции в магазинах стоят на которых галстуки или рубашки висят, вот там используются такие скобы для соединения хромированных трубок. Двигатель соединили с валом муфтой, которую сделали из куска стального прута диаметром 14мм, просверлив по центру отверстие и пару отверстий сбоку, для зажимания винтами. Можно не заморачиваться и купить готовые на ebay по запросу cnc coupling их куча выпадает. Несущий конструктив нам вырубили на гильотине за 1000 р. Сборка всего этого заняло не много времени и получили на выходе вот такой станок, на фото еще не установлены концевики, контроллер и не установлен двигатель фрезы.

Точность получилась просто изумительная, во-первых шаговый двигатель шагает 1/16 шага, во-вторых вал с мелкой резьбой. Когда в станок вставили ручку вместо фрезы, он нарисовал сложную фигуру, потом еще несколько раз обвел эту фигуру, а на рисунке видно как будто он один раз рисовал, под лупой рассматривали пытались другую линию найти. Жесткость станка тоже хорошая. Шатается только в пошипниках в допустимых пределах их собственого допуска и посадки. Немного шатается еще по оси Y, ну здесь я думаю конструктив оси Z надо доработать.
Фото получилось не качественное, на заднем плане стекло отражает. Не знаю какой я конструктор станка, но фотограф я просто никакой. Вот чуть получше.

Теперь об управляющей программе. Не помню почему, но мы решили сделать свою программу, которая готовый G-код с компьютера передает в контроллер. Может просто не нашли подходящий.
Программа написана на Microsoft Visual C , использовалась библиотеки:
Module: SERIALPORT.H
Purpose: Declaration for an MFC wrapper class for serial ports
Copyright 1999 by PJ Naughter. All rights reserved.
Программа еще сырая, ну в двух словах используем
port.Open(8, 9600, CSerialPort::NoParity, 8, CSerialPort::OneStopBit, CSerialPort::XonXoffFlowControl);
для открытия порта
port.Write(text, l); - запись в порт
port.Read(sRxBuf, LEN_BUF); - чтение порта.
Использовался еще стандартный компонент msflexgrid таблица, в которую в реальном времени заносится выполняемый в настоящий момент G-код. Т.е. эта программа просто открывает готовый G-код и маленькими порциями запихивает его в контроллер.
Исходный код управляющей программы можно посмотреть здесь github.com/konstantin1970/cnc.git
Для понимания добавлю еще, что стандартный windows hyperterminal или putty делает то-же самое, запихивает данные в контроллер.
Сам G-код можно сделать в любой CAD/CAM системе например, мне понравился ARTCAM.
В планах у нас сделать более мощный станок на двигателях NEMA 23, но для этого нужно придумать, из чего делать более мощные направляющие. В прошивке контроллера добавить возможность изменять скорость вращения шпинделя. Особенно интересно нам установить камеру и сделать что-то подобное системе технического зрения, что бы станок сам определял размеры заготовки, вычислял начальную координату заготовки по всем осям в программе минимум. В программе максимум, чтобы с помощью камеры станок контролировал все этапы своей работы, возможно даже принимал решения изменить программу. Ну, например, увидел он, что шероховатость больше допустимого, взял и послал фрезу по второму кругу все отшлифовать с более высокой скоростью.
Надеюсь, сможем и в дальнейшем делиться своими разработками с вами уважаемые хаброчитатели.
Шаг 1: дизайн
На этом этапе я расскажу о конструкции этой машины. На этом шаге нет файлов для загрузки. Я добавлю эти файлы на этапах, где я буду рассказывать о сборке или установке отдельных частей лазерного резака. Что касается этого шага, я просто объясню, как и почему я пришел к этому дизайну. Я вдохновлялся внешним видом дизайна лазерного резака серии hobby от Full Spectrum Laser.
Прежде чем сделать набросок того, как должна выглядеть машина, я составил список вещей, которые нужно учитывать при ее проектировании.
Первое и самое главное безопасность! При создании данной машины не забывайте, что безопасность является приоритетом. Поскольку этот лазерный резак использует CO2-лазер мощностью 40 Вт, очевидно, что лазерный луч и даже его отражения. Должны оставаться внутри станка. Поэтому для чехла машины я использовал темную акриловую пластину. Пластина достаточно прозрачная, чтобы вы могли видеть, что происходит внутри. Для боковых панелей я использовал ламинат высокого давления, потому что он хорошо выглядит и устойчив к лазерному излучению.
Второй фактор, который я имел в виду, — это размер рабочей зоны и самого резака. Я хотел, чтобы у него была большая площадь реза 600 на 1000 миллиметров. Зачем строить маленькую машину, если можно построить большую? Поскольку это все еще машина, сделанная своими руками, я хотел, чтобы при необходимости было легко заменять или добавлять детали. Поэтому поля всех отдельных «комнат» в машине выбраны немного шире.
Помня о простоте сборки и возможной модификации этого лазерного резака, я решил построить раму из Т-образных алюминиевых 30×30 профилей.
Теперь я объясню базовый дизайн этого проекта. На изображениях этого шага я добавил несколько черновиков, которые показывают вам различные ракурсы каркаса. Конструкция состоит из пяти отдельных мест. Самое большое пространство — это рабочая зона лазерного резака. Пространство сразу за рабочей зоной — это вентиляционная комната, все пары будут всасываться из рабочей зоны в это место и выводиться наружу по вентиляционному шлангу. За вентиляционным помещением расположены два пространства друг над другом. Верхнее пространство — это пространство, куда войдет лазер. Я хотел, чтобы лазер не находился в рабочей зоне, потому что было бы плохо, если бы он был во всех этих парах. Нижнее пространство — это пространство, где будут находиться резервуар для воды и водяной насос, они необходимы для охлаждения лазера. Последняя комната — это пространство справа от машины, где будет вся электроника, драйверы, расходные материалы и сенсорный экран. Отдельные зоны пространства будут разделены акрилом толщиной 3 мм.
Станки дома 




(1 оценок, среднее: 4,00 из 5)