RecLaserBean: CNC laser

CNC Láser construida con Arduino y compatible con gcode

Idea

La intención de este proyecto es el de desarrollar una máquina cnc-láser de dos ejes. Está máquina permitirá tanto el corte de materiales blandos como el grabado de patrones sobre madera y materiales similares. La diferenciación de grabado o corte será posible gracias al uso de señales pwm para controlar un láser de alta potencia.

Planteamiento

Nuestro planteamiento inicial nos deja las manos libres en cuanto a objetivos, no tenemos fijada la forma o mecanismos físicos de la CNC ni su interacción con el usuario. Por lo que creamos grupos de trabajo que hagan las correspondientes partes, dejándole a cada grupo las decisiones de diseño que ellos crean más oportunas, comunicándoselo entre ellos.
Nos dividimos en dos grupos:

  • Desarrollo del hardware: su misión es desarrollar la estructura física de la CNC, la electrónica y la compra de material.
  • Desarrollo del software: su misión es seleccionar el dispositivo empotrado sobre la que hacer el programa y hacer todo el programa de control de la CNC.

El equipo

En el grupo de hardware esta:
Javier Lamparero López – Estudiante de Ingeniería Informática + Computadores

En el grupo de software esta:
Ildefonso Macarro Pueyo – Estudiante de Ingeniería de Computadores

Recursos

Inicialmente disponemos de ciertos recursos que ponemos los integrantes del grupo, los cuales consideramos a coste 0, el resto de materiales los reflejamos en la siguiente tabla:

MaterialUnidadesPrecio €
Cabezal Láser 10W163,99
Perfiles aluminio V-Slot 2020 350mm320,37
Ruedas para V-slot99,99
Correa x 5m14,99
Ruedas dentadas35
Varilla roscada x 1m12.5
Perfil aluminio cuadrado x 1m12.5
Tornilleria variada115
Drivers a4988416,85
Arduino Mega 256010
Arduino Ethernet SHIELD10
Fuente de alimentación 24v 20A10
Motor Nema 1730
Fuente de alimentación 12V 15A10
Resistencias 10k30
Pulsadores30
Cableado variado10
Bobinas PLA 1kg (Plástico para prototipado mediante impresión 3D)230
PCB 500x500mm (Placa de circuito impreso)10
Ácido Clorhídrico10
Peróxido de Hidrógeno10
TOTAL43171,19

Hardware

Estructura

Para el desarrollo de la estructura se ha empleado vslots como base rígida, debido a su estandarización y fácil manejo. Para el resto de partes clave se ha empleado un impresora 3D para su producción y hemos desarrollado nuestras propias piezas a medida.

Electrónica

En el desarrollo de la electrónica hemos empleado drivers de control de motores paso paso a4988, resistencias, pulsadores, elementos de conexión y condensadores.
Para conectarlo todo hemos producido una PCB con un circuito de conexión de todos los elementos.

Software

Solo se han empleado dos librerías de terceros: SPI.h y SD.h
El resto del código es completamente producido por el grupo de software.
El sistema empotrado empleado ha sido:

  • Arduino Mega 2560
  • Arduino Ethernet Shield

Se compone de 3 librerías, 3 páginas de código externalizado y un programa principal.
Todas las librerías y paginas dependen unas de otras.

El concepto del funcionamiento se basa en un solo botón.
El usuario puede iniciar la ejecución de un solo código de gcode (el primero que se encuentra en la SD) con solo apretar un botón.
Una vez iniciado el gcode, se puede pausar entre instrucciones de gcode y reanudar o cuando el programa encuentra un error en el gcode, se para hasta que el usuario dé el visto bueno pulsando el botón.
La ejecución no se puede cancelar durante la misma, siendo la única salida hacer reset de la Arduino o desconectar la fuente de alimentación.
El botón también se le conoce como botón de acción o acción.

  • RLB -> main del código de Arduino (la única aquí publicada)
  • structs.h -> Estructuras del programa
  • constants.h -> Constantes del programa
  • vars.h -> variables globales del programa
  • functions.h -> funciones generales y de sistema del programa
  • move_motor.h -> drivers de los motores paso paso
  • gcode.h -> librería de interpretación de gcode

El flujo del programa en el loop se muestra en el siguiente gráfico:

RLB
/*
Nombre Proyecto: RecLaserBean
Version: 0.0
Autores: Ildefonso Macarro Pueyo, Javier Lamparero Lopez
Fecha: 20/01/2021
Placa empleada: Arduino Mega 2560
Shield: Arduino Ethernet SHIELD
Version de Arduino en diseño: 1.8.13
*/

//External libs
#include <SPI.h>
#include <SD.h>

//My libs
#include "structs.h"
#include "constants.h"
#include "vars.h"
#include "functions.h"
#include "move_motor.h"
#include "gcode.h"

void setup()
{
  pinMode(PIN_ERROR,OUTPUT);
  pinMode(PIN_DMOTOR_X,OUTPUT);
  pinMode(PIN_MMOTOR_X,OUTPUT);
  pinMode(PIN_DMOTOR_Y,OUTPUT);
  pinMode(PIN_MMOTOR_Y,OUTPUT);
  pinMode(PIN_LASER_PWM,OUTPUT);
  pinMode(PIN_PULSADOR_X,INPUT);
  pinMode(PIN_PULSADOR_Y,INPUT);
  pinMode(PIN_ACTION,INPUT);
  Serial.begin(9600);
  cleanAlarm();
  flagAction=false;
  posicion.x=0;
  posicion.y=0;
  laserP=0;
  laserE=false;
  timing=0;
  cleanBuff();
  while(!SD.begin(PIN_SD))
    alarm();
  attachInterrupt(0,setAction, RISING);
  home();
}

void loop()
{
  File fileCode;
  bool execState=true;
  Serial.println(WALL_RECORD);
  Serial.println(RECORD_NOT_START);
  if(flagAction) //Se detecta accion
  {
    setAction();
    cleanBuff();
    Serial.println(MSG_AT_START_RECORS);
    if(!SD.begin(PIN_SD)) //Lector y tarjeta disponible
    {
      Serial.println(SD_NOT_FOUND);
      alarm();
      execState=false; //Error
    }
    else
    {
      cleanAlarm();
      fileCode=SD.open(FILE_ROOT);
    }
    if(fileCode&&execState) //Acceso a la SD verificado
    {
      cleanAlarm();
      Serial.println(SD_FOUND);
      Serial.println(TITTLE_SD_LOOP_SEARCH);
      execState=false;
      do //Buscar primer fichero con la extension adecuada
      {
        fileCode=fileCode.openNextFile();
        Serial.println(fileCode.name());
        //if(!fileCode.isDirectory()) //Prime fichero
        if(!fileCode.isDirectory()&&charLastContains(fileCode.name(),(char*)GCODE_EXTENSION)) //Si es un fichero y tiene la extension adecuada
        {
          execState=true;
          break;
        }
      } while(fileCode);
      Serial.print(FILE_SELECTED);
      Serial.println(fileCode.name());
      Serial.print(FILE_SELECTED_CODE);
      if(execState)
      {
        Serial.println(FILE_IS_GOOD);
        Serial.println(FILE_IS_EXIST);
        //Fichero encontrado
        if(!fileCode.available()) //No se puede abrir o esta vacio
        {
          Serial.println(FILE_HAVE_PROBLEM);
          alarm();
          execState==255;
        }
        else
        {
          gcomand comando;
          initGcomand(&comando);
          while(fileCode.available())
          {
            execState=false;
            Serial.println(READ_FILE_GCODE);
            int iterationBuff=0;
            char readComand[]={0}; //Tiene tener un valor inicial para evitar no leer la instruccion a partir de la segunda iteracion
            if(flagAction) //accion -> si la ejecucion esta en proceso la detiene y viceversa
            {
              Serial.println("STOP");
              bool laserLastState=statLaser();
              if(laserLastState)
                disableLaser();
              while(flagAction)
                while(flagAction);
              if(laserLastState)
                enableLaser();
                Serial.println("START");
            }
            cleanBuff();
            while(readComand[0]!='\n') //Carga una sola instruccion
            {
              fileCode.read(readComand,1);
              if(readComand[0]<0||iterationBuff==BUFF_SIZE) //Termina la lectura, bien por falta de espacio en el buffer o por terminar la lectura de archivo
              {
                if(readComand[0]<0)
                {
                  execState=true;
                }
                break;
              }
              if(readComand[0]!='\n')
                buffer[iterationBuff++]=readComand[0];
            }
            Serial.print(TITTLE_LINE_GCODE);
            Serial.println(buffer);
            if(execState) //Salir de la ejecucion al terminar de leer el archivo
            {
              Serial.println(END_PREMATURE_FILE);
              break;
            }
            Serial.print(MY_POSITION);
            debugPos();
            switch(translate(buffer, &comando))
            {
              case 0: //Comando reconocido
              {
                Serial.println(FORMALIZED_COMMAND);
                debugGcomand(&comando);
                if(execute(&comando)<0) //Error al efectuar la ejecucion de la orden; poner a la espera de arranque
                {
                  Serial.println(ERROR_COMMAND);
                  alarm();
                  bool laserLastState=statLaser();
                  if(laserLastState)
                    disableLaser();
                  while(flagAction)
                    while(flagAction);
                  if(laserLastState)
                    enableLaser();
                  cleanAlarm();
                }
                else
                  Serial.println(GOOD_EXECUTE);
                break;
              }
              case 1: //Es un comentario, no hacer nada
                Serial.println(COMMAND_COMENTED);
                break;
              default: //Comando no reconocido; poner a la espera de arranque
              {
                Serial.println(BAD_COMAND);
                alarm();
                bool laserLastState=statLaser();
                if(laserLastState)
                  disableLaser();
                while(flagAction)
                  while(flagAction);
                if(laserLastState)
                  enableLaser();
                cleanAlarm();
              }
            }
            Serial.print(POSITION_AFTER_COMMAND);
            debugPos();
          }
          setPowerLaser(12);
          disableLaser();
        }
        Serial.println(END_FILE_NATURAL);
      }
      else
        Serial.println(FILE_IS_BAD);
      Serial.println(CLOSE_SD);
      fileCode.close();
      home();
    }
    else
      alarm();
  }
  delay(1000);
}

Modelo producido

Esta es nuestra CNC.

Conclusiones

Como conclusión en cuanto a la parte práctica el usar por primera vez arduino “en condiciones” y poder llevar a cabo en la vida real un proyecto de la nada, descubrir la posibilidad de poder crear cualquier cosa que se te ocurra y la percepción de que no hay límites. A esto añadiría la ilusión de ver funcionar un proyecto como este al que le hemos dedicado tanto tiempo.

Entrando en una parte más técnica y como conclusión general de la parte hardware nos hemos dado cuenta de la importancia para este proyecto de una impresora 3D, ya que nos ha permitido crear las piezas que necesitábamos a medida, algo que de otra forma no habría sino posible, y le habría quitado mucha calidad.

Como mejora nos habría gustado añadir algún soporte para cablear bien la CNC, así como la creación de una caja en la que guardar la electrónica y un soporte para incluir la fuente de alimentación dentro de la máquina.

También nos habría gustado la incorporación de una pantalla desde la que poder seleccionar los archivos a grabar.

Algunas de las mejoras que planteamos en un principio era el poder controlar la máquina desde el móvil, incluyendo un módulo wifi, y la incorporación de lo que llamamos “modo manual” que lo imaginamos como un joystick con el que mover la máquina y dibujar libremente, y la implementación de esto desde el móvil.

Resultado – Vídeos

https://www.youtube.com/watch?v=yDJvK8iGvLk
Vídeo explicativo del proyecto

También te podría gustar...

1 respuesta

  1. Carlos dice:

    Hola buenas,
    Me parece un proyecto muy interesante. Enhorabuena.
    Me gustaría llevar a cabo un proyecto parecido.
    ¿Podrían publicar o hacerme llegar de alguna forma el resto de librerías utilizadas?
    Muchísimas gracias de antemano.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *