This is an old revision of the document!
This project is an interactive, standalone CNC-style drawing machine powered by the ATmega328P microcontroller. It translates user inputs from a resistive touch panel or pre-loaded data into precise mechanical motion using NEMA 17 stepper motors. The system features a built-in UI displayed on an ILI9486 LCD, allowing the user to select between distinct operating modes via a potentiometer.
Mini-Plotter is an automated drawing system based on the ATmega328P-XMINI. The system operates as a closed-loop interface where user input is captured via a resistive touch screen or an SD card and translated into physical motion through two NEMA 17 stepper motors. The project logic is divided into three functional layers:
| Component | Specification | Role/Connection |
|---|---|---|
| ATmega328P-XMINI | 8-bit Microcontroller | Central processing and logic control |
| NEMA 17 Stepper | 1.8° Step Angle, High Torque | Dual-axis (X-Y) mechanical movement |
| DRV8825 Driver | Up to 1/32 microstepping | Current control for stepper motors |
| ILI9486 LCD Module | 3.5” TFT with Integrated SD Slot | UI display and data storage (SPI Interface) |
| Resistive Touch | 4-Wire Overlay | Coordinate input for manual drawing |
| Potentiometer | 10k Ohm Rotary | Menu navigation and mode selection |
| Power Supply | 12V DC / 2A | Powering motors and logic (via step-down) |
The hardware architecture of the mini-plotter has been fully designed, verified, and mapped. The implementation is executed in two concurrent phases:
Due to the high number of peripherals required by this project (2 stepper drivers, an 8-bit parallel display, an SPI SD card reader, a touch panel, and a navigation potentiometer), the ATmega328P's pin map is utilized at 100% capacity.
To achieve this without using external multiplexers or IO expanders, several hardware-level optimizations were implemented:
| Component | Pin Name | MCU Pin | Type | Technical Justification |
|---|---|---|---|---|
| X-Axis Driver (A1) | STEP | PD2 | Digital Out | Dedicated hardware pin for step pulses. |
| DIR | PD3 | Digital Out | Direction control logic signal. | |
| Y-Axis Driver (A2) | STEP | PD4 | Digital Out | Dedicated hardware pin for step pulses. |
| DIR | PD5 | Digital Out | Direction control logic signal. | |
| SD Card Module | SD_SS | PB2 | Digital Out | Dedicated Slave Select line for SPI. |
| SD_DI (MOSI) | PB3 | Hardware SPI | Master Out Slave In - standard high-speed data line. | |
| SD_DO (MISO) | PB4 | Hardware SPI | Master In Slave Out - standard high-speed data line. | |
| SD_SCK | PB5 | Hardware SPI | Serial Clock line to synchronize data transfers. | |
| ILI9486 LCD (Control) | LCD_RST | PC4 | Digital Out | System reset line for the display controller. |
| LCD_CS | PC3 | Digital Out | Chip Select line for the parallel display bus. | |
| LCD_RS | PC2 | Digital Out | Register Select (Commands vs. Pixel Data). | |
| LCD_WR | PC1 | Digital Out | Write strobe signal clocking the 8-bit bus. | |
| LCD_RD | +5V | Hardwired | Optimization: Permanently tied to High. The MCU only writes data; reading from the display is disabled to save 1 digital GPIO pin. | |
| ILI9486 LCD (Data) | LCD_D0 - D1 | PD0 - PD1 | Parallel Bus | Lower 2 bits of the 8-bit data bus. |
| LCD_D2 - D3 | PD6 - PD7 | Parallel Bus | Middle bits of the 8-bit data bus. | |
| LCD_D4 - D5 | PB0 - PB1 | Parallel Bus | Higher bits of the 8-bit data bus. | |
| LCD_D6 - D7 | PC0 - PC5 | Parallel Bus | Remaining bits routing the full parallel byte. |
The circuit diagram is structurally grouped into three distinct functional blocks to isolate high-power inductive loads from sensitive logic electronics:
The main system power is provided by an external 12V DC / 2A adapter connected through a DC Barrel Jack (J1).
Two Pololu DRV8825 breakout boards control the NEMA 17 stepper motors.
The display block handles the routing for the 3.5” TFT LCD Shield. It separates the high-volume display pixel transfers onto an 8-bit parallel topology while routing the SD Card operations through the standardized hardware SPI pins (`MOSI`, `MISO`, `SCK`).
The physical setup for the initial milestone focuses entirely on the core power distribution network and the dual-axis motion subsystem. The ATmega328P-XMINI development board is mounted alongside the custom-wired breakout board housing the two DRV8825 stepper drivers and the LM2596 buck converter module.
To provide concrete validation of hardware functionality and signal integrity under heavy dynamic loads, a continuous firmware diagnostic routine was uploaded to the microcontroller. The routine commands both NEMA 17 stepper motors to cycle recursively through a strict directional pattern:
Given that the NEMA 17 motors feature a standard $1.8^\circ$ step angle (requiring 200 full steps per single $360^\circ$ rotation) and the DRV8825 pins M0-M2 are left floating (defaulting to full-step mode), the control script alternates precisely between sending a train of 600 pulses for the forward phase and 400 pulses for the reverse phase via the `STEP` pins (`PD2` and `PD4`).
The successful and continuous execution of this directional cycle validates several critical design factors of the current hardware revision:
The software implementation is fully functional and successfully integrated with the hardware. The system is capable of initializing peripheral devices (TFT LCD, SD Card, Stepper Motors), processing user commands via a non-blocking UART interface, and executing physical movements by reading and parsing G-code (.GCO files) directly from the SD card. The entire kinetics engine operates asynchronously via hardware interrupts, ensuring highly precise and smooth 2D plotting.
To ensure maximum performance and strict timing, standard Arduino libraries (such as Serial or Stepper.h) were intentionally avoided in favor of bare-metal AVR C++ programming. The only external third-party library used is:
All other modules (UART, LCD rendering, and Stepper control) were written entirely from scratch using direct register manipulation (e.g., PORTA, TCCR1B) to maintain absolute control over CPU cycles.
The defining novel element of this software architecture is the Custom Interrupt-Driven Kinetics Engine. In standard hobbyist plotters, stepper motors are driven using blocking delay loops (e.g., _delay_ms()), which paralyzes the microcontroller. In this project, the Bresenham Line Algorithm is deeply integrated into an AVR Hardware Timer Interrupt Service Routine (ISR). This allows the ATmega2560 to pulse the motors seamlessly in the background at exactly 4,000 Hz, while the main loop simultaneously parses complex G-code, updates the UI, and communicates over Serial without dropping a single physical step.
The project heavily applies concepts taught during the laboratory sessions:
Timer1 is configured in CTC (Clear Timer on Compare Match) mode with a custom prescaler and compare match register (OCR1A = 499). This triggers an ISR(TIMER1_COMPA_vect) exactly 4,000 times per second for high-resolution 1/16th Microstepping control.UBRR0, UCSR0A, and UDR0 registers for a non-blocking 115200 baud command-line interface.PORTA, PORTF) for maximum switching speed on the stepper direction/step pins and LCD data buses.
The codebase is heavily decoupled and structured into independent C++ modules (stepper, uart, lcd, gcode, ui, sd_handler) interconnected through a shared globals state.
gcode module, it invokes moveTo(). The moveTo() function calculates the discrete step vectors and safely loads them into volatile memory. The Timer1 ISR then automatically takes over, converting those vectors into physical step pulses asynchronously.
To manage the user interface and system modes without blocking the main execution loop, a Finite State Machine (FSM) was implemented. The system operates in one of four distinct states at any given time, defined by an enum:
STATE_MAIN_MENUSTATE_SD_MENUSTATE_TOUCH_DRAWSTATE_HOME
The FSM is driven by the UART non-blocking parser. When a user issues a command (such as SELECT 1 or BACK), the parser acts as a state transition controller, updating the currentState variable and setting a needsRendering boolean flag. The primary infinite loop evaluates a switch(currentState) statement and routes execution to the appropriate module to redraw the TFT LCD.
This FSM architectural pattern is critical: it prevents the microcontroller from getting trapped in nested sub-menu loops. Because the state machine evaluates and exits rapidly, the main loop is free to continuously poll for new serial commands, read the SD card, and pass coordinates to the interrupt-driven kinetic engine simultaneously.
drv8825-stepper-motor-driver-arduino-tutorial[Stepper Motor Setup]