Simultaneous tone and light flash

Play with it! Please tell us which board you're using.
For CircuitPython issues, ask in the Adafruit CircuitPython forum.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
Arnie_Pi_in_the_sky
 
Posts: 11
Joined: Tue Dec 06, 2022 11:14 pm

Simultaneous tone and light flash

Post by Arnie_Pi_in_the_sky »

Hello,

I'm following/enhancing the project here https://learn.adafruit.com/circuitplayg ... /change-it. Using my express, my goal is to build a morse code flasher so the subtle changes in the LED flashes are very important to distinguish between Morse's dashes and dots. I was experimenting with adding tone noises in simultaneously with the lights. Any time I try to add tones via cpx.play_tone(270, 1) it causes the LED flashes to become far slower/more drawn out, therefore slowing down the speed of the morse code.

Is it expected that the circuit processing the tone function would slow down the LED flashes? I'm a newbie to coding and circuitry so it might just be a software (or user!) issue.

User avatar
mikeysklar
 
Posts: 13936
Joined: Mon Aug 01, 2016 8:10 pm

Re: Simultaneous tone and light flash

Post by mikeysklar »

Yes, adding a tone could slow down the flashes.

Do you want to post your code? We might be able to suggest a way to speed it up so you can do both.

User avatar
Arnie_Pi_in_the_sky
 
Posts: 11
Joined: Tue Dec 06, 2022 11:14 pm

Re: Simultaneous tone and light flash

Post by Arnie_Pi_in_the_sky »

Thank you for the quick response, mikeysklar!

My first attempt was to add cpx.play_tone(262, 1) into the light function (which is inside the MorseFlasher class). This slows down the LED flashes and the dots vs. dashes are indistinguishable. If I remove this line, the code/LED flashes work perfectly fast!

How the code works: the user presses button A and a number from 1-3 is chosen at random and communicated via Morse code through LED flashes. If button B is pressed after button A, it will re-display the same message. If the user presses button A again, another message randomly chosen from the list will be displayed.

Code: Select all

import time
import board
import random
from adafruit_circuitplayground.express import cpx


# Message to display

messageList = ['3', '2', '1']

# Configuration:
dot_length = 0.2  # Duration of one Morse dot
dash_length = (dot_length * 3.0)  # Duration of one Morse dash
symbol_gap = dot_length  # Duration of gap between dot or dash
character_gap = (dot_length * 3.0)  # Duration of gap between characters
flash_color = (255,0,0)  # Color of the morse display.
brightness = 0.5  # Display brightness (0.0 - 1.0)

morse = [
    ('0', '-----'),
    ('1', '.----'),
    ('2', '..---'),
    ('3', '...--'),
    ('4', '....-'),
    ('5', '.....'),
    ('6', '-....'),
    ('7', '--...'),
    ('8', '---..'),
    ('9', '----.'),
]


# Define a class that represents the morse flasher.


class MorseFlasher:
    def __init__(self, color=(255, 255, 255)):
        # set the color adjusted for brightness
        self._color = (
            int(color[0] * brightness),
            int(color[1] * brightness),
            int(color[2] * brightness)
        )

    def light(self, on=True):
        if on:
            pixels.fill(self._color)
            cpx.play_tone(262, 1)
        else:
            pixels.fill((0, 0, 0))
        pixels.show()


    def showDot(self):
        self.light(True)
        time.sleep(dot_length)
        self.light(False)
        time.sleep(symbol_gap)

    def showDash(self):
        self.light(True)
        #self.beep(True)
        time.sleep(dash_length)
        self.light(False)
        time.sleep(symbol_gap)

    def encode(self, string):
        output = ""
        # iterate through string's characters
        for c in string:
            # find morse code for a character
            for x in morse:
                if x[0] == c:
                    # add code to output
                    output += x[1]
            # add a space in between characters
            output += " "
        # save complete morse code output to display
        self.display(output)

    def display(self, code=".-.-.- "):
        # iterate through morse code symbols
        for c in code:
            # show a dot
            if c == ".":
                self.showDot()
            # show a dash
            elif c == "-":
                self.showDash()
            # show a gap
            elif c == " ":
                time.sleep(character_gap)

def rainbow(num):
    for i in range(num):
        cpx.pixels[0] = (255, 0, 0)
        cpx.pixels[1] = (255, 85, 0)
        cpx.pixels[2] = (255, 255, 0)
        cpx.pixels[3] = (0, 255, 0)
        cpx.pixels[4] = (34, 139, 34)
        cpx.pixels[5] = (0, 255, 255)
        cpx.pixels[6] = (0, 0, 255)
        cpx.pixels[7] = (0, 0, 139)
        cpx.pixels[8] = (255, 0, 255)
        cpx.pixels[9] = (75, 0, 130)
        time.sleep(0.5)
        pixels.fill((0, 0, 0))
        pixels.show()
        time.sleep(0.3)


pixels = cpx.pixels
pixels.fill((0, 0, 0))
pixels.show()

# Create a morse flasher object.
flasher = MorseFlasher(flash_color)
cpx.play_file("lightsaber.wav")

# Main loop will run forever
while True:

    if cpx.button_a:
        cpx.play_file("coin.wav")
        num = random.randrange(0,len(messageList))
        message = messageList[num]
        message = message.upper()
        flasher.encode(message)
        rainbow(3)
        time.sleep(1)
    elif cpx.button_b:
        cpx.play_file("jump.wav")
        try:
            flasher.encode(message)
            rainbow(3)
            time.sleep(1)
        except:
            cpx.play_file("oops.wav")



User avatar
mikeysklar
 
Posts: 13936
Joined: Mon Aug 01, 2016 8:10 pm

Re: Simultaneous tone and light flash

Post by mikeysklar »

Have you had any luck with adjusting the dot_length / dash_length while playing audio? I see you have moved from the default .15 to .2 would it help to go to .5 or even 1 second durations? Your symbol_gap is tied to dot_length so slowing everything down might make it clearer?

Another option is to explore the multitasking ability of CircuitPython. It is a more complicated setup to use asyncio, but you might be able to make things work.

https://learn.adafruit.com/cooperative- ... th-asyncio
This guide describes how to do cooperative multitasking in CircuitPython, using the asyncio library and the async and await language keywords. The asyncio library is included with CPython, the host-computer version of Python. MicroPython also supplies a version of asyncio, and that version has been adapted for use in CircuitPython.

User avatar
adafruit_support_bill
 
Posts: 88088
Joined: Sat Feb 07, 2009 10:11 am

Re: Simultaneous tone and light flash

Post by adafruit_support_bill »

Since play_tone is going to delay for the specified time, Why not just replace the sleep with a call to play_tone using the same duration. Something like:

Code: Select all

    def showDot(self):
        self.light(True)
        cpx.play_tone(262, dot_length)
        self.light(False)
        time.sleep(symbol_gap)

    def showDash(self):
        self.light(True)
        cpx.play_tone(262, dash_length)
        self.light(False)
        time.sleep(symbol_gap)

User avatar
Arnie_Pi_in_the_sky
 
Posts: 11
Joined: Tue Dec 06, 2022 11:14 pm

Re: Simultaneous tone and light flash

Post by Arnie_Pi_in_the_sky »

Hi mikeysklar and adafruit_support_bill - thanks so much for taking the time to reply. I will consider both responses and let you know the outcome!

Best,

Arnie

Locked
Please be positive and constructive with your questions and comments.

Return to “Circuit Playground Classic, Circuit Playground Express, Circuit Playground Bluefruit”