+
+ +
+

BLDC Haptics

+

The BldcHaptics class is a high-level interface for controlling a BLDC motor +with a haptic feedback loop. It is designed to be used to provide haptic +feedback as part of a rotary input device (the BLDC motor). The component +provides a DetentConfig interface for configuring the input / haptic feedback +profile for the motor dynamically with configuration of:

+
+
    +
  • Range of motion (min/max position + width of each position)

  • +
  • Width of each position in the range (which will be used to calculate the +actual range of motion based on the number of positions)

  • +
  • Strength of the haptic feedback at each position (detent)

  • +
  • Strength of the haptic feedback at the edges of the range of motion

  • +
  • Specific positions to provide haptic feedback at (detents)

  • +
  • Snap point (percentage of position width which will trigger a snap to the +nearest position)

  • +
+
+

The component also provides a HapticConfig interface for configuring the +haptic feedback loop with configuration of:

+
+
    +
  • Strength of the haptic feedback

  • +
  • Frequency of the haptic feedback [currently not implemented]

  • +
  • Duration of the haptic feedback [currently not implemented]

  • +
+
+
+

API Reference

+
+

Header File

+ +
+
+

Header File

+ +
+
+

Header File

+ +
+
+

Classes

+
+
+template<MotorConcept M>
class espp::BldcHaptics
+

Class which creates haptic feedback for the user by vibrating the motor This class is based on the work at https://github.com/scottbez1/smartknob to use a small BLDC gimbal motor as a haptic feedback device. It does so by varying the control type, setpoints, and gains of the motor to create a vibration. The motor is driven using the ESP32’s MCPWM peripheral. The motor is driven in a closed loop using the encoder feedback.

+

+The haptics provided by this class enable configuration of:

    +
  • Positions (with non-magnetic detents) - evenly spaced across the allowed range of motion

  • +
  • Number of magnetic detents - where the

  • +
  • Width of the detents

  • +
  • Strength of the detents

  • +
  • Snap point (position at which the motor will snap to the next detent / position)

  • +
  • Bounds on the rotation of the motor - can be unbounded, bounded within a single revolution, or bounded within multiple revolutions

  • +
+

+

The haptics provided by this class provide the following functionality:

    +
  • Positions: Evenly spaced positions across the allowed range of motion (specified by the min and max position) will have a detent.

  • +
  • Detents: Manually specified detents will be placed at the specified positions. The detents will have a specified width and strength.

  • +
  • End Stops: The motor will vibrate when it is at the min or max position. This is useful for providing feedback when the motor is at the end of its range of motion. The end stops are configured by specifying the strength of the end stops.

  • +
  • Snap point: The snap point is the position at which the motor will snap to the next detent / position. This is useful for providing feedback when the motor is at a certain position. The snap point is configured by specifying the snap point (percentage of the way through the detent) and the snap point bias (percentage of the way through the detent to bias the snap point).

  • +
+

+

Some example configurations are provided as static constexpr in espp::detail. They are:

    +
  • UNBOUNDED_NO_DETENTS: No detents, no end stops, no snap point, no bounds

  • +
  • BOUNDED_NO_DETENTS: No detents, no end stops, no snap point, bounded within a single revolution

  • +
  • MULTI_REV_NO_DETENTS: No detents, no end stops, no snap point, bounded within multiple revolutions

  • +
  • COARSE_VALUES_STRONG_DETENTS: detents, end stops, snap point, bounded within a single revolution

  • +
  • FINE_VALUES_NO_DETENTS: No detents, end stops, snap point, bounded

  • +
  • FINE_VALUES_WITH_DETENTS: detents, end stops, snap point, bounded

  • +
  • RETURN_TO_CENTER_WITH_DETENTS: 3 detents, end stops, snap point, bounded within a single revolution

  • +
  • RETURN_TO_CENTER_WITH_DETENTS_AND_MULTIPLE_REVOLUTIONS: 3 detents, end stops, snap point, bounded within multiple revolutions

  • +
+

+

Some haptic behaviors that can be implemented with this library are:

    +
  • Unbounded with no detents

  • +
  • Bounded with no detents

  • +
  • Multiple revolutions

  • +
  • On/off with strong detent

  • +
  • Return to center without detents

  • +
  • Return to center with detents

  • +
  • Fine values with no detents

  • +
  • Fine values with detents

  • +
  • Coarse values with strong detents

  • +
  • Coarse values with weak detents

  • +
+

+
+

Example 1: Bounded with magnetic detents

+

    // set the motion control type to velocity openloop for the haptics
+    static auto motion_control_type = BldcMotor::MotionControlType::VELOCITY_OPENLOOP;
+    motor.set_motion_control_type(motion_control_type);
+
+    using BldcHaptics = espp::BldcHaptics<BldcMotor>;
+
+    auto haptic_motor = BldcHaptics({.motor = motor, .log_level = espp::Logger::Verbosity::INFO});
+    logger.info("Setting detent config to MAGNETIC_DETENTS");
+    haptic_motor.update_detent_config(espp::detail::MAGNETIC_DETENTS);
+    haptic_motor.start();
+
+    // TODO: test the haptic buzz / click
+    logger.info("Playing haptic buzz for 1 second");
+    haptic_motor.play_haptic(espp::detail::HapticConfig{
+        .strength = 5.0f,
+        .frequency = 200.0f, // Hz, NOTE: frequency is unused for now
+        .duration = 1s // NOTE: duration is unused for now
+    });
+
+
+

+
+
+

Note

+

The motor is configured to be driven in an open-loop mode, so that the PID contained in the motor controller does not interfere with the haptic feedback.

+
+
+

Public Functions

+
+
+inline BldcHaptics(const Config &config)
+

Constructor for the haptic motor.

+
+
Parameters
+

config – Configuration for the haptic motor

+
+
+
+ +
+
+inline void start()
+

Start the haptic motor.

+
+ +
+
+inline void stop()
+

Stop the haptic motor.

+
+ +
+
+inline void update_detent_config(const detail::DetentConfig &config)
+

Configure the detents for the haptic motor.

+
+ +
+
+inline void play_haptic(const detail::HapticConfig &config)
+

Play haptic feedback.

+
+

Note

+

Plays a somewhat-configurable haptic “buzz” / “click” for the user

+
+
+

Note

+

This is a blocking call that will wait for the haptic feedback to finish before returning. It will also block the motor/detent task from running until the haptic feedback is finished.

+
+
+
Parameters
+

config – Configuration for the haptic feedback

+
+
+
+ +
+
+
+struct Config
+

Configuration for the haptic motor.

+
+

Public Members

+
+
+std::reference_wrapper<M> motor
+

Pointer to the motor to use for haptics.

+
+ +
+
+Logger::Verbosity log_level
+

Log level to use for the haptics.

+
+ +
+
+ +
+ +
+
+
+ + +
+