External stepper motor drivers are typically used when you want more power than the the small plug-in drivers can supply. You can also get advanced features like closed loop stepper and servo motors.
As long as they accept step and direction signals, you can probably use them. They usually have an enable signal and some have a fault signal. FluidNC supports the enable signal, either on a per driver basis or a shared pin that controls all drivers. It also supports the fault output on a shared basis, where all the fault outputs are connected together in parallel.
On most external drivers, the input labeled ENA really should be thought of as disable. If you leave it unconnected, the driver will be enabled. To disable the driver, you must connect that input to the FluidNC controller and apply voltage from ENA+ to ENA-.
They typically have opto isolated inputs. These use LEDs and optical sensors to isolate the signal. Any noise or spikes on the motor side cannot jump that optical gap and hurt the controller side. These optoisolated inputs are often specified for use with 5V and higher signals. The ESP32 outputs 3.3V, so driving some external drivers directly from ESP32 outputs is not within spec.
Note: Some people have found that their drivers work fine at 3.3V. Be careful. It is hard to tell if the driver is happy all the time, or 99.9% of the time. Follow the published spec of the driver.
Some drivers have a signal voltage switch. These usually give a 5V and 24V option. You should use the 5V option for most controllers.
3.3V to 5V Level shifting
Some controllers will have this built in. The 6 Pack has a jumper option for 3.3V and 5V output option. You should use the 5V output with external drivers.
Note: Do not mix external with Trinamic (TMC) drivers when using 5V. TMC drivers send signals back to the ESP32 and will damage it with 5V
The 5V must have enough current to activate the LEDs inside the optoisolators. The current is generally in the range of 10 to 20mA, which is more than some level shifts can deliver . Some level shifters (like T.I. TXB type) use a pull up resistors for the 5V and this will not power an optocoupler.
Here is a what a typical stepper driver looks like inside (ignore the controller side). Each signal connection basically goes top both sides of an LED. You see each connection is fully isolated from the rest of the stepper driver including the other signals connections. Therefore you must wire to both the + and - sides of each connection.
Here is a typical way to wire it with the - sides daisy chained.
These isolating input features can add a little lag time on the speed of detecting the step, direction and enable signals. FluidNC has several settings to compensate for this.
Many signals also have to be inverted. The isolation circuit flips the signal, so FluidNC may need to adjust for that.
In the image below, you can see the pulse length requirements and required gaps between signals. The PUL (step signal) and DIR are inverted. The ENA is not, but you still might need to invert it because FluidNC considers it a disable signal. If the motors lock after you issue the FluidNC $MD (Motor/Disable) command and unlock (turn freely) after $ME (Motor/Enable), you have the enable backwards, and will have to either add or remove the :low attribute from the disable pin definition.
The following settings under the stepping: group can be used to control the pulse durations.
Here are the settings. The "t" numbers from the image above are indicated.
Example: Stepping section
stepping:
pulse_us: 2
dir_delay_us: 1
disable_delay_us: 0
There are a couple of adapters available to help with this. These both send the signals to the existing connectors.
6 Pack Adapter. This is just re-routes the 5V signals to the terminal blocks. It also allows the option of common 5V or common ground.
Note: Be very careful when wiring. If you short the outputs you could permanently damage the controller.
StepStick Adapter. This adapter does level shifting and re-routes the signals to the motor connector. It would be used on controllers that don't have 5V signals. It can be used on 3.3V or 5V controllers.
Each signal typically has a + and - connection. This allow you to wire them totally isolated from each other. The signals on the FluidNC side generally will not be isolated from each other and share a common ground.
The easiest way to wire that is to connect all the minus sides together and connect that to ground on the controller. Wire the plus sides to the signals. This is shown below.
You could also wire the + sides together and connect that to +5V on the controller side. The minus sides would connect to the signals on the controller side. This is shown below.
As far as FluidNC is concerned, external drivers are the simplest stepper motors. It is very unlikely there is a firmware problem. Problems almost always have something to do with your driver, the wiring or the stepping config.
Optocouplers are often misunderstood. They do not work like most other common circuit elements that are sensitive primarily to voltage differences. Optocouplers work by passing current through an internal LED whose light shines on an internal phototransistor. The phototransistor then conducts current depending on how much light is falling on it.
The optocoupler LED always has a resistor in series with it to limit the current. That resistor is usually inside the external driver box. Its value is often in the range of 220 to 470 ohms, but there is no real standard for what the value should be.
The amount of current that goes through the LED can be calculated as Iled = (Vin - Vf) / R, where Iled is the current through the LED, Vin is the input voltage across the combination of the resistor and the optocoupler, Vf is the "forward voltage" of the LED - usually about 1.1V, and R is the external resistor value. If, for example, the resistor value is 220 ohms, then with Vin = 3.3V, Iled is (3.3 - 1.1) / 220 = 10 mA. At Vin = 5V, a similar calculation give Iled = 17mA. But that is only the input side of the story. The phototransistor and its external load resistor must also be considered.
Optocouplers are specified by Current Transfer Ratio (CTR), which is the ratio between the LED current and the current through the phototransistor when it is illuminated. The CTR value typically ranges from 50% (phototransitor current is half of LED current) to 200% (phototransistor current is twice the LED current). That spec is not very precise. It changes with the LED current, the temperature, the age of the device, the load resistance in the circuit on the phototransistor end, the part number of the optocoupler, and from unit to unit.
If we assume a CTR at the low end of the usual range, say 50%, if Iled is 10 mA, then the phototransistor current will be 5mA. That would be enough to drive a 1000 ohm load resistor to 5V, more than enough to create a logic 1 state on the downstream circuitry. The load resistors in external drivers are often much more than 1000 ohms - say perhaps 5K - so 1mA of phototransistor current would be plenty.
But the problem is usually not turn-on, but rather turn-off. When you stop illuminating a phototransistor, it doesn't stop conducting current immediately. It can take many milliseconds before the light-induced charge carriers in the phototransitor dissipate and let the phototransistor stop conducting. The turn-off time can be decreased by using very small load resistors, but that is not typically done in external drivers.