Week 8: Electronics Production

The focus of this week was producing a functional printed circuit board (PCB) using digital fabrication tools. The process involved generating fabrication files from a PCB design, milling the board using a PCB milling machine, soldering electronic components onto the board, and finally programming and testing the board to ensure it functions correctly.

By the end of the week, the goal was to have a fully assembled and operational PCB.

The workflow for this week included:

  • Understanding the structure and layers of a PCB
  • Preparing fabrication files from KiCad
  • Milling the PCB using a PCB milling machine
  • Soldering surface-mount components
  • Programming and testing the board

  • This week was guided by Saheen, Sibin, and Revisankar.



    Group Assignment Insights

    Click to view details on our Group Assignment page.

    The Roland Modela MDX-20 is a compact 3-axis (X, Y, Z) desktop milling machine used for precision fabrication tasks such as PCB prototyping. It is widely used in educational and small-scale production environments due to its reliability and fine control over toolpaths.


    The first test piece was traced using a 0.4 mm flat end mill, while the one on the right was done using a 0.2 mm V-bit. For the individual assignment, a V-bit is being used.

    Observations and Constraints

  • Minimum trace width: 0.3 mm (v-bit)
  • Minimum trace spacing: 0.4 mm

  • Smaller spacing increases risk of:
  • Trace bridging
  • Incomplete isolation

  • These values depend on:
  • Tool geometry
  • Machine calibration
  • Surface flatness





  • Introduction to PCBs

    The week began with a lecture presentation by Sibin, introducing the structure and components of a printed circuit board (PCB). This provided the foundational understanding required before moving into fabrication.



    A PCB mechanically supports and electrically connects electronic components through conductive pathways etched from copper sheets laminated onto an insulating substrate.



    Preparing Fabrication Files in KiCad

    After the introduction, the focus shifted to preparing fabrication files from KiCad.

    gerber2png Plugin

    The Gerber2PNG plugin was installed in KiCad to convert PCB fabrication files into PNG images suitable for the PCB milling workflow used in the lab.



    Using this plugin, the following files were generated:

    The gerber2png website allows you to download the following png files:

  • Traces Top Layer PNG - contains the copper traces to be milled
  • Drills Top Layer PNG - indicates hole locations
  • Outline Top layer PNG - defines the outer shape of the board

  • These files are later used to generate toolpaths for PCB milling.


    Figure: gerber2png


    Generating Toolpaths with Mods Project

    After preparing the PCB fabrication files, the next step was to generate toolpaths for milling the board. For this workflow, the Mods Project was used.

    Mods is a modular, browser-based software environment developed at MIT. It is commonly used in Fab Labs to convert PCB design files into machine instructions (G-code or RML) that can be executed by desktop PCB milling machines.

    In this case, Mods was used to convert the exported PNG trace and outline files into toolpaths for the milling machine.

    Mods can be accessed directly through a web browser. After opening the Mods interface, the PCB milling program is loaded.


    The loaded program usually contains the following modules:

  • Read PNG - imports the PNG file of the PCB traces or outline
  • Set PCB defaults - defines milling parameters
  • Mill raster 2D - generates the milling toolpath




  • PCB Production (Milling)


    The PCB blank was first fixed onto the bed of the Roland Modela MDX-20 using double-sided tape to ensure it remained stable during milling.



    Next, the offline version of Mods Project used in the lab was opened and the trace PNG generated from Gerber2PNG was loaded.



    Using an Allen key, the grub screw was loosened and the V-bit was inserted. The machine was then returned to the origin position. The bit was gently lowered until it touched the PCB surface, after which the grub screw was tightened. This procedure set the Z-axis reference for milling the traces.





    Milling Trace -Top Layer



    With the V-bit selected, the milling parameters were adjusted in Mods Project. The cut depth was set to 0.09 mm, and the toolpath was generated by clicking Calculate.

    After verifying the toolpath preview, the job was started by clicking Send File, which began milling the PCB traces on the Roland Modela MDX-20.


    Video: Changing the tool TO V-bit (0.2 mm) for tracing Top Layer.

    Video: Milling Trace - Top Layer.



    Image: Completed Trace Top Layer Milling

    Image: Changing the tool to 0.8 mm flat endmill for milling the drill file.




    Milling Drills -Top Layer



    Issue with Drill Holes in Mods

    While generating the toolpaths in Mods Project, an issue appeared when loading the drill PNG file.

    After loading the traces PNG, drill PNG, and outline PNG, the toolpaths were calculated using the Calculate function in Mods. The traces and outline appeared correctly in the calculated preview. However, when the drill PNG was loaded, the pin holes for the microcontroller (XIAO RP2040) were not visible in the calculated toolpath preview.

    This indicated that the milling machine would not recognize or mill those holes.

    Cause of the Issue

    The issue originated from a mismatch introduced during the Gerber-to-PNG conversion process.

    In the KiCad footprint for the Seeed Studio XIAO RP2040, the pin hole diameter was defined as 0.8 mm, which exactly matched the diameter of the drill bit used for milling. Due to a known bug in the Gerber2PNG plugin, a slight tolerance error was introduced during export.

    Because the hole diameter and tool diameter were identical, this small deviation prevented Mods from correctly recognizing the hole geometry during toolpath generation. Consequently, the holes were omitted from the preview.

    Solution

    In KiCad PCB Editor, the minimum through-hole constraint was first changed from 0.8 mm to 0.85 mm.



    To further resolve this issue, the footprint in KiCad had to be modified. Steps taken:

  • Open the PCB design in KiCad.
  • Locate the footprint for the XIAO RP2040.
  • Edit the pad drill diameter of the pin holes.
  • Increase the drill diameter from 0.8 mm to 0.85 mm.




  • Apply this change to all eight pin holes.
  • Save the updated footprint.
  • Regenerate the Gerber2PNG output files (drills outline PNG).
  • Reload the updated PNG files into Mods.
  • Result


    After increasing the drill hole diameter and regenerating the PNG files, the holes appeared correctly in the toolpath preview inside Mods. This confirmed that the milling machine would correctly recognize and mill the holes during fabrication.


    Image: Pinholes clearly shown.



    Image: Completed drill top layer milling.



    Milling Outline -Top Layer

    After the drills were completed, the outline PNG file was loaded into Mods Project. For this step, the tool remained the same as used for drilling: a 0.8 mm flat end mill. The outline toolpath was then calculated and sent to the Roland Modela MDX-20 to cut the PCB board out from the stock material.






    Image: Completed Outline Top Layer milling.

    After the milling was completed on the Roland Modela MDX-20, the PCB was carefully removed from the machine bed using a scraper.



    Any remaining adhesive from the double-sided tape was cleaned using an IPA (isopropyl alcohol) solution, which helped remove the sticky residue from the back of the board and left the PCB clean for the next step of assembly.



    After removing the PCB, the remaining material on the machine bed was also scraped off. A vacuum was then used to clean the milling area so the Roland Modela MDX-20 bed was ready for the next user.



    Accessing Components from the Lab Inventory (FabStash)

    To obtain the electronic components required for PCB assembly, the Fab Lab Kerala inventory system called FabStash is used. This platform allows students to search the lab inventory and request components needed for their projects.

    FabStash functions as a digital inventory management interface, making it easier to track available electronic components and their storage locations within the lab.

    Logging into FabStash:The FabStash system can be accessed through the lab inventory portal:

    inventory.fablabkerala.in

    After opening the website, users log in using their Fab Lab credentials. Once logged in, the interface displays all available electronic components stored in the lab inventory.

    Searching for Components:The inventory system allows users to quickly locate components required for PCB assembly.

    Using FabStash helps maintain accurate inventory records while ensuring that components are distributed efficiently among users.



    Collecting Components

    After milling the PCB, the required components were searched in FabStash. Most components were available in the inventory system, but the button and JST connector were not listed even though they were physically available. These were noted manually on the printed request sheet.



    Once the request was approved and printed, the inventory was visited and the required components were collected from their respective storage locations.



    All the collected components were placed on double-sided sticky tape attached to the printed component list to keep them organized and to prevent the tiny components from getting lost. After that, I moved to the soldering station, where a brief session on soldering techniques was conducted before assembling the board.



    Soldering

    Soldering Station Setup

    Before starting assembly, the basic soldering workstation setup was introduced. The station included the essential tools used for surface-mount soldering:




  • Soldering iron - used for heating pads and melting solder to attach components.
  • Fume extractor - removes solder fumes from the workspace for safer operation.
  • Soldering iron tip cleaner - used to keep the iron tip clean for better heat transfer.
  • Hot air blower - useful for reflow soldering or removing components.
  • Silicone work mat - heat-resistant surface that protects the workbench and keeps small parts organized.
  • Tweezers - used for accurately placing small surface-mount components.


  • This was my second time soldering. The first time was a few weeks earlier when I soldered header pins to a Seeed Studio XIAO RP2040.

    After collecting all the components, I moved to the soldering station where a short refresher session on surface-mount soldering was given before assembling the PCB.



    Interactive HTML BOM Plugin

    The Interactive HTML BOM (iBOM) plugin was installed in KiCad to support the soldering and assembly process. It generates an interactive HTML page where each component listed in the Bill of Materials is directly linked to its exact location on the PCB layout. This makes it easier to identify, locate, and place components accurately during soldering.

    Key features include:

  • Visual highlighting of components on the PCB
  • Clear guidance on where each component should be placed

  • Figure: Interactive bom


    Before soldering, the PCB surface was lightly sanded/cleaned to ensure better solder adhesion. The components were then carefully soldered onto the milled board.




    Soldering was a bit tricky at first and required patience, focus, and steady hands, especially when handling the small surface-mount components. With careful placement and controlled soldering, the components were gradually assembled onto the board.





    Testing


    A digital microscope was also available at the soldering station to inspect the joints closely. It helped check the quality of the solder connections, identify solder bridges, and ensure that the small surface-mount components were properly aligned and connected.

    After soldering the LEDs, I used a multimeter to check the continuity. Since LEDs are polarized components, incorrect orientation would prevent them from functioning. The multimeter helped verify the continuity and confirm that the LEDs were placed with the correct polarity.









    Programming

    After completing the soldering, the board was tested by running a Blink LED program using Arduino IDE.


    This board used the Seeed Studio XIAO ESP32C6, which required a different setup from the Seeed Studio XIAO RP2040 that I had previously used.


    To configure the board, I followed the setup guide from Seeed Studio.


    The required board package was installed, the correct board and port were selected in the Arduino IDE, and the Blink example program was uploaded.


    After uploading the program, the LED blinked as expected, confirming that the PCB was successfully fabricated, soldered, and functioning correctly.



    Visual Pin Mapping on the PCB for Programming reference

    #define LED_BUILTIN D0 // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); } // the loop function runs over and over again forever void loop() { digitalWrite(LED_BUILTIN, HIGH); // change state of the LED by setting the pin to the HIGH voltage level delay(500); // wait for a second digitalWrite(LED_BUILTIN, LOW); // change state of the LED by setting the pin to the LOW voltage level delay(100); // wait for a second }

    Hero Shot





    I took the programs from week 4, updated the pin numbers according to my PCB schematic, and ran the code; while I verified the basic LED blinking, I also wanted to test the button input and serial monitor programs.

    LED Chase with Push Button


    // Define names for each LED pin #define YELLOW D2 #define WHITE D0 // Define button pin #define BUTTON D8 // Time delay between LED changes (in milliseconds) #define time 100 // Store all LED pins inside an array // This lets us control them using a loop int leds[] = {YELLOW, WHITE}; // Total number of LEDs in the array int numLeds = 2; void setup() { // Set all LED pins as OUTPUT (they send voltage out) pinMode(YELLOW, OUTPUT); pinMode(WHITE, OUTPUT); // Set button as INPUT with internal pulldown resistor // When pressed, reads HIGH // When not pressed, reads LOW pinMode(BUTTON, INPUT_PULLDOWN); } void loop() { // Check if button is pressed if (digitalRead(BUTTON) == HIGH) { // If pressed, run LED chase pattern chase_2(); } else { // If not pressed, turn all LEDs OFF // Loop goes through each LED one by one for (int i = 0; i < numLeds; i++) { // leds[i] selects LED number 0,1,2,3 digitalWrite(leds[i], LOW); } } } // Function to run LEDs one after another void chase_2() { // Loop through each LED for (int i = 0; i < numLeds; i++) { // Turn current LED ON digitalWrite(leds[i], HIGH); // Wait for defined time delay(time); // Turn current LED OFF before moving to next digitalWrite(leds[i], LOW); } }


    Push Button & Serial Monitor


    #define BUTTON D8 int lastState = HIGH; void setup() { pinMode(BUTTON, INPUT_PULLUP); Serial.begin(9600); } void loop() { int currentState = digitalRead(BUTTON); if (lastState == HIGH && currentState == LOW) { Serial.println("Ouch, that hurts!"); } lastState = currentState; }



    Push Button, LED & Serial Monitor


    #define LED_PIN D0 #define BUTTON_PIN D8 bool blinking = false; bool lastButtonState = LOW; // Default state is LOW with pull-down bool ledState = LOW; unsigned long previousMillis = 0; const long interval = 500; void setup() { pinMode(LED_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT_PULLDOWN); // Internal pull-down enabled Serial.begin(9600); } void loop() { bool currentButtonState = digitalRead(BUTTON_PIN); // Detect rising edge (LOW → HIGH) if (lastButtonState == LOW && currentButtonState == HIGH) { blinking = !blinking; // Toggle blinking mode if (blinking) { Serial.println("ITS ON BABE"); } else { Serial.println("ITS OFF BABE"); digitalWrite(LED_PIN, LOW); ledState = LOW; } delay(50); // debounce } lastButtonState = currentButtonState; if (blinking) { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; ledState = !ledState; digitalWrite(LED_PIN, ledState); } } }



    Button Controlled Brightness


    #define LED_PIN D0 #define BUTTON_PIN D8 int brightness = 0; int stepSize = 64; bool lastButtonState = HIGH; void setup() { pinMode(LED_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); } void loop() { bool currentButtonState = digitalRead(BUTTON_PIN); if (lastButtonState == HIGH && currentButtonState == LOW) { brightness += stepSize; if (brightness > 255) { brightness = 0; } analogWrite(LED_PIN, brightness); delay(50); // debounce } lastButtonState = currentButtonState; }



    Insights

    This week made me realize how sensitive the transition from digital design to physical making actually is. Even something as small as a drill size matching the tool diameter caused a real issue, and fixing it meant going back and understanding what was actually happening instead of just trying things randomly.

    It also made the whole process feel more connected. Designing, milling, soldering, and testing are not separate steps, each one depends on the previous one being done right. It made me slow down, pay attention, and be more careful with decisions throughout the workflow.



    Source Files

  • Gerber Files
  • Gerber2PNG Files
  • Basic Blink xiaoESP32C6
  • LED Button Chase
  • Ouch That Hurts (Push Button)
  • Its ON Babe (LED, Button & Serial Monitor)
  • Button Controlled Brightness


  • References

    To better understand PCB structure and fabrication, I referred to the following resources:

  • How to make a PCB – PCB production process in 33 steps
  • What Are the Layers of a PCB (Printed Circuit Board)?