Controlling multiple LEDs/Lasers with multiplexers and Pi Pico using PWM
Tags: raspberrypi, python, multiplexers
Published: 2024-04-18 05:43:36

Hi

I hope you all are well.

I am using the following code to connect 12 3V lasers to 2 multiplexers (16 channel 74HC4067) and the multiplexers are then connected to Raspberry Pi Pico. I am using Mosfets for the TTL modulation via PWM. I am using PWM to smoothly increase the power of each laser from off to full power and then drop from full power back to off or zero. Each laser will do this and there will be a delay between them so that they give the illusion that the lights are moving and for that to happen the outputs from these lasers or leds should overlap.

As mentioned, I want the lasers to have smooth transitions, i.e., the should overlap each other. Unfortunately, in my code that only happens during the rise time, i.e., laser 1 connected to multiplexer (mux) 1 comes on and a short while later while laser 1 is reaching high, laser 2 connected to mux 2 comes on and then there is a delay between their fall time as well. However, laser 3 only comes on when the whole cycle of laser 1 rising and falling and laser 2 rising and falling has run its course, which makes the transition clunky and there is a hard stop in between every 2 pairs of the lasers/leds. Any idea what I can do to solve this issue ?

from machine import Pin, PWM
from time import sleep, ticks_ms
import math

# Number of channels in each multiplexer
NUM_CHANNELS = 3

# Define the pins for channel selection on the first multiplexer (mux_1)
s_pins_1 = [Pin(i, Pin.OUT) for i in range(4)]  # Assuming S0-S3 pins are connected to GPIO pins 0 to 3
z_pin_1 = Pin(4, Pin.OUT)  # Assuming the LED pin for the first multiplexer is connected to GPIO pin 4

# Define the pins for channel selection on the second multiplexer (mux_2)
s_pins_2 = [Pin(i, Pin.OUT) for i in range(5, 9)]  # Assuming S4-S8 pins are connected to GPIO pins 5 to 8
z_pin_2 = Pin(9, Pin.OUT)  # Assuming the LED pin for the second multiplexer is connected to GPIO pin 9

# Initialize LED PWM for the first multiplexer (mux_1)
led_pwm_1 = PWM(z_pin_1)
led_pwm_1.freq(100)  # Set PWM frequency

# Initialize LED PWM for the second multiplexer (mux_2)
led_pwm_2 = PWM(z_pin_2)
led_pwm_2.freq(100)  # Set PWM frequency

# Step size for changing the duty cycle for PWMs
min_duty = 0
max_duty = 65534
duty_step = 100

# Function to select a channel on the first multiplexer (mux_1)
def select_channel_1(channel):
    for i in range(4):
        s_pins_1[i].value((channel >> i) & 1)

# Function to select a channel on the second multiplexer (mux_2)
def select_channel_2(channel):
    for i in range(4):
        s_pins_2[i].value((channel >> i) & 1)


def increase_pwm(pwm, max_duty, duration):
    for duty_cycle in range(min_duty, max_duty, duration):
        pwm.duty_u16(int(duty_cycle))
        sleep(0.005)

def decrease_pwm(pwm, max_duty, duration):
    for duty_cycle in range(max_duty, min_duty, duration):
        pwm.duty_u16(int(duty_cycle))
        sleep(0.005)

try:
    while True:
        for channel in range(NUM_CHANNELS):
            select_channel_1(channel)
            select_channel_2(channel)

            # Increase the duty cycle for led_1 and led_2
            increase_pwm(led_pwm_1, max_duty, duty_step)
            increase_pwm(led_pwm_2, max_duty, duty_step)

            # Decrease the duty cycle for led_1 and led_2 
            decrease_pwm(led_pwm_1, max_duty, duty_step)
            decrease_pwm(led_pwm_2, max_duty, duty_step)

except KeyboardInterrupt:
    led_pwm_1.duty_u16(0)
    led_pwm_2.duty_u16(0)