Нужно избавиться от задержки time.sleep в python.

Тема в разделе "Arduino & Shields", создана пользователем Airo, 14 мар 2024.

  1. Airo

    Airo Нерд

    Пытаюсь сделать своего рода проект светомузыки.
    Вкратце что делает код в данный момент.
    Данный код производит запись аудио с 3 источников и считывает уровень громкость. Если громкость становиться выше 100 единиц, то активируется другой код связанный с Ардуино.
    В нем необходимо поочередно активировать пины с задержкой.
    Проблема заключается в том что time.sleep останавливает работу записи звука и если в момент когда код стоит на паузе звук станет выше 100 единиц программа это не успеет зафиксировать и пропустит.
    Мне нужно, что следующее:
    1. считывание 3 каналов звука с трех дорожек
    2. Если звук в одной из дорожек стал выше 100, то необходимо активировать пин11 потом задержка, отключить пин11 задержка активировать пин9 потом задержка, отключить пин9.
    3. если во время действия 2 условия звук в одном из двух других аудио каналах будет выше 100 то ПОСЛЕ окончания 2 условия необходимо сделать то же самое в, то же самое и с другими дорожками.

    РЕДАКТИРОВАННО:
    Я видимо не корректно описал работу pyaudio. Она не считывает данные с ардуино. Она работает непосредственно с ПК. Установлена программа, которая создает виртуальные аудио дорожки эти аудио дорожки прикрепляются к 3 открытым приложениям.
    Название аудио дорожек Line (1-4). Обращение к ним происходит через
    Код (Python):
     device_indices = [3, 4, 5, 6]
    .

    Код (Python):
    from pyfirmata import Arduino, SERVO, util
    import time, pyfirmata
    import pyaudio
    import audioop
    from random import randint, uniform
    import random

    t1 = random.uniform(0.05, 0.1)
    t2 = random.uniform(0.1, 0.15)
    t3 = random.uniform(0.5, 0.53)

    win1 = 1
    win2 = 1
    win3 = 1

    arduino = 1  # вкл адруино

    kanal1 = 100
    kanal2 = 100
    kanal3 = 100
    kanal4 = 50000

    start_time = time.time()
    start_time1 = time.time()
    start_time2 = time.time()

    listening_start_time = time.time()
    listening_start_time1 = time.time()
    listening_start_time2 = time.time()

    if arduino == 1:
        p0 = uniform(60, 70)
        board = Arduino('COM6')
        pin_9 = 9
        board.digital[pin_9].mode = pyfirmata.OUTPUT
        pin_10 = 10  # 1
        board.digital[pin_10].mode = pyfirmata.OUTPUT
        pin_11 = 11
        board.digital[pin_11].mode = pyfirmata.OUTPUT
        pin_12 = 12
        board.digital[pin_12].mode = pyfirmata.OUTPUT

    while True:

        def open_microphone_stream(device_index):
            p = pyaudio.PyAudio()
            stream = p.open(format=pyaudio.paInt16,
                            channels=1,
                            rate=44100,
                            input=True,
                            frames_per_buffer=1024,
                            input_device_index=device_index)
            return stream


        def record_from_multiple_microphones():
            device_indices = [3, 4, 5, 6]  # индексы микрофонов
            streams = [open_microphone_stream(idx) for idx in device_indices]
            return streams


        if __name__ == "__main__":
            audio_streams = record_from_multiple_microphones()


        if win3 == 1:
            data2 = audio_streams[1].read(1024)  # Чтение данных со второго микрофона
            rms2 = audioop.rms(data2, 2)
            print("2 Канал:", rms2)

        if win1 == 1:
            data3 = audio_streams[2].read(1024)  # Чтение данных с третьего микрофона
            rms3 = audioop.rms(data3, 2)
            print("3 Канал:", rms3)

        if win2 == 1:
            data4 = audio_streams[3].read(1024)  # Чтение данных с четвертого микрофона
            rms4 = audioop.rms(data4, 2)
            print("4 Канал:", rms4)

        audio_streams[0].stop_stream()
        audio_streams[0].close()
        audio_streams[1].stop_stream()
        audio_streams[1].close()
        audio_streams[2].stop_stream()
        audio_streams[2].close()
        audio_streams[3].stop_stream()
        audio_streams[3].close()

        if __name__ == "__main__":
            audio_streams = record_from_multiple_microphones()

        if win1 == 1:
            if rms3 > kanal1 and time.time() - start_time > 5:
                start_time = time.time()
                listening_start_time = time.time()
                execute_code1()

        def execute_code1():
            time.sleep(t1)
            board.digital[pin_11].write(1)
            time.sleep(t2)
            board.digital[pin_11].write(0)
            time.sleep(t3)

            board.digital[pin_9].write(1)
            time.sleep(t2)
            board.digital[pin_9].write(0)


        if win2 == 1:
            if rms4 > kanal1 and time.time() - start_time1 > 5:
                start_time1 = time.time()
                listening_start_time1 = time.time()
                execute_code2()

        def execute_code2():
            time.sleep(t1)
            board.digital[pin_11].write(1)
            time.sleep(t2)
            board.digital[pin_11].write(0)
            time.sleep(t3)

            board.digital[pin_9].write(1)
            time.sleep(t2)
            board.digital[pin_9].write(0)


        if win3 == 1:
            if rms2 > kanal3 and time.time() - start_time2 > 5:
                start_time2 = time.time()
                listening_start_time2 = time.time()
                execute_code3()

        def execute_code3():
            time.sleep(t1)
            board.digital[pin_11].write(1)
            time.sleep(t2)
            board.digital[pin_11].write(0)
            time.sleep(t3)

            board.digital[pin_9].write(1)
            time.sleep(t2)
            board.digital[pin_9].write(0)


     
     

    Вложения:

    Последнее редактирование: 15 мар 2024
  2. a1000

    a1000 Гуру

    Не забывайте, что ADC в ATmegа один, и делать замеры он будет поочереди. А каждый замер это 13 тактов, и совсем не на частоте осцилятора. Не помню точно, но тактирование ADC, для его корректной работы, идёт на частоте сотен килогерц. Добавьте время на получение результатов и запуск нового отсчёта. Одновременного замера не получится.
     
  3. parovoZZ

    parovoZZ Гуру

    в ардуине, скорее всего, сделано через одно место. Согласно даташиту, прежде, чем проводить замеры, необходимо выдержать паузу после включения аналоговых цепей. Я так подозреваю, что в ардуине это делается перед каждым замером. Посему, если хочется очень быстрых замеров, то только нативные Си и только на прерываниях. Никаких дурин и, тем более, питонов.
     
  4. Ariadna-on-Line

    Ariadna-on-Line Гуру

    1. Если вы пользуетесь стандартной функцией analogRead() - то она естественно каждый раз повторяет процедуру инициализации и зачистки после себя. Поэтому надо переводить АЦП в авто-режим. Примеры для Ардуины - есть. И примеры ускорения АЦП - тоже
    2. А как же без "дурин" ? Софт без харда как свадьба без жениха.))))))
    3. А насчет питонов - это вы верно..
     
  5. parovoZZ

    parovoZZ Гуру

  6. fps

    fps Нерд

    В цикле функцию определять не надо в любом случае.
     
  7. Airo

    Airo Нерд

    Я видимо не корректно описал работу pyaudio. Она не считывает данные с ардуино. Она работает непосредственно с ПК. Установлена программа, которая создает виртуальные аудио дорожки эти аудио дорожки прикрепляются к 3 открытым приложениям.
    Название аудио дорожек Line (1-4). Обращение к ним происходит через
    Код (Python):
    device_indices = [3, 4, 5, 6]
     
  8. Airo

    Airo Нерд

    Я видимо не корректно описал работу pyaudio. Она не считывает данные с ардуино. Она работает непосредственно с ПК. Установлена программа, которая создает виртуальные аудио дорожки эти аудио дорожки прикрепляются к 3 открытым приложениям.
    Название аудио дорожек Line (1-4). Обращение к ним происходит через
    Код (Python):
    device_indices = [3, 4, 5, 6]
     
  9. Airo

    Airo Нерд

    Согласен, не заметил этот момент
     
  10. Airo

    Airo Нерд

    По сути мне просто нужно избавиться от time.sleep(). Что бы он не останавливал работу пргограммы.
    Код (Python):

            time.sleep(t1)
            board.digital[pin_11].write(1)
            time.sleep(t2)
            board.digital[pin_11].write(0)
            time.sleep(t3)

            board.digital[pin_9].write(1)
            time.sleep(t2)
            board.digital[pin_9].write(0)
    Я попробывал изменить код по сути вышел костыль

    Код (Python):

        if win2 == 1:
            if rms4 > kanal1 and time.time() - start_time1 > 5:
                start_time1 = time.time()
                listening_start_time1 = time.time()
                P11 = 1
                P9 = 1
                Stop =1
                print("WWWWWWWWWWWWWWWW:")

        if P11 == 1 and time.time() - start_time1 > 0.2:
            start_time1 = time.time()
            print("111111111111111111:")
            P11 = 0
            P111=1
            board.digital[pin_11].write(1)
        if P111 == 1 and time.time() - start_time1 > 0.2:
            start_time1 = time.time()
            print("22222222222:")
            P111 = 0
            Next = 1
            board.digital[pin_11].write(0)


        if P9 == 1 and Next==1 and time.time() - start_time1 > 0.2:
            start_time1 = time.time()
            print("33333333:")
            P9 = 0
            P99 = 1
            Next = 0
            board.digital[pin_9].write(1)
        if P99 == 1 and time.time() - start_time1 > 0.2:
            start_time1 = time.time()
            print("44444444:")
            Stop = 0
            P99 = 0
            board.digital[pin_9].write(0)
    Но есть один нюанс если во время выполнения этого учатка кода Активируется один из других
    Код (Python):
        if win3 == 1:
            if rms2 > kanal3 and time.time() - start_time2 > 5:
     
    или
    Код (Python):

        if win1 == 1:
            if rms3 > kanal1 and time.time() - start_time > 5:
    То он не успевает полность выполнеиться и происходит свого рода смешивание незавершонного кода с новым. Я понимаю что это очень плохой вариант решить проблему но другие у меня не получились.
     
    Последнее редактирование: 20 мар 2024