This code provides the INDI driver for the OpenOGMA Filter Wheel, an astrophotography accessory manufactured by OGMAVision. It allows Linux, macOS, and other INDI-compatible systems (e.g., KStars/Ekos) to control the OpenOGMA filter wheel hardware over USB.
- Device: OpenOgma Filter Wheel
- Connection: USB CDC (Serial)
- Baud: 115200
- INDI Interface: Filter Wheel
- Auto protocol detection: FRAMED → TEXT (FRAMED preferred | TEXT for dvelopment).
- Robust framed RX with magic resync + CRC.
- Atomic state via
GET_STATE (0x1003)(state/position/slots). - Calibration flow:
- Firmware auto-calibrates on power-up (USB plug).
- Driver exposes a Calibrate Now button.
- Driver queues user moves until wheel is IDLE & calibrated.
- Safe UX:
- Reports last known slot while moving (hides “255/unknown”).
- 1-based slots in UI, 0-based on the wire.
- Hot-unplug recovery:
- Detects serial errors, auto-reconnects, re-handshakes, waits out firmware’s auto-calibration, then resumes.
- Connect your OpenOGMA Filter Wheel via USB
- Start the INDI server
- In your INDI client (e.g., KStars/Ekos):
- Add a Filter Wheel device
- Select "OpenOGMA Filter Wheel"
- Choose the correct serial port (usually
/dev/ttyACM0or/dev/ttyUSB0) - Click Connect
- Change Filter: Set
FILTER_SLOTto desired position (1-7) - Calibrate: Set
FILTER_SLOTto0to start calibration - Monitor Status: Watch the device state (IDLE/MOVING/CALIBRATING/ERROR)
- Filter Names: Automatically sized to match your wheel's slot count
The driver intelligently manages filter properties to match your specific wheel configuration:
- Auto-Sizing: After calibration,
FILTER_NAMEentries are automatically created to exactly match your wheel's slot count - No Confusion: Moving from a 7-slot to 5-slot wheel automatically hides extra properties
- Reasonable Bounds: Safety limits (1-7 slots) prevent excessive property creation
- Seamless Switching: Hot-swapping different filter wheels "just works" without manual configuration
The driver implements clean position normalization following INDI standards:
- External Interface: Uses 1-based positions (Filter 1, Filter 2, etc.) as expected by INDI clients
- Internal Communication: Converts to firmware's 0-based positions (0, 1, 2, etc.) automatically
- Moving State: Hides firmware's "255 while moving" value, keeping last known position visible in UI
- Calibration: Slot 0 triggers calibration, 1-N moves to specific filters
- Error Handling: Out-of-range positions are gracefully clamped to valid ranges
This ensures perfect compatibility with all INDI clients while handling firmware quirks transparently.
The driver implements intelligent protocol detection that automatically identifies which communication protocol your OpenOGMA Filter Wheel supports:
-
FRAMED Protocol (Modern, Recommended)
- Binary protocol with error detection
- CRC checksums for data integrity
- Most robust for production use
-
TEXT Protocol (Development/Debugging)
- Human-readable commands
- Easy to test manually
- CRLF line endings (
\r\n)
Driver Start → Serial Connection → Protocol Detection → Device Ready
↓ ↓ ↓ ↓
Initialize Open Port Try FRAMED Get Status
Properties → Set Baud Rate → Try TEXT → Start Polling
→ Handshake → Ready for Use
The driver includes an intelligent one-shot upgrade mechanism that automatically attempts to upgrade the device to the best available protocol:
- Automatic Detection: During idle periods (every 5 minutes), the driver checks if a better protocol is available
- FRAMED Priority: If currently using TEXT, attempts to upgrade to FRAMED protocol
- Silent Operation: Upgrades happen transparently without user intervention
- Fail-Safe: If upgrade fails, driver continues with the current working protocol
- No Interruption: Upgrades only occur when the filter wheel is idle (not moving)
This ensures that devices with firmware updates or intermittent communication issues can automatically benefit from the most robust protocol available.
The driver includes comprehensive error handling and logging:
- Connection Issues: Detailed serial port diagnostics
- Protocol Failures: Individual protocol attempt logging
- Communication Errors: TTY error code translation
- Device States: Real-time status monitoring
Command Format (11 bytes):
[Magic:0xA5][Length][CommandID(4)][Value(4)][CRC]
Features:
- Magic byte (
0xA5) for synchronization - Length field for variable-size responses
- XOR CRC checksum for error detection
- Auto-detection and response matching
- Frame Synchronizer: Intelligent 0xA5 hunter with:
- CR/LF noise skipping for clean detection
- 128-byte scan guard to prevent infinite searching
- CRC failure debugging with hexdump (first 16 bytes)
Commands:
| Command | Description | Example Response |
|---|---|---|
CALIBRATE\r\n |
Start calibration | OK |
POS 3\r\n |
Move to position 3 | OK |
POS\r\n |
Get current position | 3 |
SLOTS\r\n |
Get total slots | 7 |
STATUS\r\n |
Get state code | 0 (IDLE) |
Important: The driver automatically adds \r\n (CRLF) to all text commands, regardless of input format.
| Command ID | Name | Description | Value | Response |
|---|---|---|---|---|
0x1001 |
FW_POSITION |
Move to position | 1-N (move), 0 (calibrate), -1 (get) | Current position |
0x1002 |
FW_SLOT |
Get slot count | 0 | Total slots (0 if uncalibrated) |
0x1003 |
FW_GET_STATE |
Get system state | 0 | Packed state data |
| Code | Name | Description |
|---|---|---|
0 |
IDLE |
Ready for commands |
1 |
CALIBRATING |
Running calibration |
2 |
MOVING |
Moving to position |
3 |
ERROR |
Hardware error |
The driver automatically configures:
- Baud Rate: 115,200 bps (default, expected by firmware)
- Data Bits: 8
- Parity: None
- Stop Bits: 1
- Flow Control: None
- Initial Connection: 3 seconds
- Protocol Detection: 2-3 seconds per protocol
- Normal Operations: 2 seconds
- Device Stabilization: 500ms after connection
- Check Device Power: Ensure the filter wheel is powered on
- Verify USB Connection: Check cable and port
- Check Permissions: Ensure user is in
dialoutgroup:sudo usermod -a -G dialout $USER # Log out and back in
- Identify Port: Find the correct device:
ls -la /dev/ttyACM* /dev/ttyUSB*
Test communication manually:
# Simple echo test
echo -e "SLOTS\r\n" > /dev/ttyACM0
# Interactive terminal
screen /dev/ttyACM0 115200
# Type: SLOTS (press Enter)
# Expected response: 8 (or your wheel's slot count)Enable verbose logging:
# Start with verbose output
indiserver -v indi_openogma
# Or check system logs
journalctl -f -u indiserver| Error | Cause | Solution |
|---|---|---|
TTY_TIME_OUT |
Device not responding | Check power, cables, baud rate |
Invalid file descriptor |
Port not accessible | Check permissions, port name |
All protocol detection attempts failed |
Communication failure | Manual test, check wiring |
Protocol detected: UNKNOWN |
Firmware issue | Contact manufacturer |
| Too many/few filter name entries | Switching between different wheels | Wait for calibration to auto-adjust properties |
indi_openogma/
├── indi_openogma.h # Driver class definition
├── indi_openogma.cpp # Main implementation
├── indi_openogma.xml.cmake # INDI device descriptor
├── CMakeLists.txt # Build configuration
├── config.h.cmake # Version information
└── README.md # This file
Key Methods:
Handshake(): Connection and protocol detectiondetectProtocol(): Auto-detection of communication protocolsendFramed/sendText(): Protocol-specific communicationTimerHit(): Periodic status polling
This section provides guidance for maintainers who want to integrate the OpenOGMA driver into the official INDI 3rd Party repository.
-
Repository Setup
# Clone the INDI 3rd party repository git clone https://github.com/indilib/indi-3rdparty.git cd indi-3rdparty # Create a feature branch git checkout -b feature/openogma-driver
-
Integration Steps
- Add driver source files to appropriate directory structure
- Update CMakeLists.txt to include OpenOGMA build option
- Add any required udev rules
- Update documentation and changelogs
-
Testing & Validation
- Verify clean builds in isolated environment
- Test installation and functionality
- Validate INDI property compliance
This section covers building the OpenOGMA driver as part of the INDI 3rd Party repository for development and testing purposes.
Before building, ensure you have the INDI 3rd Party repository set up:
# Clone the INDI 3rd party repository
git clone https://github.com/indilib/indi-3rdparty.git
cd indi-3rdparty
# Create a feature branch (if developing)
git checkout -b feature/openogma-driverFor active development work, create a debug build with detailed logging and symbols:
Note: (Type = Debug)
# Debug build
mkdir build && cd build
rm -rf ./*
cmake -DCMAKE_BUILD_TYPE=Debug ..
make -j$(nproc)
# Install locally for testing
sudo cmake --install . --component openogma
sudo ldconfigBefore submitting a pull request, thoroughly test the integration build with release settings:
Note (Type = Release)
# Clean build environment
cd /var/www/indi-dev/build
rm -rf ./*
cmake -DCMAKE_BUILD_TYPE=Relase ..
make -j$(nproc)
sudo make installConfirm the driver was installed correctly:
# Check binary installation
ls -l /usr/local/bin/indi_openogma
# Check XML descriptor
ls -l /usr/share/indi/indi_openogma.xml
# Verify driver startup
indiserver -v indi_openogmaWith GDB:
gdb --args indiserver -v indi_openogma
(gdb) set follow-fork-mode child
(gdb) runDebug Logging: The driver includes extensive debug logging. Look for:
Starting handshake with OpenOGMA Filter Wheel...Protocol detected: [FRAMED|TEXT]sendText: sending 'SLOTS\n' (7 bytes)readExact: attempting to read X bytes with Y second timeout
-
udev Rules (if applicable):
sudo udevadm control --reload-rules sudo udevadm trigger
-
Device Detection:
# Identify available serial ports ls -l /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
-
INDI Property Testing:
# Set device port (adjust path as needed) indi_setprop "OpenOGMA Filter Wheel.DEVICE_PORT.PORT=/dev/ttyACM0" # Connect to device indi_setprop "OpenOGMA Filter Wheel.CONNECTION.CONNECT=On" # Verify connection status indi_getprop "OpenOGMA Filter Wheel.CONNECTION.*"
Expected output:
OpenOGMA Filter Wheel.CONNECTION.CONNECT=On OpenOGMA Filter Wheel.CONNECTION.DISCONNECT=Off
- INDI Core Library (>= 1.9)
- CMake (>= 3.5)
- GCC/G++ with C++11 support
This driver is released under the Affero GNU General Public License v3 (AGPLv3).
See the LICENSE.txt file for full terms.
- INDI Library: indilib.org
- OGMAVision: getogma.com
- Issues: GitHub Issues
- INDI Forum: indilib.org/forum