Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions m8-controller-box/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# M8 Controller Box (PR1 Prototype)

The **M8 Controller Box (PR1)** is a versatile USB-connected I/O and communication expansion module designed to simplify integration with CAN devices, sensors, relays, and general-purpose GPIO.

It connects directly to your host device via USB and provides a compact, robust interface for industrial and embedded applications.

## Key Features

### USB ↔ CAN Bus Interface

- Integrated **USB to CAN transceiver**
- Connected internally over an on-board **USB 2.0 hub**
- Powered by **candleLight firmware**
- Compatible with **can-utils** on Linux
- Optional **120Ω termination resistor** (not enabled by default)

**Linux setup example:**

```bash
sudo ip link set can0 type can bitrate 500000
sudo ip link set can0 up
cansend can0 123#1122334455667788
```

Note: Linux is required for CAN functionality.

### USB Audio (Speaker)

- Integrated via USB hub using **PCM2912APJTR**
- No additional drivers required (Linux tested)

### USB 2.0 Expansion

- USB-A ports act as **USB 2.0 extensions**
- Connected via internal USB hub
- Up to **500mA current limit**

### UART1 – RS232

Available via dedicated interface.

Contact us for configuration and usage details.

### FSYNC & Strobe

Hardware support available.

Contact us for integration support and documentation.

### IO Interface (via rp2040_u2if)

General-purpose I/O is handled through the **RP2040 USB-to-interface firmware**:

Repository:
https://github.com/luxonis/rp2040_u2if

**Setup:**

1. Download the repository
2. Install dependencies
3. Flash firmware
4. Refer to pinout diagram for GPIO mapping

## Buttons & LEDs

**Buttons (Top → Bottom):**

- GPIO19
- GPIO20
- GPIO21

**LEDs (Top → Bottom):**

- GPIO17
- GPIO16
- GPIO18

## GPIO Overview

- GPIOs: **0–13, 26, 27**
- GPIO64–71 available
- Configurable as:
- Outputs
- Inputs

## Relays

Relays are present in hardware but **not yet supported in firmware**.

Contact us for early access support.

## What’s in the Box

- M8 Controller Box (PR1 Prototype)
- M8 Cable (Male–Female)
- Plug-in screw terminals:
- 3× 6-pin
- 1× 4-pin
- 2× 3-pin

## OS & Prerequisites

- Linux required for CAN functionality
- USB configuration may require:
- USB muxing
- Forcing USB Host mode

Setup differs between **OAK-4 S** and **OAK-4 D**.

(Example configuration guide coming soon.)

## Pinout Diagram

![M8 Controller Box Schematics](media/schematics.png)

## Example Application

The repository includes the following example applications:

### simple-example

A minimal container example running directly on the M8 Controller Box.

- LED on **pin 18** blinks continuously
- Button on **pin 19** turns on LED on **pin 17**

### depthai-example

Based on the official Luxonis hand pose example.

- Performs hand detection and landmark estimation
- Turns on LED on **pin 17** when a hand is detected

### can-example

Demonstrates CAN transmission triggered by a physical button.

- Monitors button on **pin 19**
- Sends a CAN frame over `can0` when pressed
- Uses `python-can` with Linux SocketCAN

## Support

For integration help, firmware support, or early-access features:

Please contact us.
33 changes: 33 additions & 0 deletions m8-controller-box/can-example/.oakappignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Python virtual environments
venv/
.venv/

# Node.js
# ignore node_modules, it will be reinstalled in the container
node_modules/

# Multimedia files
media/

# Documentation
README.md

# VCS
.git/
.github/
.gitlab/

# The following files are ignored by default
# uncomment a line if you explicitly need it

# !*.oakapp

# Python
# !**/.mypy_cache/
# !**/.ruff_cache/

# IDE files
# !**/.idea
# !**/.vscode
# !**/.zed

52 changes: 52 additions & 0 deletions m8-controller-box/can-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# M8 CAN Transmission Example (Button Triggered)

This example demonstrates how to send data over the **CAN bus** from the M8 Controller Box by pressing a physical button.

The application runs inside a container directly on the device and uses `python-can` with the Linux SocketCAN interface.

## Functionality

This example performs the following actions:

- Monitors the button connected to **GPIO pin 19**.
- When the button is pressed, a CAN frame is transmitted over the M8 CAN interface (`can0`).

This provides a minimal, practical reference for sending CAN messages from a containerized application running on the OAK4 device.

## CAN Interface Setup (Required)

Before running the application, the CAN interface must be configured on the target device where CAN messages should be transmitted.

Run the following commands on the device:

```bash
sudo ip link set can0 type can bitrate 500000
sudo ip link set can0 up
```

This:

- Configures the CAN bitrate to **500 kbps**
- Brings the `can0` interface online

The bitrate must match the rest of the CAN network.

## Monitoring CAN Traffic

To verify transmission, you can listen to CAN traffic on a Linux system using:

```bash
candump can0
```

When the button on **pin 19** is pressed, a CAN frame will appear on the bus.

## Use Case

This example serves as a minimal reference implementation for:

- Sending CAN messages from the M8 Controller Box
- Integrating containerized applications with CAN-based systems
- Trigger-based CAN communication using GPIO inputs

It can be extended to transmit structured data, control messages, or sensor outputs over CAN.
3 changes: 3 additions & 0 deletions m8-controller-box/can-example/backend-run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh
echo "Starting Backend"
exec python3.12 /app/main.py
54 changes: 54 additions & 0 deletions m8-controller-box/can-example/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import time
import can
from utils.rp2040_u2if import RP2040_u2if

# button
BUTTON_PIN = 19

rp2040 = RP2040_u2if()
rp2040.open()

# Button uses pull-up; typical behavior: released=1, pressed=0
rp2040.gpio_init_pin(BUTTON_PIN, RP2040_u2if.GPIO_IN, RP2040_u2if.GPIO_PULL_UP)

# --- CAN (python-can with SocketCAN) ---
CAN_IFACE = "can0"
CAN_ID = 0x123
CAN_DATA = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]

bus = can.interface.Bus(channel=CAN_IFACE, interface="socketcan")


def send_can_frame():
msg = can.Message(
arbitration_id=CAN_ID,
data=CAN_DATA,
is_extended_id=False,
)
bus.send(msg)
print(f"Sent CAN: {CAN_IFACE} id=0x{CAN_ID:X} data={CAN_DATA}")


# --- Button edge detection (send once per press) ---
last_button_state = rp2040.gpio_get_pin(BUTTON_PIN)

# Debounce
last_press_time = 0.0
debounce_s = 0.05

while True:
button_state = rp2040.gpio_get_pin(BUTTON_PIN)

# With pull-up: a press is usually 1->0 (falling edge)
now = time.monotonic()
pressed_edge = (last_button_state != 0) and (button_state == 0)

if pressed_edge and (now - last_press_time) > debounce_s:
try:
send_can_frame()
except Exception as e:
print(f"[ERROR] Failed to send CAN frame: {e}")
last_press_time = now

last_button_state = button_state
time.sleep(0.001)
33 changes: 33 additions & 0 deletions m8-controller-box/can-example/oakapp.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
identifier = "com.example.m8-controller-box.can-example"
entrypoint = ["bash", "-c", "/usr/bin/runsvdir -P /etc/service"]
app_version = "1.0.2"
assign_frontend_port = true

prepare_container = [
{ type = "COPY", source = "./requirements.txt", target = "./requirements.txt" },
{ type = "RUN", command = "python3.12 -m pip install -r /app/requirements.txt --break-system-packages" },
{ type = "RUN", command = "bash -lc 'set -e; apt-get update && apt-get install -y libhidapi-hidraw0 libhidapi-libusb0'" }
]

build_steps = [
"mkdir -p /etc/service/backend",
"cp /app/backend-run.sh /etc/service/backend/run",
"chmod +x /etc/service/backend/run",
]

allowed_devices = [{ allow = true, access = "rwm" }]

additional_mounts = [
{ source = "/dev", target = "/dev", type = "devtmpfs", options = [
"mode=777",
] }
]

[base_image]
api_url = "https://registry-1.docker.io"
service = "registry.docker.io"
oauth_url = "https://auth.docker.io/token"
auth_type = "repository"
auth_name = "luxonis/oakapp-base"
image_name = "luxonis/oakapp-base"
image_tag = "1.2.6"
2 changes: 2 additions & 0 deletions m8-controller-box/can-example/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
hidapi
python-can
Loading
Loading