Skip to content

devilhyt/lump-device-builder-library

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

5 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

LUMP Device Builder Library

GitHub Repo stars GitHub forks GitHub commit activity GitHub License

This is an Arduino library that implements the LEGO UART Message Protocol (LUMP) for building custom devices.

Introduction

Hi Makers! I'm HsiangYi from the OFDL Robotics Lab. We've open-sourced our internal library for building custom devices for LEGO hosts. For the open-source release, we've significantly refactored it and turned it into an Arduino library that's easy for both novices and professionals to use.

Have fun building your own devices, and don't forget to share your creations with the community!

Todos

  • API Reference page
  • Advanced Topics page
  • Publish to Arduino Library Manager
  • Publish to PlatformIO Library Registry
  • Troubleshooting page
  • FAQ page

Table of Contents

Features

  • LUMP Communication
    • Communicates with LEGO hosts using the LEGO UART Message Protocol (LUMP).
    • Supports up to 16 modes for SPIKE Hub and 8 modes for EV3.
    • Configurable constant power on SPIKE Hub Pin 2, enabling external peripheralsโ€”such as servo motors or camera modulesโ€”to be powered at battery voltage.
    • Automatically detects host type for high-speed handshake, allowing SPIKE Hub to rapidly complete the handshake process.
  • Easy to Use
    • Designed as an Arduino library, making it easy for both novices and professionals to use.
  • Non-Blocking Architecture
    • Enabling programs to remain responsive while handling messages.
  • Easy Watchdog Timer Integration
    • Just register the callback functions for watchdog timer initialization, feeding and deinitialization. The library handles the rest.
    • See Advanced Topics - Watchdog Timer.
  • Compatible with Multiple Dev Boards
  • Provides Basic Debugging Information
    • Including device state tracking, decoded host messages, etc.
    • See Advanced Topics - Debug Mode.

Quickstart

Requirements

To use the quickstart guide, you need:

This guide uses a SPIKE Hub with Pybricks and an ESP32-C3 SuperMini as an example.

Tip

Using SPIKE Hub with Pybricks is suggested for most users, as this combination is the simplest.

Other combinations require additional steps. For example, using SPIKE Hub with SPIKE 3 requires emulating an existing LEGO sensor, while using the EV3 with EV3 Lab requires developing custom blocks.

Tip

Choosing a dev board with at least two UART interfacesโ€”one for programming and one for device communicationโ€”makes development easier.

Install the Library

For Arduino IDE

  1. In the menu bar, select Tools > Manage Librariesโ€ฆ.
  2. Search for LumpDeviceBuilder.
  3. Click install.

For PlatformIO

  1. Go to PlatformIO Home > Libraries > Registry.
  2. Search for LumpDeviceBuilder.
  3. Click Add to Project.

Manual Installation

  1. Download the latest version of the library from the GitHub Releases page and unzip it.
  2. Move the library folder to the proper location.

Wiring

Warning

Do not use multiple power sources simultaneously unless you are certain that the dev board has power management circuits.

For SPIKE Hub

  • Development Wiring Diagram

    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Burner  โ”‚     โ”‚  Dev Board  โ”‚     โ”‚  Host Port  โ”‚
    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
    โ”‚          โ”‚     โ”‚             โ”‚     โ”‚  1. M1      โ”‚      LPF2 Socket Pinout
    โ”‚          โ”‚     โ”‚             โ”‚     โ”‚  2. M2      โ”‚     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚   GND    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค     GND     โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  3. GND     โ”‚     โ”‚   6 5 4 3 2 1   โ”‚
    โ”‚   VCC    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค     VIN     โ”‚     โ”‚  4. VCC     โ”‚     โ”‚ โ”Œโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ” โ”‚
    โ”‚          โ”‚     โ”‚     RX      โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  5. TX      โ”‚     โ””โ”€โ”˜             โ””โ”€โ”˜
    โ”‚          โ”‚     โ”‚     TX      โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  6. RX      โ”‚
    โ”‚   ...    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค     ...     โ”‚     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Production Wiring Diagram

    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Dev Board  โ”‚     โ”‚  Host Port  โ”‚
    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
    โ”‚             โ”‚     โ”‚  1. M1      โ”‚      LPF2 Socket Pinout
    โ”‚             โ”‚     โ”‚  2. M2      โ”‚     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚     GND     โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  3. GND     โ”‚     โ”‚   6 5 4 3 2 1   โ”‚
    โ”‚     VIN     โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  4. VCC     โ”‚     โ”‚ โ”Œโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ” โ”‚
    โ”‚     RX      โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  5. TX      โ”‚     โ””โ”€โ”˜             โ””โ”€โ”˜
    โ”‚     TX      โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  6. RX      โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

For EV3

  • Development Wiring Diagram

    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Burner  โ”‚     โ”‚  Dev Board  โ”‚     โ”‚  Host Port  โ”‚      RJ12 Socket
    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค      Pinout  โ”Œโ”€โ”€โ”
    โ”‚          โ”‚     โ”‚             โ”‚  โ”Œโ”€โ”€โ”ค  1. M1      โ”‚            โ”Œโ”€โ”˜  โ””โ”€โ”
    โ”‚          โ”‚     โ”‚             โ”‚  โ”‚  โ”‚  2. M2      โ”‚     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚
    โ”‚   GND    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค     GND     โ”œโ”€โ”€โ”ดโ”€โ”€โ”ค  3. GND     โ”‚     โ”‚             โ”‚
    โ”‚   VCC    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค     VIN     โ”‚     โ”‚  4. VCC     โ”‚     โ”‚             โ”‚
    โ”‚          โ”‚     โ”‚     RX      โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  5. TX      โ”‚     โ”‚ 6 5 4 3 2 1 โ”‚
    โ”‚          โ”‚     โ”‚     TX      โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  6. RX      โ”‚     โ””โ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”˜
    โ”‚   ...    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค     ...     โ”‚     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Production Wiring Diagram

    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Dev Board  โ”‚     โ”‚  Host Port  โ”‚      RJ12 Socket
    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค      Pinout  โ”Œโ”€โ”€โ”
    โ”‚             โ”‚  โ”Œโ”€โ”€โ”ค  1. M1      โ”‚            โ”Œโ”€โ”˜  โ””โ”€โ”
    โ”‚             โ”‚  โ”‚  โ”‚  2. M2      โ”‚     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚
    โ”‚     GND     โ”œโ”€โ”€โ”ดโ”€โ”€โ”ค  3. GND     โ”‚     โ”‚             โ”‚
    โ”‚     VIN     โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  4. VCC     โ”‚     โ”‚             โ”‚
    โ”‚     RX      โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  5. TX      โ”‚     โ”‚ 6 5 4 3 2 1 โ”‚
    โ”‚     TX      โ”œโ”€โ”€โ”€โ”€โ”€โ”ค  6. RX      โ”‚     โ””โ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”ดโ”€โ”˜
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Build a Simple Device โ€” Analog / Digital Reader

Step 1: Create a new Arduino sketch and include the library

#include <LumpDeviceBuilder.h>

Step 2: Define the supported modes for the device

For this device, two modes are implemented:

  • mode 0: Analog Reader
  • mode 1: Digital Reader
LumpMode modes[]{
  {"Analog", DATA16, 1, 4, 0, "raw", {0, 4095}, {0, 100}, {0, 4095}},
  {"Digital", DATA8, 1, 1, 0, "raw", {0, 1}, {0, 100}, {0, 1}}
};

uint8_t numModes = sizeof(modes) / sizeof(LumpMode);

Parameter descriptions:

LumpMode(const char *name, uint8_t dataType, uint8_t numData,
         uint8_t figures, uint8_t decimals, const char *symbol,
         LumpValueSpan raw, LumpValueSpan pct, LumpValueSpan si,
         ...)
  • name: Mode name.

    • Naming rules:

      • Must not be an empty string "" or nullptr.
      • Must start with a letter (Aโ€“Z, aโ€“z).

      If invalid, the name will be set to the string "null".

    • Length limit (excluding null terminator):

      • If power parameter is false: 11 (default)
      • If power parameter is true: 5

      Names exceeding the limit will be truncated.

  • dataType: Data type.

    • Possible values: DATA8, DATA16, DATA32, DATAF.
  • numData: Number of data.

    • The maximum depends on data type due to 32-byte payload limit:
      • DATA8 (1 byte) : [1..32]
      • DATA16 (2 bytes): [1..16]
      • DATA32 (4 bytes): [1..8]
      • DATAF (4 bytes): [1..8]
  • figures: Number of characters shown in view and data log (including the decimal point).

    • Valid range: [0..15]
  • decimals: Number of decimals shown in view and data log.

    • Valid range: [0..15]
  • symbol: Symbol of the measurement unit (default: "").

    • Rules:
      • Set to empty string "" or nullptr if not required.
      • Length limit (excluding null terminator): 4
  • raw: Raw value span (default: false).

    • When set to false, this value span will not be provided to the host. The host will use the default range [0, 1023].
  • pct: Percentage value span (default: false).

    • When set to false, this value span will not be provided to the host. The host will use the default range [0, 100].
  • si: Scaled value span (default: false).

    • When set to false, this value span will not be provided to the host. The host will use the default range [0, 1023].

Note

For a comprehensive list and detailed descriptions, please refer to the LumpMode API Reference.

Step 3: Instantiate the device

Select a serial interface for device communication and initialize the device with the defined modes.

// Select a serial interface for device communication.
#define DEVICE_SERIAL Serial0
#define RX_PIN        20
#define TX_PIN        21

LumpDevice<HardwareSerial> device(&DEVICE_SERIAL, RX_PIN, TX_PIN, 68, 115200, modes, numModes);

Parameter descriptions:

template <typename T>
LumpDevice(T *uart, uint8_t rxPin, uint8_t txPin,
           uint8_t type, uint32_t speed,
           LumpMode *modes, uint8_t numModes,
           ...);
  • T: Type of the serial interface (typically hardwareSerial).

  • uart: Serial interface used for UART communication (e.g., Serial0, Serial1).

  • rxPin: RX pin number of the serial interface.

  • txPin: TX pin number of the serial interface.

  • type: Device type.

  • speed: Communication speed.

  • modes: Device modes (must be an array of LumpMode).

  • numModes: Number of modes.

    • The maximum depends on the host type:

      • SPIKE Hub: [1..16]
      • EV3: [1..8]

      Modes beyond the limit will be ignored.

Note

For a comprehensive list and detailed descriptions, please refer to the LumpDevice API Reference.

Step 4: Define the actions for each mode

The library uses a state machine to manage communication and reserves 2 states for developers to implement mode-specific actions.

Developers must implement the following states:

  • LumpDeviceState::InitMode

    • Initializes the mode.
      • e.g., resetting values, configuring hardware.
  • LumpDeviceState::Communicating

    • Acquires data.
      • e.g., analog or digital reading.
    • Sends data to the host.
      • It is suggested to keep the data sending rate below 1000 Hz to prevent UART overrun errors.
      • For best practice, refer to Event-Driven Data Transmission in Advanced Topics.
    • Handles NACK from the host.
      • Upon receiving a NACK, send data to the host immediately.

When the mode is changed, the device state transitions to LumpDeviceState::InitMode, and then to LumpDeviceState::Communicating after one iteration. These transitions are handled automatically by the library.

Warning

The entire program must be non-blocking when using this library. Avoid using blocking functions such as delay(). Use non-blocking techniques instead.

Let's design a function to run the device modes:

// Pin definitions.
#define ANALOG_PIN  3
#define DIGITAL_PIN 4

void runDeviceModes() {
  // Get the device state and mode.
  auto state = device.state();
  auto mode  = device.mode();

  // Check the device state and perform actions accordingly.
  switch (state) {
    case LumpDeviceState::InitMode:
      // Initialize the mode.
      switch (mode) {
        case 0:
          pinMode(ANALOG_PIN, INPUT);
          break;
        case 1:
          pinMode(DIGITAL_PIN, INPUT);
          break;

        default:
          break;
      }
      break;

    case LumpDeviceState::Communicating: {
      static uint16_t value0     = 0;
      static uint8_t value1      = 0;
      static uint32_t period     = 5; // 200Hz
      static uint32_t prevMillis = 0;
      uint32_t currentMillis     = millis();

      // Send data to the host.
      if (device.hasNack() || (currentMillis - prevMillis > period)) {
        switch (mode) {
          case 0:
            value0 = analogRead(ANALOG_PIN);
            device.send(value0);
            break;

          case 1:
            value1 = digitalRead(DIGITAL_PIN);
            device.send(value1);
            break;

          default:
            break;
        }

        prevMillis = currentMillis;
      }
      break;
    }

    default:
      break;
  }
}

Note

The value passed to send() must match the mode's dataType defined in LumpMode.

For example, use uint16_t / int16_t for DATA16, and uint8_t / int8_t for DATA8.

Step 5: Initialize the device and run it

void setup() {
  device.begin();
}

void loop() {
  device.run();
  runDeviceModes();
}

The full code is here.

Step 6: Upload the sketch to the dev board.

Ensure that the sketch is successfully uploaded to the dev board.

Step 7: Test the device.

Connect the dev board to SPIKE Hub Port A. Copy and paste the following code into the Pybricks IDE, then run it to verify device functionality:

from pybricks.iodevices import PUPDevice
from pybricks.parameters import Port
from pybricks.tools import wait

device = PUPDevice(Port.A)
print(device.info())

while True:
    print(f"analog  (mode 0): {device.read(0)}")
    print(f"digital (mode 1): {device.read(1)}")
    wait(1000)

You should see the following output in the console:

{'id': 68, 'modes': (('Analog', 1, 1), ('Digital', 1, 0))}
analog  (mode 0): (4095,)
digital (mode 1): (1,)

All steps are done!

You can start building your own devices.

See Advanced Topics for in-depth guides.

Compatible LEGO Hosts and Firmwares

The firmware versions listed below were used for testing during the library's initial release.

Host Firmware Version
SPIKE Hub Pybricks 3.6.1
Hub OS 1.6.62
EV3 EV3-G 1.09E

Compatible Dev Boards

The Dev boards listed below are ones we have used before and can run stably.

However, the library is designed to be compatible with any board that has a UART interface. If you have a board that is not listed here, please feel free to try it out.

Dev Board MCU Add'l Config
ESP32-C3 SuperMini ESP32
ESP32-DevKitC
NodeMCU-32s
NodeMCU DEVKIT V1.0 ESP8266
Raspberry Pi Pico RP2040 Yes
RP2040-Zero
Seeed Studio XIAO-RP2040
STM32 Blue Pill STM32F103C8T6
Arduino UNO R3 ATmega328/P Yes
Arduino Nano
Arduino Pro Mini

Important

Some Dev boards and MCUs require additional configuration.

See Additonal Configuration for MCUs for details.

Limitations

  • The entire program must be non-blocking when using this library.
  • No support for sending the Combined Mode information during handshake.
  • Not all MCUs support automatic host type detection. This feature must be manually disabled.

Acknowledgements

Thanks to the Pybricks team for publishing a detailed LUMP specification. For our open-source release, we adopted the more comprehensive LUMP header file defined by Pybricks.

Disclaimers

LEGOยฎ is a trademark of the LEGO Group of companies which does not sponsor, authorize or endorse this project.

License

This library is licensed under the LGPL 3.0 or later license.

About

Arduino library that implements the LEGO UART Message Protocol (LUMP) for building custom devices.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published