Skip to content
Merged
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
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ openmv --port /dev/ttyACM0 --quiet

# Debug mode (verbose logging)
openmv --port /dev/ttyACM0 --debug

# Preview a custom data channel
openmv --port /dev/ttyACM0 --channel ticks
```

### Options
Expand All @@ -47,6 +50,7 @@ openmv --port /dev/ttyACM0 --debug
| `--timeout SEC` | 1.0 | Protocol timeout in seconds |
| `--baudrate N` | 921600 | Serial baudrate |
| `--firmware FILE` | None | Firmware ELF file for profiler symbol resolution |
| `--channel NAME` | None | Custom data channel to poll and print |
| `--quiet` | False | Suppress script output text |
| `--debug` | False | Enable debug logging |

Expand Down Expand Up @@ -108,6 +112,46 @@ with Camera('/dev/ttyACM0') as camera:
print(text, end='')
```

### Custom Channels

Custom channels allow bidirectional data exchange between the camera and host.

**Camera-side script (MicroPython):**

```python
import time
import protocol

class TicksChannel:
def size(self):
return 10

def read(self, offset, size):
return f'{time.ticks_ms():010d}'

def poll(self):
return True

protocol.register(name='ticks', backend=TicksChannel())
```

**Host-side (Python):**

```python
from openmv import Camera

with Camera('/dev/ttyACM0') as camera:
camera.exec(script)

while True:
# Check if channel has data
if camera.has_channel('ticks'):
size = camera.channel_size('ticks')
if size > 0:
data = camera.channel_read('ticks', size)
print(f"Ticks: {data.decode()}")
```

## API Reference

Full API documentation: [docs/api.md](https://github.com/openmv/openmv-python/blob/master/docs/api.md)
Expand Down
31 changes: 30 additions & 1 deletion src/openmv/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,25 @@

# Default test script for csi-based cameras
test_script = """
import csi, image, time
import time
import protocol
import csi
import image

class TicksChannel:
def __init__(self):
pass

def size(self):
return 10

def read(self, offset, size):
return f'{time.ticks_ms():010d}'

def poll(self):
return True

ch1 = protocol.register(name='ticks', backend=TicksChannel())

csi0 = csi.CSI()
csi0.reset()
Expand Down Expand Up @@ -145,6 +163,10 @@ def main():
action='store_true',
help='Suppress script output text')

parser.add_argument('--channel',
action='store', default=None,
help='Custom channel to poll and read')

args = parser.parse_args()

# Register signal handlers for clean exit
Expand Down Expand Up @@ -249,6 +271,13 @@ def main():
if text := camera.read_stdout():
print(text, end='')

# Read custom channel
if args.channel and status and status.get(args.channel):
if size := camera.channel_size(args.channel):
data = camera.channel_read(args.channel, size=size)
preview = data[:10] if len(data) > 10 else data
logging.info(f"[{args.channel}] ({size} bytes) {preview}")

# Read frame data
if frame := camera.read_frame():
fps = fps_clock.get_fps()
Expand Down