ESPP Logo
  • ADC APIs
  • ADRC APIs
  • Base Component
  • Base Peripheral
  • Battery APIs
  • Motor (BDC + BLDC) APIs
  • BLE APIs
  • Button APIs
  • ALXV Labs Byte90
  • Controller APIs
  • Command Line Interface (CLI) APIs
  • COBS (Consistent Overhead Byte Stuffing)
  • Color APIs
  • CSV APIs
  • Display APIs
  • Distance Sensor APIs
  • Encoder APIs
  • ESP32 TimerCam
  • ESP BOX
  • Event Manager APIs
  • File System APIs
  • Filter APIs
  • FTP APIs
  • Haptics APIs
  • HID APIs
  • I2C
  • IMU APIs
  • Interrupt APIs
  • Input APIs
  • IO Expander APIs
  • Iperf Menu
  • Joystick APIs
  • LED APIs
  • LED Driver Components
  • LED Strip APIs
  • Logging APIs
  • M5Stack Tab5
  • Math APIs
  • MaTouch Rotary Display
  • Monitoring APIs
  • MotorGo Mini
  • MotorGo Plink
    • MotorGo Plink
      • MotorGo Plink Example
    • API Reference
      • Header File
      • Classes
  • Neopixel APIs
  • Network APIs
  • NFC APIs
  • NVS APIs
  • ODrive ASCII Protocol Component
  • PID APIs
  • Power Monitoring APIs
  • QtPy ESP32 Pico and QtPy ESP32-S3
  • QwiicNES
  • Remote Debug APIs
  • Remote Control Transceiver (RMT)
  • RTC APIs
  • RTSP APIs
  • RunQueue APIs
  • Seeed Studio Round Display
  • Serialization APIs
  • Smart Panlee SC01 Plus
  • SPI
  • State Machine APIs
  • LilyGo T-Deck
  • LilyGo T-Dongle S3
  • Tabulate APIs
  • Task APIs
  • Thermistor APIs
  • Timer APIs
  • WiFi APIs
  • ESP32-WROVER-KIT
  • Waveshare ESP32-S3 GEEK
  • Waveshare ESP32-S3 LCD 1.47”
  • Waveshare ESP32-S3 TouchLCD
  • XIAO ESP32S3 Sense
ESPP
  • MotorGo Plink
  • Edit on GitHub

MotorGo Plink

MotorGo Plink

The MotorGo Plink is a four-channel ESP32-S3 motor-control board from Every Flavor Robotics. The espp::MotorGoPlink component provides a singleton board abstraction for the documented pin mapping of its DC motor outputs, encoder chip-selects, servo signal header, onboard LSM6DS33 IMU, Qwiic and internal I2C buses, and user/status LEDs.

It also provides helper methods for:

  • initializing the four dual-PWM motor channels via espp::BdcDriver on MCPWM and commanding normalized motor speeds, where positive commands drive pwm_a and negative commands drive pwm_b

  • initializing the shared SSI/SPI encoder bus and creating four espp::Mt6701<SSI> helpers

  • initializing the onboard LSM6DS33 IMU on the hidden I2C bus via the espp::Lsm6dso helper

  • accessing the four RC-servo signal pins for use with an external servo driver

  • controlling the user and status LEDs with direct brightness setters or a Gaussian breathing effect

  • MotorGo Plink Example
    • How to use example
      • Hardware Required
      • Configuration
      • Build and Flash

API Reference

Header File

  • components/motorgo-plink/include/motorgo-plink.hpp

Classes

class MotorGoPlink : public espp::BaseComponent

MotorGoPlink is a lightweight board-support component for the MotorGo Plink hardware.

It exposes the documented pin mapping for the board’s:

  • four dual-PWM DC motor outputs

  • four encoder chip-selects on a shared SSI/SPI bus

  • four RC-servo signal pins

  • one onboard LSM6DS33 IMU on the hidden I2C bus

  • Qwiic and hidden I2C buses

  • user and status LEDs

The class is a singleton and can be accessed with get().

MotorGo Plink Example

  auto &board = espp::MotorGoPlink::get();

  if (!board.initialize_leds()) {
    logger.warn("Failed to initialize indicator LEDs");
  } else {
    board.start_led_breathing();
  }

#if CONFIG_MOTORGO_PLINK_EXAMPLE_ENABLE_MOTOR_SWEEP
  if (!board.initialize_motors()) {
    logger.error("Failed to initialize motor drivers");
  } else {
    board.stop_all_motors();
  }
#else
  logger.info("Motor drivers not initialized because motor sweep is disabled");
#endif

  if (!board.initialize_imu()) {
    logger.warn("Failed to initialize onboard IMU");
  } else {
    logger.info("IMU initialized");
  }

  log_board_info(board);

#if CONFIG_MOTORGO_PLINK_EXAMPLE_ENABLE_ENCODER_POLLING
  if (!board.initialize_encoders(false)) {
    logger.warn("Failed to initialize encoders");
  } else {
    logger.info("Encoder polling enabled");
  }
#else
  logger.info("Encoder polling disabled");
#endif

#if CONFIG_MOTORGO_PLINK_EXAMPLE_ENABLE_MOTOR_SWEEP
  logger.warn("Motor sweep enabled; using an aggressive {:.0f}% to {:.0f}% duty sweep after a "
              "{:.0f}% zero window. Ensure the board is connected to a safe test setup",
              35.0f, 85.0f, 5.0f);
#else
  logger.info("Motor sweep disabled; all motors remain stopped");
#endif

#if CONFIG_MOTORGO_PLINK_EXAMPLE_ENABLE_MOTOR_SWEEP
  float motor_phase = 0.0f;
#endif
  while (true) {
#if CONFIG_MOTORGO_PLINK_EXAMPLE_ENABLE_MOTOR_SWEEP
    update_motor_demo(board, motor_phase);
    log_motor_outputs(board);
#endif

#if CONFIG_MOTORGO_PLINK_EXAMPLE_ENABLE_ENCODER_POLLING
    log_encoder_angles(board);
#endif

    log_imu_data(board);

    using namespace std::chrono_literals;
    std::this_thread::sleep_for(500ms);
  }

Public Types

using Encoder = espp::Mt6701<espp::Mt6701Interface::SSI>

Alias for the SSI-based magnetic encoder helper used on each motor channel.

using MotorDriver = espp::BdcDriver

Alias for the brushed DC motor driver helper used on each motor channel.

using Imu = espp::Lsm6dso<espp::lsm6dso::Interface::I2C>

Alias for the onboard hidden-bus IMU helper.

Public Functions

MotorGoPlink(const MotorGoPlink&) = delete

Deleted copy constructor.

MotorGoPlink &operator=(const MotorGoPlink&) = delete

Deleted copy assignment operator.

MotorGoPlink(MotorGoPlink&&) = delete

Deleted move constructor.

MotorGoPlink &operator=(MotorGoPlink&&) = delete

Deleted move assignment operator.

I2c &get_external_i2c()

Get the external Qwiic I2C bus.

Returns:

Reference to the initialized external I2C bus.

I2c &qwiic_i2c()

Get the external Qwiic I2C bus.

Returns:

Reference to the initialized external I2C bus.

I2c &hidden_i2c()

Get the internal hidden I2C bus.

Returns:

Reference to the initialized internal I2C bus.

std::array<MotorPins, 4> motor_pins() const

Get the documented motor pin mappings for all four channels.

Returns:

Array containing the two PWM pins for each motor channel.

MotorPins motor_pins(size_t index) const

Get one motor channel pin mapping.

Parameters:

index – Zero-based motor index in the range [0, num_motor_channels()).

Returns:

The motor pin mapping for the requested channel, or a default `MotorPins{}` with `GPIO_NUM_NC` entries if the index is invalid.

EncoderBusPins encoder_bus_pins() const

Get the shared encoder bus pin mapping.

Returns:

The shared SCLK, MISO, and dummy MOSI pins used for the encoder bus.

std::array<gpio_num_t, 4> encoder_cs_pins() const

Get the four encoder chip-select pins.

Returns:

Array containing the chip-select pin for each encoder channel.

gpio_num_t encoder_cs_pin(size_t index) const

Get one encoder chip-select pin.

Parameters:

index – Zero-based encoder index in the range [0, num_motor_channels()).

Returns:

The requested encoder chip-select pin, or `GPIO_NUM_NC` if the index is invalid.

std::array<gpio_num_t, 4> servo_pins() const

Get the four servo signal pins.

Returns:

Array containing the four documented RC-servo signal GPIOs.

gpio_num_t servo_pin(size_t index) const

Get one servo signal pin.

Parameters:

index – Zero-based servo index in the range [0, num_servo_channels()).

Returns:

The requested servo signal pin, or `GPIO_NUM_NC` if the index is invalid.

I2cPins qwiic_pins() const

Get the external Qwiic I2C pin mapping.

Returns:

The external Qwiic SDA/SCL pin mapping.

I2cPins hidden_i2c_pins() const

Get the hidden internal I2C pin mapping.

Returns:

The internal SDA/SCL pin mapping.

LedPins led_pins() const

Get the user/status LED pins.

Returns:

The documented user and status LED GPIOs.

bool initialize_motors(size_t pwm_frequency_hz = motor_default_pwm_frequency_hz())

Initialize the four MCPWM-backed motor driver helpers.

Parameters:

pwm_frequency_hz – PWM carrier frequency for all four motor channels.

Returns:

True if the motor driver helpers were initialized; false if the PWM frequency is invalid or any motor channel could not be configured.

bool set_motor_speed(size_t index, float speed)

Set a normalized motor speed in the range [-1, 1].

Parameters:
  • index – Zero-based motor index in the range [0, num_motor_channels()).

  • speed – Normalized motor command. Values are clamped to [-1.0, 1.0], with positive values driving `pwm_a`, negative values driving `pwm_b`, and zero disabling both PWM outputs for that motor.

Returns:

True if the motor command was applied; false if the motor PWM subsystem has not been initialized or the index is invalid.

float motor_speed(size_t index) const

Get the last commanded normalized motor speed.

Parameters:

index – Zero-based motor index in the range [0, num_motor_channels()).

Returns:

The last commanded normalized speed for that channel, or 0.0f if the index is invalid.

void stop_motor(size_t index)

Stop one motor channel.

Parameters:

index – Zero-based motor index in the range [0, num_motor_channels()).

void stop_all_motors()

Stop all motor channels.

If the motor PWM subsystem has been initialized, each motor is actively commanded to zero speed. Otherwise the cached command values are simply reset to zero.

std::shared_ptr<MotorDriver> motor_driver(size_t index) const

Get one motor driver helper.

Parameters:

index – Zero-based motor index in the range [0, num_motor_channels()).

Returns:

Shared pointer to the requested motor driver helper, or `nullptr` if the index is invalid or that motor has not been initialized yet.

bool initialize_encoders(bool run_tasks = true)

Initialize the shared encoder bus and create the four MT6701 SSI helpers.

Parameters:

run_tasks – If true, each encoder starts its own update task after initialization. If false, callers must invoke `Encoder::update()` manually.

Returns:

True if the shared bus and all four encoder helpers were initialized successfully; false otherwise.

std::shared_ptr<Encoder> encoder(size_t index)

Get one encoder helper.

Parameters:

index – Zero-based encoder index in the range [0, num_motor_channels()).

Returns:

Shared pointer to the requested encoder helper, or `nullptr` if the index is invalid or that encoder has not been initialized yet.

void reset_encoder_accumulator(size_t index)

Reset one encoder’s accumulator.

If the encoder has not been initialized, the request is ignored after logging an error.

Parameters:

index – Zero-based encoder index in the range [0, num_motor_channels()).

bool initialize_imu (const Imu::filter_fn &orientation_filter=nullptr, const Imu::ImuConfig &imu_config={ .accel_range=Imu::AccelRange::RANGE_2G,.accel_odr=Imu::AccelODR::ODR_104_HZ,.gyro_range=Imu::GyroRange::DPS_1000,.gyro_odr=Imu::GyroODR::ODR_104_HZ, })

Initialize the onboard IMU on the hidden I2C bus.

Parameters:
  • orientation_filter – Optional orientation filter callback used by the IMU driver when update() is called.

  • imu_config – Basic accelerometer / gyroscope configuration to apply during initialization.

Returns:

True if the hidden-bus I2C device and IMU helper were initialized successfully; false otherwise.

std::shared_ptr<Imu> imu() const

Get the onboard IMU helper.

Returns:

Shared pointer to the initialized IMU helper, or `nullptr` if initialize_imu() has not been called yet.

bool initialize_leds(float breathing_period = 3.5f)

Initialize the user/status LED helpers.

Parameters:

breathing_period – Default breathing period in seconds for start_led_breathing().

Returns:

True if the indicator LED PWM helper and breathing task were created successfully; false if they were already initialized or the LEDs could not be driven after setup.

void start_led_breathing()

Start breathing both indicator LEDs.

This uses the shared Gaussian waveform returned by gaussian().

void stop_led_breathing()

Stop breathing and turn both indicator LEDs off.

bool set_user_led_brightness(float brightness)

Set the user LED brightness in the range [0, 1].

Parameters:

brightness – Desired brightness, clamped to [0.0, 1.0].

Returns:

True if the user LED duty cycle was updated; false if the LEDs have not been initialized or the breathing task is currently running.

float get_user_led_brightness()

Get the user LED brightness in the range [0, 1].

Returns:

Current user LED brightness normalized to [0.0, 1.0], or 0.0f if the LEDs have not been initialized or the duty cycle could not be read.

bool set_status_led_brightness(float brightness)

Set the status LED brightness in the range [0, 1].

Parameters:

brightness – Desired brightness, clamped to [0.0, 1.0].

Returns:

True if the status LED duty cycle was updated; false if the LEDs have not been initialized or the breathing task is currently running.

float get_status_led_brightness()

Get the status LED brightness in the range [0, 1].

Returns:

Current status LED brightness normalized to [0.0, 1.0], or 0.0f if the LEDs have not been initialized or the duty cycle could not be read.

bool set_led_breathing_period(float period)

Set the LED breathing period in seconds.

Parameters:

period – Breathing period in seconds. Must be greater than zero.

Returns:

True if the period was accepted; false if the value is not positive.

float get_led_breathing_period()

Get the LED breathing period in seconds.

Returns:

The configured LED breathing period in seconds.

std::shared_ptr<espp::Led> leds()

Get the LED helper used for the indicator LEDs.

Returns:

Shared pointer to the indicator LED helper, or `nullptr` if initialize_leds() has not been called yet.

espp::Gaussian &gaussian()

Get the Gaussian waveform used for LED breathing.

Returns:

Reference to the Gaussian waveform object used by the LED breathing task.

inline const std::string &get_name() const

Get the name of the component

Note

This is the tag of the logger

Returns:

A const reference to the name of the component

inline void set_log_tag(const std::string_view &tag)

Set the tag for the logger

Parameters:

tag – The tag to use for the logger

inline espp::Logger::Verbosity get_log_level() const

Get the log level for the logger

See also

Logger::Verbosity

See also

Logger::set_verbosity

Returns:

The verbosity level of the logger

inline void set_log_level(espp::Logger::Verbosity level)

Set the log level for the logger

See also

Logger::Verbosity

See also

Logger::set_verbosity

Parameters:

level – The verbosity level to use for the logger

inline void set_log_verbosity(espp::Logger::Verbosity level)

Set the log verbosity for the logger

See also

set_log_level

See also

Logger::Verbosity

See also

Logger::set_verbosity

Note

This is a convenience method that calls set_log_level

Parameters:

level – The verbosity level to use for the logger

inline espp::Logger::Verbosity get_log_verbosity() const

Get the log verbosity for the logger

See also

get_log_level

See also

Logger::Verbosity

See also

Logger::get_verbosity

Note

This is a convenience method that calls get_log_level

Returns:

The verbosity level of the logger

inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)

Set the rate limit for the logger

See also

Logger::set_rate_limit

Note

Only calls to the logger that have _rate_limit suffix will be rate limited

Parameters:

rate_limit – The rate limit to use for the logger

Public Static Functions

static inline MotorGoPlink &get()

Access the singleton board instance.

Returns:

Reference to the singleton MotorGoPlink object.

static inline constexpr size_t num_motor_channels()

Get the number of supported motor channels.

Returns:

The number of motor channels exposed by the board.

static inline constexpr size_t num_servo_channels()

Get the number of exposed servo signal pins.

Returns:

The number of servo channels exposed by the board.

static inline constexpr size_t motor_default_pwm_frequency_hz()

Get the default PWM frequency used for motor outputs.

Returns:

Default motor PWM frequency in Hz.

static inline constexpr size_t encoder_spi_clock_speed_hz()

Get the encoder bus clock speed.

Returns:

Default encoder SSI/SPI clock speed in Hz.

static inline constexpr gpio_num_t user_led_pin()

Get the user LED GPIO.

Returns:

User LED pin.

static inline constexpr gpio_num_t status_led_pin()

Get the status LED GPIO.

Returns:

Status LED pin.

struct EncoderBusPins

Shared encoder SSI/SPI bus pins.

Public Members

gpio_num_t sclk = {GPIO_NUM_NC}

Shared encoder clock pin.

gpio_num_t miso = {GPIO_NUM_NC}

Shared encoder data pin.

gpio_num_t mosi = {GPIO_NUM_NC}

Dummy MOSI pin used to satisfy the SPI host.

struct I2cPins

I2C pin mapping.

Public Members

gpio_num_t sda = {GPIO_NUM_NC}

I2C SDA pin.

gpio_num_t scl = {GPIO_NUM_NC}

I2C SCL pin.

struct LedPins

User-visible LED pin mapping.

Public Members

gpio_num_t user = {GPIO_NUM_NC}

User LED pin.

gpio_num_t status = {GPIO_NUM_NC}

Status LED pin.

struct MotorPins

Pin mapping for one DC motor channel.

Public Members

gpio_num_t pwm_a = {GPIO_NUM_NC}

First PWM pin for the motor channel.

gpio_num_t pwm_b = {GPIO_NUM_NC}

Second PWM pin for the motor channel.

Previous Next

© Copyright 2022 - 2026, William Emfinger.

  • Built with Sphinx using a theme based on Read the Docs Sphinx Theme.