How to update firmware on the Flipsky 75100 & 75200 FOC ESC

For anyone else interested, I ran a diff between the hw_mksesc_75_100_old and hw_mksesc_75_100_v2_old firmware and TL;DR, there is essentially no difference between them. If the VESC tool shows you are running Hw: MKSESC_75_100_OLD then you may as well stick with it. So if you are like me and have a “MKSESC 75100” from AliExpress (more info in this post here) there isn’t any real benefit moving to the v2_old firmware.

EDIT: With that being said, there are a handful of differences between the hw_mksesc_75_100_old and flipsky hw_75_100_V2 However, they seem to be almost functionally identical, thus the almost identical-looking PCBs between the Flipsky 75100V202 and the Makerbase MKSESC 75100. Due to these small differences, however, I would still recommend sticking with whatever firmware type your ESC originally came with.

Full diff as of 4/25/2026 f2865b5:

===== DIFF: hwconf/makerbase/75_100/hw_mksesc_75_100_old.h <-> hwconf/makerbase/75_100_V2/hw_mksesc_75_100_v2_old.h =====
diff --git a/hwconf/makerbase/75_100/hw_mksesc_75_100_old.h b/hwconf/makerbase/75_100_V2/hw_mksesc_75_100_v2_old.h
index 06f09532..fd4a5ced 100644
--- a/hwconf/makerbase/75_100/hw_mksesc_75_100_old.h
+++ b/hwconf/makerbase/75_100_V2/hw_mksesc_75_100_v2_old.h
@@ -18,10 +18,10 @@
 */
 	
-#ifndef HW_MKSESC_75_100_OLD_H_
-#define HW_MKSESC_75_100_OLD_H_
+#ifndef HW_MKSESC_75_100_V2_OLD_H_
+#define HW_MKSESC_75_100_V2_OLD_H_
 
-#define HW75_100_OLD
+#define HW75_100_V2_OLD
 
-#include "hw_mksesc_75_100_core.h"
+#include "hw_mksesc_75_100_v2_core.h"
 
-#endif /* HW_MKSESC_75_100_OLD_H_ */
+#endif /* HW_MKSESC_75_100_V2_OLD_H_ */
===== DIFF: hwconf/makerbase/75_100/hw_mksesc_75_100_core.h <-> hwconf/makerbase/75_100_V2/hw_mksesc_75_100_v2_core.h =====
diff --git a/hwconf/makerbase/75_100/hw_mksesc_75_100_core.h b/hwconf/makerbase/75_100_V2/hw_mksesc_75_100_v2_core.h
index a3a39062..c8a434fc 100644
--- a/hwconf/makerbase/75_100/hw_mksesc_75_100_core.h
+++ b/hwconf/makerbase/75_100_V2/hw_mksesc_75_100_v2_core.h
@@ -18,17 +18,19 @@
 */
 	
-#ifndef HW_MKSESC_75_100_CORE_H_
-#define HW_MKSESC_75_100_CORE_H_
+#ifndef HW_MKSESC_75_100_V2_CORE_H_
+#define HW_MKSESC_75_100_V2_CORE_H_
 
 //Makerbase reminds you: When choosing to compile a board, 
 //you need to confirm the motherboard model you have, 
 //because burning the wrong firmware may cause damage to the board.
-////It is highly recommended to contact the merchant for confirmation.
+//It is highly recommended to contact the merchant for confirmation.
 
 //hardware version
-#ifdef HW75_100_OLD
-#define HW_NAME					"MKSESC_75_100_OLD"
-#elif defined(HW75_100)
-#define HW_NAME					"MKSESC_75_100"
+#ifdef HW75_100_V2_OLD
+#define HW_NAME					"MKSESC_75_100_V2_OLD"
+#elif defined(HW75_100_V2)
+#define HW_NAME					"MKSESC_75_100_V2"
+#else
+#error "Must include hardware type"
 #endif
 
@@ -49,6 +51,8 @@
 #define LED_RED_OFF()			palClearPad(LED_RED_GPIO, LED_RED_PIN)
 
-//MKSESC 75100 version with phase filter is being designed, please wait patiently.
-#if defined (HW75_100)
+//MKSESC 75100 V2_003 adds many new features, including phase filtering. 
+//You can determine which version of MKSESC 75100 V2 you have by observing the appearance. 
+//The most obvious feature is that 003 has a toggle switch.
+#if defined (HW75_100_V2)
 #define HW_HAS_PHASE_FILTERS
 #define PHASE_FILTER_GPIO		GPIOC
@@ -56,12 +60,23 @@
 #define PHASE_FILTER_ON()		palSetPad(PHASE_FILTER_GPIO, PHASE_FILTER_PIN)
 #define PHASE_FILTER_OFF()		palClearPad(PHASE_FILTER_GPIO, PHASE_FILTER_PIN)
+
+// Shutdown pin
+#define HW_SHUTDOWN_GPIO		GPIOC
+#define HW_SHUTDOWN_PIN			5
+#define HW_SHUTDOWN_HOLD_ON()   palSetPad(HW_SHUTDOWN_GPIO, HW_SHUTDOWN_PIN)
+#define HW_SHUTDOWN_HOLD_OFF()  palClearPad(HW_SHUTDOWN_GPIO, HW_SHUTDOWN_PIN)
+#define HW_SAMPLE_SHUTDOWN()    hw_sample_shutdown_button()
+
+// Hold shutdown pin early to wake up on short pulses
+#define HW_EARLY_INIT()			palSetPadMode(HW_SHUTDOWN_GPIO, HW_SHUTDOWN_PIN, PAL_MODE_OUTPUT_PUSHPULL); \
+					            HW_SHUTDOWN_HOLD_ON();    
 #endif
 
-//MKSESC 75100 is also expected to add a current filter, 
-//but since it is low-test sampling, we set this configuration to off by default, 
-//leaving only the circuit as an expansion function.
-#define CURRENT_FILTER_GPIO		GPIOD
-//#define CURRENT_FILTER_ON()		palSetPad(CURRENT_FILTER_GPIO, 2)
-#define CURRENT_FILTER_OFF()    palClearPad(CURRENT_FILTER_GPIO, 2)
+//MKSESC 75100 V2_003 added phase filtering and 
+//current filtering in November 2023. However, since it is low-end sampling, 
+//we do not recommend turning on the current filtering function, so it is set to off here.
+#define CURRENT_FILTER_GPIO		    GPIOD
+// #define CURRENT_FILTER_ON()		palSetPad(CURRENT_FILTER_GPIO, 2)
+#define CURRENT_FILTER_OFF()		palClearPad(CURRENT_FILTER_GPIO, 2)
 
 /*
@@ -78,5 +93,5 @@
  * 8  (3):	IN3		TEMP_MOS
  * 9  (1):	IN14    TEMP_MOTOR
- * 10 (2):	IN15    ADC_EXT3
+ * 10 (2):	IN15    SHUTDOWN
  * 11 (3):	IN13    AN_IN
  * 12 (1):	Vrefint
@@ -100,7 +115,7 @@
 #define ADC_IND_CURR3			5
 #define ADC_IND_VIN_SENS		11
-#define ADC_IND_EXT             6
+#define ADC_IND_EXT			    6
 #define ADC_IND_EXT2			7
-#define ADC_IND_EXT3			10
+#define ADC_IND_SHUTDOWN		10
 #define ADC_IND_TEMP_MOS		8
 //#define ADC_IND_TEMP_MOS_2		15
@@ -115,5 +130,4 @@
 #define V_REG				    3.34
 #endif
-//The voltage dividing acquisition circuit on the Makerbase VESC motherboard is 560K and 21.5K resistors.
 #ifndef VIN_R1
 #define VIN_R1				    56000.0 
@@ -122,5 +136,4 @@
 #define VIN_R2				    2200.0 
 #endif
-
 #ifndef CURRENT_AMP_GAIN
 #define CURRENT_AMP_GAIN		20.0 
@@ -135,8 +148,8 @@
 // NTC Termistors
 #define NTC_RES(adc_val)		((4095.0 * 10000.0) / adc_val - 10000.0)
-#define NTC_TEMP(adc_ind)		(1.0 / ((logf(NTC_RES(ADC_Value[adc_ind]) / 10000.0) / 3435.0) + (1.0 / 298.15)) - 273.15) 
+#define NTC_TEMP(adc_ind)		(1.0 / ((logf(NTC_RES(ADC_Value[adc_ind]) / 10000.0) / 3380.0) + (1.0 / 298.15)) - 273.15) 
 
-#define NTC_RES_MOTOR(adc_val)	(10000.0 / ((4095.0 / (float)adc_val) - 1.0)) // Motor temp sensor on low side
-#define NTC_TEMP_MOTOR(beta)	(1.0 / ((logf(NTC_RES_MOTOR(ADC_Value[ADC_IND_TEMP_MOTOR]) / 10000.0) / beta) + (1.0 / 298.15)) - 273.15)
+#define NTC_RES_MOTOR(adc_val)  (10000.0 / ((4095.0 / (float)adc_val) - 1.0)) // Motor temp sensor on low side
+#define NTC_TEMP_MOTOR(beta)    (1.0 / ((logf(NTC_RES_MOTOR(ADC_Value[ADC_IND_TEMP_MOTOR]) / 10000.0) / beta) + (1.0 / 298.15)) - 273.15)
 
 // Voltage on ADC channel
@@ -242,27 +255,26 @@
 // Default setting overrides
 #ifndef MCCONF_L_MIN_VOLTAGE
-//Since the gate drive voltage is 12V, the bus power supply must be greater than 12V to keep the DC-DC in normal working condition.
-#define MCCONF_L_MIN_VOLTAGE			12.0	// Minimum input voltage
+#define MCCONF_L_MIN_VOLTAGE		12.0	// Minimum input voltage
 #endif
 #ifndef MCCONF_L_MAX_VOLTAGE
-#define MCCONF_L_MAX_VOLTAGE			90.0	// Maximum input voltage
+#define MCCONF_L_MAX_VOLTAGE		90.0	// Maximum input voltage
 #endif
 #ifndef MCCONF_DEFAULT_MOTOR_TYPE
-#define MCCONF_DEFAULT_MOTOR_TYPE		MOTOR_TYPE_FOC
+#define MCCONF_DEFAULT_MOTOR_TYPE	MOTOR_TYPE_FOC
 #endif
 #ifndef MCCONF_FOC_F_ZV
-#define MCCONF_FOC_F_ZV				    30000.0 
+#define MCCONF_FOC_F_ZV			    30000.0 
 #endif
 #ifndef MCCONF_L_MAX_ABS_CURRENT
-#define MCCONF_L_MAX_ABS_CURRENT		150.0	// The maximum absolute current above which a fault is generated
+#define MCCONF_L_MAX_ABS_CURRENT	150.0	// The maximum absolute current above which a fault is generated
 #endif
 #ifndef MCCONF_FOC_SAMPLE_V0_V7
-#define MCCONF_FOC_SAMPLE_V0_V7			false	// Run control loop in both v0 and v7 (requires phase shunts)
+#define MCCONF_FOC_SAMPLE_V0_V7		false	// Run control loop in both v0 and v7 (requires phase shunts)
 #endif
 #ifndef MCCONF_L_IN_CURRENT_MAX
-#define MCCONF_L_IN_CURRENT_MAX			100.0	// Input current limit in Amperes (Upper)
+#define MCCONF_L_IN_CURRENT_MAX		100.0	// Input current limit in Amperes (Upper)
 #endif
 #ifndef MCCONF_L_IN_CURRENT_MIN
-#define MCCONF_L_IN_CURRENT_MIN			-20.0	// Input current limit in Amperes (Lower)
+#define MCCONF_L_IN_CURRENT_MIN		-20.0	// Input current limit in Amperes (Lower)
 #endif
 
@@ -271,6 +283,6 @@
 #define HW_LIM_CURRENT_IN		-120.0, 120.0 
 #define HW_LIM_CURRENT_ABS		0.0, 200 
-#define HW_LIM_VIN				6.0, 120.0 
-#define HW_LIM_ERPM				-200e3, 200e3 
+#define HW_LIM_VIN			    6.0, 120.0 
+#define HW_LIM_ERPM			    -200e3, 200e3 
 #define HW_LIM_DUTY_MIN			0.0, 0.1
 #define HW_LIM_DUTY_MAX			0.0, 0.99
@@ -278,4 +290,5 @@
 
 // HW-specific functions
+bool hw_sample_shutdown_button(void);
 
-#endif /* HW_MKSESC_75_100_CORE_H_ */
+#endif /* HW_MKSESC_75_100_V2_CORE_H_ */
===== DIFF: hwconf/makerbase/75_100/hw_mksesc_75_100_core.c <-> hwconf/makerbase/75_100_V2/hw_mksesc_75_100_v2_core.c =====
diff --git a/hwconf/makerbase/75_100/hw_mksesc_75_100_core.c b/hwconf/makerbase/75_100_V2/hw_mksesc_75_100_v2_core.c
index 6b8c980f..98b7a31b 100644
--- a/hwconf/makerbase/75_100/hw_mksesc_75_100_core.c
+++ b/hwconf/makerbase/75_100_V2/hw_mksesc_75_100_v2_core.c
@@ -13,5 +13,5 @@
     */
 
-// 
+// V2
 
 #include "hw.h"
@@ -25,4 +25,8 @@
 // Variables
 static volatile bool i2c_running = false;
+#if defined (HW75_100_V2)
+	static mutex_t shutdown_mutex;
+	static float bt_diff = 0.0;
+#endif
 
 // I2C configuration
@@ -34,4 +38,7 @@ static const I2CConfig i2cfg = {
 
 void hw_init_gpio(void) {
+	#if defined (HW75_100_V2)
+		chMtxObjectInit(&shutdown_mutex);
+	#endif
 	// GPIO clock enable
 	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
@@ -75,5 +82,5 @@ void hw_init_gpio(void) {
 
 	// Phase filters
-	#if defined (HW75_100)
+	#if defined (HW75_100_V2)
 		palSetPadMode(PHASE_FILTER_GPIO, PHASE_FILTER_PIN,
 				PAL_MODE_OUTPUT_PUSHPULL |
@@ -110,5 +117,7 @@ void hw_init_gpio(void) {
 	palSetPadMode(GPIOC, 3, PAL_MODE_INPUT_ANALOG);
 	palSetPadMode(GPIOC, 4, PAL_MODE_INPUT_ANALOG);
+	#if defined (HW75_100_V2_OLD)
 	palSetPadMode(GPIOC, 5, PAL_MODE_INPUT_ANALOG);
+	#endif	
 }
 
@@ -243,2 +252,26 @@ void hw_try_restore_i2c(void) {
 	}
 }
+
+#if defined(HW75_100_V2)
+bool hw_sample_shutdown_button(void) {
+	chMtxLock(&shutdown_mutex);
+
+	bt_diff = 0.0;
+
+	for (int i = 0;i < 3;i++) {
+		palSetPadMode(HW_SHUTDOWN_GPIO, HW_SHUTDOWN_PIN, PAL_MODE_INPUT_ANALOG);
+		chThdSleep(5);
+		float val1 = ADC_VOLTS(ADC_IND_SHUTDOWN);
+		chThdSleepMilliseconds(1);
+		float val2 = ADC_VOLTS(ADC_IND_SHUTDOWN);
+		palSetPadMode(HW_SHUTDOWN_GPIO, HW_SHUTDOWN_PIN, PAL_MODE_OUTPUT_PUSHPULL);
+		chThdSleepMilliseconds(1);
+
+		bt_diff += (val1 - val2);
+	}
+
+	chMtxUnlock(&shutdown_mutex);
+	
+	return (bt_diff > 0.12);
+}
+#endif
1 Like