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:
Material | Unidades | Precio € |
Cabezal Láser 10W | 1 | 63,99 |
Perfiles aluminio V-Slot 2020 350mm | 3 | 20,37 |
Ruedas para V-slot | 9 | 9,99 |
Correa x 5m | 1 | 4,99 |
Ruedas dentadas | 3 | 5 |
Varilla roscada x 1m | 1 | 2.5 |
Perfil aluminio cuadrado x 1m | 1 | 2.5 |
Tornilleria variada | 1 | 15 |
Drivers a4988 | 4 | 16,85 |
Arduino Mega 2560 | 1 | 0 |
Arduino Ethernet SHIELD | 1 | 0 |
Fuente de alimentación 24v 20A | 1 | 0 |
Motor Nema 17 | 3 | 0 |
Fuente de alimentación 12V 15A | 1 | 0 |
Resistencias 10k | 3 | 0 |
Pulsadores | 3 | 0 |
Cableado variado | 1 | 0 |
Bobinas PLA 1kg (Plástico para prototipado mediante impresión 3D) | 2 | 30 |
PCB 500x500mm (Placa de circuito impreso) | 1 | 0 |
Ácido Clorhídrico | 1 | 0 |
Peróxido de Hidrógeno | 1 | 0 |
TOTAL | 43 | 171,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.
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.