Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

CNC VMC 3 Eixos DIY: Construa uma Fresadora de Precisão

Componentes e Materiais

Arduino Nano R3 × 1
Raspberry Pi 3 Model B × 1
Driver de motor de passo A4988 (placa SparkFun) × 1
Shield RepRap Adafruit para Arduino Nano (4 steppers + 1 DC) × 1
Espaçadores de Alumínio OpenBuilds × 1
Fonte chaveada 12V/5A × 1
Suporte L OpenBuilds × 1
Porcas T M5 OpenBuilds (pacote 10) × 1
Parafusos baixo perfil M5 OpenBuilds (pacote 10) × 1
Parafusos cabeça cilíndrica M3 OpenBuilds × 1
Parafuso de ajuste OpenBuilds × 1
Arruela de canaleta OpenBuilds 15×5×2mm × 1
Bloco porca anti-backlash para fuso ACME 8mm OpenBuilds × 2
Placa fuso rosqueado para motor NEMA 17 OpenBuilds × 1
Fuso ACME métrico 8mm OpenBuilds × 1
Rolamento esferas 625 2RS 5×16×5 OpenBuilds × 1
Haste lisa (eixos guias) × 1
Ventoinha BLDC de refrigeração × 1
Motor DC genérico × 1
Servo Tower Pro MG996R × 1
Driver dual H-Bridge L293D Texas Instruments × 1

Ferramentas e Máquinas Necessárias

Aplicativos e Serviços Online

Sobre o Projeto

Nosso modelo protótipo é baseado em IoT, proporcionando uma arquitetura escalável para uso de praticamente qualquer lugar com conexão à internet. Esta é uma CNC de 350mm × 350mm com área de trabalho de 250mm × 240mm, rodando software de controle de movimento open source (GRBL). Nosso hardware também é majoritariamente open source, o que reduz drasticamente os custos. A máquina é feita inteiramente com itens comprados localmente e pode usinar madeira, plásticos, borracha dura, resina dura, etc. Nosso alvo principal é a fabricação de PCBs de baixo custo.

A perspectiva de entalhe em madeira também está presente.

Planejamos adicionar suporte a usinagem a laser como parte de nosso projeto futuro.

Como o sistema pode ser controlado atualmente a partir de uma intranet local sem fio, queremos escalá-lo ainda mais para criar um modelo de aplicação web distribuída para conectar um ecossistema de múltiplos dispositivos deste tipo.

As possibilidades são ilimitadas com nossa máquina.

Nosso protótipo tem estrutura base feita de extrusões de alumínio T-slot 2020 e juntas em L. A máquina entrega cerca de 80–85 Watts com seu fuso de 2000 rpm controlado por DC. Utiliza esquema de movimento por fuso rosqueado e haste roscada com hastes lisas guias com rolamentos de esferas de encaixe radial para operação suave nos 3 eixos.

O passo mínimo do fuso é 0.8mm/revolução; com 2000 passos/revolução, temos resolução de 1600 para todos os eixos. Dimensões aproximadas da máquina: 430×430×330mm; área de trabalho: 270×170×65mm com precisão posicional de 0.04mm. O portal do eixo Z é impresso em 3D do zero com dupla haste guia.

O curso do eixo Z é 4.8 cm com a broca montada. Usamos broca V-bit 45° para gravação de PCB, também suporta fresas de topo de 0.2mm a 1.8mm. Motores de passo NEMA 23 com corrente máxima de 3A por eixo. Os motores são acionados por drivers A4988 de 2.5A com microstepping máximo de 1/16, proporcionando precisão de usinagem máxima a custo muito econômico.

Para a parte IoT, tornamos possível controlar o roteador CNC a partir de um display headless como tela de celular/tablet (atuando como nossa IHM) de qualquer lugar com conexão à internet. Usamos um Raspberry Pi e um roteador (segurança) conectados à internet rodando um servidor web para fornecer interface de controle sem fio. Também planejamos obter insights valiosos de peças da máquina como torque do motor em tempo real, corrente consumida, vibração, ruído etc. e gerar insights em tempo real em plataforma web para melhor colaboração. O que talvez seja chamado no setor manufatureiro como IoT Industrial (INDÚSTRIA 4.0).

Código

G-code de Exemplo VHDL

(Versão rabiscada de C:\Users\ABDERR~1\AppData\Local\Temp\ink_ext_XXXXXX.svgISF45X @ 3000.00)
( unicorn.py --tab="plotter_setup" --pen-up-angle=50 --pen-down-angle=30 --start-delay=160 --stop-delay=150 --xy-feedrate=3000 --z-feedrate=150 --z-height=0 --finished-height=0 --register-pen=true --x-home=0 --y-home=0 --num-copies=1 --continuous=false --pause-on-layer-change=true C:\Users\ABDERR~1\AppData\Local\Temp\ink_ext_XXXXXX.svgISF45X )
G21 (métrico)
G90 (modo absoluto)
G92 X0.00 Y0.00 Z0.00 (você está aqui)
M300 S30 (caneta baixa)
G4 P160 (espera 160ms)
M300 S50 (caneta alta)
G4 P150 (espera 150ms)
M18 (desengata drives)
M01 (Teste de registro bem-sucedido?)
M17 (engata drives se SIM, e continua)
M01 (Plotando camada 'Calque 1')
(Polilinha consistindo de 29 segmentos.)
G1 X16.85 Y4.97 F3000.00
M300 S30.00 (caneta baixa)
G4 P160 (espera 160ms)
G1 X14.07 Y5.98 F3000.00
G1 X13.33 Y6.40 F3000.00
...
(Arquivo truncado — faça download para ver o conteúdo completo)

Código do Motor de Passo Arduino

// AMIT
#include <Servo.h>
#include <AFMotor.h>

#define LINE_BUFFER_LENGTH 512
char STEP = MICROSTEP;

// Posições do servo para cima e baixo
const int penZUp = 115;
const int penZDown = 83;

// Servo no pino PWM 10
const int penServoPin = 10;

// Passos por revolução (para steppers de DVD)
const int stepsPerRevolution = 48;

// Cria objeto servo
Servo penServo;

// Inicializa steppers para eixos X e Y usando pinos do Arduino para H-bridge L293D
AF_Stepper myStepperY(stepsPerRevolution, 1);
AF_Stepper myStepperX(stepsPerRevolution, 2);

/* Estruturas, variáveis globais */
struct point {
  float x;
  float y;
  float z;
};

// Posição atual do cabeçote
struct point actuatorPos;

// Configurações de desenho
float StepInc = 1;
int StepDelay = 0;
int LineDelay = 0;
int penDelay = 50;

// Passos do motor para 1 milímetro
// Use sketch de teste para dar 100 passos. Meça o comprimento da linha.
// Calcule passos por mm. Insira aqui.
float StepsPerMillimeterX = 100.0;
float StepsPerMillimeterY = 100.0;

// Limites do robô desenhista, em mm
float Xmin = 0; float Xmax = 40;
float Ymin = 0; float Ymax = 40;
float Zmin = 0; float Zmax = 1;
float Xpos = Xmin; float Ypos = Ymin; float Zpos = Zmax;

// Set true para saída de debug
boolean verbose = false;

/* Precisa interpretar:
   G1 para movimento
   G4 P300 (espera 150ms)
   M300 S30 (caneta baixa)
   M300 S50 (caneta alta)
   Descarta qualquer coisa com (
   Descarta qualquer outro comando!
*/

void setup() {
  Serial.begin(9600);
  penServo.attach(penServoPin);
  penServo.write(penZUp);
  delay(100);
  myStepperX.setSpeed(600);
  myStepperY.setSpeed(600);

  Serial.println("Mini CNC Plotter vivo e chutando!");
  Serial.print("Faixa X é de "); Serial.print(Xmin); Serial.print(" a "); Serial.print(Xmax); Serial.println(" mm.");
  Serial.print("Faixa Y é de "); Serial.print(Ymin); Serial.print(" a "); Serial.print(Ymax); Serial.println(" mm.");
}

void loop() {
  delay(100);
  char line[LINE_BUFFER_LENGTH];
  char c;
  int lineIndex;
  bool lineIsComment, lineSemiColon;

  lineIndex = 0;
  lineSemiColon = false;
  lineIsComment = false;

  while (1) {
    while (Serial.available() > 0) {
      c = Serial.read();
      if ((c == '\n') || (c == '\r')) {
        if (lineIndex > 0) {
          line[lineIndex] = '\0';
          if (verbose) {
            Serial.print("Recebido: ");
            Serial.println(line);
          }
          processIncomingLine(line, lineIndex);
          lineIndex = 0;
        } else {
          // Linha vazia ou comentário. Pula bloco.
        }
        lineIsComment = false;
        lineSemiColon = false;
        Serial.println("ok");
      } else {
        if (lineIsComment || lineSemiColon) {
          if (c == ')') lineIsComment = false;
        } else {
          if (c <= ' ') {
            // Descarta whitespace e caracteres de controle
          } else if (c == '/') {
            // Block delete não suportado. Ignora.
          } else if (c == '(') {
            lineIsComment = true;
          } else if (c == ';') {
            lineSemiColon = true;
          } else if (lineIndex >= LINE_BUFFER_LENGTH - 1) {
            Serial.println("ERRO - overflow lineBuffer");
            lineIsComment = false;
            lineSemiColon = false;
          } else if (c >= 'a' && c <= 'z') {
            line[lineIndex++] = c - 'a' + 'A';
          } else {
            line[lineIndex++] = c;
          }
        }
      }
    }
  }
}

void processIncomingLine(char* line, int charNB) {
  int currentIndex = 0;
  char buffer[64];
  struct point newPos;
  newPos.x = 0.0; newPos.y = 0.0;

  while (currentIndex < charNB) {
    switch (line[currentIndex++]) {
      case 'U': penUp(); break;
      case 'D': penDown(); break;
      case 'G':
        buffer[0] = line[currentIndex++];
        buffer[1] = '\0';
        switch (atoi(buffer)) {
          case 0: // G00 & G01 - Movimento ou movimento rápido. Mesmo aqui.
          case 1:
            char* indexX = strchr(line + currentIndex, 'X');
            char* indexY = strchr(line + currentIndex, 'Y');
            if (indexY <= 0) {
              newPos.x = atof(indexX + 1);
              newPos.y = actuatorPos.y;
            } else if (indexX <= 0) {
              newPos.y = atof(indexY + 1);
              newPos.x = actuatorPos.x;
            } else {
              newPos.y = atof(indexY + 1);
              indexY = '\0';
              newPos.x = atof(indexX + 1);
            }
            drawLine(newPos.x, newPos.y);
            actuatorPos.x = newPos.x;
            actuatorPos.y = newPos.y;
            break;
        }
        break;
      case 'M':
        buffer[0] = line[currentIndex++];
        buffer[1] = line[currentIndex++];
        buffer[2] = line[currentIndex++];
        buffer[3] = '\0';
        switch (atoi(buffer)) {
          case 300: {
            char* indexS = strchr(line + currentIndex, 'S');
            float Spos = atof(indexS + 1);
            if (Spos == 30) penDown();
            if (Spos == 50) penUp();
            break;
          }
          case 114: // M114 - Reporta posição
            Serial.print("Posição absoluta: X = ");
            Serial.print(actuatorPos.x);
            Serial.print(" - Y = ");
            Serial.println(actuatorPos.y);
            break;
          default:
            Serial.print("Comando não reconhecido: M");
            Serial.println(buffer);
        }
        break;
    }
  }
}

void drawLine(float x1, float y1) {
  if (verbose) {
    Serial.print("fx1, fy1: "); Serial.print(x1); Serial.print(","); Serial.print(y1); Serial.println();
  }

  // Limita às bordas
  if (x1 >= Xmax) x1 = Xmax;
  if (x1 <= Xmin) x1 = Xmin;
  if (y1 >= Ymax) y1 = Ymax;
  if (y1 <= Ymin) y1 = Ymin;

  if (verbose) {
    Serial.print("Xpos, Ypos: "); Serial.print(Xpos); Serial.print(","); Serial.print(Ypos); Serial.println();
    Serial.print("x1, y1: "); Serial.print(x1); Serial.print(","); Serial.print(y1); Serial.println();
  }

  // Converte coordenadas para passos
  x1 = (int)(x1 * StepsPerMillimeterX);
  y1 = (int)(y1 * StepsPerMillimeterY);
  float x0 = Xpos;
  float y0 = Ypos;

  long dx = abs(x1 - x0);
  long dy = abs(y1 - y0);
  int sx = x0 < x1 ? StepInc : -StepInc;
  int sy = y0 < y1 ? StepInc : -StepInc;
  long i, over = 0;

  if (dx > dy) {
    for (i = 0; i < dx; ++i) {
      myStepperX.onestep(sx, STEP);
      over += dy;
      if (over >= dx) {
        over -= dx;
        myStepperY.onestep(sy, STEP);
      }
      delay(StepDelay);
    }
  } else {
    for (i = 0; i < dy; ++i) {
      myStepperY.onestep(sy, STEP);
      over += dx;
      if (over >= dy) {
        over -= dy;
        myStepperX.onestep(sx, STEP);
      }
      delay(StepDelay);
    }
  }

  if (verbose) {
    Serial.print("dx, dy:"); Serial.print(dx); Serial.print(","); Serial.print(dy); Serial.println();
    Serial.print("Indo para ("); Serial.print(x0); Serial.print(","); Serial.print(y0); Serial.println(")");
  }

  delay(LineDelay);
  Xpos = x1;
  Ypos = y1;
}

void penUp() {
  penServo.write(penZUp);
  delay(penDelay);
  Zpos = Zmax;
  digitalWrite(15, LOW);
  digitalWrite(16, HIGH);
  if (verbose) Serial.println("Caneta alta!");
}

void penDown() {
  penServo.write(penZDown);
  delay(penDelay);
  Zpos = Zmin;
  digitalWrite(15, HIGH);
  digitalWrite(16, LOW);
  if (verbose) Serial.println("Caneta baixa.");
}

Bibliotecas Arduino

// Biblioteca Adafruit Motor Shield
// copyright Adafruit Industries LLC, 2009
// domínio público, aproveite!
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#if defined(__AVR__)
#include 
#endif
#include "WProgram.h"
#endif
#include "AFMotor.h"

static uint8_t latch_state;

#if (MICROSTEPS == 8)
uint8_t microstepcurve[] = {0, 50, 98, 142, 180, 212, 236, 250, 255};
#elif (MICROSTEPS == 16)
uint8_t microstepcurve[] = {0, 25, 50, 74, 98, 120, 141, 162, 180, 197, 212, 225, 236, 244, 250, 253, 255};
#endif

// ... (código completo da biblioteca AFMotor omitido por brevidade — disponível no repositório original)

Peças Personalizadas e Gabinetes

cnc_contour_SNa09InGkY.gm1

cnc_coppertop_PIxEVyoMWI.gtl

Esquemáticos

CNC VMC 3 Eixos DIY: Construa uma Fresadora de Precisão CNC VMC 3 Eixos DIY: Construa uma Fresadora de Precisão CNC VMC 3 Eixos DIY: Construa uma Fresadora de Precisão CNC VMC 3 Eixos DIY: Construa uma Fresadora de Precisão CNC VMC 3 Eixos DIY: Construa uma Fresadora de Precisão

Processo de manufatura

  1. Construa Seu Próprio LUMAZOID: Visualizador de Música DIY com Arduino
  2. Construa um Voltímetro Inteligente com Arduino e Smartphone – Projeto DIY Fácil
  3. Construa um Skate VR DIY com Arduino, Google Cardboard e Bluetooth
  4. Máquina CNC Tripla – Upgrade Premium com Motor Brushless
  5. Mesa Lateral Zen Garden com CNC: Construa Seu Próprio Móvel Inteligente
  6. Dispositivo de Tratamento Radiônico EMR DIY com Arduino Nano
  7. Construa uma Máquina CNC Totalmente Funcional com Arduino Nano R3
  8. Simulador de Corrida 2D DIY com Arduino Nano e Servos SG90
  9. Usinagem Vertical e CNC VMC: Introdução Abrangente
  10. Mini Máquina VMC Explicada: Fresamento CNC Compacto para Projetos de Pequena Escala