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

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

  1. Dan

    Dan Гик

    Всем привет!

    Ребята, я "зеленый" в программировании на Ардуино, но нужна Ваша помощь.
    Хочу сделать электронную ударную установку, скетч на один датчик я начал писать, попробовал, он работает, но не так как должно быть:

    Должно быть так:
    Стучишь по пьезе -> один звук ноты

    Как у меня:
    Стучишь по пьезе -> один звук ноты + паразитные призвуки

    Если кто-то может помочь, буду очень рад. А если кто-то еще и скетч сможет написать, могу его заказать за адекватную цену.

    Вот мой скетч:

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

    const int KICK = A0;    //объявляем константу бас-бочки как вывод A0 на Ардуино

    const int THRESHOLD = 50;
    const int KICK_THRESHOLD = 50;

    MIDI_CREATE_DEFAULT_INSTANCE();


    int KICK_VAL = 0;

    byte KICK_DRUM = 36;



    void setup()
    {
        pinMode(KICK, INPUT);
        Serial.begin(38400);  
     
    }

    void playNOTE(int value, int note)
    {
        int velocity = value;
       
       
        MIDI.sendNoteOn(note,velocity,1);  // Send a Note (pitch 42, velo 127 on channel 1)
        MIDI.sendNoteOff(note,0,1);   // Stop the note
     
       
           
           
     
    }

    void loop()
    {      
            KICK_VAL = analogRead(KICK);
            if(KICK_VAL > KICK_THRESHOLD)
            {
            playNOTE(KICK_VAL, KICK_DRUM);
            KICK_VAL = 0;
            }
            if(KICK_VAL > 127)
            {
              KICK_VAL = 127;
            }
            if(KICK_VAL < 0)
            {
              KICK_VAL = 0;
            }
           
             
    }
     
    Схема подключения пьезы была такая (только без светодиода):

    [​IMG]
     
  2. rkit

    rkit Гуру

    В лупе порядок действий перепутан.
     
  3. Dan

    Dan Гик

    можно поподробнее, пожалуйста?
     
  4. rkit

    rkit Гуру

    Там кода десять строчек. Попробуйте самостоятельно разобраться, что вы написали.
     
  5. Dan

    Dan Гик

    просто мне интересно, там KICK_VAL = analogRead(KICK); нужно в начале кода оставить или сначала условия, а потом данное считывание?
     
  6. mcureenab

    mcureenab Гуру

    Код (C++):
    void loop()
    {      
            KICK_VAL = analogRead(KICK);
            if(KICK_VAL > KICK_THRESHOLD)
            { // Тут KICK_VAL случайное значение
            playNOTE(KICK_VAL, KICK_DRUM);
            KICK_VAL = 0; // Это зачем? Далее KICK_VAL не используется, кроме как для изменния себя!!!
            }
            if(KICK_VAL > 127)
            {
              KICK_VAL = 127;
            }
            if(KICK_VAL < 0)
            {
              KICK_VAL = 0;
            }
    }
    видимо так надо, чтобы velocity <= 127 было для вызова sendNoteOn

    Код (C++):
    void loop()
    {      
            KICK_VAL = analogRead(KICK);
            if(KICK_VAL > KICK_THRESHOLD)
            {
                if(KICK_VAL > 127) KICK_VAL = 127;
                playNOTE(KICK_VAL, KICK_DRUM);
            }
    }
     
    Но фигня еще в том, что замер может произойти сразу после удара значение будет мальньким или на максимуме, тогда значение будет большим. Тут не ясно что вы хотите измерить.
     
  7. Dan

    Dan Гик

    Спасибо за разъяснение, тут важно, чтобы звук имитировал звук барабана. Громкость должна быть пропорциональна силе удара по датчику.
     
  8. mcureenab

    mcureenab Гуру

    Может быть ноту не выключать, пока KICK_VAL больше порога? Правда, не ясно сколько времени удар длиться.

    Для начала просто сбросьте KICK_VAL в Serial чтобы оценить график удара.
    А то может статься что за время удара программа много раз включает и отключает ноту с частотой в несколько кГц. Отсюда и посторонние шумы.
     
  9. Dan

    Dan Гик

    А как я его сброшу и пойму график без осцилла?
     
  10. Onkel

    Onkel Гуру

    а что за пьезо сенсор удара у вас? Где такой взять?
     
  11. Dan

    Dan Гик

    Обычный пьезо ЗП-25, у меня нет оборудования, чтобы мерить сигнал, у меня задача сделать не мега качественные ударные, а относительно примитивные, чтобы было комфортно играть
     
  12. rkit

    rkit Гуру

    Для комфортной игры придется немало поработать. И без оборудования и сноровки не вижу смысла и подходить.
     
  13. mcureenab

    mcureenab Гуру

    Код (C++):

    void setup() {
      Serial.begin(9600);      // открываем последовательное соединение
    }


    void loop()
    {  
            KICK_VAL = analogRead(KICK);
    Serial.println(KICK_VAL);
            if(KICK_VAL > KICK_THRESHOLD)
            {
                if(KICK_VAL > 127) KICK_VAL = 127;
                playNOTE(KICK_VAL, KICK_DRUM);
            }
    }
     
  14. mcureenab

    mcureenab Гуру

    Силу или скорость удара не так просто измерить.
    Как вариант - снять 2 или более показаний и экстраполировать их, видимо синусом. Оценить амплитуду полученной функции и тогда уже отправлять в MIDI звук нужной громкости и длительности.
    Можно через конденсатор и диод подать сигнал на прерывание МК. Когда напряжение на датчике пойдет на спад, возникнет прерывание и можно измерить почти максимальное напряжение.

    Ещё нужна релаксация. Наверняка после удара датчик некоторое время будет колебаться. Эти колебания не нужно учитывать. В это время должен звучать электронный барабан.
     
  15. Dan

    Dan Гик

    А время этих колебаний как то можно определить или задать в коде?
    Ведь, в ударных же есть функция глушения тарелки, когда по ней ударяют и сразу глушат рукой. А в коде ведь нужно тогда учитывать время колебаний пьезы, чтоб реализовать подобное?
     
  16. Dan

    Dan Гик

    этот скетч у меня не сработал. попробовал написать другой, чтоб вообще упростить, но творится полный трэш: хочу сделать, чтоб при ударе был звук бас-бочки, а в итоге звук малого. плюс еще когда берешься руками за оба провода пьезодатчика (за изоляцию), то звук воспроизводится бесконечно

    вот такой скетч набросал:

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

    const int KICK = A0;


    const int KICK_THRESHOLD = 500;


    MIDI_CREATE_DEFAULT_INSTANCE();


    int KICK_VAL = 0;
    int velocity = 0;
    int KICK_DRUM = 36;




    void setup()
    {

        pinMode(KICK, INPUT);

        Serial.begin(38400);  
     
    }


    void loop()
    {      
           
            KICK_VAL = analogRead(KICK);
            if(KICK_VAL > KICK_THRESHOLD)
            {
                velocity = KICK_VAL;
                MIDI.sendNoteOn(KICK_DRUM,velocity,1);
                Serial.print(KICK_VAL);
            }
            else
            {
                velocity = 0;
                MIDI.sendNoteOn(KICK_DRUM,velocity,1);
            }
           
       
    }
     
  17. mcureenab

    mcureenab Гуру

    И какие значения он на консоль выводит?
     
  18. Dan

    Dan Гик

    в самой проге ардуино вообще serial.print ниче не выводит, а в проге виртуального миди-порта он пишет, что нота 40 (отвечающая за малый барабан) воспроизведена с такой-то скоростью (velocity)
     

    Вложения:

    • 1.png
      1.png
      Размер файла:
      26,1 КБ
      Просмотров:
      856
  19. Dan

    Dan Гик

    я вообще не понимаю почему так происходит и эти помехи меня бесят. держишься за провод, что к земле идет, датчик не издает никаких лишних звуков, подносишь палец к другому проводу датчик начинает воспроизводить ноту, чудеса емае
     
  20. mcureenab

    mcureenab Гуру

    От рук на провода наводка электрическая идет. Эту помеху АЦП воспринимает как сигнал.

    Звук KICK_DRUM сколько времени должен длиться, чтобы на слух он правильно воспринимался?

    Я бы для начала ограничился фиксированным значением velocity и добавил delay(???) после отправки ноты на MIDI.

    Код (C++):
    void loop()
    {      
         
            KICK_VAL = analogRead(KICK);
            if(KICK_VAL > KICK_THRESHOLD)
            {
                velocity = 30 ; // ??? подобрать // KICK_VAL;
                MIDI.sendNoteOn(KICK_DRUM,velocity,1);
                delay(500); // ??? подобрать
                Serial.print(KICK_VAL);
            }
            else
            {
                velocity = 0;
                MIDI.sendNoteOn(KICK_DRUM,velocity,1);
            }
         
     
    }
    Когда получится стабильный результат можно заняться измереним скорости удара.