5.6 KiB
Custom IR Protocol Development Guide
This guide will help you develop a custom decoder for an unknown IR protocol using the tools provided.
Step 1: Capture Raw Signal Data
First, use the IR signal analyzer to capture raw timing data from your unknown remote:
python3 ir_signal_analyzer.py --gpio-pin 18 --verbose
Instructions:
- Point your unknown remote at the IR receiver
- Press buttons to capture signals
- Press the same button multiple times to check consistency
- Press different buttons to understand the protocol structure
- Press Ctrl+C to stop and save analysis
The analyzer will save a JSON file with all captured signals and generate an analysis summary.
Step 2: Analyze the Captured Data
Examine the generated JSON file and analysis summary to understand:
Key Questions to Answer:
-
How many pulses does each signal have?
- Consistent pulse count indicates a structured protocol
- Variable pulse count might indicate variable-length data
-
What are the common timing values?
- Look for repeated timing values across different buttons
- These likely represent bit 0, bit 1, header, footer, etc.
-
Is there a header pattern?
- First few pulses often form a header
- Headers are usually longer than data bits
-
How are bits encoded?
- Pulse Width Modulation: Different pulse lengths for 0/1
- Space Width Modulation: Different space lengths for 0/1
- Both: Different combinations of pulse and space lengths
-
Is there a repeat code?
- Usually 2 pulses with specific timing
- Much shorter than normal frames
Step 3: Customize the Protocol Decoder
Edit custom_ir_protocol.py and update the timing constants based on your analysis:
Example Analysis Results:
# If your analysis shows these common timings:
# 9000μs, 4500μs, 560μs, 1690μs, 560μs
# Update the constants:
self.HEADER_PULSE = 9000 # Long pulse at start
self.HEADER_SPACE = 4500 # Long space after header
self.BIT_1_PULSE = 560 # Short pulse for all bits
self.BIT_1_SPACE = 1690 # Long space for bit 1
self.BIT_0_PULSE = 560 # Short pulse for all bits
self.BIT_0_SPACE = 560 # Short space for bit 0
Common Protocol Patterns:
NEC-like Protocol:
- 34 pulses total (header + 32 data bits)
- Header: 9000μs pulse + 4500μs space
- Data: 560μs pulse + (560μs or 1690μs) space
- Repeat: 9000μs pulse + 2250μs space
RC5-like Protocol:
- 14 bits total
- Manchester encoding
- 889μs bit time
- Start bits: 11
Custom Protocol Example:
- 20 pulses total
- Header: 8000μs pulse + 4000μs space
- Data: 500μs pulse + (500μs or 1500μs) space
- Footer: 500μs pulse + 100000μs space
Step 4: Test Your Decoder
Test your custom decoder with the captured signals:
python3 custom_ir_protocol.py
This will attempt to decode all captured signals using your custom protocol.
Step 5: Integrate with IR System
Once your decoder works, integrate it into your IR system:
- Add to protocol list in your IR listeners
- Update IR mapping to include your custom protocol codes
- Test with real remote to ensure it works correctly
Troubleshooting
Common Issues:
-
No signals decoded:
- Check timing constants match your analysis
- Verify pulse count expectations
- Check tolerance settings (try increasing to 0.3)
-
Inconsistent decoding:
- Remote might have timing variations
- Increase tolerance or add timing ranges
- Check for different button types (some might be repeats)
-
Wrong data extracted:
- Verify bit order (LSB vs MSB)
- Check address vs command bit allocation
- Ensure proper bit indexing
Debug Tips:
-
Enable debug logging:
logging.basicConfig(level=logging.DEBUG) -
Add print statements in decode methods to see what's happening
-
Compare with known protocols to understand similarities
-
Use the analyzer's timing analysis to identify patterns
Advanced Features
Variable-Length Protocols:
Some protocols have variable data lengths. Modify the decoder to handle this:
def _determine_data_length(self, pulse_times):
# Analyze pulse count to determine data length
# Return appropriate bit counts
pass
Multiple Protocol Variants:
If your remote uses multiple similar protocols:
class CustomIRProtocolVariant1(CustomIRProtocol):
def __init__(self):
super().__init__("CUSTOM_V1")
# Different timing constants
class CustomIRProtocolVariant2(CustomIRProtocol):
def __init__(self):
super().__init__("CUSTOM_V2")
# Different timing constants
Checksum Validation:
Some protocols include checksums:
def _validate_checksum(self, address, command):
# Calculate and validate checksum
# Return True if valid, False otherwise
pass
Example: Complete Custom Protocol
Here's an example of a complete custom protocol based on analysis:
class MyCustomProtocol(CustomIRProtocol):
def __init__(self):
super().__init__("MY_CUSTOM")
# Based on analysis of captured signals
self.HEADER_PULSE = 8500
self.HEADER_SPACE = 4200
self.BIT_1_PULSE = 580
self.BIT_1_SPACE = 1650
self.BIT_0_PULSE = 580
self.BIT_0_SPACE = 580
self.REPEAT_PULSE = 8500
self.REPEAT_SPACE = 2100
self.EXPECTED_PULSE_COUNT = 36 # 2 header + 34 data
self.DATA_BITS = 32
self.ADDRESS_BITS = 16
self.COMMAND_BITS = 16
This protocol would decode signals as MY_CUSTOM_1234_5678 format.