-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathISXMPL3710ex4-IS3710 DMX Receiver Raspberry Pi Python Example.py
More file actions
146 lines (121 loc) · 5.02 KB
/
Copy pathISXMPL3710ex4-IS3710 DMX Receiver Raspberry Pi Python Example.py
File metadata and controls
146 lines (121 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# ==============================================================================
# Title: ISXMPL3710ex4 - IS3710 DMX Receiver Raspberry Pi Example
# Product: Kappa3710Rasp (Raspberry Pi HAT)
# Product Page: https://inacks.com/kappa3710rasp
# IC: INACKS IS3710 (DMX to I2C Receiver)
# Datasheet: https://inacks.com/IS3710_datasheet_isdoc133
#
# Description:
# This script demonstrates the use of the IS3710 IC to bridge DMX512 data
# to the I2C bus. By using the IS3710, the Raspberry Pi avoids the complex
# timing requirements of the DMX protocol, hardware interrupts, and high-speed
# UART sampling, receiving processed DMX frames as standard I2C registers.
#
# Key Benefits:
# 1. Zero CPU overhead for DMX protocol decoding and signal timing.
# 2. Simplified hardware interface via standard I2C (SMBus).
# 3. Robust data handling: The IC manages frame breaks and MAB timings internally.
#
# Usage:
# Read the I2C memory map address corresponding to the DMX channel.
# I2C memory map addresses are 16-bit wide.
# Memory map registers are 8-bit wide.
#
# Example 1: To read DMX channels 1 to 10, perform an I2C read operation
# starting at register address 1 and read up to 10 bytes.
#
# Example 2: To read DMX channels 510 and 511, perform an I2C read operation
# starting at register address 510 and read 2 bytes.
#
# Date: 2025-05-22
# Revision: 1.0
# ==============================================================================
from smbus2 import SMBus, i2c_msg
import RPi.GPIO as GPIO
import time
import sys
# --- Configuration Constants ---
# Default I2C bus on Raspberry Pi (usually Bus 1 on modern models)
I2C_BUS = 1
# Default 7-bit I2C hardware address for the IS3710 IC
I2C_DEVICE_ADDRESS = 0x10
# GPIO Setup using Broadcom (BCM) pin numbering
GPIO.setmode(GPIO.BCM)
# Define physical GPIO pins for PWM output (RGB LED feedback)
LED_PIN_R = 12
LED_PIN_G = 13
LED_PIN_B = 19
# --- Hardware Initialization ---
# Initialize pins as outputs for visualizing DMX channel intensity
GPIO.setup(LED_PIN_R, GPIO.OUT)
GPIO.setup(LED_PIN_G, GPIO.OUT)
GPIO.setup(LED_PIN_B, GPIO.OUT)
# Initialize PWM at 1 kHz to map 8-bit DMX values to LED duty cycles
pwm1 = GPIO.PWM(LED_PIN_R, 1000)
pwm2 = GPIO.PWM(LED_PIN_G, 1000)
pwm3 = GPIO.PWM(LED_PIN_B, 1000)
# Start PWM with 0% duty cycle (Off state)
pwm1.start(0)
pwm2.start(0)
pwm3.start(0)
def read_registers(start_register, length):
"""
Reads a block of data from the IS3710 registers via the I2C bus.
Args:
start_register (int): The 16-bit register address to start reading from.
length (int): The number of consecutive bytes to read.
Returns:
list: Data bytes retrieved from the IC.
"""
# Split the 16-bit register address into two 8-bit bytes for the I2C write
high_addr = (start_register >> 8) & 0xFF
low_addr = start_register & 0xFF
try:
with SMBus(I2C_BUS) as bus:
# Prepare a combined write-read transaction (I2C Repeated Start)
write_msg = i2c_msg.write(I2C_DEVICE_ADDRESS, [high_addr, low_addr])
read_msg = i2c_msg.read(I2C_DEVICE_ADDRESS, length)
# Execute the I2C transaction
bus.i2c_rdwr(write_msg, read_msg)
return list(read_msg)
except OSError as e:
# Handle I/O errors, commonly caused by missing hardware or pull-up issues
if e.errno == 5:
print("\n[!] I2C Bus Error: Device not responding.")
print("Check if the Kappa3710Rasp is seated correctly.")
print("Verify I2C pull-up solder jumpers on the HAT's backside.")
sys.exit(1)
else:
raise e
# --- Main Application Logic ---
print("Scanning I2C bus for IS3710 IC...")
# Register 513: Chip ID | Register 514: Revision
chip_id_data = read_registers(513, 1)
chip_rev_data = read_registers(514, 1)
if chip_id_data[0] == 0x10:
print(f"Success: IS3710 detected! (ID: {chip_id_data[0]}, Rev: {chip_rev_data[0]})")
else:
print(f"Error: Unknown device found at address {hex(I2C_DEVICE_ADDRESS)}")
sys.exit(1)
try:
print("Reading DMX data... Press Ctrl+C to stop.")
while True:
# Read the first three DMX channels (Registers 1, 2, and 3)
# The IS3710 updates these automatically when a DMX frame arrives.
r_val, g_val, b_val = read_registers(1, 3)
# Convert 8-bit DMX (0-255) to PWM duty cycle (0-100%)
# Logic is inverted (100 - value) to accommodate common-anode LED wiring
pwm1.ChangeDutyCycle(100 - (r_val * 100 / 255))
pwm2.ChangeDutyCycle(100 - (g_val * 100 / 255))
pwm3.ChangeDutyCycle(100 - (b_val * 100 / 255))
# Output current values to console for debugging and indexing
print(f"DMX Frame Data -> R: {r_val:3} | G: {g_val:3} | B: {b_val:3}", end='\r')
# Small delay to prevent excessive I2C polling
time.sleep(0.02)
finally:
# Safe cleanup of GPIO resources
pwm1.stop()
pwm2.stop()
pwm3.stop()
GPIO.cleanup()
print("GPIO resources released.")