Group Assignment Individual Assignment SPI with SAMD21 NFC+Motor Board NFC Control MQTT Morse Code Device Design Files
Week 12

Machine Design

This week, I focused on designing, fabricating, and assembling a custom PCB. I used KiCad for schematic and PCB design, then fabricated the board using milling and laser etching, and finally assembled and tested it.

Learning Objectives

  • Select and use software for circuit board design
  • Demonstrate workflows used in circuit board design

  • Assignments

    Group Assignments

  • probe an input device's analog levels and digital signals

  • Individual Assignments

  • measure something: add a sensor to a microcontroller board that you have designed and read it

  • Group Assignment

    Group Assignment

    Learning Section

    Communication Protocols

    UART/I2C/SPI

    WiFi/Bluetooth/ZigBee

    NFC/RFID

    MQTT/HTTP/Websockets

    MQTT Process

    ESP-NOW WS2812B LED Control

    ESP-NOW is a wireless communication protocol defined by Espressif, which enables the direct, quick and low-power control of smart devices, without the need of a router. ESP-NOW can work with Wi-Fi and Bluetooth LE, and supports the ESP8266, ESP32, ESP32-S and ESP32-C series of SoCs. It's widely used in smart-home appliances, remote controlling, sensors, etc.

    Getting Started with ESP-NOW

    To communicate via ESP-NOW, you need to know the MAC Address of the ESP32 receiver. That's how you know to which device you'll send the data to. Each ESP32 has a unique MAC Address and that's how we identify each board to send data to it using ESP-NOW

    /*
    Rui Santos & Sara Santos - Random Nerd Tutorials
    Complete project details at https://RandomNerdTutorials.com/get-change-esp32-esp8266-mac-address-arduino/
    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.  
    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    */
    #include 
    #include 
    
    void readMacAddress(){
    uint8_t baseMac[6];
    esp_err_t ret = esp_wifi_get_mac(WIFI_IF_STA, baseMac);
    if (ret == ESP_OK) {
    	Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
    				baseMac[0], baseMac[1], baseMac[2],
    				baseMac[3], baseMac[4], baseMac[5]);
    } else {
    	Serial.println("Failed to read MAC address");
    }
    }
    
    void setup(){
    Serial.begin(115200);
    
    WiFi.mode(WIFI_STA);
    WiFi.STA.begin();
    
    Serial.print("[DEFAULT] ESP32 Board MAC Address: ");
    readMacAddress();
    }
    
    void loop(){
    
    }
    								  

    For better understanding, we'll call “sender” to ESP32 #1 and “receiver” to ESP32 #2.

    Here's what we should include in the sender sketch:

    • Initialize ESP-NOW;
    • Register a callback function upon sending data - the OnDataSent function will be executed when a message is sent. This can tell us if the message was successfully delivered or not;
    • Add a peer device (the receiver). For this, you need to know the receiver MAC address;
    • Send a message to the peer device.

    On the receiver side, the sketch should include:

    • Initialize ESP-NOW;
    • Register for a receive callback function (OnDataRecv). This is a function that will be executed when a message is received.
    • Inside that callback function, save the message into a variable to execute any task with that information.
    ESP-NOW works with callback functions that are called when a device receives a message or when a message is sent (you get if the message was successfully delivered or if it failed).

    typedef struct structName {
    	type member1;
    	type member2;
    	// ...
    } typedefName;
    Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");

    This is a ternery operator,replacing if-else statement. If the status is successful, then print 'Delivery Success' else print 'Delivery Fail'

    ESP32 Sender Code

    
    /*
    	Rui Santos & Sara Santos - Random Nerd Tutorials
    	Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
    	Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
    	The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
      */
      #include 
      #include 
      
      // REPLACE WITH YOUR RECEIVER MAC Address
      uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
      
      // Structure example to send data
      // Must match the receiver structure
      typedef struct struct_message {
    	char a[32];
    	int b;
    	float c;
    	bool d;
      } struct_message;
      
      // Create a struct_message called myData
      struct_message myData;
      
      esp_now_peer_info_t peerInfo;
      
      // callback when data is sent
      void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
    	Serial.print("\r\nLast Packet Send Status:\t");
    	Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
      }
       
      void setup() {
    	// Init Serial Monitor
    	Serial.begin(115200);
       
    	// Set device as a Wi-Fi Station
    	WiFi.mode(WIFI_STA);
      
    	// Init ESP-NOW
    	if (esp_now_init() != ESP_OK) {
    	  Serial.println("Error initializing ESP-NOW");
    	  return;
    	}
      
    	// Once ESPNow is successfully Init, we will register for Send CB to
    	// get the status of Trasnmitted packet
    	esp_now_register_send_cb(OnDataSent);
    	
    	// Register peer
    	memcpy(peerInfo.peer_addr, broadcastAddress, 6);
    	peerInfo.channel = 0;  
    	peerInfo.encrypt = false;
    	
    	// Add peer        
    	if (esp_now_add_peer(&peerInfo) != ESP_OK){
    	  Serial.println("Failed to add peer");
    	  return;
    	}
      }
       
      void loop() {
    	// Set values to send
    	strcpy(myData.a, "THIS IS A CHAR");
    	myData.b = random(1,20);
    	myData.c = 1.2;
    	myData.d = false;
    	
    	// Send message via ESP-NOW
    	esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
    	 
    	if (result == ESP_OK) {
    	  Serial.println("Sent with success");
    	}
    	else {
    	  Serial.println("Error sending the data");
    	}
    	delay(2000);
      }
    

    ESP32 receiver Code

    
    	/*
      Rui Santos & Sara Santos - Random Nerd Tutorials
      Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/  
      Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    */
    
    #include 
    #include 
    
    // Structure example to receive data
    // Must match the sender structure
    typedef struct struct_message {
        char a[32];
        int b;
        float c;
        bool d;
    } struct_message;
    
    // Create a struct_message called myData
    struct_message myData;
    
    // callback function that will be executed when data is received
    void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
      memcpy(&myData, incomingData, sizeof(myData));
      Serial.print("Bytes received: ");
      Serial.println(len);
      Serial.print("Char: ");
      Serial.println(myData.a);
      Serial.print("Int: ");
      Serial.println(myData.b);
      Serial.print("Float: ");
      Serial.println(myData.c);
      Serial.print("Bool: ");
      Serial.println(myData.d);
      Serial.println();
    }
     
    void setup() {
      // Initialize Serial Monitor
      Serial.begin(115200);
      
      // Set device as a Wi-Fi Station
      WiFi.mode(WIFI_STA);
    
      // Init ESP-NOW
      if (esp_now_init() != ESP_OK) {
        Serial.println("Error initializing ESP-NOW");
        return;
      }
      
      // Once ESPNow is successfully Init, we will register for recv CB to
      // get recv packer info
      esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
    }
     
    void loop() {
    
    }
    

    ESP32 MCODE(Color) Sender

    This code sends what brush size to select - 1,2,3 with 3 colors to select - RED, GREEN, BLUE.

    • M051 - Brush 1
    • M052 - Brush 2
    • M053 - Brush 3
    • M054 - LED OFF

    By default, the LED will be RED. You can add color parameters with the M Code to select color(RED, GREEN, BLUE). For. eg. M051 GREEN

    Firmware

    Firmware Urumbu

    Firmware to ESP32

    
    	/*
    	Rui Santos & Sara Santos - Random Nerd Tutorials
    	Modified by Ashish & ChatGPT for improved serial handling and user interaction.
    	Original: https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
      */
      
      #include < esp_now.h >
      #include < WiFi.h >
      
      // Replace with your receiver's MAC address
      uint8_t broadcastAddress[] = {0x7C, 0x2C, 0x67, 0x64, 0xBA, 0xF8}; //7C:2C:67:64:BA:F8
      
      int led;
      String receivedData = "";
      
      esp_now_peer_info_t peerInfo;
      
      // Optional: onboard LED pin for visual feedback (usually GPIO 2)
      const int onboardLED = 2;
      
      // Callback when data is sent
      void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
    	Serial.print("\r\nLast Packet Send Status:\t");
    	Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
      
    	// Blink onboard LED to indicate a send action
    	digitalWrite(onboardLED, HIGH);
    	delay(100);
    	digitalWrite(onboardLED, LOW);
      }
      
      void setup() {
    	// Init Serial Monitor
    	Serial.begin(115200);
    	WiFi.mode(WIFI_STA); // Set device as a Wi-Fi Station
      
    	// Set onboard LED pin as output
    	pinMode(onboardLED, OUTPUT);
    	digitalWrite(onboardLED, LOW);
      
    	// Info for user
    	Serial.println("ESP-NOW Command Sender Initialized");
    	Serial.println("Available Commands:");
    	Serial.println("  - M051 (LED 1)");
    	Serial.println("  - M052 (LED 2)");
    	Serial.println("  - M053 (LED 3)");
    	Serial.println("  - M054 (LED 4)");
    	Serial.println("Type your command and press Enter...\n");
      
    	// Init ESP-NOW
    	if (esp_now_init() != ESP_OK) {
    	  Serial.println("Error initializing ESP-NOW");
    	  return;
    	}
      
    	// Register callback for sent message
    	esp_now_register_send_cb(OnDataSent);
      
    	// Register peer
    	memcpy(peerInfo.peer_addr, broadcastAddress, 6);
    	peerInfo.channel = 0;
    	peerInfo.encrypt = false;
      
    	if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    	  Serial.println("Failed to add peer");
    	  return;
    	}
      }
      
      void loop() {
    	// Check if data is available in Serial
    	if (Serial.available() > 0) {
    	  char incomingChar = Serial.read();
      
    	  if (incomingChar != '\n') {
    		receivedData += incomingChar;
    	  } else {
    		receivedData.trim();
    		receivedData.toUpperCase();
      
    		Serial.print("Full command received: ");
    		Serial.println(receivedData);
      
    		esp_err_t result;
      
    		// Command handling
    		if(receivedData == "M051"){
    		  led = 1;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
      
    		}
      
    		else if (receivedData == "M051 GREEN") {
    		  led = 11;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		}
    		else if (receivedData == "M051 RED") {
    		  led = 12;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		} 
      
    		else if (receivedData == "M051 BLUE") {
    		  led = 13;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		}
      
    		else if (receivedData == "M052") {
    		  led = 2;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		}
    		else if (receivedData == "M052 GREEN") {
    		  led = 21;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		}
    		else if (receivedData == "M052 RED") {
    		  led = 22;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		} 
      
    		else if (receivedData == "M052 BLUE") {
    		  led = 23;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		} 
      
    		else if (receivedData == "M053 BLUE") {
    		  led = 3;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		} 
    		
    		else if (receivedData == "M053 GREEN") {
    		  led = 31;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		}
    		else if (receivedData == "M053 RED") {
    		  led = 32;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		} 
      
    		else if (receivedData == "M053 BLUE") {
    		  led = 33;
    		  result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		} 
    		
    		else if (receivedData == "M054") {
    		 	led = 0;
    			result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    		} 
    			   
    		
    		
      else if (receivedData == "HELP") {
    		  Serial.println("Available Commands:");
    		  Serial.println("  - M051 GREEN/RED/BLUE(LED 1)");
    		  Serial.println("  - M052 (LED 2)");
    		  Serial.println("  - M053 (LED 3)");
    		  Serial.println("  - M054 (LED 4)");
    		  receivedData = "";
    		  return;
    		} else {
    		  Serial.println("Unknown command. Type HELP to see available commands.");
    		  receivedData = "";
    		  return;
    		}
      
    		// Check send result
    		if (result == ESP_OK) {
    		  Serial.println("Command sent successfully");
    		} else {
    		  Serial.println("Failed to send command");
    		}
      
    		receivedData = ""; // Clear input buffer
    		delay(500); // Optional delay
    	  }
    	}
      }
      
    

    ESPNOW Reciever LED Control

    
    #include 
    #include < WiFi.h >
    #include < Adafruit_NeoPixel.h >
    
    #define PIN        0           // Change 'D0' to 0 if you're using GPIO0
    #define NUMPIXELS  7
    
    int led = -1;
    int lastLed = -1;
    int brush = 0;
    
    uint32_t color;
    uint32_t green, red, blue;
    
    Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
    
    // ✅ ESP-NOW receive callback
    void OnDataRecv(const esp_now_recv_info_t *recvInfo, const uint8_t *incomingData, int len) {
    	memcpy(&led, incomingData, sizeof(led));
    	// Serial.print("Bytes received: ");
    	// Serial.println(len);
    	Serial.print("LED value received: ");
    	Serial.println(led);
    }
    
    void setup() {
    	Serial.begin(115200);
    	WiFi.mode(WIFI_STA);
    
    	// Print MAC address (for pairing with sender)
    	Serial.print("Receiver MAC Address: ");
    	Serial.println(WiFi.macAddress());
    
    	if (esp_now_init() != ESP_OK) {
    	Serial.println("Error initializing ESP-NOW");
    	return;
    	}
    
    	esp_now_register_recv_cb(OnDataRecv);  // Register receive callback
    
    	// Initialize NeoPixels
    	pixels.begin();
    	pixels.clear();
    	pixels.show();
    
    		green=pixels.Color(0,150,0);
    		red=pixels.Color(150,0,0);
    		blue=pixels.Color(0,0,150);
    }
    
    void loop() {
    	if (led != lastLed) {
    	lastLed = led;
    	pixels.clear();
    
    	// Determine number of pixels to light up
    	switch (led) {
    		case 1: brush = 1; color=red; break;      
    		case 11: brush = 1; color=green; break;
    		case 12: brush = 1; color=red; break;
    		case 13: brush = 1; color=blue; break;
    
    		case 2: brush = 4; color=red;break;
    		case 21: brush = 4; color=green;break;
    		case 22: brush = 4; color=red;break;
    		case 23: brush = 4; color=blue;break;
    
    		case 3: brush = 7; color=red;break;
    		case 31: brush = 7; color=green;break;
    		case 32: brush = 7; color=red;break;
    		case 33: brush = 7; color=blue;break;
    
    		case 0: brush = 0; break;
    		default: brush = 0; break;
    	}
    
    	Serial.print("Brush level: ");
    	Serial.println(brush);
    
    	// Light up pixels
    	for (int i = 0; i < brush; i++) {
    		
    		pixels.setPixelColor(i, color);  // Green
    	}
    
    	pixels.show();
    	}
    }
    		 
    	

    Sending Brush Size and Color using HEX

    Sender Code

    
    	/*
    	Rui Santos & Sara Santos - Random Nerd Tutorials
    	Modified by Ashish & ChatGPT for improved serial handling and user interaction.
    	Original: https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
      */
      
      #include <esp_now.h>
      #include <WiFi.h>
      
      // Replace with your receiver's MAC address
      uint8_t broadcastAddress[] = {0x7C, 0x2C, 0x67, 0x64, 0xBA, 0xF8}; //7C:2C:67:64:BA:F8
      
      typedef struct struct_message {
    	int brushSize;
    	char hexColor[8];  // "#RRGGBB" + null terminator
      } struct_message;
      
      struct_message led;
      
      String receivedData = "";
      
      esp_now_peer_info_t peerInfo;
      
      // Optional: onboard LED pin for visual feedback (usually GPIO 2)
      const int onboardLED = 2;
      
      // Callback when data is sent
      void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
    	Serial.print("\r\nLast Packet Send Status:\t");
    	Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
      
    	// Blink onboard LED to indicate a send action
    	digitalWrite(onboardLED, HIGH);
    	delay(100);
    	digitalWrite(onboardLED, LOW);
      }
      
      void setup() {
    	// Init Serial Monitor
    	Serial.begin(115200);
    	WiFi.mode(WIFI_STA); // Set device as a Wi-Fi Station
      
    	// Set onboard LED pin as output
    	pinMode(onboardLED, OUTPUT);
    	digitalWrite(onboardLED, LOW);
      
    	// Info for user
    	Serial.println("ESP-NOW Command Sender Initialized");
    	Serial.println("Available Commands:");
    	Serial.println("  - M051 (LED 1)");
    	Serial.println("  - M052 (LED 2)");
    	Serial.println("  - M053 (LED 3)");
    	Serial.println("  - M054 (LED 4)");
    	Serial.println("Type your command and press Enter...\n");
      
    	// Init ESP-NOW
    	if (esp_now_init() != ESP_OK) {
    	  Serial.println("Error initializing ESP-NOW");
    	  return;
    	}
      
    	// Register callback for sent message
    	esp_now_register_send_cb(OnDataSent);
      
    	// Register peer
    	memcpy(peerInfo.peer_addr, broadcastAddress, 6);
    	peerInfo.channel = 0;
    	peerInfo.encrypt = false;
      
    	if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    	  Serial.println("Failed to add peer");
    	  return;
    	}
      }
      
      void loop() {
    	if (Serial.available()) {
    	  receivedData = Serial.readStringUntil('\n');  // Read until newline
    	  receivedData.trim();                          // Remove trailing \r or whitespace
      
    	  if (receivedData.length() == 0) return;
      
    	  // Extract command and color
    	  int spaceIndex = receivedData.indexOf(' ');
    	  String command, hexColor;
      
    	  if (spaceIndex != -1) {
    		command = receivedData.substring(0, spaceIndex);
    		hexColor = receivedData.substring(spaceIndex + 1);
    		hexColor.trim();
    		hexColor.toUpperCase();  // Make sure color is uppercase
    		hexColor.toCharArray(led.hexColor, sizeof(led.hexColor));
    	  } else {
    		command = receivedData;
    		strcpy(led.hexColor, "#FFFFFF");
    	  }
      
    	  command.toUpperCase();  // Convert command to uppercase for matching
      
    	  if (command == "HELP") {
    		Serial.println("Available Commands:");
    		Serial.println("  - M051 <#HEXCOLOR> (LED 1)");
    		Serial.println("  - M052 (LED 2)");
    		Serial.println("  - M053 (LED 3)");
    		Serial.println("  - M054 (LED 4)");
    		return;
    	  }
      
    	  if (command == "M051") {
    		led.brushSize = 1;
    	  } else if (command == "M052") {
    		led.brushSize = 2;
    	  } else if (command == "M053") {
    		led.brushSize = 3;
    	  } else if (command == "M054") {
    		led.brushSize = 0;
    	  } else {
    		Serial.println("Unknown command. Type HELP to see available commands.");
    		return;
    	  }
      
    	  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *)&led, sizeof(led));
    	  Serial.print("Sending -> Brush Size: ");
    	  Serial.print(led.brushSize);
    	  Serial.print(" | Color: ");
    	  Serial.println(led.hexColor);
    	  Serial.println(result == ESP_OK ? "Command sent successfully" : "Failed to send command");
    	  delay(500);
    	}
      }
      
      
    

    Recieving Brush Size and Hex Color

    
    #include <esp_now.h>
    #include <WiFi.h>
    #include <Adafruit_NeoPixel.h>
    
    #define PIN        0
    #define NUMPIXELS  7
    
    typedef struct struct_message {
    	int brushSize;
    	char hexColor[8];  // "#RRGGBB" + null terminator
    } struct_message;
    
    struct_message ledData;
    
    int lastBrushSize = -1;
    int brush = 0;
    uint32_t color = 0;
    
    Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
    
    // Convert HEX string to RGB color
    uint32_t hexToColor(const String &hex) {
    	String hexClean = hex;
    	if (hexClean.startsWith("#")) hexClean.remove(0, 1);
    	long number = strtol(hexClean.c_str(), NULL, 16);
    	int r = (number >> 16) & 0xFF;
    	int g = (number >> 8) & 0xFF;
    	int b = number & 0xFF;
    	return pixels.Color(r, g, b);
    }
    
    // Callback when data is received
    void OnDataRecv(const esp_now_recv_info_t *recvInfo, const uint8_t *incomingData, int len) {
    	memcpy(&ledData, incomingData, sizeof(ledData));
    	Serial.print("Brush Size: ");
    	Serial.println(ledData.brushSize);
    	Serial.print("Hex Color: ");
    	Serial.println(ledData.hexColor);
    
    	color = hexToColor(String(ledData.hexColor));
    	Serial.print("RGB Color Code: ");
    	Serial.println(color);
    }
    
    void setup() {
    	Serial.begin(115200);
    	WiFi.mode(WIFI_STA);
    
    	Serial.print("Receiver MAC Address: ");
    	Serial.println(WiFi.macAddress());
    
    	if (esp_now_init() != ESP_OK) {
    	Serial.println("Error initializing ESP-NOW");
    	return;
    	}
    
    	esp_now_register_recv_cb(OnDataRecv);
    
    	pixels.begin();
    	pixels.clear();
    	pixels.show();
    }
    
    void loop() {
    	if (ledData.brushSize != lastBrushSize || brush > 0) {
    	lastBrushSize = ledData.brushSize;
    	
    	switch (ledData.brushSize) {
    		case 1: brush = 1; break;
    		case 2: brush = 4; break;
    		case 3: brush = 7; break;
    		default: brush = 0; break;
    	}
    
    	pixels.clear();
    	for (int i = 0; i < brush; i++) {
    		pixels.setPixelColor(i, color);
    	}
    	pixels.show();
    
    	Serial.print("Lighting up ");
    	Serial.print(brush);
    	Serial.println(" pixels.");
    	}
    }
    		
    		
    

    Neoπ Wireless CNC Controller (3-axis)

    The NeoPi Wireless CNC Controller was designed by Saheen Palayi, our instructor. It offers a 3 Axis CNC Contoller which runs using the ESP32 as the Main Control Unit of the controller. We used the DRV8825 as motor drivers for the two motors.

    Neoπ CNC Controller - Documentation

    The CNC Machine works on Core X Y Configuration.

    Firmware - GRBL ESP32

    GRBL ESP32 Github
    SERCOM SPI

    Design Files

    You can download my design files from below

    • NFC+Motor XIAO ESP32C6 Board

      Milling Files

    • KiCad Files

      Laser Files

    x
    Menu