Once finished (deadline is end of January) this project will become open-source software and hardware.
My quadruple BDC driver for supports up to 4 brushed motors with encoders. Each motor is controlled by its individual closed loop and individual PID gain settings. Additionally, motor speed can also be individually addressed. Analog part of the driver is based on DRV8701P predriver and is controlled by STM32F4 microcontroller.
- 35 V max input voltage (recommended up to 30V)
- 13 A max continuous motor current (recommended up to 10A)
- 50 kHz max encoder pulse frequency (recommended 30kHz)
- Serial communication
- ROS compatible with available library
- XT-60 power connector
- XT-30 motor connectors
- XH2.54 connectors for encoders
- Adjustable current protection (0.1A – 13A)
- Adjustable current alert (LED or on serial)
- Temperature protection
- Hardware emergency stop
- RGB LED for status report
- Extra 24V power switch for external 24V load
The circuit is divided in two parts. The analog power part and the digital part with peripherals. Let’s talk about the power side firstly.
Everything is based on DRV8701P integrated circuit that takes care of dead times, gate currents and ensures higher voltage for opening high side n-mosfets. The DRV has four control inputs. One is sleep (it is used for emergency stop) and two are PWM signals for forward or reverse drive. The DRV also features braking (though not regenerative) with both PWM signals on at the same time. The fourth control input is reference voltage for limiting the current.
The DRV has shunt amplifier built-in with fixed gain of 20. This is ideal for current sensing with a 10 mOhm shunt resistor. Once the voltage on the output of the shunt amplifier exceeds the voltage reference set on the control pin the driver enters so called current chopping mode in which it effectively limits the motor current to set level.
The driver measures voltage drop across transistors and immediately enters fault mode when the drop is too large. It also features internal temperature protection.
The schematic (1) is only for 1 channel. The actual circuit board has 4 identical ones.
Digital side and peripherals
Digital side is based on STM32F4 microcontroller. I used one in QFN housing to make it more immune to possible mechanical vibrations. The microcontroller is generating 8 PWM signals at 21 kHz with 1000 sections (10bit). The encoders are read by interrupt active pins. All four motors work in PID closed loop. Some additional features are motor sensing motor current, input voltage, used energy and temperature sensing.
An RGB LED indicator is present on board to provide basic information about the driver state.
- Blue LED indicates whether the driver (as a unit) is in sleep mode and motors drives are disabled.
- Red LED blinks with a fault code and indicates a possible problem.
- Green LED indicates whether one of the channels is braking.
The board has got a connector for remote emergency stop switch. A relay or NPN/n-channel transistor can also be connected on this input to work as an emergeny stop with external watchdog module.
Two small 1 A buck switching regulators take care of providing 3.3V and 5V from the input supply.
Additionally another N-channel MOSFET switch is implemented. It can switch currents up to 20A.
The communication with the driver is based on UART. User has multiple write registers (to set motor speed, PID gains, etc.) and multiple read register that will contain information about temperature, used energy, encoder ticks, etc. Scroll down to software section to view register-map.
There were some problems in first two revisions with step-down converter supplying 3.3V to the MCU. The switcher would randomly burn and take the microcontroller with it. Since I couldn’t figure out what was the problem in the first two revisions, I chose to implement a solution with different step-down regulators. I chose LM53601 because it supports up to 35V (all other components are also rated for 35V) and is for automotive use which is perfect for my application. There are two step-downs on board. One is supplying 3.3V to the MCU and other peripherals while the second one provides power for encoders (5V). Both are rated for 1 A.
The first prototype was thoroughly tested and initial mistakes were corrected. Some problems were as follows:
- Wrong interrupt pins (joined interrupt lines in the MCU)
- Wrong 3.3V switcher layout
- Huge button bounce (solved with a capacitor, the button was removed in rev. 0.3 due to lack of space)
Some other minor mistakes that were solved with second revision
- Added 2.5 V reference for ADC
- Added forward and reverse PWM signals of a single driver to a single MCU timer
- Added a resistor in parallel with NTC to make it more linear
- Improved board layout
The power side of the circuit worked perfectly in the first revision and no correction were made there.
Prototype PCBs were manufactured by PCBWay. Their rapid prototype service is fast (5 days from gerbers to PCBs in my hands), reliable and the quality of the PCBs is completely comparable with a local manufacturer. Not to mention 20 boards with 6mil clearance were just 30$ including shipping. I’ll definitely order again.
Rev 0.1 issues solved:
- Issue with interrupt pins was solved in this revision. All four of the encoders could be read simultaneously.
Rev 0.1 issues still present:
- Improved step-down switcher layout did not help. It was still unstable and “powergood” signal would stay false.
- Because I wanted to improve the accuracy of the ADC readings a 2.5V reference was added on the STM32 AREF pin. It turned out that my reference which was a single 2.5V reference diode did not supply enough current and the voltage collapsed to 1.6V which caused the mcu to reset right after the initialization of the ADC. It was a shameful lesson.
- DRV8701 has a 5V output rated for 10 mA. It turned out that 10 mA is not enough current to power most of the encoders.
Revision 0.3 – final
Rev 0.2 issues solved:
- Step-down switcher replaced with a more suitable one, rising the maximum input voltage of the circuit to 35V.
- The AREF pin is connected directly to 3.3V rail. The new switcher is believed to have cleaner output compared to the first one (it had 100 mV ripple) and thus an ADC reference would not be needed anymore.
- 5V 1A supply to power encoders
- Added XH2.54 connectors for encoders (they can be bought on ebay for cheap)
- Added one big RGB led instead of three small ones for indicating status
- Removed button because it was proven to be useless and was taking up space
- Extra track on bottom solder layer that runs along with the wide power supply tracks. If overheating problems should occour due to too low trach amperage, a thich copper wire can be soldered on top of the trach for better current conductivity and reduced heat.
Pictures of the PCB
Click on the picture to open the connection diagram in PDF format.
Most of the software has already been written.
What can the driver do:
- Control the motors in open loop with duty cycle in both directions
- Read the motor speed from encoders
- Control the motors in closed loop in both directions
- Read temperature
- Read motor current
- Read input voltage
- Calculate used energy
- Transmit/receive data over serial port
- Register map
- Adjustable under-voltage and over-current protection
- Fault code
- Startup routine (beeping and such…)
- Active breaking (routines for active braking in PID regulation)
- Adjustable UART timeout (driver enters sleep mode if no UART packets are received in specified time interval – used as an fail-safe feature)
- Regenerative braking
- Encoder timeout (fail-safe in encoder failuire event)
- RGB LED status report
Click on the picture to open register map in PDF form.
Example command that sets motor 3 speed to “10”:
0x7e 0x83 0x00 0x00 0x27 0x10 0x1f 0x83 0x7e Explained: 0x7E Start of frame 0x80 Address byte - 10000011 in binary - MSB bit sets the write command, address is 6 lsb bits - in this case the address is 0x03 0x00 Data byte 0 0x00 Data byte 1 0x27 Data byte 2 0x10 Data byte 3 0x00002710 translates to 10000(dec) Note: the actual parameter is multiplied by 1000 / set speed is divided by 1000 0x1F CRC byte 1 0x83 CRC byte 2 More about CRC: https://www.lammertbies.nl/comm/info/crc-calculation.html 0x7E End of frame The driver then returns: 0xC3 or 11000011 in binary: Bit7 (msb) indicates that an write command was executed. Bit6 is acknowledge bit which is also set to 1 - the parameter was in range and set accordingly. Bit5:0 is addres - in this case it indicates which register was set.
Click on the picture to open example frame in PDF form.