Самодельные электронные ударные

Тема в разделе "Arduino & Shields", создана пользователем Dan, 24 дек 2016.

  1. Dan

    Dan Гик

    блин, глючено отправилось, два сообщения
     
  2. Dan

    Dan Гик

    а вот фотка того, что происходит, если ударить сильно по датчику. прям мощный щелбан отвесить
     

    Вложения:

    • 7.png
      7.png
      Размер файла:
      26,3 КБ
      Просмотров:
      669
  3. mcureenab

    mcureenab Гуру

    Не правильно подключено. Откуда b25, если по схеме должно быть b18?
     
  4. Dan

    Dan Гик

    точно, как-то я подзапутался в проводах при подключении
     
  5. mcureenab

    mcureenab Гуру

    Не мудрено, столько проводов на простую схему навешать. Детали можно непосредственно к синей шине подключать без дополнительных проводов.
    Так что теперь, после исправления схемы, получилось с графиком и ардуиной?
     
  6. Dan

    Dan Гик

    можно, конечно)щас вот пробую
    уже нет вроде никакого дребезга, но со значениями нужно поэкспериментировать. такое ощущение, что порог срабатывания чрезмерно высок. величина удара 0 при любом ударе. ща буду пробовать
     
  7. Dan

    Dan Гик

    вот я сейчас попробовал с разной скоростью постучать по датчику, а такое ощущение, что прям конкретный интервал времени задан, через который нота будет воспроизводится
     
  8. mcureenab

    mcureenab Гуру

    Попробуйте ощущения в числа перевести. На мой взгляд время затухания примерно 0.5 сек должно быть.
    С таким фильтром тау = 0.1, т.е. за 0.1 сек напряжение на фильтре уменьшается в e (2,71828) раз.
     
  9. Dan

    Dan Гик

    вот я сейчас загрузил предыдущий скетч и записал звук с датчика. получилось, что время звучания ноты примерно 3500 миллисекунд
    вот сам скетч:
    Код (C++):
    #include <MIDI.h>

    MIDI_CREATE_DEFAULT_INSTANCE();


    int KICK = A0;
    int KICK_VAL = 0;
    int KICK_THRESHOLD = 8;

    long previousMillis = 0;

    int velocity = 0;
    int t = 0;
    int t_note = 0;

    byte KICK_DRUM = 36;

    void setup() {

    MIDI.begin();
    Serial.begin(115200);
    pinMode(KICK, INPUT);

    }

        void loop()
       
        {
       
        KICK_VAL = analogRead(KICK);
            if(KICK_VAL > KICK_THRESHOLD)
            {
     
                        while(1){
                            int kv = analogRead(KICK);
                            if(kv <  KICK_VAL ) break;
                            KICK_VAL = kv;
                        }
     
                        velocity = (KICK_VAL * 127) / 80;
                        t_note = (velocity*(0.6*velocity));
                        if(millis() - previousMillis > 50)
                        {
                          if(velocity > 127)
                          {
                            velocity = 127;
                          }
                            previousMillis = millis();
                       
                            MIDI.sendNoteOn(KICK_DRUM, velocity, 1);
                            delay(5);
                MIDI.sendNoteOff(KICK_DRUM, 0, 1);

                            while(KICK_THRESHOLD*0.3  < analogRead(KICK)){};
                           
                           
                   
                        }
                         
            }
    }
     

    Вложения:

    • 8.png
      8.png
      Размер файла:
      97 КБ
      Просмотров:
      417
  10. Dan

    Dan Гик

    но, я думаю, будет все же правильнее использовать последний скетч, только разобраться почему нет звука
     
  11. Dan

    Dan Гик

    а нет, есть звук и при использовании последнего скетча, но только когда прям сильно ударишь по датчику. а значения все выставлены низкие у меня:

    Код (C++):
    #include <MIDI.h>

    MIDI_CREATE_DEFAULT_INSTANCE();


    uint32_t kick_note_off=0; // счетчик времени звучания семпла
    uint16_t kick_sample_time=50; // время звучания семпла
    uint16_t kick_treshold=10; // пороговый уровень датчика
    uint16_t kick_gist=2; // гистерезис датчика (неопределенная зона)
    uint16_t kick_val=0; // предыдущее значение датчика
    uint8_t kick_note_number=38; // номер ноты в GeneralMIDI
    bool kick_can_sound=false; // признак, что можно играть ноту (начался подъем на датчике)
    const uint8_t kick_pin=A0;

    int tmp;
    void setup() {

    MIDI.begin();
    Serial.begin(115200);
    pinMode(kick_pin, INPUT);

    }

        void loop()
       
        {
       
        if (kick_note_off > 0) { // здесь проверяем время звучания семпла и выключаем ноту
        if (millis() > kick_note_off) { // нота уже должна отзвучать
          kick_note_off=0;
          MIDI.sendNoteOff(kick_note_number, 0, 1);
        }
      }

      tmp = analogRead(kick_pin);
      if (tmp > (kick_treshold + kick_gist)) { // уровень превышает порог+гистерезис
          if (tmp < (kick_val - kick_gist)) { // датчик пошел на спад - пик уже получен
            if ( kick_can_sound ) {
              uint8_t velocity = (uint32_t) (kick_val * 127) / 10; // 50 подобрать
              MIDI.sendNoteOn(kick_note_number, velocity, 1); // играем ноту
              kick_note_off = millis() + kick_sample_time; // ставим таймер на время звучания семпла
              kick_can_sound = false; // запрещаем следующие sendNoteOn до нового подъема и спада
            }
            kick_val = tmp; // запоминаем для поиска следующего возможного подъема
          }
          else { // сигнал сенсора растет
            kick_val = tmp; // запоминаем текущее значение для сравнения со следующим
            kick_can_sound = true; // разрешаем играть ноту как только пойдет спад
          }
      } else if (tmp < (kick_treshold - kick_gist)) { // уровень ниже порога-гистерезис
        kick_val=0; // готовы к следующему удару
      }
    }
     
  12. mcureenab

    mcureenab Гуру

    Наверное потому что после включения проходит всего 5 мс и нота выключается

    Код (C++):
                         MIDI.sendNoteOn(KICK_DRUM, velocity, 1);
                            delay(5);
                MIDI.sendNoteOff(KICK_DRUM, 0, 1);
     
  13. sslobodyan

    sslobodyan Гик

    Код (C++):
    uint16_t kick_sample_time=50; // время звучания семпла
    uint16_t kick_treshold=10; // пороговый уровень датчика
    uint16_t kick_gist=2; // гистерезис датчика (неопределенная зона)
    Поставьте порог 8 и гистерезис 0 и у вас должно работать с такими же уровнями, как и ранние скетчи
    И время звучания семпла задается в миллисекундах. Я думаю, 3500 для начала будет гораздо лучше
     
  14. mcureenab

    mcureenab Гуру

    график странный. не должно быть на нем нижних полуволн. Разме что на входе платы конденсатор имеется фильтрующий постоянное напряжение. Но все равно что то не то. Как буд-то диод не работает.
     
  15. Dan

    Dan Гик

    не не не. это я уже начинаю Вас путать, извините. Этот кусок из первого скетча, который мы с Вами совместно делали, до того, как к нам присоединился sslobodyan. Это был ПЕРВЫЙ СКЕТЧ.
    Потом он мне написал пример другого скетча. это был ВТОРОЙ СКЕТЧ. Вот сейчас я думаю, остановиться все же на использовании ВТОРОГО, так как он более подробный.
    Сейчас я его еще раз, на всякий пожарный выложу, чтобы не запутать никого.
    Код (C++):
    #include <MIDI.h>

    MIDI_CREATE_DEFAULT_INSTANCE();


    uint32_t kick_note_off=0; // счетчик времени звучания семпла
    uint16_t kick_sample_time=50; // время звучания семпла
    uint16_t kick_treshold=10; // пороговый уровень датчика
    uint16_t kick_gist=2; // гистерезис датчика (неопределенная зона)
    uint16_t kick_val=0; // предыдущее значение датчика
    uint8_t kick_note_number=38; // номер ноты в GeneralMIDI
    bool kick_can_sound=false; // признак, что можно играть ноту (начался подъем на датчике)
    const uint8_t kick_pin=A0;

    int tmp;
    void setup() {

    MIDI.begin();
    Serial.begin(115200);
    pinMode(kick_pin, INPUT);

    }

        void loop()
       
        {
       
        if (kick_note_off > 0) { // здесь проверяем время звучания семпла и выключаем ноту
        if (millis() > kick_note_off) { // нота уже должна отзвучать
          kick_note_off=0;
          MIDI.sendNoteOff(kick_note_number, 0, 1);
        }
      }

      tmp = analogRead(kick_pin);
      if (tmp > (kick_treshold + kick_gist)) { // уровень превышает порог+гистерезис
          if (tmp < (kick_val - kick_gist)) { // датчик пошел на спад - пик уже получен
            if ( kick_can_sound ) {
              uint8_t velocity = (uint32_t) (kick_val * 127) / 10; // 50 подобрать
              MIDI.sendNoteOn(kick_note_number, velocity, 1); // играем ноту
              kick_note_off = millis() + kick_sample_time; // ставим таймер на время звучания семпла
              kick_can_sound = false; // запрещаем следующие sendNoteOn до нового подъема и спада
            }
            kick_val = tmp; // запоминаем для поиска следующего возможного подъема
          }
          else { // сигнал сенсора растет
            kick_val = tmp; // запоминаем текущее значение для сравнения со следующим
            kick_can_sound = true; // разрешаем играть ноту как только пойдет спад
          }
      } else if (tmp < (kick_treshold - kick_gist)) { // уровень ниже порога-гистерезис
        kick_val=0; // готовы к следующему удару
      }
    }
    Вот он работает уже хорошо, никаких ложных срабатываний, но чтобы проиграла нота, по датчику нужно прям сильно сильно ударить.
     
  16. sslobodyan

    sslobodyan Гик

    Выведите kick_val перед посылкой ноте_он. Будем знать на какой порог ориентироваться
     
  17. Dan

    Dan Гик

    вот что получается при параметрах
    Код (C++):
    uint16_t kick_sample_time=3500; // время звучания семпла
    uint16_t kick_treshold=8; // пороговый уровень датчика
    uint16_t kick_gist=0; // гистерезис датчика (неопределенная зона)
    вывести через Serial.print(kick_val) значение kick_val не получается
     

    Вложения:

    • 9.png
      9.png
      Размер файла:
      33,8 КБ
      Просмотров:
      399
  18. sslobodyan

    sslobodyan Гик

    Ну хотя бы так. Давайте анализировать.
    1. Наибольшее значение велосити 113. Пересчитываем вашу формулу и получаем 113*10/127 = 8. Значит ваш датчик сильно тихий получился. Я бы заменил диод на что-нибудь из диодов Шоттки.
    2. Убрав гистерезис в 0, вы получили подряд звучащие ноты. Это потому, что вместо монотонного поднятия-спада у вас присутствует пила на входе и скетч ловит это как множественные удары. Пробуйте понемногу увеличивать гистерезис, пока не пропадут задваивания одиночного удара. Также понизьте порог до 4 (трешолд).
    3. Если не заработал Serial.print, то отключите пока полностью миди-команды и отладьте скетч. Лучше вместо ноте_он или ноте_офф шлите в сериал текст отладки.
     
  19. rkit

    rkit Гуру

    Насколько я понял, он не осциллограмму записывает, а звук, который получается в конце всей цепочки.
     
  20. Dan

    Dan Гик

    но формула немного другая: 113*127/10 (для значения 113)
    с сериал попробую