How do you feel about this article? Help us to provide better content for you.
Thank you! Your feedback has been received.
There was a problem submitting your feedback, please try again later.
What do you think of this article?
1 Introduction
This project involves the creation and programming of a machine capable of drawing following G-code instructions. The primary focus of the project is on the software and electronics rather than the mechanical aspects. By integrating physical components and software, the aim is to develop an automated drawing system. The project objectives include:
- Mimic how CNC machines work
- Assembling the structure
- Programming the PIC16F877A to control the machine
- Establishing serial communication with the PIC16F877A for instruction reception
- Creating a user interface to send commands
This document details the technical and practical aspects involved in the project, from component selection to addressing challenges encountered during development. The goal is to enhance our knowledge in electronic project development, incorporating elements of design and physical assembly.
The project was developed as part of the Digital Systems course at UPNA. Therefore, certain functionalities and features are designed to meet the specific requirements of the assignment.
2 Materials
2.1 Necessary components to build the physical model:
- Linear rail (30 cm) MGN12H
- Linear rail (9 cm) LML9B
- 2x chrome steel rods (8 mm x35 cm)
- 2x linear bearings
- GT2 belt and polys
- M3 screws and lag screws
- Plywood sheet
- 3D printed parts
2.2 Electronics and others:
- Analog servo
- 2x NEMA 17 motors
- 2x motor drivers capable of 1/16 stepping, A4988
- PIC16F877A development kit
- DB9-USB “active” adaptor if required
- Cables, push buttons, resistors, capacitors, LCD, potentiometers, piezoelectric, end switches, power supply etc.
2.3 Tools:
- MPLAB ICD2
- Computer with MPALB IDE software and Python 3.x
- 3D printer
- All the other tools necessary to build the model
3 Specifications
We want a machine that draws whatever drawing we send to it. We also want to adjust its drawing velocity (feed) on the fly and, why not, that it would play music at the finish.
The way we implement such things is influenced by the requisites of the project. The LCD, music or potentiometer are not necessary; those modules could be replaced by a more functional pc interface.
Precision in movement is ensured by GT2 belts and pulleys, preventing slippage and allowing accurate pen control. A servo adjusts the pen's contact with the paper to control drawing actions. The custom-designed pen holder mechanism uses a servo and linear guide to lift or lower the pen as needed.
Using Inkscape and DrawingBOT V3 software, images are converted into vector drawings and then into Gcode, a standard language in computer-aided manufacturing (CAM) for controlling machines. The Gcode instructions are sent to the PIC16F877A, which interprets and executes the drawing commands.
4 Physical assembly
The physical part is heavily inspired by this YouTube video. The video is excellent, and it shows how to build the machine bottom up. We use some of their 3D parts. We modify the pen holder section because of the parts we had available (custom 3D design attached in the attachments). That’s the only part our machine differs from theirs.
5 Connections with the microcontroller (PIC16F877A)
1. Stepper Motors
The stepper motors are driven by A4988 drivers. Each stepper motor driver typically has the following connections:
- Step Pin: Controls the steps of the motor.
- Direction Pin: Controls the rotation direction.
- Enable Pin: Activates or deactivates the driver.
- VDD and GND: Power supply for the logic circuit (3.3V or 5V).
- VMOT and GND: Power supply for the motor (typically 8-35V).
For each stepper motor (X-axis and Y-axis), the connections are as follows:
X-Axis Motor Driver:
- Step Pin -> RB1
- Direction Pin -> RB2
- Enable Pin -> Ex
Y-Axis Motor Driver:
- Step Pin -> RB4
- Direction Pin -> RB5
- Enable Pin -> Ey
2. Servo Motor
The servo motor controlling the pen requires a PWM signal, with a frequency of 50 Hz, to adjust its position. The PIC16F877A can emulate this type of signal using the Timer 0 Module.
- Servo Signal Pin -> RC0
3. Limit Switches
Limit switches are used to detect the boundaries of the drawing area and prevent the machine from overextending. These switches are connected to an inverter circuit made with 2 transistors to adapt the signal.
4. Serial Communication (USART)
The serial communication for receiving G-code instructions is handled by the USART module of the PIC16F877A.
- o TX (Transmit) -> RC6
- o RX (Receive) -> RC7
This connection allows the PIC to communicate with a PC via a DB9-USB adapter.
5. LCD Display
A standard 16x2 LCD display can be connected as follows:
- o RS -> RD4
- o E (Enable) -> RD6
- o D4 -> RD0
- o D5 -> RD1
- o D6 -> RD2
- o D7 -> RD3
6. Additional Components
- Button Inputs:
- RA4 Button -> RA4
- RB0 Button 2 -> RB0
- Potentiometer:
- Analog Input -> RA0
- Piezoelectric Buzzer:
- Buzzer Signal -> RC2
- Power Supply
The microcontroller and its components require a stable power supply. Typically, the PIC16F877A operates at 5V, while the stepper motors need higher voltages (e.g., 9V). Voltage regulators can be used to provide the necessary power levels:
- Microcontroller Power Supply:
- VDD -> 5V
- VSS -> GND
- Motor Power Supply:
- VMOT -> 9V(for stepper motors
- VSS -> GND
Summary of Connections
Component | PIC16F877A Pin | Function |
---|---|---|
X-Axis Step (Step) | RB1 | Step Signal |
X-Axis Direction | RB2 | Direction Signal |
Y-Axis Step (Step) | RB4 | Step Signal |
Y-Axis Direction | RB5 | Direction Signal |
Servo Motor | RC0 | Servo position |
USART TX | RC6 | Transmit Data |
USART RX | RC7 | Receive Data |
LCD RS | RD4 | Register Select |
LCD E | RD6 | Enable Signal |
LCD D4 | RD0 | Data Line |
LCD D5 | RD1 | Data Line |
LCD D6 | RD2 | Data Line |
LCD D7 | RD3 | Data Line |
RA4 Button | RA4 | User Input |
RB0 Button | RB0 | User Input |
Potentiometer | RA0 | Analog Input |
Buzzer | RC0 | Audible Feedback |
Libraries and registers on the PIC16F877A
The LCD is connected as we were using the < style="font-family: 'Noto Sans',sans-serif; color: #1f1f1f; background: white;">PICDEM2+ development kit so we will use the LCD library that we have for that kit. Motor drivers and the RB0 switch are connected to PORT B and the register's initial configuration is:
TRISB = 0x11001001;
PORTB = 0x00;
The configuration of the serial port:
TRISC7 = 1; //TX pin
TRISC6 = 0; // RX pin
We also configure RC2 and RC0 as output:
TRISC0 = 0; // servo
TRISC2 = 0; // piezoelectric
Finally, the port A is configure as an input by default, nevertheless we write it explicitly:
TRISA = 0xff;
6 Code
The code is the core of the project, integrating multiple functionalities to make the drawing machine work seamlessly. Below is a detailed breakdown of the software modules implemented in this project:
6.1 How most CNC machines work: Gcode
G-code is a programming language used to control CNC machines. It comprises commands such as:
- G0 X__ Y__ : Rapid movement to a specified point without drawing. Where "__" represents numbers that are the coordinates of the end point.
- G1 X__ Y__ : Linear movement to a specified point while drawing.
- G2/G3 X__ Y__ I__ J__: Circular movements. Where X and Y are the end points of the arc and I and J are the distances to the centre of the arc from the starting point.
Commands we added:
- G4: End of drawing
- G5: Connection establish successfully
6.2 Implement G0, G1, G2 and G3
In this case for the sake of simplicity, we just implemented the slow linear movement; so that regardless of G0 or G1 instruction we suppose it is G1.
First, it parses the message that came through the serial port and identifies the instruction and the coordinates.
When all the incoming information is processed, it applies the Bresenham's line algorithm. It is the same algorithm applied to drawing lines in pixel screens. In a certain way, it transforms the continuous 2D space of the paper into a discrete grid. I personally recommend the Wikipedia page on the topic; there it is extremely well explained.
For G2 and G3, it’s just dividing the arc into small enough segments and then applying the things described above. For that task, we implemented a function called atan3 whose image is contained in the interval [0, 2*Pi).
6.3 PIC16F877A modules
We did not use the USART communication library as it was not convenient. Instead, the input shift register interrupt was enabled to receive the information. As characters arrive, they are accumulated in a buffer. This continues until the character 0x0D or 0x0A is received, which is interpreted as the end of the message.
To send data through the serial port, the printf function is used, which internally calls the putch function to handle the character-by-character transmission. For sending data to the LCD or via the serial port, a global variable called output is used to control the flow of information.
The module is configured for a transfer speed of 9600 Baud, with the rest of the parameters properly adjusted.
// configura el módulo USART /* Inicializacion USART */
TRISC7 = 1; //TX pin
TRISC6 = 0; // RX pin
SPBRG = 25; // 9600 baud para Fosc=4MHz
RCSTA = 0x90; // SPEN on
TXSTA = 0b00100100; // TX en On, modo asíncrono con 8 bits y alta velocidad
6.3.2 Timer 0: Servo
Timer 0 has been implemented to generate the 50 Hz signal required to control the servo. This is a square wave signal where the ton ranges from 1 ms to 2 ms. We only need two positions: in contact with the paper and not in contact.
To generate a signal with a period of approximately 20 ms, Timer 0 can be configured with a prescaler of 128. The signal sent to the servo is created using interrupts and a logical structure.
Depending on the desired state of the servo, the appropriate value is loaded into Timer 0 to achieve the required ton, and immediately after, the value needed to complete a 20 ms period is loaded. This can be better understood with an example. Suppose we want to set the servo to approximately 110º:
The servo moves to 0º for a ton of 1 ms and to 180º for a ton of 2 ms.
The clock oscillates at 4 MHz.
With a prescaler of 128, the values 248 and 241 must be loaded into TMR0 for 1 ms and 2 ms, respectively.
Based on the above, a function can be created to input the desired angle and obtain the value to load into TMR0.
f(angle) = N_TMR0= (248-241)/(-180)+248
If we substitute the value of 110º into the equation, we get 241.
To complete the 20 ms period, 113 must be loaded in the next cycle.
This creates a square wave signal with the desired duty cycle to position the servo as needed.
When configuring the module, the implementation in the code was as follows (PIC16F877A code):
// configuracion del servo -> una PWM de 20 ms -> 50 Hz de periodo y 1-2 ms de ton, mediante TMR0
TRISC0 = 0; // configuramos como salida el puerto al que se conecta el servo
T0CS = 0; // configuro el Timer 0 como temporizador
PSA = 0; // asigno el predivisor al timer0
PS2 = 1; // predivisor de 128
PS1 = 1;
PS0 = 0;
T0IE = 1; // activo interrupcion por timer 0
T0IF = 0;
TMR0 = 0x00;
6.3.3 Hardware interruptions
The RB0 interrupt was used. It was implemented as follows:
// Configuración de las interrupciones
GIE=1; // Habilito las interrupciones.
PEIE = 1; // habilito las itnerrupciones de periféricos
RCIE = 1; // habilito las interrupciones de llenado del buffer de entrada
RCIF = 0; // por si acaso
INTE = 1; // habilitamos las interrupciones por RB0
INTF = 0; // por si acaso
6.3.4 CCP
For both the implementation of the music system and the use of the analog-to-digital converter, we utilized the CCP1 and CCP2 modules, respectively.
Regarding the music system, it uses the CCP1 module in Pulse Width Modulation (PWM) mode (configured with CCP1CON=0x0C). Essentially, we aim to generate a specific frequency for a defined period of time. While the duration of the note is managed externally, the desired frequency is configured through the CCP1 module. Specifically, we load the value N into the PR2 register, where N is calculated using the following formula:
T = (N+1)*P*4*T_osc
Where:
T is the period of the note to be played, i.e., the inverse of its frequency.
P is the prescaler value of TMR2, set to 16 to avoid overflow issues across a wide range of frequencies.
T_osc is the period of the microcontroller's primary oscillator.
Additionally, for each note, the PWM duty cycle is actively set to approximately 50% to optimize the emitted sound. This is achieved by loading half the value of N into the CCPR1L register.
We disable the CCP1 module interrupts (CCP1IE=0) as they are not needed for this application.
In contrast, this interrupt configuration is essential for the analog-to-digital converter, where the CCP2 module is used in comparison mode (CCP2CON = 0b00001011). When an interrupt is triggered, TMR1 is reset, and a new conversion is initiated. This mechanism notifies us when a conversion is complete, allowing us to process the data and start a new one.
CCPR2H=0b10000101; //para 250 ms
CCPR2L=0b11101110;
6.3.5 A/D conversion
Complementary to the CCP2 module, the following code has been used to configure the analog-to-digital converter:
ADCON1 = 0x00; //Entradas analógicas y justificamos a la izquierda
CHS2 = 0; //Seleccionamos el primer canal
CHS1 = 0;
CHS0 = 0;
ADCS1 = 1; //Seleccionamos el oscilador interno
ADCS0 = 1;
ADON = 1; //Encendido convertidor A/D
ADIF = 0; //Bajar flag conversión A/D
ADIE = 0; //Habilitamos las interrupciones necesarias
6.4 PIC16F877A “printf”
The function printf is shared between the serial port and the LCD. The way we implemented it was by using a help variable called salida. The function printf will call the function putch, who is in charge of outputting the character to the correct register. So we modified putch adding a switching condition depending on salida.
void putch(unsigned char byte){ // saca un byte
switch (salida){
case 0: // salida por el puerto serie
while(!TXIF) //'1' cuando el registro esté vacio
continue;
TXREG = byte;
break;
case 1: // salida por el LCD
#ifdef INCLUYE_LCD
lcd_putch(byte);
#endif
break;
default:
salida = 0; //llegamos aqui si algo ha ido mal
}
}// Fin putch
7 How to send commands to the board
7.1 Generating a .svg file and the commands file
Inkscape is used to transform a pixelated image into a vector drawing. The vectorized image is fed into DrawingBotV3 software and then it requires some tinkering to generate the file with the G-code of the image.
7.2 Python serial interface
A Python script was developed to send commands to the PIC16F877A. It uses the library SERIAL for communications through the USB port of the computer and the library TKINTER for the graphical interface.
8 Result
To better illustrate the functionality and performance of the drawing machine, a demonstration video has been recorded.
9 Conclusion
This project successfully demonstrates the integration of hardware and software to create an automated drawing machine based on G-code commands. Through the use of the PIC16F877A microcontroller, precise movement control and functionality was achieved, simulating the basic operations of a CNC machine.
Key achievements include:
Designing and assembling a functional mechanical structure.
Implementing communication between the microcontroller and the pc to send the stream of commands.
Developing custom software modules to process G-code commands and translate them into machine movements using fancy algorithms.
Challenges, such as adapting the physical design and ensuring reliable serial communication, were effectively addressed, resulting in a fully operational system. By combining theoretical knowledge with practical application, this project serves as a foundation for understanding CNC principles and electronic system design. Moreover, the successful completion of this machine emphasizes the importance of multidisciplinary collaboration and iterative problem-solving in engineering projects.
This project not only fulfils the requirements of the Digital Systems course at UPNA but also provides a platform for future enhancements.
Thanks for your attention!
And also, thanks...
- To Grbl CNC controller, open-source project.
- To this YouTube tutorial by the channel DIY Machines
- To Aser Méndez for putting up with my crazy ideas and to Carlos Ruiz, the course professor, for his endless patience.
Comments