0

Sound changes in Circuit Python 6.x for Hallowing M0
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Sound changes in Circuit Python 6.x for Hallowing M0

by michaelmeissner on Wed Jan 06, 2021 11:19 pm

I'm doing a virtual panel next week at the Arisia science fiction convention in Boston and I will focus on electronics and costumes. I did a similar panel last year, and I figured I should make sure things still work. This panel is a little broader in scope than the previous one that was only about lights, and I hope to add a few things on sound, servos, etc. if I have time.

One of the things I wanted to show is the Hallowing M0 lightsaber, because this requires no soldering, and it would be easy for people to jump into that are not up on either soldering or programming.

I got a new M0 and I loaded up Circuit Python 6.0.1 and the current 6.x libraries (20210103) on it, and I discovered that the sound module no longer produces sound. If I go back to Circuit Python 5.3.1 with the 20210103 5.x libraries, it works fine. I also tried Circuit Python 6.0.0 and 6.1.0-beta3, and it had the same results.

So something seems to have changed in Circuit Python 6.0.0 with regard to sound on the Halloween M0. Is this a known problem? If so there an easy fix? Note, I generally don't program in Circuit Python (typically I do Arduino programming), so I don't follow changes that are made between releases.

michaelmeissner
 
Posts: 1442
Joined: Wed Aug 29, 2012 12:40 am

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by dastels on Thu Jan 07, 2021 11:56 am

It's not a problem, just a restructuring. Have a look at the updated example at https://learn.adafruit.com/circuitpython-essentials/circuitpython-audio-out.

Dave

dastels
 
Posts: 4850
Joined: Tue Oct 20, 2015 3:22 pm

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by michaelmeissner on Thu Jan 07, 2021 12:26 pm

It is a shame that it used to work, but with the new revision, it no longer works.

I sent in a comment on the learning section for the lightsaber to add verbiage to say you must use Circuit Python 5.x to get the sound to work. I also sent in a comment that the page you mentioned does not mention the Hallowing M0 (yeah, I know keeping track of all of the boards Adafruit has released over the years is a chore).

michaelmeissner
 
Posts: 1442
Joined: Wed Aug 29, 2012 12:40 am

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by tannewt on Thu Jan 07, 2021 2:20 pm

Does it raise an error or simply produce no output? 6.x removed `audioio.WaveFile` because it's been replaced with `audiocore.WaveFile` (5.x has both) An error should be raised if it's the issue you are having. If not, it sounds like a bug we need to look into.

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

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by michaelmeissner on Thu Jan 07, 2021 6:26 pm

I don't see an error being raised on the screen. I can't attach to the session with mu-editor from my Fedora 33 system so I can't see more than the 128x128 display shows.

michaelmeissner
 
Posts: 1442
Joined: Wed Aug 29, 2012 12:40 am

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by danhalbert on Fri Jan 08, 2021 12:13 am

When you plug in the board, you should see a new `/dev/tty*` device appear, probably /dev/ttyACM0 or /dev/tty/USB0 or similar. You should then be able connect to the board with screen, picocom, or minicom, giving the new tty as the device.

danhalbert
 
Posts: 2262
Joined: Tue Aug 08, 2017 12:37 pm

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by michaelmeissner on Fri Jan 08, 2021 1:00 am

Yes I know that (in this case the new tty is /dev/ttyACM0). It works for the other Circuit Python code that I've used on other microprocessors, but it doesn't seem to work if I have code.py installed. If I delete code.py, I can attach to the terminal.

What I have to do is:
  • Delete code.py from the CIRCUITPYTHON filesystem.
  • Double press reset and load the .UF2 file into the HALLOWBOOT filesystem.
  • After it reboots, update adafruit_lis3dh.mpy and neopixel.mpy from the correct library to /lib in the CIRCUITPYTHON filesystem.
  • Then I can attach to the serial device with mu-editor
  • From another terminal copy in the code.py that I want to use. I will see the initial boot, but after that I won't see anything on the terminal. I saw no error messages.

In addition to going back and forth between CP 5.3.1 and CP 6.0.1, I discovered that the unicorn.py script does not work on CP 6.0.1 (even without the sound) because it references a neopixel field 'order' that is in the CP 5.x library, but not the CP 6.x library. [EDIT by danhalbert: ordered -> order]

michaelmeissner
 
Posts: 1442
Joined: Wed Aug 29, 2012 12:40 am

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by danhalbert on Fri Jan 08, 2021 9:15 am

When you say "it doesn't seem to work" do you mean you connect but see nothing, or do you mean it can't connect?

If it's looping, then you'll see no output. If you type ctrl-C you can get to the REPL. Then if you type ctrl-D it should restart, and you can see what it prints from the beginning.

We can try to reproduce this, and correct the Guide code as necessary, or else figure out what is wrong with the sound part of the code. Are you using the unmodified lightsaber code from https://learn.adafruit.com/hallowing-li ... cuitpython ?

danhalbert
 
Posts: 2262
Joined: Tue Aug 08, 2017 12:37 pm

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by michaelmeissner on Fri Jan 08, 2021 10:58 am

What I meant is the basic lightsaber LEDs work fine using Circuit Python 6.0.1 and the current 6.x libraries (1/3/2021) for adafruit_lis3dh and neopixel. However, I hear no sounds when I attach a Molex PicoBlade speaker (product #3923) to the speaker port. I am using one of the 0.5m neopixel 60led/meter strips with the 3 pin JST connector on the end (#3919 or #4801).

If I switch to Circuit Python 5.3.1 and the current 5.x libraries (1/3/2021), the same setup has the sound working fine.

I have downloaded the current scripts and they are identical to the ones I was using. I did a slight modification to both standard and unicorn scripts to take the sound files from two separate directories, so that I can easily switch which saber I am using by just switching the .py file, and I don't have to copy the different sounds files. I had run the same code unmodified using the standard sounds directory before modifying it so I could switch between the two different sabers.

I bought the Hallowing M0 two weeks ago from Digikey.

As I mentioned, the unicorn variant will not work with Circuit Python 6.x libraries because it references an 'order' field that is no longer supported. [EDIT by danhalbert: ordered -> order]

michaelmeissner
 
Posts: 1442
Joined: Wed Aug 29, 2012 12:40 am

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by danhalbert on Sun Jan 10, 2021 12:39 pm

Here is a slightly revised program with minor changes in the top imports and in `play_wav()`. Note that there was a catch-all try-except in play_wav() which was hiding an error.

I tested this on 6.1.0-rc.1 but it probably would work on 6.0.1 also.

Code: Select all | TOGGLE FULL SIZE
"""LASER SWORD (pew pew) example for Adafruit Hallowing & NeoPixel strip"""
# pylint: disable=bare-except

import time
import math
import audiocore
import audioio
import busio
import board
import touchio
import neopixel
import adafruit_lis3dh

# CUSTOMIZE YOUR COLOR HERE:
# (red, green, blue) -- each 0 (off) to 255 (brightest)
COLOR = (0, 100, 255)  # jedi
#COLOR = (255, 0, 0)  # sith

# CUSTOMIZE SENSITIVITY HERE: smaller numbers = more sensitive to motion
HIT_THRESHOLD = 250
SWING_THRESHOLD = 125

NUM_PIXELS = 30                        # NeoPixel strip length (in pixels)
NEOPIXEL_PIN = board.EXTERNAL_NEOPIXEL # Pin where NeoPixels are connected
STRIP = neopixel.NeoPixel(NEOPIXEL_PIN, NUM_PIXELS, brightness=1, auto_write=False)
STRIP.fill(0)                          # NeoPixels off ASAP on startup
STRIP.show()
TOUCH = touchio.TouchIn(board.A2)      # Rightmost capacitive touch pad
AUDIO = audioio.AudioOut(board.A0)     # Speaker
MODE = 0                               # Initial mode = OFF

# Set up accelerometer on I2C bus, 4G range:
I2C = busio.I2C(board.SCL, board.SDA)
try:
    ACCEL = adafruit_lis3dh.LIS3DH_I2C(I2C, address=0x18) # Production board
except:
    ACCEL = adafruit_lis3dh.LIS3DH_I2C(I2C, address=0x19) # Beta hardware
ACCEL.range = adafruit_lis3dh.RANGE_4_G

# "Idle" color is 1/4 brightness, "swinging" color is full brightness...
COLOR_IDLE = (int(COLOR[0] / 4), int(COLOR[1] / 4), int(COLOR[2] / 4))
COLOR_SWING = COLOR
COLOR_HIT = (255, 255, 255)  # "hit" color is white

def play_wav(name, loop=False):
    """
    Play a WAV file in the 'sounds' directory.
    @param name: partial file name string, complete name will be built around
                 this, e.g. passing 'foo' will play file 'sounds/foo.wav'.
    @param loop: if True, sound will repeat indefinitely (until interrupted
                 by another sound).
    """
    try:
        wave_file = open('sounds/' + name + '.wav', 'rb')
        wave = audiocore.WaveFile(wave_file)
        AUDIO.play(wave, loop=loop)
    except Exception as e:
        print(e)
        return

def power(sound, duration, reverse):
    """
    Animate NeoPixels with accompanying sound effect for power on / off.
    @param sound:    sound name (similar format to play_wav() above)
    @param duration: estimated duration of sound, in seconds (>0.0)
    @param reverse:  if True, do power-off effect (reverses animation)
    """
    start_time = time.monotonic()  # Save function start time
    play_wav(sound)
    while True:
        elapsed = time.monotonic() - start_time  # Time spent in function
        if elapsed > duration:                   # Past sound duration?
            break                                # Stop animating
        fraction = elapsed / duration            # Animation time, 0.0 to 1.0
        if reverse:
            fraction = 1.0 - fraction            # 1.0 to 0.0 if reverse
        fraction = math.pow(fraction, 0.5)       # Apply nonlinear curve
        threshold = int(NUM_PIXELS * fraction + 0.5)
        for pixel in range(NUM_PIXELS):          # Fill NeoPixel strip
            if pixel <= threshold:
                STRIP[pixel] = COLOR_IDLE        # ON pixels BELOW threshold
            else:
                STRIP[pixel] = 0                 # OFF pixels ABOVE threshold
            STRIP.show()
    if reverse:
        STRIP.fill(0)                            # At end, ensure strip is off
    else:
        STRIP.fill(COLOR_IDLE)                   # or all pixels set on
    STRIP.show()
    while AUDIO.playing:                         # Wait until audio done
        pass

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))

# Main program loop, repeats indefinitely
while True:
    if TOUCH.value:                         # Capacitive pad touched?
        if MODE is 0:                       # If currently off...
            power('on', 1.7, False)         # Power up!
            play_wav('idle', loop=True)     # Play background hum sound
            MODE = 1                        # ON (idle) mode now
        else:                               # else is currently on...
            power('off', 1.15, True)        # Power down
            MODE = 0                        # OFF mode now
        while TOUCH.value:                  # Wait for button release
            time.sleep(0.2)                 # to avoid repeated triggering

    elif MODE >= 1:                         # If not OFF mode...
        ACCEL_X, ACCEL_Y, ACCEL_Z = ACCEL.acceleration # Read accelerometer
        ACCEL_SQUARED = ACCEL_X * ACCEL_X + ACCEL_Z * ACCEL_Z
        # (Y axis isn't needed for this, assuming Hallowing is mounted
        # sideways to stick.  Also, square root isn't needed, since we're
        # just comparing thresholds...use squared values instead, save math.)
        if ACCEL_SQUARED > HIT_THRESHOLD:   # Large acceleration = HIT
            TRIGGER_TIME = time.monotonic() # Save initial time of hit
            play_wav('hit')                 # Start playing 'hit' sound
            COLOR_ACTIVE = COLOR_HIT        # Set color to fade from
            MODE = 3                        # HIT mode
        elif MODE is 1 and ACCEL_SQUARED > SWING_THRESHOLD: # Mild = SWING
            TRIGGER_TIME = time.monotonic() # Save initial time of swing
            play_wav('swing')               # Start playing 'swing' sound
            COLOR_ACTIVE = COLOR_SWING      # Set color to fade from
            MODE = 2                        # SWING mode
        elif MODE > 1:                      # If in SWING or HIT mode...
            if AUDIO.playing:               # And sound currently playing...
                BLEND = time.monotonic() - TRIGGER_TIME # Time since triggered
                if MODE == 2:               # If SWING,
                    BLEND = abs(0.5 - BLEND) * 2.0 # ramp up, down
                STRIP.fill(mix(COLOR_ACTIVE, COLOR_IDLE, BLEND))
                STRIP.show()
            else:                           # No sound now, but still MODE > 1
                play_wav('idle', loop=True) # Resume background hum
                STRIP.fill(COLOR_IDLE)      # Set to idle color
                STRIP.show()
                MODE = 1                    # IDLE mode now

danhalbert
 
Posts: 2262
Joined: Tue Aug 08, 2017 12:37 pm

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by michaelmeissner on Sun Jan 10, 2021 1:55 pm

Cool, I'll try it tonight. Thanks.

michaelmeissner
 
Posts: 1442
Joined: Wed Aug 29, 2012 12:40 am

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by michaelmeissner on Sun Jan 10, 2021 6:42 pm

It does work with the 6.0.1 Circuit Python UF2 and libraries. Thanks. It would be helpful if the learning section gets the updated script.

I don't know what we want to do about the unicorn variant, but at least the main effect works.

michaelmeissner
 
Posts: 1442
Joined: Wed Aug 29, 2012 12:40 am

Re: Sound changes in Circuit Python 6.x for Hallowing M0

by danhalbert on Sun Jan 10, 2021 7:12 pm

Thanks for testing. I will be updating the script, and will also take a look at the unicorn script issue.

danhalbert
 
Posts: 2262
Joined: Tue Aug 08, 2017 12:37 pm

Please be positive and constructive with your questions and comments.