UC2 Logo UC2 ESP32 Flashing Tool

Quickly install and update firmware for UC2 ESP32 boards in your browser – no extra software required!

Ask questions in our Forum

1. Install ESP32 Drivers

Many ESP32 boards use USB-to-UART chips like CP2102 or CH340. If your board isn’t recognized, install the correct driver:

For other OS or details, see this driver installation tutorial.

2. Camera Software

For Daheng or HIK cameras, see:

The actual camera model you have (e.g. Mercury 2 1220 vs. MV-CE060-10UC) may differ from what’s on our website. Always confirm with the manufacturer’s official info.

3. Flash the Firmware

Select your UC2 device and click “Install” to flash your ESP32 with the UC2 firmware.

ESP32 WEMOS D1 R32-based UC2 board

This is an off-the-shelf board that can be used with a CNC Shield v3.
More info at here.

Pin Layout


            // ESP32-WEMOS D1 R32
            const int PIN_DEF_MOTOR_DIR_A = 0;
            const int PIN_DEF_MOTOR_DIR_X = GPIO_NUM_16;
            const int PIN_DEF_MOTOR_DIR_Y = GPIO_NUM_27;
            const int PIN_DEF_MOTOR_DIR_Z = GPIO_NUM_14;
            const int PIN_DEF_MOTOR_STP_A = 0;
            const int PIN_DEF_MOTOR_STP_X = GPIO_NUM_26;
            const int PIN_DEF_MOTOR_STP_Y = GPIO_NUM_25;
            const int PIN_DEF_MOTOR_STP_Z = GPIO_NUM_17;
            const int PIN_DEF_MOTOR_EN_A = GPIO_NUM_12;
            const int PIN_DEF_MOTOR_EN_X = GPIO_NUM_12;
            const int PIN_DEF_MOTOR_EN_Y = GPIO_NUM_12;
            const int PIN_DEF_MOTOR_EN_Z = GPIO_NUM_12;
            const bool PIN_DEF_MOTOR_EN_A_INVERTED = true;
            const bool PIN_DEF_MOTOR_EN_X_INVERTED = true;
            const bool PIN_DEF_MOTOR_EN_Y_INVERTED = true;
            const bool PIN_DEF_MOTOR_EN_Z_INVERTED = true;
  
            const int PIN_DEF_LASER_1 = GPIO_NUM_18;
            const int PIN_DEF_LASER_2 = GPIO_NUM_19;
            const int PIN_DEF_LASER_3 = 0; //GPIO_NUM_21
  
            const int PIN_DEF_LED = GPIO_NUM_4;
            const int PIN_DEF_LED_NUM = 64;
  
            const int PIN_DEF_END_X = GPIO_NUM_13;
            const int PIN_DEF_END_Y = GPIO_NUM_5;
            const int PIN_DEF_END_Z = GPIO_NUM_23;
  
            const String PIN_PS4_MAC_DEF = "1a:2b:3c:01:01:01";
            const int PIN_PS4_ENUM_DEF = 2;
  
  
            #define WEMOS_D1_R32_BOARD_NAME "ESPDUINO-32 Wemos D1 R32"
  
            // timer definitions
            #define WEMOS_D1_R32_STEP_TIMER_GROUP TIMER_GROUP_0
            #define WEMOS_D1_R32_STEP_TIMER_INDEX TIMER_0
  
            // Define step pulse output pins.
            #define WEMOS_D1_R32_X_STEP_PIN          GPIO_NUM_26
            #define WEMOS_D1_R32_Y_STEP_PIN          GPIO_NUM_25
            #define WEMOS_D1_R32_Z_STEP_PIN          GPIO_NUM_17
            #define WEMOS_D1_R32_A_STEP_PIN          GPIO_NUM_19
  
            // Define step direction output pins. NOTE: All direction pins must be on the same port.
            #define WEMOS_D1_R32_X_DIRECTION_PIN     GPIO_NUM_16
            #define WEMOS_D1_R32_Y_DIRECTION_PIN     GPIO_NUM_27
            #define WEMOS_D1_R32_Z_DIRECTION_PIN     GPIO_NUM_14
            #define WEMOS_D1_R32_A_DIRECTION_PIN     GPIO_NUM_18
  
            #define WEMOS_D1_R32_X_END_STOP          GPIO_NUM_13 // arduino 9
            #define WEMOS_D1_R32_X_END_STOP          GPIO_NUM_5  // arduino 10
            #define WEMOS_D1_R32_X_END_STOP          GPIO_NUM_23  // arduino 11
  
  
            // Define stepper driver enable/disable output pin(s).
            #define WEMOS_D1_R32_STEPPERS_ENABLE_PIN GPIO_NUM_12
  
            // Define homing/hard limit switch input pins and limit interrupt vectors.
            #define WEMOS_D1_R32_X_LIMIT_PIN         GPIO_NUM_13
            #define WEMOS_D1_R32_Y_LIMIT_PIN         GPIO_NUM_5
            #define WEMOS_D1_R32_Z_LIMIT_PIN         GPIO_NUM_23
  
            // Define spindle enable and spindle direction output pins.
            #define WEMOS_D1_R32_SPINDLE_ENABLE_PIN  GPIO_NUM_18
            #define WEMOS_D1_R32_SPINDLEPWMPIN       GPIO_NUM_19
  
            // Define flood enable output pin.
            #define WEMOS_D1_R32_COOLANT_FLOOD_PIN   GPIO_NUM_32
  
            // Define user-control CONTROLs (cycle start, reset, feed hold) input pins.
            #define WEMOS_D1_R32_RESET_PIN           GPIO_NUM_2
            #define WEMOS_D1_R32_FEED_HOLD_PIN       GPIO_NUM_4
            #define WEMOS_D1_R32_CYCLE_START_PIN     GPIO_NUM_35
  
            // Define probe switch input pin.
            #define WEMOS_D1_R32_PROBE_PIN           GPIO_NUM_39
  
            #define WEMOS_D1_R32_UART2_RX_PIN            GPIO_NUM_33
            #define WEMOS_D1_R32_UART2_TX_PIN            GPIO_NUM_32
            #define WEMOS_D1_R32_MODBUS_DIRECTION_PIN    GPIO_NUM_15
            #define WEMOS_D1_R32_MODBUS_BAUD             19200
  
  
            // Pin mapping when using SPI mode.
            // With this mapping, SD card can be used both in SPI and 1-line SD mode.
            // Note that a pull-up on CS line is required in SD mode.
            #define WEMOS_D1_R32_PIN_NUM_MISO        GPIO_NUM_19
            #define WEMOS_D1_R32_PIN_NUM_MOSI        GPIO_NUM_23
            #define WEMOS_D1_R32_PIN_NUM_CLK         GPIO_NUM_18
            #define WEMOS_D1_R32_PIN_NUM_CS          GPIO_NUM_5
          

ESP32 DEV-based UC2 standalone board V1 (deprecated)

Design files can be found here.

Pin Layout


            // UC2 STandalone V1
            const int PIN_DEF_MOTOR_DIR_A = GPIO_NUM_21;
            const int PIN_DEF_MOTOR_DIR_X = GPIO_NUM_33;
            const int PIN_DEF_MOTOR_DIR_Y = GPIO_NUM_16;
            const int PIN_DEF_MOTOR_DIR_Z = GPIO_NUM_14;
            const int PIN_DEF_MOTOR_STP_A = GPIO_NUM_22;
            const int PIN_DEF_MOTOR_STP_X = GPIO_NUM_2;
            const int PIN_DEF_MOTOR_STP_Y = GPIO_NUM_27;
            const int PIN_DEF_MOTOR_STP_Z = GPIO_NUM_12;
            const int PIN_DEF_MOTOR_EN_A = GPIO_NUM_13;
            const int PIN_DEF_MOTOR_EN_X = GPIO_NUM_13;
            const int PIN_DEF_MOTOR_EN_Y = GPIO_NUM_13;
            const int PIN_DEF_MOTOR_EN_Z = GPIO_NUM_13;
            const bool PIN_DEF_MOTOR_EN_A_INVERTED = true;
            const bool PIN_DEF_MOTOR_EN_X_INVERTED = true;
            const bool PIN_DEF_MOTOR_EN_Y_INVERTED = true;
            const bool PIN_DEF_MOTOR_EN_Z_INVERTED = true;
  
            const int PIN_DEF_LASER_1 = GPIO_NUM_4;
            const int PIN_DEF_LASER_2 = GPIO_NUM_15;
            const int PIN_DEF_LASER_3 = 0; //GPIO_NUM_21
  
            const int PIN_DEF_LED = GPIO_NUM_17;
            const int PIN_DEF_LED_NUM = 25;
  
            const int PIN_DEF_END_X = GPIO_NUM_10;
            const int PIN_DEF_END_Y = GPIO_NUM_11;
            const int PIN_DEF_END_Z = 0;
  
            const String PIN_PS4_MAC_DEF = "1a:2b:3c:01:01:01";
            const int PIN_PS4_ENUM_DEF = 2;
          

ESP32 DEV-based UC2 standalone board V2

Design files: here.

Pin Layout


            // UC2 STandalone V2
            const int PIN_DEF_MOTOR_DIR_A = GPIO_NUM_21;
            const int PIN_DEF_MOTOR_DIR_X = GPIO_NUM_33;
            const int PIN_DEF_MOTOR_DIR_Y = GPIO_NUM_16;
            const int PIN_DEF_MOTOR_DIR_Z = GPIO_NUM_14;
            const int PIN_DEF_MOTOR_STP_A = GPIO_NUM_22;
            const int PIN_DEF_MOTOR_STP_X = GPIO_NUM_2;
            const int PIN_DEF_MOTOR_STP_Y = GPIO_NUM_27;
            const int PIN_DEF_MOTOR_STP_Z = GPIO_NUM_12;
            const int PIN_DEF_MOTOR_EN_A = GPIO_NUM_13;
            const int PIN_DEF_MOTOR_EN_X = GPIO_NUM_13;
            const int PIN_DEF_MOTOR_EN_Y = GPIO_NUM_13;
            const int PIN_DEF_MOTOR_EN_Z = GPIO_NUM_13;
            const bool PIN_DEF_MOTOR_EN_A_INVERTED = true;
            const bool PIN_DEF_MOTOR_EN_X_INVERTED = true;
            const bool PIN_DEF_MOTOR_EN_Y_INVERTED = true;
            const bool PIN_DEF_MOTOR_EN_Z_INVERTED = true;
  
            const int PIN_DEF_LASER_1 = GPIO_NUM_17;
            const int PIN_DEF_LASER_2 = GPIO_NUM_4;
            const int PIN_DEF_LASER_3 = GPIO_NUM_15;
  
            const int PIN_DEF_LED = GPIO_NUM_32;
            const int PIN_DEF_LED_NUM = 25;
  
            const int PIN_DEF_END_X = GPIO_NUM_34;
            const int PIN_DEF_END_Y = GPIO_NUM_35;
            const int PIN_DEF_END_Z = 0;
  
            const String PIN_PS4_MAC_DEF = "1a:2b:3c:01:01:01";
            const int PIN_PS4_ENUM_DEF = 2;
            

This board is the updated version of the V1 with additional transistors to control High Power LEDs. It also features an updated pin layout to access more functionalities of the ESP32. More information can be found here.

ESP32 DEV-based UC2 standalone board V3

Updated version of the V2 with transistors, port extenders, etc. More info here.

Pin Layout


            // UC2 STandalone V3
            const char * pindefName = "UC2_3";
  
            int8_t MOTOR_A_STEP = GPIO_NUM_15;
            int8_t MOTOR_X_STEP = GPIO_NUM_16;
            int8_t MOTOR_Y_STEP = GPIO_NUM_14;
            int8_t MOTOR_Z_STEP = GPIO_NUM_0;
  
            bool MOTOR_ENABLE_INVERTED = true;
            bool MOTOR_AUTOENABLE = true;
            bool useFastAccelStepper = true;
            int8_t AccelStepperMotorType = 1;
  
            int8_t LASER_1 = GPIO_NUM_12;
            int8_t LASER_2 = GPIO_NUM_4;
            int8_t LASER_3 = GPIO_NUM_2;
  
            int8_t LED_PIN = GPIO_NUM_13;
            int8_t LED_COUNT = 64;
  
            // FIXME: Is this redudant?!
            int8_t PIN_DEF_END_X = disabled;
            int8_t PIN_DEF_END_Y = disabled;
            int8_t PIN_DEF_END_Z = disabled;
            int8_t DIGITAL_IN_1 = PIN_DEF_END_X;
            int8_t DIGITAL_IN_2 = PIN_DEF_END_Y;
            int8_t DIGITAL_IN_3 = PIN_DEF_END_Z;
  
            // const char * PSX_MAC = "1a:2b:3c:01:01:04";
            // int8_t PSX_CONTROLLER_TYPE = 2; // 1: PS3, 2: PS4
            bool enableBlueTooth = true;
            bool useBtHID = true;
  
            int8_t JOYSTICK_SPEED_MULTIPLIER = 30;
            int8_t JOYSTICK_MAX_ILLU = 100;
            int8_t JOYSTICK_SPEED_MULTIPLIER_Z = 30;
  
            // for caliper
            int8_t X_CAL_DATA = GPIO_NUM_32;
            int8_t Y_CAL_DATA = GPIO_NUM_34;
            int8_t Z_CAL_DATA = GPIO_NUM_36;
            int8_t X_CAL_CLK = GPIO_NUM_33;
            int8_t Y_CAL_CLK = GPIO_NUM_35;
            int8_t Z_CAL_CLK = GPIO_NUM_17;
  
            // I2c
            int8_t I2C_SCL = GPIO_NUM_22;
            int8_t I2C_SDA = GPIO_NUM_21;
            int8_t I2C_ADD = 0x27;
            gpio_num_t  I2C_INT = GPIO_NUM_27;
  
            // SPI
            int8_t SPI_MOSI = GPIO_NUM_23;
            int8_t SPI_MISO = GPIO_NUM_19;
            int8_t SPI_SCK = GPIO_NUM_18;
            int8_t SPI_CS = GPIO_NUM_5;
  
            // WiFI
            bool enableWifi = false;
            
        

This board is the updated version of the V2 with additional transistors to control High Power LEDs and a port extender to drive the dirrection and enabling pins of the Motors. The board also enables the use of linear encoders that are used in callipers. It also features an updated pin layout to access more functionalities of the ESP32. More information can be found here.

ESP32 DEV-based UC2 standalone board V3 (BETA)

Based on new firmware (reworkBD). More info here.

ESP32 DEV-based UC2 standalone board V4

Updated version of the V3 with enhanced features. More info here.

Pin Layout


              //This is for the standalone aka mAIkroscope::mainboard Rev. G, dated 2025-08-15.
              /*
              New in this Hardware Rev: 
              3 flicker-less LED drivers with field-settable current, 
              CAN transceiver with FRAME-backbone-compatible 12V+XH port, 
              XH 6-pin port to connect directly to LASERBOX, 
              XH and SH ports with pinout identical to off-the-shelf endstop boards
              */

              #pragma once
              #include "Arduino.h"
              #include "PinConfigDefault.h"

              // only for linting
              #define MOTOR_CONTROLLER
              #define USE_TCA9535
              #define BLUETOOTH
              #define BTHID
              //#define WIFI
              #define HOME_MOTOR
              #define LASER_CONTROLLER
              #define DIGITAL_IN_CONTROLLER 
              #define LED_CONTROLLER

              struct UC2_4 : PinConfig
              {
                  /*
                  This is the newest electronics where direction/enable are on a seperate port extender
                  */
                
                  const char * pindefName = "UC2_4";
                  const unsigned long BAUDRATE = 115200;

                  int8_t MOTOR_A_STEP = GPIO_NUM_15;
                  int8_t MOTOR_X_STEP = GPIO_NUM_16;
                  int8_t MOTOR_Y_STEP = GPIO_NUM_14;
                  int8_t MOTOR_Z_STEP = GPIO_NUM_0;
                  bool isDualAxisZ = false;

                  // THIS LIVES ON TCA
                  int8_t MOTOR_ENABLE = 0; 
                  int8_t MOTOR_X_DIR = 1;
                  int8_t MOTOR_Y_DIR = 2;
                  int8_t MOTOR_Z_DIR = 3;
                  int8_t MOTOR_A_DIR = 4;

                        /*
                  WARNING PLEASE HANDLE WITH CARE
                  */
                  const bool dumpHeap = false;
                  const uint16_t DEFAULT_TASK_PRIORITY = 0;
                  const uint16_t MAIN_TASK_STACKSIZE = 8128;
                  const uint16_t ANALOGJOYSTICK_TASK_STACKSIZE = 0;
                  const uint16_t HIDCONTROLLER_EVENT_STACK_SIZE = 4* 2048; // Don't go below 2048
                  const uint16_t HTTP_MAX_URI_HANDLERS = 35;
                  const uint16_t BT_CONTROLLER_TASK_STACKSIZE = 4 * 2048; // TODO check if this is ending in stackoverflow
                  const uint16_t MOTOR_TASK_STACKSIZE = 4 * 1024;
                  const uint16_t MOTOR_TASK_UPDATEWEBSOCKET_STACKSIZE = 0;
                  const uint16_t INTERRUPT_CONTROLLER_TASK_STACKSIZE = 0;
                  const uint16_t TCA_TASK_STACKSIZE = 1024;
                  const uint16_t SCANNER_TASK_STACKSIZE = 0;
                  const uint16_t TEMPERATURE_TASK_STACKSIZE = 0; // 8096;


                  bool MOTOR_ENABLE_INVERTED = true;
                  bool MOTOR_AUTOENABLE = true;
                  int8_t AccelStepperMotorType = 1;

                  //The PWM channels 1-3 go to headers, LED drivers, LASERBOX jack.
                  //LASER_4 is exclusively on the LASERBOX jack.
                  int8_t LASER_1 = GPIO_NUM_12;
                  int8_t LASER_2 = GPIO_NUM_4;
                  int8_t LASER_3 = GPIO_NUM_2;
                  int8_t LASER_4 = GPIO_NUM_17;

                  //neopixels. LED_1
                  int8_t LED_PIN = GPIO_NUM_13;
                  int8_t LED_COUNT = 64;

                  // THESE LIVE ON THE TCA
                  int8_t DIGITAL_IN_1 = 5;
                  int8_t DIGITAL_IN_2 = 6;
                  int8_t DIGITAL_IN_3 = 7;
                  
                  //DAC pins go out to pinheaders DAC_1 and DAC_2
                  int8_t dac_fake_1 = disabled; //GPIO_NUM_25; // RESET-ABORT just toggles between 1 and 0
                  int8_t dac_fake_2 = disabled; //GPIO_NUM_26; // Coolant




                  // const char * PSX_MAC = "1a:2b:3c:01:01:04";
                  // int8_t PSX_CONTROLLER_TYPE = 2; // 1: PS3, 2: PS4

                  int8_t JOYSTICK_SPEED_MULTIPLIER = 2;
                  int8_t JOYSTICK_MAX_ILLU = 255;
                  int8_t JOYSTICK_SPEED_MULTIPLIER_Z = 1;
                  
                  /*
                  FIXME: Not featured in this revision anymore
                  // for caliper
                  int8_t ENC_X_A = GPIO_NUM_32;
                  int8_t ENC_Y_A = GPIO_NUM_34;
                  int8_t ENC_Z_A = GPIO_NUM_36;
                  int8_t ENC_X_B = GPIO_NUM_33;
                  int8_t ENC_Y_B = GPIO_NUM_35;
                  int8_t ENC_Z_B = GPIO_NUM_17;
                  */

                  // I2c
                  int8_t I2C_SCL = GPIO_NUM_22;      // This is the poart that connects to all other slaves
                  int8_t I2C_SDA = GPIO_NUM_21;

                  // Auxilarry I2C devices
                  int8_t I2C_ADD_TCA = 0x27; // this is the port extender on the PCB that controls the direction of the motors
                  gpio_num_t I2C_INT = GPIO_NUM_27;

                  int8_t I2C_ADD_MOT_X = 0x40;
                  int8_t I2C_ADD_MOT_Y = 0x41;
                  int8_t I2C_ADD_MOT_Z = 0x42;
                  int8_t I2C_ADD_MOT_A = 0x43;
                  int8_t I2C_ADD_LEX_MAT = 0x50;
                  int8_t I2C_ADD_LEX_PWM1 = 0x51;
                  int8_t I2C_ADD_LEX_PWM2 = 0x52;
                  int8_t I2C_ADD_LEX_PWM3 = 0x53;
                  int8_t I2C_ADD_LEX_PWM4 = 0x54;
                  /*
                  FIXME: 
                  I/O expander, nothing new in this Revision.
                  The notation/labels are weird. Not sure if they are correct.
                  Step_Enable for all motors on P00
                  X_Dir: P01
                  Y_Dir: P02
                  Z_Dir: P03
                  A_Dir: P04
                  X_LIMIT: P05
                  Y_LIMIT: P06
                  Z_LIMIT: P07
                  Just broken out to 2.54mm pitch holes: P10-P17
                  
                  Also connected: 
                  int8_t IOEXP_INTERRUPT = GPIO_NUM_27;
                  */


                  // SPI
                  int8_t SPI_MOSI = GPIO_NUM_23; // PICO
                  int8_t SPI_MISO = GPIO_NUM_19; // POCI
                  int8_t SPI_SCK = GPIO_NUM_18;
                  int8_t SPI_CS = GPIO_NUM_5;

                  /*
                  // WIFI - specific to SEEED microscope
                  const char *mSSID = "UC2xSeeed-";
                  const char *mPWD =  "";
                  bool mAP = true; // false;
                  const char *mSSIDAP = "UC2";            
                  const char *hostname = "youseetoo";    
                  */ 

                  /*
                  FIXME: Maybe this is application-based?
                  // Temperature
                  int8_t DS28b20_PIN = GPIO_NUM_25;
                  int8_t LASER_0 = GPIO_NUM_26;
                  */

                  // CAN
                  int8_t CAN_RX = GPIO_NUM_33;
                  int8_t CAN_TX = GPIO_NUM_32;

                  uint32_t CAN_ID_CURRENT = CAN_ID_CENTRAL_NODE;

              };
              const UC2_4 pinConfig;
            
        

This board is the updated version of the V3 with additional features and improvements. More information can be found here.

Xiao LED and Servo Motor Board

Based on the new firmware (betaBD). Features an I2C bus for integration with UC2 ecosystem.

Pin Layout


            // UC2 Xiao ESP32S3 LED and Servo board
            const char * pindefName = "Xiao_LED_SERVO";
        
            // Pin definitions for Xiao ESP32S3 (using D1, D2, etc.)
            #define NEOPIXEL_PIN D6         // Neopixel data pin (TX)
            #define TOUCH_PIN_1 D0          // Touch Button 1 (Touch Pad 1)
            #define TOUCH_PIN_2 D1          // Touch Button 2 (Touch Pad 2)
            #define MOTOR_1_IN1 D3          // Motor 1 IN1 (GPIO0)
            #define MOTOR_1_IN2 D4          // Motor 1 IN2 (GPIO9)
            #define MOTOR_2_IN1 D9          // Motor 2 IN1 (GPIO10)
            #define MOTOR_2_IN2 D10         // Motor 2 IN2 (GPIO3)
            #define I2C_SDA D4              // I2C SDA (GPIO4)
            #define I2C_SCL D5              // I2C SCL (GPIO5)
            #define SERVO_PIN_1 D7          // Servo 1 PWM (GPIO8)
            #define SERVO_PIN_2 D8          // Servo 2 PWM (GPIO11)          

Xiao Motor Board

For TMC2209 stepper driver + AS5600 encoder. Acts as a slave on I2C/USB. More info here.

Pin Layout



            const char * pindefName = "UC2_3_I2CSlaveMotorX";
            const unsigned long BAUDRATE = 115200;
            
            int8_t MOTOR_X_STEP = GPIO_NUM_8;  // D9 -> GPIO8
            int8_t MOTOR_X_DIR = GPIO_NUM_7;   // D8 -> GPIO7
            int8_t MOTOR_ENABLE = GPIO_NUM_9;  // D10 -> GPIO9
            bool MOTOR_ENABLE_INVERTED = true;
            bool MOTOR_AUTOENABLE = true;
            int8_t AccelStepperMotorType = 1;
            
            // I2c
            const char *I2C_NAME = "MOTX";
            I2CControllerType I2C_CONTROLLER_TYPE = I2CControllerType::mMOTOR;
            int8_t I2C_MOTOR_AXIS = 1;   // On the slave we have one motor axis per slave
            int8_t I2C_ADD_SLAVE = I2C_ADD_MOT_X;    // I2C address of the ESP32 if it's a slave ( 0x40;)
            int8_t I2C_SCL = GPIO_NUM_2; // D1 -> GPIO2
            int8_t I2C_SDA = GPIO_NUM_3; // D2 -> GPIO3
            
            // I2C configuration (using updated GPIO values)
            int8_t I2C_SCL_ext = GPIO_NUM_6; // D5 -> GPIO6
            int8_t I2C_SDA_ext = GPIO_NUM_5; // D4 -> GPIO5
            
            // TMC UART
            int8_t tmc_SW_RX = 44;// GPIO_NUM_44; // D7 -> GPIO44
            int8_t tmc_SW_TX = 43;// GPIO_NUM_43; // D6 -> GPIO43
            int8_t tmc_pin_diag = GPIO_NUM_4; // D3 -> GPIO4
            
            int tmc_microsteps = 16;
            int tmc_rms_current = 500;
            int tmc_stall_value = 100;
            int tmc_sgthrs = 100;
            int tmc_semin = 5;
            int tmc_semax = 2;
            int tmc_sedn = 0b01;
            int tmc_tcoolthrs = 0xFFFFF;
            int tmc_blank_time = 24;
            int tmc_toff = 4;
            
            // TEmporarily for endstop
            int8_t DIGITAL_IN_1 = GPIO_NUM_1; // D0 -> GPIO1 - > TOUCH
            
          

Xiao LED Ring & Brightfield

A board with LED ring for brightfield illumination. More info here.

Pin Layout



            const char *pindefName = "UC2_ESP32S3_XIAO_LEDRING";
            const unsigned long BAUDRATE = 115200;

            uint8_t I2C_CONTROLLER_TYPE = I2CControllerType::mLASER;
            uint8_t I2C_ADD_SLAVE = I2C_ADD_LEX_PWM1; // I2C address of the ESP32 if it's a slave

            // Laser control pins (using updated GPIO values)
            int8_t LASER_1 = GPIO_NUM_3; // D2
            int8_t LASER_2 = GPIO_NUM_4; // D3 => Motor 1/1

            int8_t DIGITAL_IN_1 = GPIO_NUM_1; // D0 // Touch 1
            int8_t DIGITAL_IN_2 = GPIO_NUM_3; // D1 // Touch 2

            // I2C configuration (using updated GPIO values)
            int8_t I2C_SCL = GPIO_NUM_6; // D5 -> GPIO6
            int8_t I2C_SDA = GPIO_NUM_5; // D4 -> GPIO5
          

Xiao CAN Slave Illumination

A board with CAN bus communication for illumination control. More info here.

Pin Layout



            const char *pindefName = "UC2_ESP32S3_XIAO_CAN_SLAVE_ILLUMINATION";
            const unsigned long BAUDRATE = 115200;

            uint8_t I2C_CONTROLLER_TYPE = I2CControllerType::mLASER;
            uint8_t I2C_ADD_SLAVE = I2C_ADD_LEX_PWM1; // I2C address of the ESP32 if it's a slave

            // Laser control pins (using updated GPIO values)
            int8_t LASER_1 = GPIO_NUM_3; // D2
            int8_t LASER_2 = GPIO_NUM_4; // D3 => Motor 1/1

            int8_t DIGITAL_IN_1 = GPIO_NUM_1; // D0 // Touch 1
            int8_t DIGITAL_IN_2 = GPIO_NUM_3; // D1 // Touch 2

            // I2C configuration (using updated GPIO values)
            int8_t I2C_SCL = GPIO_NUM_6; // D5 -> GPIO6
            int8_t I2C_SDA = GPIO_NUM_5; // D4 -> GPIO5
          

Seeed Studio Webcamera (USB)

Firmware turns the Xiao into a USB webcam.
See more here.

Waveshare ESP32S3 Matrix

Standalone Neopixel LED matrix with an ESP32S3. Caution: can get hot at high brightness!
More info.

Pin Layout


            const char *pindefName = "UC2_ESP32S3_XIAO_LEDRING";
            const unsigned long BAUDRATE = 115200;

            uint8_t I2C_CONTROLLER_TYPE = I2CControllerType::mLASER;
            uint8_t I2C_ADD_SLAVE = I2C_ADD_LEX_PWM1; // I2C address of the ESP32 if it's a slave

            // Laser control pins (using updated GPIO values)
            int8_t LASER_1 = GPIO_NUM_3; // D2
            int8_t LASER_2 = GPIO_NUM_4; // D3 => Motor 1/1

            int8_t DIGITAL_IN_1 = GPIO_NUM_1; // D0 // Touch 1
            int8_t DIGITAL_IN_2 = GPIO_NUM_3; // D1 // Touch 2

            // I2C configuration (using updated GPIO values)
            int8_t I2C_SCL = GPIO_NUM_6; // D5 -> GPIO6
            int8_t I2C_SDA = GPIO_NUM_5; // D4 -> GPIO5
          

Xiao ESP32S3 ODMR Server

Firmware turns the Xiao ESP32S3 the ODMR Server.
See more here.

Xiao ESP32C3 ODMR Server

Firmware turns the Xiao ESP32C3 the ODMR Server.
See more here.

4. Test the Firmware

After flashing, you can test your firmware with our UC2 WebSerial test page, which lets you:

5. FAQ / Tips

Advanced Users

We provide multiple firmware versions: older UC2-REST (Arduino-based) and UC2-ESP (PlatformIO-based, more recent).