A DIY electric bike motor controller with comprehensive hardware validation, safety features, and diagnostic capabilities. This project includes both simple test code for getting started and full-featured firmware for production use.
- The PCB design supports up to 2000W at 72V or 1000W at 48V using 18 MOSFETs, or simply use 6 MOSFETs for low power drive.
- 6-step trapezoidal commutation based on hall sensor feedback
- PWM speed control with configurable frequencies (3.9-7.8 kHz)
- Smooth acceleration ramping for comfortable riding
- Shoot-through protection to prevent MOSFET damage
- Isense shunt resistence is inherent in the PCB tracks (around 0.2ohms).
eBike-Controller/
βββ code_BLDC_simple/ # Simple getting-started code
β βββ code_BLDC_simple.ino # Main test program
β βββ tests.ino # Hall sensor & MOSFET tests
β
βββ code_nano_main/ # Full-featured production firmware
β βββ code_nano_main.ino # Main program & control loop
β βββ motor.ino # Commutation logic
β βββ thot.ino # Throttle processing
β βββ io.ino # Hall sensors, buzzer, temp
β βββ checks.ino # System diagnostics
β βββ dummy.ino # Debug/test functions
β
βββ PCB_files/ # PCB design files (hardware)
βββ ProteusSimulations/ # Circuit simulations
βββ README.md # This file
- Arduino Nano or compatible ATmega328P board
- Recommended: Nano SuperMini Type-C with CH340 USB chip
- BLDC Motor with hall effect sensors (3-phase)
- Hall sensors must provide valid 6-state sequence
- 3-phase MOSFET bridge (6 MOSFETs: 3 high-side, 3 low-side) - IRF3077 or similar.
- Gate drivers compatible with 3.3V/5V logic 6EDL04N06PT
- Operating voltage: 12-72V DC (configurable)
- Throttle: Analog potentiometer (0.18-0.85V / 180-850 ADC)
- Current sensing: Shunt resistor + amplifier to ADC
- Voltage sensing: Resistor divider per phase (configurable factor)
- Buzzer: Passive buzzer for audio feedback
- Optional: Temperature sensor (NTC), PAS sensor, halt button
Preview not available. Open the Schematic or download it.
Complete BOM for the schamatic
Links:
- Gate driver IC 6EDL04N06PT
- Heatsink backplate (originally for 2.5β SSD)
- Arduino Nano Supermini
- DC-DC booster for 5V to 12V
- A good 5V step down regulator (avoid aliexpress)
- High quality capacitors (avoid aliexpress), see BOM
- MOSFETS: NCE85H21 or IRFB3077.
Optional:
- Optionally, for tracking and extra functions TTGO T-Call V1.3 ESP32
- Optionally, along with T-Call, GPS module
Use the simple test code to validate your hardware before running the full firmware:
# Upload to Arduino
File: code_BLDC_simple/code_BLDC_simple.inoWhat it does:
- Runs motor at slow speed (10/255 PWM)
- Tests all MOSFETs individually
- Validates hall sensors
- Reports errors via serial monitor
Expected output at 33V:
Start
H1 U: 1 V: 0 W: 0
F0 399 0;
F1 397 0;
F2 396 0;
Before testing:
- Adjust voltage thresholds in
tests.ino:#define CRITITAL_LOW_VOLTS 7 // Set based on your test voltage #define VOLTS_ADC_FACTOR 12.31 // Calibrate for your voltage divider
- Connect motor and power supply
- Open serial monitor (115200 baud)
- Motor should spin slowly if all checks pass
Once hardware is validated, upload the full firmware:
File: code_nano_main/code_nano_main.inoAll pins are defined in the main .ino files. Verify these match your hardware:
// MOSFET gates
#define pin_U_H 3 // Phase U high-side (PWM)
#define pin_U_L 9 // Phase U low-side
#define pin_V_H 5 // Phase V high-side (PWM)
#define pin_V_L 10 // Phase V low-side
#define pin_W_H 6 // Phase W high-side (PWM)
#define pin_W_L 11 // Phase W low-side
// Hall sensors
#define pin_U_HALL 4
#define pin_V_HALL 7
#define pin_W_HALL 8
// Analog inputs
#define pin_UOx A0 // Phase U voltage sensing
#define pin_VOx A2 // Phase V voltage sensing
#define pin_WOx A1 // Phase W voltage sensing
#define pin_Isense A5 // Current sensing
#define pin_THOT_sense A3 // Throttle input
// Other I/O
#define pin_BUZZ 13 // Buzzer/LED
#define pin_HALT_IN 12 // Emergency halt (active low)Default settings are optimized for quiet operation and minimal jitter. Adjust if needed in setup():
// Timer 0 (pins D5, D6): 7812.50 Hz
TCCR0B = TCCR0B & B11111000 | B00000010;
// Timer 2 (pin D3): 3921.16 Hz
TCCR2B = TCCR2B & B11111000 | B00000010;Adjust these values in thot.ino based on your throttle:
#define THOT_ADC_MIN 180 // ADC at minimum throttle
#define THOT_ADC_MAX 850 // ADC at maximum throttleTo calibrate:
- Connect throttle and open serial monitor
- Read ADC values:
analogRead(pin_THOT_sense) - Set MIN to value at rest position
- Set MAX to value at full throttle
Configure for your battery voltage and divider ratio in checks.ino:
#define CRITITAL_LOW_VOLTS 32.5 // Minimum operating voltage (V)
#define VOLTS_ADC_FACTOR 12.31 // ADC to voltage conversionCalculate VOLTS_ADC_FACTOR:
VOLTS_ADC_FACTOR = (R1 + R2) / (R2 * 1024) * V_ref
Where:
- R1, R2 = voltage divider resistors
- V_ref = Arduino ADC reference (typically 5V)
Set overcurrent threshold in the main file:
#define Isense_kill_limit 200 // ADC value (adjust for your sensor)The system reports various error codes via serial:
| Code | Meaning | Description |
|---|---|---|
| E10 | Throttle fault | Throttle disconnected or reading too low |
| E20 | MOSFET test failed | One or more FETs not functioning |
| E21 | High-side fault | High-side FET blown or undervoltage |
| E22 | Low-side fault | Low-side FET blown or short circuit |
| E75 | Hall sensor fault | Invalid hall state (disconnected/damaged) |
| E85 | Idle current high | Possible short circuit detected |
- Ready (kind=0): Descending tones (system OK)
- Overload (kind=1): Descending alarm (overcurrent)
- General error (kind=2): 3-tone alert
- Severe error (kind=3): 4-tone high-pitched alarm
Progressive audio warnings based on voltage:
- >38.1V: 1 beep (first warning)
- 37-38V: 2 beeps
- 35.5-37V: 3 beeps
- <34V: 4 rapid beeps (critically low)
- All MOSFETs turned off
- Pin configuration validated
- MOSFET switching test (both high and low side)
- Hall sensor validation
- Throttle presence check
- Voltage level verification
- Optional: Secret ignition sequence (disabled by default)
- Periodic health checks during idle (every 5th idle cycle)
- Continuous hall state validation
- Current monitoring (if enabled)
- Automatic shutdown on any critical fault
The code ensures low-side MOSFETs are OFF before activating high-side:
digitalWrite(LOW_SIDE_pins[i], LOW); // Turn off low-side first
analogWrite(HIGH_SIDE_pins[i], thot); // Then activate high-sideOpen serial monitor at 115200 baud to see:
- Startup diagnostics
- Hall states (
H1-H6) - MOSFET test results (
F0,F1,F2) - Voltage readings
- Error messages
For advanced testing, uncomment in loop():
dummy_loop_for_ic_test(); // Test individual MOSFET switching
dummy_run(); // Run motor at full speedMotor doesn't start:
- Check serial output for error codes
- Verify hall sensor wiring (should show states 1-6)
- Confirm voltage is above
CRITITAL_LOW_VOLTS - Test throttle ADC reading
Motor stutters or vibrates:
- Hall sensors may be swapped - try different wiring
- Check PWM frequency settings
- Verify power supply can handle current draw
Random shutdowns:
- Check current sensor calibration
- Verify voltage divider ratios
- Inspect battery voltage under load
- Check for loose hall sensor connections
MOSFETs overheating:
- Reduce current limit
- Check for shoot-through (scope gate signals)
- Verify gate driver voltage levels
- Ensure adequate heatsinking
This is a high-power motor controller project.
- Always test with motor disconnected first
- Use current-limited power supply during testing
- Verify all connections before applying power
- MOSFETs can fail catastrophically if wired incorrectly
- Li-ion batteries can be dangerous if short-circuited
- Wear safety glasses when testing
- Start with low voltage (<20V) for initial tests
The authors are not responsible for any damage, injury, or loss caused by using this project.
This project is provided as-is for educational and DIY purposes.





