スキル一覧に戻る
Sun-Lab-NBB

implementing-microcontroller-interface

by Sun-Lab-NBB

A Python library that provides tools to acquire, manage, and preprocess scientific data in the Sun (NeuroAI) lab.

2🍴 1📅 2026年1月24日
GitHubで見るManusで実行

SKILL.md


name: implementing-microcontroller-interface description: >- Guides implementation of microcontroller hardware modules and PC interfaces using sl-micro-controllers and ataraxis-communication-interface. Covers firmware module creation, PC interface implementation, and integration patterns. Use when adding microcontroller-based hardware to any acquisition system.

Microcontroller Interface Implementation

Guides the implementation of microcontroller hardware modules and their corresponding PC interfaces. This skill covers the complete stack from firmware (C++) to Python interface for hardware controlled by Teensy microcontrollers.


When to Use This Skill

Use this skill when:

  • Adding a new hardware module to microcontrollers (sensors, actuators, I/O)
  • Implementing the PC-side interface for a firmware module
  • Understanding the communication protocol between PC and microcontrollers
  • Troubleshooting microcontroller communication issues
  • Learning the module development patterns

For system-specific integration (modifying sl-shared-assets configuration, integrating into mesoscope-vr), use the /modifying-mesoscope-vr-system skill instead.


Verification Requirements

Before writing any microcontroller code, verify the current state of dependent libraries.

Step 0: Version Verification

Follow the Cross-Referenced Library Verification procedure in CLAUDE.md:

  1. Check local sl-micro-controllers version against GitHub
  2. Check local ataraxis-communication-interface version against GitHub
  3. If version mismatch exists, ask the user how to proceed
  4. Use the verified source for API reference

Step 1: Content Verification

RepositoryFile/DirectoryWhat to Check
sl-micro-controllerssrc/*.hExisting module patterns
sl-micro-controllerssrc/main.cppModule registration and controller IDs
ataraxis-communication-interfaceREADME.mdCurrent API and usage patterns
sl-experimentmodule_interfaces.pyExisting PC interface patterns

Step 2: Hardware Verification

Before implementing a new module, verify microcontrollers are connected and accessible using MCP tools.

The ataraxis-communication-interface library provides an MCP server for hardware discovery. Start the server with:

axci-mcp

MCP Tools for Microcontroller Verification:

ToolPurpose
list_microcontrollers()Discovers connected microcontrollers and their ports
check_mqtt_broker()Verifies MQTT broker is running (for Unity comms)

Verification workflow:

  1. Discover microcontrollers: Run list_microcontrollers() to identify connected devices
  2. Note port assignments: Record which port corresponds to which controller (ACTOR, SENSOR, ENCODER)
  3. Verify MQTT (if applicable): Run check_mqtt_broker(host="127.0.0.1", port=1883)

Expected output from list_microcontrollers():

Port: /dev/ttyACM0, Controller ID: 101 (ACTOR)
Port: /dev/ttyACM1, Controller ID: 152 (SENSOR)
Port: /dev/ttyACM2, Controller ID: 203 (ENCODER)

If the target microcontroller is not listed:

  • Check USB connection
  • Verify firmware is uploaded with correct controller ID
  • Check for port permission issues (sudo usermod -a -G dialout $USER)

Architecture Overview

The microcontroller ecosystem consists of three interconnected layers:

┌─────────────────────────────────────────────────────────────────────────────────┐
│                           Hardware Layer (Teensy 4.1)                           │
│  ┌───────────────────────────────────────────────────────────────────────────┐  │
│  │  sl-micro-controllers                                                     │  │
│  │  ────────────────────                                                     │  │
│  │  Module classes (C++)  →  Command handlers  →  GPIO/ADC/PWM control       │  │
│  │  Kernel scheduling     →  Runtime cycle     →  Communication              │  │
│  └───────────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────────┘
                                    │ Serial/USB
┌─────────────────────────────────────────────────────────────────────────────────┐
│                         Communication Layer (Python)                            │
│  ┌───────────────────────────────────────────────────────────────────────────┐  │
│  │  ataraxis-communication-interface                                         │  │
│  │  ────────────────────────────────                                         │  │
│  │  SerialCommunication  →  Message serialization  →  Transport layer        │  │
│  │  MicroControllerInterface  →  Process management  →  Queue routing        │  │
│  └───────────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────────┘
                                    │ API calls
┌─────────────────────────────────────────────────────────────────────────────────┐
│                          Application Layer (Python)                             │
│  ┌───────────────────────────────────────────────────────────────────────────┐  │
│  │  sl-experiment                                                            │  │
│  │  ─────────────                                                            │  │
│  │  ModuleInterface subclasses  →  User-facing API  →  SharedMemory IPC      │  │
│  │  MicroControllerInterfaces   →  Orchestration    →  Lifecycle management  │  │
│  └───────────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────────┘

Implementation Workflow

Adding a new microcontroller hardware module requires changes in multiple repositories:

Phase 1: Firmware Implementation (sl-micro-controllers)
├── 1.1 Create module header file (new_module.h)
├── 1.2 Define type codes, command codes, data codes
├── 1.3 Implement command handlers
├── 1.4 Register module in main.cpp
└── 1.5 Upload firmware to microcontroller

Phase 2: PC Interface Implementation (sl-experiment)
├── 2.1 Create ModuleInterface subclass in module_interfaces.py
├── 2.2 Define matching codes and parameters
├── 2.3 Implement lifecycle methods
├── 2.4 Add to MicroControllerInterfaces binding class
└── 2.5 Integrate into data_acquisition.py

Phase 1: Firmware Implementation

See FIRMWARE_MODULE_GUIDE.md for the complete firmware implementation reference including:

  • Module class structure and inheritance
  • Template parameter patterns
  • Command handler implementation
  • Multi-stage command execution
  • Parameter structures and serialization
  • Module registration in main.cpp

Quick Reference: Module Structure

template <const uint8_t kPin, const bool kDefaultState>
class NewModule final : public Module {
  public:
    // Constructor registers with communication
    explicit NewModule(
        const uint8_t module_type,
        const uint8_t module_id,
        Communication& communication
    ) : Module(module_type, module_id, communication) {}

    // Required virtual methods
    bool SetupModule() override;
    bool SetCustomParameters() override;
    bool RunActiveCommand() override;

  private:
    // Module-specific enums and parameters
    enum class kModuleCommands : uint8_t { kCommand1 = 1, kCommand2 = 2 };
    enum class kCustomStatusCodes : uint8_t { kStatus1 = 51, kStatus2 = 52 };

    struct CustomRuntimeParameters {
        uint32_t parameter_a = 1000;
    } PACKED_STRUCT _custom_parameters;

    // Command handler methods
    void ExecuteCommand1();
    void ExecuteCommand2();
};

Phase 2: PC Interface Implementation

See PC_INTERFACE_GUIDE.md for the complete PC interface implementation reference including:

  • ModuleInterface class structure
  • Lifecycle methods (initialize_remote_assets, terminate_remote_assets)
  • Command sending patterns
  • Data processing with process_received_data
  • SharedMemoryArray IPC patterns
  • Integration with MicroControllerInterfaces

Quick Reference: Interface Structure

class NewModuleInterface(ModuleInterface):
    """PC interface for the new hardware module.

    Args:
        parameter_a: Configuration parameter from system config.
    """

    def __init__(self, parameter_a: int) -> None:
        data_codes: set[np.uint8] = {np.uint8(51), np.uint8(52)}
        super().__init__(
            module_type=np.uint8(X),      # Must match firmware
            module_id=np.uint8(Y),        # Must match firmware
            data_codes=data_codes,
            error_codes=None,
        )
        self._parameter_a: int = parameter_a
        self._command1: np.uint8 = np.uint8(1)  # Must match firmware

    def initialize_remote_assets(self) -> None:
        """Called in communication process before message loop."""
        pass  # Connect to shared memory if needed

    def terminate_remote_assets(self) -> None:
        """Called in communication process during shutdown."""
        pass  # Disconnect from shared memory

    def process_received_data(self, message: ModuleData | ModuleState) -> None:
        """Processes incoming data from the module."""
        if message.event == 51:
            # Handle status 1
            pass

    def execute_command1(self) -> None:
        """User-facing method to trigger command 1."""
        self.send_command(
            command=self._command1,
            noblock=np.bool_(False),
            repetition_delay=np.uint32(0),
        )

Code Matching Requirements

The firmware and PC interface MUST use matching codes:

Code TypeFirmware LocationPC Location
Module typeConstructor parameter__init__ module_type
Module IDConstructor parameter__init__ module_id
CommandskModuleCommands enumnp.uint8 command constants
Data codeskCustomStatusCodes enumdata_codes set in __init__
Error codeskCustomStatusCodes enumerror_codes set in __init__
ParametersCustomRuntimeParameterssend_parameters() tuple order

Critical: Parameter types and order in send_parameters() must exactly match the firmware's CustomRuntimeParameters struct. Mismatches cause communication failures or data corruption.


Module Type Code Allocation

Current sl-micro-controllers allocations:

Type CodeModuleControllerPurpose
1TTLModuleSENSORTTL input/output
2EncoderModuleENCODERQuadrature encoder
3BrakeModuleACTORElectromagnetic brake
4LickModuleSENSORConductive lick sensor
5ValveModuleACTORSolenoid valves
6TorqueModuleSENSORTorque sensor
7ScreenModuleACTORScreen power control

Available type codes: 8-255 (reserve 8-49 for common modules, 50+ for specialized)


Controller ID Allocation

Current microcontroller assignments:

Controller IDTypePurpose
101ACTORControls outputs (valves, brakes)
152SENSORMonitors inputs (lick, torque, TTL)
203ENCODERHigh-speed encoder monitoring

Troubleshooting

Communication Failures

  1. Verify port assignment matches physical connection
  2. Check keepalive interval matches between PC and firmware
  3. Verify module type/ID codes match between firmware and PC
  4. Check parameter types match exactly (numpy types on PC)

Command Not Executing

  1. Verify command code matches firmware enum value
  2. Check module is registered in firmware main.cpp
  3. Verify module instance is added to MicroControllerInterface

Data Not Received

  1. Verify data codes are in data_codes set
  2. Check process_received_data() handles the event code
  3. Verify SharedMemoryArray is connected in both processes

Implementation Checklist

Before integrating a new microcontroller module:

Firmware (sl-micro-controllers)

- [ ] Created module header file with template parameters
- [ ] Defined module commands enum (kModuleCommands)
- [ ] Defined status codes enum (kCustomStatusCodes, codes >= 51)
- [ ] Implemented SetupModule() with hardware initialization
- [ ] Implemented SetCustomParameters() for runtime parameters
- [ ] Implemented RunActiveCommand() with command dispatch
- [ ] Created command handler methods
- [ ] Added module registration to main.cpp for appropriate controller
- [ ] Compiled and uploaded firmware successfully

PC Interface (sl-experiment)

- [ ] Created ModuleInterface subclass with matching type/ID codes
- [ ] Defined matching command codes as np.uint8 constants
- [ ] Added data_codes set with matching status codes
- [ ] Implemented initialize_remote_assets() (connect shared memory)
- [ ] Implemented terminate_remote_assets() (disconnect shared memory)
- [ ] Implemented process_received_data() for all data codes
- [ ] Created user-facing methods using send_command()
- [ ] Created parameter setter using send_parameters()
- [ ] Added to MicroControllerInterfaces binding class
- [ ] Integrated into data_acquisition.py lifecycle
- [ ] MyPy strict passes

スコア

総合スコア

75/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

レビュー

💬

レビュー機能は近日公開予定です