Skip to main content
Version: FILS English

PicoMatic

A compact CNC plotter controlled by a Raspberry Pi Pico 2W, moving a pencil in 3 axes (X, Y, Z) using stepper motors and drivers.

info

Author: Aliwi Walid
GitHub Project Link: https://github.com/UPB-PMRust-Students/project-AliwiWalid

Description​

This project consists of building a CNC plotter machine that uses a pencil as its tool head. It is designed to move across three axes: X, Y, and Z, using stepper motors and motor drivers. The system is controlled by a Raspberry Pi Pico 2W microcontroller, which receives G-code commands via USB serial communication. The commands are parsed on the Pico and translated into precise movements of the motors, allowing the machine to draw complex shapes automatically on paper. An external power supply is used to power the motors, providing enough current without overloading the Pico.

Motivation​

Initially I wanted to build a 3D printer, but due to the high cost, complexity and potential dangers with heating elements and mechanical failures, I decided to scale down the project to something safer and more achievable in the desired price range. The goal remained to build something which involves motion control and automation, where mechanical movement is precisely driven by software. And that is how I ended up choosing the CNC plotter as my project idea, as it shares a bunch of fundamental principles with a 3D printer, but clearly a lot cheaper and safer to build at home. This will help me continue my journey of learning about embedded programming and real time systems.

Architecture​

alt text

Log​

Week 5 – 11 May​

Since I had a clear idea of my project well before Week 7 and had already received approval, I ordered all the necessary components from AliExpress. This week, I 3D printed the structure of the CNC plotter and assembled the mechanical frame. I also created the initial architecture schematic and began researching which Rust crates I would need for motor control, serial communication, and other core features. One obstacle I encountered was that the STL file source I used did not specify the required screw sizes, which delayed the mechanical assembly. Here's how the build looked at this stage:

alt text

Week 12 – 18 May​

This week, I secured all the components to the CNC structure using the correct screws and mounted everything onto a wooden base to give it a solid foundation. I also decided to add an LCD screen to the project, which will display the current status while the CNC is running, such as when it's starting, drawing, or finished. I updated the system architecture and KiCad schematics to include this new addition.

On the software side, I wrote the initial code to allow the CNC to draw basic shapes like squares. It's a good starting point, but I’ll continue improving it so the machine can handle more complex drawings in the coming updates.

alt text

Week 19 - 25 May​

This week, i completed the code. I wrote the logic for all the GCode commands that i might use for my CNC, tested it on more complex drawings to make sure it can now draw arcs and full circles also using bresenham's algorithm, as suggested by my professor. I also completed the code for the display interface. To make it look better, i added a cardboard that will cover the wiring where there will also be a cutout for the display.

Hardware​

3Γ— 28BYJ-48 Stepper Motors Each stepper motor is used to drive movement along one of the three axesβ€”X, Y, and Z. They are each controlled by a dedicated ULN2003 driver board, with signal lines connected to the Raspberry Pi Pico via GPIO as follows:

Stepper 1: GPIO 15, 14, 16, 17

Stepper 2: GPIO 18, 19, 13, 12

Stepper 3: GPIO 20, 21, 11, 10

1Γ— 1.8 Inch LCD (ST7735, SPI) Used to display messages like β€œCNC starting to plot…”, β€œCNC plotting…”, and β€œCNC has finished plotting!”. Connected to the Raspberry Pi Pico via SPI0 as follows:

MOSI: GPIO 3

SCK: GPIO 2

DC (A0): GPIO 6

RESET: GPIO 7

CS: GPIO 5

VCC and GND connected to 3.3V and GND respectively.

CH340G USB-to-UART Converter This module establishes serial communication between the Raspberry Pi Pico and a host computer. It is used to send G-code commands from the host (via a Python script) to the Pico for real-time stepper control. The pin connections are:

CH340G TX β†’ Pico GPIO 1 (UART0 RX)

CH340G RX β†’ Pico GPIO 0 (UART0 TX)

External Power Supply A separate 5V external power source is used to power the stepper motors through the ULN2003 driver boards. This is necessary to avoid overloading the Raspberry Pi Pico, which cannot provide sufficient current for motor operation. Ground from the external power supply is tied to the system ground to ensure a common reference.

Here is what the hardware is looking like so far:

alt text

Schematics​

KiCad Schematic alt text

Bill of Materials​

DeviceUsagePrice
Raspberry Pi Pico 2WThe microcontroller39.66 RON
Debug ProbeThe debug probe66.17 RON
CH340GThe USB to UART convertor2.52 RON
28BYJ-48 + ULN2003Stepper motors + drivers27.1 RON for a set of 3
Male to male/female jumper wiresWires0.1 * 23 = 2.3 RON
Breadboard Power Supply + batteryExternal power for motors4.69 RON
1.8 inch TFT LCD ST7735LCD Display4.42 RON

Software​

LibraryDescriptionUsage
embassy-executorAsync/await executor optimized for embedded systemsRuns asynchronous tasks without an OS
embassy-embedded-halCollection of utilities to use embedded-hal and embedded-storage traits with EmbassyUsed for shared SPI communication
embassy-timeTimekeeping, delays, and timeoutsUsed for non-blocking delays and timeouts
embassy-syncno-std, no-alloc synchronization primitives with async support.Used to create a mutex for sharing the SPI bus
embassy-rpLibrary for peripheral accessInterfaces with RP2350 peripherals (GPIO, UART, etc.)
defmtLightweight and efficient logging framework for embedded systemsProvides low-overhead debug output
defmt-rttRTT backend for defmt loggingSends logs from device to host over RTT
heaplessstatic-friendly data structures without heap allocationUsed for queues, buffers, and collections without alloc
cortex-m-rtMinimal runtime for Cortex-M microcontrollersSets up vector table, stack, and entry point
embedded-graphics2D graphics library that is focused on memory constrained embedded devicesUsed to display the messages on the LCD
libmA Rust implementations of the C math libraryUsed to calculate the coordinates of points along the circle's circumference
beresenhamIterator-based integer-only implementation of Bresenham's line algorithmUsed to calculate points along arcs and circles
mipidsiMIPI Display Command Set compatible generic driverCrate used to initalize the ST7735 display
display-interface-spiSPI implementation for display interfacesUsed for implementing the interface of the ST7735

Python​

LibraryDescriptionUsage
timeThis module provides various functions to manipulate time values.Used to pause the program for 4 seconds between sending each G-code command.
serialAllows communication with devices over a serial port (e.g., USB, UART)Used to open a connection to the CNC machine via a specified serial port.
  1. inspiration