Custom Drivers¶
Overview¶
EVA Motors provides a clean hardware abstraction layer that makes adding support for new motor drivers straightforward. The driver layer is designed to be minimal, focused, and easy to implement while maintaining consistency with the rest of the library.
Driver Interface Requirements¶
To create a custom driver, your class must implement one or both of the following protected methods:
| Method | Purpose | Input Range |
|---|---|---|
actBipolar(signed short) |
Bidirectional control | -1000..1000 |
actUnipolar(unsigned short) |
Unidirectional control | 0..1000 |
Understanding Bipolar vs Unipolar¶
Bipolar Interface (actBipolar)¶
Used for devices that support both forward and reverse directions. The input range -1000..1000 represents: - Negative values: Reverse direction (0% to 100% power) - Zero: Stop or neutral - Positive values: Forward direction (0% to 100% power)
Typical applications: DC motors with H-bridges, bidirectional servos
Unipolar Interface (actUnipolar)¶
Used for devices that operate in only one direction. The input range 0..1000 represents: - 0: Minimum output (stop or idle) - 1000: Maximum output (full power)
Typical applications: Aircraft ESCs, pumps, fans, LEDs, linear actuators
Custom Driver Example¶
Here is how to create a driver for a hypothetical motor controller:
#ifndef MY_DRIVER_H_
#define MY_DRIVER_H_
#include <Arduino.h>
namespace evam {
/**
* @brief Driver for hypothetical specific motor controller
*
* This driver demonstrates how to wrap any motor control hardware
* into the EVA Motors driver interface.
*/
class MyDriver {
public:
/**
* @brief Constructor - initialize hardware
*/
MyDriver() {
// Initialize your hardware here
SpecificController.begin();
actBipolar(0); // Start in safe state
}
protected:
/**
* @brief Bipolar control implementation
* @param aValue Range -1000..1000
*/
void actBipolar(signed short aValue) {
// Constrain input to valid range
aValue = constrain(aValue, -1000, 1000);
// Convert to your hardware-specific format
// For example: -1000..1000 to -255..255
int scaledValue = map(aValue, -1000, 1000, -255, 255);
// Send to your hardware
SpecificController.writeSignal(scaledValue);
}
private:
// Your hardware-specific members
};
} // namespace evam
#endif // MY_DRIVER_H_
Using Your Custom Driver¶
Once implemented, your driver can be used with any compatible motor wrapper:
#include <evamDirectionalMotor.h>
#include "MyDriver.h"
// Combine your driver with EVA Motors wrappers
using MyMotor = evam::DirectionalMotor<MyDriver>;
MyMotor motor;
void setup() {
motor.SetupRange(-1000, -200, 200, 1000);
}
void loop() {
motor.Go(750); // 75 percent forward
delay(2000);
motor.Go(-500); // 50 percent reverse
delay(2000);
}
Key Points¶
- Implement only what you need – Your driver can implement one or both interfaces
- Initialize to safe state – Always call
actBipolar(0)oractUnipolar(0)in constructor - Constrain inputs – Use
constrain()before mapping to hardware values - Keep it minimal – The driver should only translate between EVA Motors ranges and your hardware
Contributing¶
If you have created a driver for a common motor controller, contributions are welcome and appreciated.
Please submit a pull request with: - Complete driver implementation - Clear documentation including pin connections - Basic usage example
Your driver will help the entire community and make EVA Motors more versatile.
Summary¶
Creating custom drivers in EVA Motors is straightforward:
- Choose the appropriate interface (
actBipolaroractUnipolar) - Implement the method with your hardware-specific logic
- Initialize pins and set safe state in constructor
- Use with any compatible motor wrapper
The driver layer is designed to be minimal yet flexible, making it easy to support virtually any motor controller hardware.