Black Lives Matter - Action and Equality.
0

Help with Circuitpython code for servo and neopixel
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Help with Circuitpython code for servo and neopixel

by TheGnomeQueen on Tue May 05, 2020 10:27 am

Hi everyone,

I'm new to circuitpython and have been trying to figure out how to combine some basic code examples to help me create a project I am working on. I've gone through the guide for circuitpython as well as for the feather m4 express and prop-maker (which is what I'm using because I had them already available). I understand the basics of changing color for the leds and changing the angle for the servos in the already generated code examples, but I have never created code from scratch.

Basically, I am trying to create a visor that once powered on performs the following:

Power on
Neopixel ring and strip are lit
Servo starts at 0 and holds there
Press momentary switch and servo moves to 180 and holds there
Press momentary switch again and servo moves back to 0 and holds there

I have a neopixel ring and strip wired to the neopixel port on the prop-maker/feather, the servo data line is in A1. The servo is powered externally with 4 AA batteries and grounded to the prop-maker/feather. The feather and leds are powered by a 3.7v 2500 mah lipo battery.

Eventually I would like to add wav files for audio and animation to the leds but I'm trying to start with what I thought was simple.
I've been trying for a while to figure out how to get the servo do what I want and I only seem to be able to find code examples that continually sweep the arm rather than moving to one position and holding. I'm hoping what I want to do is even possible.

TheGnomeQueen
 
Posts: 5
Joined: Fri May 01, 2020 8:58 pm

Re: Help with Circuitpython code for servo and neopixel

by tannewt on Tue May 05, 2020 11:43 am

Hi! Staying at a specific angle should be as simple as not setting a new value.

I'd suggest posting whatever your current code is, what it does now and what you'd like it to do. That way we can give specific suggestions.

Welcome!

tannewt
 
Posts: 1644
Joined: Thu Oct 06, 2016 8:48 pm

Re: Help with Circuitpython code for servo and neopixel

by TheGnomeQueen on Wed May 06, 2020 7:33 am

I'm sure this is a mess, I was trying to Frankenstein some basic codes as well as one that I had used for another project to get the neopixel animation and sound effect that I want. But, I know when I press the momentary switch on the original project it turns the power off and resets everything which is not what i want. I've been trying to teach myself how to do this properly, but the problem is I don't know how to combine different codes to create a coherent "sentence".

Code: Select all | TOGGLE FULL SIZE
import time
import digitalio
import audioio
import audiocore
import board
import neopixel
from adafruit_motor import servo
 

NUM_RING = 16   
NUM_STRIP = 15 
NUM_PIXELS = NUM_STRIP + NUM_RING  #total number of pixels
 
NEOPIXEL_PIN = board.D5  # PropMaker Wing uses D5 for NeoPixel plug
POWER_PIN = board.D10
 
 
# CUSTOMISE COLORS HERE:
COLOR = (200, 0, 150)      # Default idle is magenta
ALT_COLOR = (200, 0, 200)  # alt color is purple

 
# CUSTOMISE IDLE PULSE SPEED HERE: 0 is fast, above 0 slows down
IDLE_PULSE_SPEED = .009   # Default is 0 seconds
 
# CUSTOMISE BRIGHTNESS HERE: must be a number between 0 and 1
IDLE_PULSE_BRIGHTNESS_MIN = 0.2  # Default minimum idle pulse brightness
IDLE_PULSE_BRIGHTNESS_MAX = 1  # Default maximum idle pulse brightness
 
WAV_FILE_NAME = "on.wav"

# Set to the length in seconds of the "on.wav" file
POWER_ON_SOUND_DURATION = 3.0

enable = digitalio.DigitalInOut(POWER_PIN)
enable.direction = digitalio.Direction.OUTPUT
enable.value = False

switch = digitalio.DigitalInOut(board.D13)
switch.switch_to_input(pull=digitalio.Pull.UP)
 
# Set up NeoPixels
strip = neopixel.NeoPixel(NEOPIXEL_PIN, NUM_PIXELS, brightness=1, auto_write=False)
strip.fill(0) 
strip.show()
 
audio = audioio.AudioOut(board.A0)  # Speaker
wave_file = audioio.wavefile(wavefile)
 
 
def play_wav(name, loop=False):
    global wave_file  # pylint: disable=global-statement
    print("playing", name)
    if wave_file:
        wave_file.close()
    try:
        wave_file = open(on.wav)
        wave = audiocore.WaveFile(wave_file)
        audio.play(wave)
       
        while audio.playing:
            pass
 
 
def power(sound, duration, reverse):
    """
    Animate NeoPixels with accompanying sound effect for power on.
    @param sound: sound name (similar format to play_wav() above)
    @param duration: estimated duration of sound, in seconds (>0.0)
    @param reverse: Reverses animation. If True, begins animation at end of strip.
    """
    if reverse:
        prev = NUM_PIXELS
    else:
        prev = 0
    start_time = time.monotonic()  # Save audio start time
    play_wav(sound)
    while True:
        elapsed = time.monotonic() - start_time  # Time spent playing sound
        if elapsed > duration:                   # Past sound duration?
            break                                # Stop animating
        total_animation_time = elapsed / duration            # Animation time, 0.0 to 1.0
        if reverse:
            total_animation_time = 1.0 - total_animation_time            # 1.0 to 0.0 if reverse
        threshold = int(NUM_PIXELS * total_animation_time + 0.5)
        num = threshold - prev # Number of pixels to light on this pass
        if num != 0:
            if reverse:
                strip[threshold:prev] = [ALT_COLOR] * -num
            else:
                strip[prev:threshold] = [ALT_COLOR] * num
            strip.show()
            prev = threshold
 
 
def mix(color_1, color_2, weight_2):
    """
    Blend between two colors with a given ratio.
    :param color_1:  first color, as an (r,g,b) tuple
    :param color_2:  second color, as an (r,g,b) tuple
    :param weight_2: Blend weight (ratio) of second color, 0.0 to 1.0
    :return (r,g,b) tuple, blended color
    """
    if weight_2 < 0.0:
        weight_2 = 0.0
    elif weight_2 > 1.0:
        weight_2 = 1.0
    weight_1 = 1.0 - weight_2
    return (int(color_1[0] * weight_1 + color_2[0] * weight_2),
            int(color_1[1] * weight_1 + color_2[1] * weight_2),
            int(color_1[2] * weight_1 + color_2[2] * weight_2))
 
 
 
mode = 0  # Initial mode = OFF
 
# Setup idle pulse
idle_brightness = IDLE_PULSE_BRIGHTNESS_MIN  # current brightness of idle pulse
idle_increment = 0.01  # Initial idle pulse direction
 
# Main loop
while True:
 
    if mode == 0:  # If currently off...
        enable.value = True
        power('on', POWER_ON_SOUND_DURATION, True)  # Power up!
        mode = 1  # Idle mode
        time.sleep(1.0) #pause before moving on
       
     
    for angle in range(0, 180, 5):  # 0 - 180 degrees, 5 degrees at a time.
        my_servo.angle = angle
        time.sleep(0.05)

 
        # Setup for idle pulse
        idle_brightness = IDLE_PULSE_BRIGHTNESS_MIN
        idle_increment = 0.01
        # lights the ring in COLOR_TOP color:
        strip[0:NUM_RING] = [([int(c*idle_brightness) for c in COLOR_TOP])] * NUM_RING
        # lights the strip in COLOR_IDLE color:
        strip[NUM_RING:NUM_PIXELS] = [([int(c*idle_brightness) for c in COLOR_IDLE])] * NUM_STRIP
        strip.show()
 
    elif mode >= 1:  # If not OFF mode...
       
        elif mode == 1:
            # Idle pulse
            idle_brightness += idle_increment  # Pulse up
            if idle_brightness > IDLE_PULSE_BRIGHTNESS_MAX or \
               idle_brightness < IDLE_PULSE_BRIGHTNESS_MIN:  # Then...
                idle_increment *= -1  # Pulse direction flip
            # light the ring:
            strip[0:NUM_RING] = [([int(c*idle_brightness) for c in COLOR_TOP])] * NUM_RING
            # light the strip:
            strip[NUM_RING:NUM_PIXELS] = [([int(c*idle_brightness) for c in
                                            COLOR_IDLE])] * NUM_STRIP
            strip.show()
            time.sleep(IDLE_PULSE_SPEED)  # Idle pulse speed set above
           
            for angle in range(180, 0, -5): # 180 - 0 degrees, 5 degrees at a time.
        my_servo.angle = angle
        time.sleep(0.05)

TheGnomeQueen
 
Posts: 5
Joined: Fri May 01, 2020 8:58 pm

Re: Help with Circuitpython code for servo and neopixel

by tannewt on Wed May 06, 2020 11:09 am

TheGnomeQueen wrote:I'm sure this is a mess, I was trying to Frankenstein some basic codes as well as one that I had used for another project to get the neopixel animation and sound effect that I want. I've been trying to teach myself how to do this properly, but the problem is I don't know how to combine different codes to create a coherent "sentence".


No worries! This is a great way to get code to do what you want.

Are you able to see the serial output by using Mu or similar? I do see some indentation errors at the end of the file.

I also don't see where you are reading the button state. Can you point me to that line of code?

tannewt
 
Posts: 1644
Joined: Thu Oct 06, 2016 8:48 pm

Re: Help with Circuitpython code for servo and neopixel

by Andre1w on Fri May 08, 2020 7:29 am

RGBW pixels incorporate a translucent diffuser layer to help mix and soften the light output.

Andre1w
 
Posts: 1
Joined: Fri May 08, 2020 7:17 am

Please be positive and constructive with your questions and comments.