Skip to content

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

  1. Implement only what you need – Your driver can implement one or both interfaces
  2. Initialize to safe state – Always call actBipolar(0) or actUnipolar(0) in constructor
  3. Constrain inputs – Use constrain() before mapping to hardware values
  4. 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:

  1. Choose the appropriate interface (actBipolar or actUnipolar)
  2. Implement the method with your hardware-specific logic
  3. Initialize pins and set safe state in constructor
  4. 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.