Нужна помощь в редактировании скетча для электронных барабанов

Dok321
Offline
Зарегистрирован: 26.10.2018

Я собираю электронные барабаны на Ардуино Леонардо с помощью пьезодатчиков, работать это все должно так: сигнал с пьезодатчика передается через виртуальный миди порт в программу-секвенсор в которой воспроизводятся звуки соответствующие конкретным барабанам. Скетч взял с интернета, поскольку в Ардуино не шарю, и вот в чем заключается проблема, в этом скетче подключается 6 барабанов, мне же нужно сделать 8, и я попросту не знаю что именно нужно в этом скетче поменять, для того чтобы все работало как надо. Может кто подскажет, что нужно сделать.
P. S. Плату паял по этой схеме, но задействовал ещё два аналоговых входа 10 и 11.
https://drive.google.com/file/d/1UD85y-yWyJkO1gNaDZq1vvZtyzQ45-AV/view?u...

Код:
https://drive.google.com/file/d/1B2z8lWn-BOEC_A6MRYdqw5ofDER0pQpt/view?u...

P. P. S. Статья по которой делал барабаны
https://medium.com/@gridmaniac/ударная-установка-на-arduino-3dba5e05401b

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Dok321, на любом форуме, не только на этом, существуют правила хорошего тона: прежде, чем писать на форум, следует 2-3 дня почитать его. Вы этим правилом пренебрегли и поэтому нарушили существующие на этом форуме традиции.

Если хотите получить помощь, все материалы (т.е. схему и код) нужно размещать в самом сообщении, отправлять читателя по ссылкам здесь считается дурным тоном.

Да, код следует вставлять по правилам форума.

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

Dok321
Offline
Зарегистрирован: 26.10.2018

Да я прочитал правила форума, но к сожалению прикрепить код и фото предписанным образом с телефона не получается, а доступ к компьютеру в настоящее время, увы, отсутствует. Как только он появится, я безусловно исправлю темы в соответствии с правилами

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

код поправил и в ищу исполнителя, пины на добавочные барабаны a6,  a7 проверить не на чем, цифровые миди коды барабанов какие? (продублировал кик)

/*
 * Copyright (c) 2015 Evan Kale
 * Email: <a href="mailto:EvanKale91@gmail.com">EvanKale91@gmail.com</a>
 * Website: <a href="http://www.ISeeDeadPixel.com" title="www.ISeeDeadPixel.com" rel="nofollow">www.ISeeDeadPixel.com</a>
 *          <a href="http://www.evankale.blogspot.ca" title="www.evankale.blogspot.ca" rel="nofollow">www.evankale.blogspot.ca</a>
 *
 * This file is part of ArduinoMidiDrums.
 *
 * ArduinoMidiDrums is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <<a href="http://www.gnu.org/licenses/" rel="nofollow">http://www.gnu.org/licenses/</a>>.
 */

//Piezo defines
#define NUM_PIEZOS 8
#define SNARE_THRESHOLD 18     //anything < TRIGGER_THRESHOLD is treated as 0
#define LTOM_THRESHOLD 18
#define RTOM_THRESHOLD 18
#define LCYM_THRESHOLD 18
#define RCYM_THRESHOLD 18
#define KICK_THRESHOLD 18
#define KICK1_THRESHOLD 18
#define KICK2_THRESHOLD 18
#define START_SLOT 0     //first analog slot of piezos

//MIDI note defines for each trigger
#define SNARE_NOTE 39
#define LTOM_NOTE 71
#define RTOM_NOTE 65
#define LCYM_NOTE 50
#define RCYM_NOTE 79
#define KICK_NOTE 36
#define KICK1_NOTE 36
#define KICK2_NOTE 36


#define PEDAL_NOTE 57

//MIDI defines
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127

//MIDI baud rate
#define SERIAL_RATE 9600

//Program defines
//ALL TIME MEASURED IN MILLISECONDS
#define SIGNAL_BUFFER_SIZE 100
#define PEAK_BUFFER_SIZE 30
#define MAX_TIME_BETWEEN_PEAKS 20
#define MIN_TIME_BETWEEN_NOTES 50

//map that holds the mux slots of the piezos
unsigned short slotMap[NUM_PIEZOS];

//map that holds the respective note to each piezo
unsigned short noteMap[NUM_PIEZOS];

//map that holds the respective threshold to each piezo
unsigned short thresholdMap[NUM_PIEZOS];

//Ring buffers to store analog signal and peaks
short currentSignalIndex[NUM_PIEZOS];
short currentPeakIndex[NUM_PIEZOS];
unsigned short signalBuffer[NUM_PIEZOS][SIGNAL_BUFFER_SIZE];
unsigned short peakBuffer[NUM_PIEZOS][PEAK_BUFFER_SIZE];

boolean noteReady[NUM_PIEZOS];
unsigned short noteReadyVelocity[NUM_PIEZOS];
boolean isLastPeakZeroed[NUM_PIEZOS];

unsigned long lastPeakTime[NUM_PIEZOS];
unsigned long lastNoteTime[NUM_PIEZOS];

int pedalPin = 2;

void setup()
{
  Serial.begin(SERIAL_RATE);
  
  //initialize globals
  for(short i=0; i<NUM_PIEZOS; ++i)
  {
    currentSignalIndex[i] = 0;
    currentPeakIndex[i] = 0;
    memset(signalBuffer[i],0,sizeof(signalBuffer[i]));
    memset(peakBuffer[i],0,sizeof(peakBuffer[i]));
    noteReady[i] = false;
    noteReadyVelocity[i] = 0;
    isLastPeakZeroed[i] = true;
    lastPeakTime[i] = 0;
    lastNoteTime[i] = 0;    
    slotMap[i] = START_SLOT + i;
  }

  thresholdMap[0] = LCYM_THRESHOLD;
  thresholdMap[1] = SNARE_THRESHOLD;
  thresholdMap[2] = LTOM_THRESHOLD;
  thresholdMap[3] = RTOM_THRESHOLD;
  thresholdMap[4] = RCYM_THRESHOLD;
  thresholdMap[5] = KICK_THRESHOLD;
    thresholdMap[6] = KICK1_THRESHOLD;
      thresholdMap[7] = KICK2_THRESHOLD;
  
  noteMap[0] = LCYM_NOTE;
  noteMap[1] = SNARE_NOTE;
  noteMap[2] = LTOM_NOTE;
  noteMap[3] = RTOM_NOTE;
  noteMap[4] = RCYM_NOTE;
  noteMap[5] = KICK_NOTE;
   noteMap[6] = KICK1_NOTE;
    noteMap[7] = KICK2_NOTE;

  pinMode(pedalPin, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentTime = millis();
  
  for(short i=0; i<NUM_PIEZOS; ++i)
  {
    //get a new signal from analog read
    unsigned short newSignal = analogRead(slotMap[i]);
    signalBuffer[i][currentSignalIndex[i]] = newSignal;
    
    //if new signal is 0
    if(newSignal < thresholdMap[i])
    {
      if(!isLastPeakZeroed[i] && (currentTime - lastPeakTime[i]) > MAX_TIME_BETWEEN_PEAKS)
      {
        recordNewPeak(i,0);
      }
      else
      {
        //get previous signal
        short prevSignalIndex = currentSignalIndex[i]-1;
        if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;        
        unsigned short prevSignal = signalBuffer[i][prevSignalIndex];
        
        unsigned short newPeak = 0;
        
        //find the wave peak if previous signal was not 0 by going
        //through previous signal values until another 0 is reached
        while(prevSignal >= thresholdMap[i])
        {
          if(signalBuffer[i][prevSignalIndex] > newPeak)
          {
            newPeak = signalBuffer[i][prevSignalIndex];        
          }
          
          //decrement previous signal index, and get previous signal
          prevSignalIndex--;
          if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;
          prevSignal = signalBuffer[i][prevSignalIndex];
        }
        
        if(newPeak > 0)
        {
          recordNewPeak(i, newPeak);
        }
      }
  
    }
        
    currentSignalIndex[i]++;
    if(currentSignalIndex[i] == SIGNAL_BUFFER_SIZE) currentSignalIndex[i] = 0;
  }

  int pedalValue = digitalRead(pedalPin);
  if (pedalValue == LOW){
    // If pedal pushed
    noteMap[0] = LCYM_NOTE;
  } else {
    // Otherwise
    noteMap[0] = PEDAL_NOTE;
  }
}

void recordNewPeak(short slot, short newPeak)
{
  isLastPeakZeroed[slot] = (newPeak == 0);
  
  unsigned long currentTime = millis();
  lastPeakTime[slot] = currentTime;
  
  //new peak recorded (newPeak)
  peakBuffer[slot][currentPeakIndex[slot]] = newPeak;
  
  //1 of 3 cases can happen:
  // 1) note ready - if new peak >= previous peak
  // 2) note fire - if new peak < previous peak and previous peak was a note ready
  // 3) no note - if new peak < previous peak and previous peak was NOT note ready
  
  //get previous peak
  short prevPeakIndex = currentPeakIndex[slot]-1;
  if(prevPeakIndex < 0) prevPeakIndex = PEAK_BUFFER_SIZE-1;        
  unsigned short prevPeak = peakBuffer[slot][prevPeakIndex];
   
  if(newPeak > prevPeak && (currentTime - lastNoteTime[slot])>MIN_TIME_BETWEEN_NOTES)
  {
    noteReady[slot] = true;
    if(newPeak > noteReadyVelocity[slot])
      noteReadyVelocity[slot] = newPeak;
  }
  else if(newPeak < prevPeak && noteReady[slot])
  {
    if (slot !=5)
      noteFire(noteMap[slot], noteReadyVelocity[slot]);
    else
      noteFire(noteMap[slot], 90);
    noteReady[slot] = false;
    noteReadyVelocity[slot] = 0;
    lastNoteTime[slot] = currentTime;
  }
  
  currentPeakIndex[slot]++;
  if(currentPeakIndex[slot] == PEAK_BUFFER_SIZE) currentPeakIndex[slot] = 0;  
}

void noteFire(unsigned short note, unsigned short velocity)
{
  if(velocity > MAX_MIDI_VELOCITY)
    velocity = MAX_MIDI_VELOCITY;
  
  midiNoteOn(note, velocity);
  midiNoteOff(note, velocity);
}

void midiNoteOn(byte note, byte midiVelocity)
{
  Serial.write(NOTE_ON_CMD);
  Serial.write(note);
  Serial.write(midiVelocity);
  //Serial.println((int)midiVelocity);
}

void midiNoteOff(byte note, byte midiVelocity)
{
  Serial.write(NOTE_OFF_CMD);
  Serial.write(note);
  Serial.write(midiVelocity);
}

 

Dok321
Offline
Зарегистрирован: 26.10.2018

О, спасибо вам большое, коды потом найду в программке и допишу сам, вот только вопрос, нельзя ли сделать добавочные барабаны на a10 и а11? Просто там схему уже не перепаяешь на а6 и а7.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Dok321 пишет:
О, спасибо вам большое, коды потом найду в программке и допишу сам, вот только вопрос, нельзя ли сделать добавочные барабаны на a10 и а11? Просто там схему уже не перепаяешь на а6 и а7.

Наверно можно но у меня нет LEONARDO
Пьезо датчики где брали, хочу внучке такие барабаны сделать
И что за барабаны 7 и 8

 

Dok321
Offline
Зарегистрирован: 26.10.2018

Датчики мне дико повезло найти в магазине, торгующем Ардуино у себя в Иркутске, но он закрывался и я забрал буквально последние. Знаю то что их точно можно найти на АлиЭкспресс, можно поискать в магазинах торгующих Ардуино, в крупных городах наверняка найдутся. Дополнительные барабаны, это ещё один том и бас(чтобы реализовать кардан). Подставки я сделал из мебельной фурнитуры joker, а пэды из пластмассовых пищевых контейнеров, к которым приклеил резину для хорошего отскока. Вот как все выглядит:

https://drive.google.com/file/d/14aiazIivJyeRNc9qoCcOZ9dl2O26AJIc/view?u...

Dok321
Offline
Зарегистрирован: 26.10.2018

Да, вот ещё, получается что если можно использовать а10 и а11, значит скетч никак не привязан к номерам пинов?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Dok321 пишет:
Да, вот ещё, получается что если можно использовать а10 и а11, значит скетч никак не привязан к номерам пинов?

Вы не поняли, переписать можно что угодно, только из красивого упорядоченного читабельного кода получится дерьмо-код. Менять придётся всё, оно того стоит?

Второе, устойчивая работа скетча при 8 барабанах уже не гарантируется, памяти остается слишком мало, каждый барабан съедает 300 байт озу

Dok321
Offline
Зарегистрирован: 26.10.2018

Выходит, чтобы использовать исправленный вами скетч, мне нужно чтобы барабаны подключались именно в a6 и а7?

Dok321
Offline
Зарегистрирован: 26.10.2018

А что нужно сделать чтобы работа была устойчивой?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

[Пьезо датчики где брали, хочу внучке такие барабаны сделать

Вопрос, правда, не ко мне, но я брал здесь (см. примечание снизу): https://ru.aliexpress.com/item/6-Pieces-27mm-Piezo-Disc-Elements-with-10cm-4-Leads-Guitar-Amplifiers-Contact-Pickups-Guitar-Repair/32413873366.html

Может, и в оригинальной конструкции их как раз 6 штук потому, что именно такими партиями на Али продают.

Собственно, как раз в пятницу закончил очередной проект http://arduino.ru/forum/proekty/konstruktsiya-vykhodnogo-dnya-prostoi-spektranalizator-480-polos-60-db-na-stm32f103-i-

поэтому раздумываю, может, как раз ударной установкой и заняться.

Dok321, все-таки не зря на данном форуме для обсуждения конструкции непременно требуют выложить код прямо на форуме и непременно в рекомендуемом виде - только так его можно целенаправленно обсуждать.

Вы пытались повторить конструкцию для начала подключив 6 барабанов? Она у Вас завелась? Работает хорошо?

Подозреваю, что не очень. И причинами своих подозрений могу поделиться. А также дать советы по преодолению возникших несовершенств. Но для этого всего нужен код перед глазами.

PS. Нет, ошибся, как раз по указанной выше ссылке ничего не получил, вернули деньги, а реально получил отсюда: https://ru.aliexpress.com/item/New-Arrival-J35-12PC-Brass-Piezoelectric-Piezos-Amplifiers-Discs-Leads-For-Cigar-Box-Guitar-Pickups-WholeSale/32714195755.html

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Dok321 пишет:
А что нужно сделать чтобы работа была устойчивой?

попробовать применить другую плату, arduino-2560 к примеру, там памяти больше, тогда и барабанов с пьезами можно аж 16 штук )))
Скетч на 11 и один от кнопки

/*
 * Copyright (c) 2015 Evan Kale
 * Email: <a href="mailto:EvanKale91@gmail.com">EvanKale91@gmail.com</a>
 * Website: <a href="http://www.ISeeDeadPixel.com" title="www.ISeeDeadPixel.com" rel="nofollow">www.ISeeDeadPixel.com</a>
 *          <a href="http://www.evankale.blogspot.ca" title="www.evankale.blogspot.ca" rel="nofollow">www.evankale.blogspot.ca</a>
 *
 * This file is part of ArduinoMidiDrums.
 *
 * ArduinoMidiDrums is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <<a href="http://www.gnu.org/licenses/" rel="nofollow">http://www.gnu.org/licenses/</a>>.
 * 
 * переделано для arduino mega2560
 * на 12 барабанов
 * корректировал UA6EM (проверять не проверял)
 */

//Piezo defines
#define NUM_PIEZOS 11
#define SNARE_THRESHOLD 18     //anything < TRIGGER_THRESHOLD is treated as 0
#define LTOM_THRESHOLD 18
#define RTOM_THRESHOLD 18
#define LCYM_THRESHOLD 18
#define RCYM_THRESHOLD 18
#define KICK_THRESHOLD 18
#define KICK1_THRESHOLD 18
#define KICK2_THRESHOLD 18
#define KICK3_THRESHOLD 18
#define KICK4_THRESHOLD 18
#define KICK5_THRESHOLD 18
#define START_SLOT 0     //first analog slot of piezos

//MIDI note defines for each trigger
#define SNARE_NOTE 39
#define LTOM_NOTE 71
#define RTOM_NOTE 65
#define LCYM_NOTE 50
#define RCYM_NOTE 79
#define KICK_NOTE 36
#define KICK1_NOTE 33
#define KICK2_NOTE 30
#define KICK3_NOTE 27
#define KICK4_NOTE 24
#define KICK5_NOTE 21


#define PEDAL_NOTE 57

//MIDI defines
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127

//MIDI baud rate
#define SERIAL_RATE 9600

//Program defines
//ALL TIME MEASURED IN MILLISECONDS
#define SIGNAL_BUFFER_SIZE 100
#define PEAK_BUFFER_SIZE 30
#define MAX_TIME_BETWEEN_PEAKS 20
#define MIN_TIME_BETWEEN_NOTES 50

//map that holds the mux slots of the piezos
unsigned short slotMap[NUM_PIEZOS];

//map that holds the respective note to each piezo
unsigned short noteMap[NUM_PIEZOS];

//map that holds the respective threshold to each piezo
unsigned short thresholdMap[NUM_PIEZOS];

//Ring buffers to store analog signal and peaks
short currentSignalIndex[NUM_PIEZOS];
short currentPeakIndex[NUM_PIEZOS];
unsigned short signalBuffer[NUM_PIEZOS][SIGNAL_BUFFER_SIZE];
unsigned short peakBuffer[NUM_PIEZOS][PEAK_BUFFER_SIZE];

boolean noteReady[NUM_PIEZOS];
unsigned short noteReadyVelocity[NUM_PIEZOS];
boolean isLastPeakZeroed[NUM_PIEZOS];

unsigned long lastPeakTime[NUM_PIEZOS];
unsigned long lastNoteTime[NUM_PIEZOS];

int pedalPin = 2;

void setup()
{
  Serial.begin(SERIAL_RATE);
  
  //initialize globals
  for(short i=0; i<NUM_PIEZOS; ++i)
  {
    currentSignalIndex[i] = 0;
    currentPeakIndex[i] = 0;
    memset(signalBuffer[i],0,sizeof(signalBuffer[i]));
    memset(peakBuffer[i],0,sizeof(peakBuffer[i]));
    noteReady[i] = false;
    noteReadyVelocity[i] = 0;
    isLastPeakZeroed[i] = true;
    lastPeakTime[i] = 0;
    lastNoteTime[i] = 0;    
    slotMap[i] = START_SLOT + i;
  }

  thresholdMap[0] = LCYM_THRESHOLD;
  thresholdMap[1] = SNARE_THRESHOLD;
  thresholdMap[2] = LTOM_THRESHOLD;
  thresholdMap[3] = RTOM_THRESHOLD;
  thresholdMap[4] = RCYM_THRESHOLD;
  thresholdMap[5] = KICK_THRESHOLD;
    thresholdMap[6] = KICK1_THRESHOLD;
      thresholdMap[7] = KICK2_THRESHOLD;
      thresholdMap[8] = KICK3_THRESHOLD;
      thresholdMap[9] = KICK4_THRESHOLD;
      thresholdMap[10] = KICK5_THRESHOLD;
  
  noteMap[0] = LCYM_NOTE;
  noteMap[1] = SNARE_NOTE;
  noteMap[2] = LTOM_NOTE;
  noteMap[3] = RTOM_NOTE;
  noteMap[4] = RCYM_NOTE;
  noteMap[5] = KICK_NOTE;
   noteMap[6] = KICK1_NOTE;
    noteMap[7] = KICK2_NOTE;
     noteMap[8] = KICK3_NOTE;
      noteMap[9] = KICK4_NOTE;
       noteMap[10] = KICK5_NOTE;

  pinMode(pedalPin, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentTime = millis();
  
  for(short i=0; i<NUM_PIEZOS; ++i)
  {
    //get a new signal from analog read
    unsigned short newSignal = analogRead(slotMap[i]);
    signalBuffer[i][currentSignalIndex[i]] = newSignal;
    
    //if new signal is 0
    if(newSignal < thresholdMap[i])
    {
      if(!isLastPeakZeroed[i] && (currentTime - lastPeakTime[i]) > MAX_TIME_BETWEEN_PEAKS)
      {
        recordNewPeak(i,0);
      }
      else
      {
        //get previous signal
        short prevSignalIndex = currentSignalIndex[i]-1;
        if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;        
        unsigned short prevSignal = signalBuffer[i][prevSignalIndex];
        
        unsigned short newPeak = 0;
        
        //find the wave peak if previous signal was not 0 by going
        //through previous signal values until another 0 is reached
        while(prevSignal >= thresholdMap[i])
        {
          if(signalBuffer[i][prevSignalIndex] > newPeak)
          {
            newPeak = signalBuffer[i][prevSignalIndex];        
          }
          
          //decrement previous signal index, and get previous signal
          prevSignalIndex--;
          if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;
          prevSignal = signalBuffer[i][prevSignalIndex];
        }
        
        if(newPeak > 0)
        {
          recordNewPeak(i, newPeak);
        }
      }
  
    }
        
    currentSignalIndex[i]++;
    if(currentSignalIndex[i] == SIGNAL_BUFFER_SIZE) currentSignalIndex[i] = 0;
  }

  int pedalValue = digitalRead(pedalPin);
  if (pedalValue == LOW){
    // If pedal pushed
    noteMap[0] = LCYM_NOTE;
  } else {
    // Otherwise
    noteMap[0] = PEDAL_NOTE;
  }
}

void recordNewPeak(short slot, short newPeak)
{
  isLastPeakZeroed[slot] = (newPeak == 0);
  
  unsigned long currentTime = millis();
  lastPeakTime[slot] = currentTime;
  
  //new peak recorded (newPeak)
  peakBuffer[slot][currentPeakIndex[slot]] = newPeak;
  
  //1 of 3 cases can happen:
  // 1) note ready - if new peak >= previous peak
  // 2) note fire - if new peak < previous peak and previous peak was a note ready
  // 3) no note - if new peak < previous peak and previous peak was NOT note ready
  
  //get previous peak
  short prevPeakIndex = currentPeakIndex[slot]-1;
  if(prevPeakIndex < 0) prevPeakIndex = PEAK_BUFFER_SIZE-1;        
  unsigned short prevPeak = peakBuffer[slot][prevPeakIndex];
   
  if(newPeak > prevPeak && (currentTime - lastNoteTime[slot])>MIN_TIME_BETWEEN_NOTES)
  {
    noteReady[slot] = true;
    if(newPeak > noteReadyVelocity[slot])
      noteReadyVelocity[slot] = newPeak;
  }
  else if(newPeak < prevPeak && noteReady[slot])
  {
    if (slot !=5)
      noteFire(noteMap[slot], noteReadyVelocity[slot]);
    else
      noteFire(noteMap[slot], 90);
    noteReady[slot] = false;
    noteReadyVelocity[slot] = 0;
    lastNoteTime[slot] = currentTime;
  }
  
  currentPeakIndex[slot]++;
  if(currentPeakIndex[slot] == PEAK_BUFFER_SIZE) currentPeakIndex[slot] = 0;  
}

void noteFire(unsigned short note, unsigned short velocity)
{
  if(velocity > MAX_MIDI_VELOCITY)
    velocity = MAX_MIDI_VELOCITY;
  
  midiNoteOn(note, velocity);
  midiNoteOff(note, velocity);
}

void midiNoteOn(byte note, byte midiVelocity)
{
  Serial.write(NOTE_ON_CMD);
  Serial.write(note);
  Serial.write(midiVelocity);
  //Serial.println((int)midiVelocity);
}

void midiNoteOff(byte note, byte midiVelocity)
{
  Serial.write(NOTE_OFF_CMD);
  Serial.write(note);
  Serial.write(midiVelocity);
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

ua6em пишет:

[Пьезо датчики где брали, хочу внучке такие барабаны сделать

Вопрос, правда, не ко мне, но я брал здесь: https://ru.aliexpress.com/item/6-Pieces-27mm-Piezo-Disc-Elements-with-10cm-4-Leads-Guitar-Amplifiers-Contact-Pickups-Guitar-Repair/32413873366.html

Может, и в оригинальной конструкции их как раз 6 штук потому, что именно такими партиями на Али продают.

Собственно, как раз в пятницу закончил очередной проект http://arduino.ru/forum/proekty/konstruktsiya-vykhodnogo-dnya-prostoi-spektranalizator-480-polos-60-db-na-stm32f103-i-

поэтому раздумываю, может, как раз ударной установкой и заняться.

Dok321, все-таки не зря на данном форуме для обсуждения конструкции непременно требуют выложить код прямо на форуме и непременно в рекомендуемом виде - только так его можно целенаправленно обсуждать.

Вы пытались повторить конструкцию для начала подключив 6 барабанов? Она у Вас завелась? Работает хорошо?

Подозреваю, что не очень. И причинами своих подозрений могу поделиться. А также дать советы по преодолению возникших несовершенств. Но для этого всего нужен код перед глазами.

В ролике вроде работала установка )))
Код практически без изменений, я просто добавил датчики, логика работы прежняя, не изменялась
Мне понравилось его решение на сантехнических трубах, только я всё сварить намереваюсь, утюг есть,

да и ножки делать не Т соединитель а повороты поставить

 

Dok321
Offline
Зарегистрирован: 26.10.2018

Да с 6 пытался запустить и ничего не получилось, конечно буду рад любым вашим советам, как только доберусь до ПК, сразу приведу код в приемлемом виде.

Dok321
Offline
Зарегистрирован: 26.10.2018

Я сперва тоже попробовал каркас сделать из водопроводных труб, но имеется у них большая проблема, а именно сильная вибрация и плохая устойчивость, ну и места больше занимают конечно

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Dok321 пишет:
Да с 6 пытался запустить и ничего не получилось, конечно буду рад любым вашим советам, как только доберусь до ПК, сразу приведу код в приемлемом виде.

Оригинально!!! )))
На 6-ти не заработало, а на восьми должно...
Пьеза в оригинале наклеивалась на оргстекло совсем не даром да и рабочая поверхность и крепления демпфировались тоже

Dok321
Offline
Зарегистрирован: 26.10.2018

Ну в конечном счёте мне все равно нужно было бы сделать их 8)

Dok321
Offline
Зарегистрирован: 26.10.2018

Честно говоря, у меня вообще какие то странности с ардуинкой, первый раз скетч загрузить получилось, а потом уже нет причем пробовал с двух разных компов разными проводами, не загружает ничего даже пустой скетч, ошибок не выдает, пишет только " ошибка при загрузке скетча". При этом попробовал потом загрузить с компьютера друга, все загрузилось прекрасно

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em, а что означают строки 234-237 по Вашему варианту из поста 12?

Dok321, в статье, приведенной в исходном сообщении темы используется Arduino Uno. Почему Вы решили замиенитьее на Leonardo?

 

И еще по поводу кода: видно, что писал его человек, не очень ориентирующийся в программировании вообще и в Ардуино в частности. Я бы не рискнул использовать его в исходном виде.

 

Dok321, по поводу "ничего не получилось".  Обратите внимание на строки 29-39 по тому же посту 12. Это - настроечные коэффициенты. Автор явно настраивал их индивидуально под каждый пэд. А теперь представьте себя на его месте: Вы знаете, что эти коэффициенты настроены конкретно под Ваши пэды и ни под какие другие не подойдут, что Вы будете делать в случае публикации? Праильно, Вы перед публикацией приведете их к некоторому сренему. Что мы и наблюдаем в исходнике. 

Если бы для всех подходил один настроечный коэффициент, автор не стал бы использовать их индивидуально для каждого свой, а ввел бы один на все. И, кстати, даже это не гарантировало бы повторяемость конструкции, т.к. у Вас технология изготовления пэдов может быть другая и Вам (даже единственный) коэффициент нужно использовать свой.

В общем, без настройки это не заработает. Хотя бы потому, что указанные настроечные коэффициенты - далеко не все настройки, которые могут понадобиться. Есть такое подозрение, что все цифры в строках 68-71 тоже требуют настройки.

Ну и некоторые замеченные ошибки:

в строке 249 делается проверка. Проверка обоснованная, только ее надо делать не здесь, а гораздо раньше - в строке 150, т.к. там может произойти даже не насыщенгие, а гораздо хуже, - потеря старших разрядов. И вообще в этом месте бы был уместен индивидуальный коэффициент масштабирования.

строки 104-109 не нужны, стандарт Си обязывает обнулить глобальные переменные перед использованием.

строки 116-138 следовало бы заменить инициализацией массивов при их описании.

ввести любые номера пинов (не обязательно последовательные) можно путем введения дополнительного массива и небольшой правки строки 150.

период оцифровки не задается жестко, а сделан "как получится", это не очень хорошо само по себе, но еще и приводит к тому, что при изменении количества пэдов, так и при замене контроллера (например с Uno на Leonardo)

millis() - не очень удачное решение, т.к. в исходнике оцифровка должна происходить с шагом около 1 мс, а в millis() эти мс "шагают" не регулярно.

Dok321
Offline
Зарегистрирован: 26.10.2018

Спасибо за советы, но проблема в том что когда я подключал к ардуинке просто пьезу, не прикреплённую к барабану, все равно ничего не работало, собственно даже виртуальный миди порт не подавал признаков жизни. P. S. Леонардо использовал потому что в Уно всего шесть входов, а в Леонардо часть Цифровых может использоваться как аналоговые

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Dok321, это как раз то, о чем я говорил: пэды и у автора и у Вас - самодельные, изготовленные по разным технологиям, а потому при переходе с одних на другие программа неизбежно требует настройки.

Я, кстати, о Вас лучше думал. Во-первых, Леонардо в отличие от Уно позволяет непосредственно подключиться к компу по USB безо всяких промежуточных примочек - сразу будет опознаваться как MIDI-устройство. Оказалось, дело не в этом. Слледующая мысль была: у Леонардо не 2 кБ памяти, как у Уно, а 2.5, что как раз и позволяет разместить массивы для двух дополнительных инструментов. Оказалось, дело тоже не в этом. 

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

Кстати, Doc321, скажите мне как художник художнику, у Вас есть осциллограф?

Dok321
Offline
Зарегистрирован: 26.10.2018

Да, честно говоря мои познания в программировании заканчиваются на самом базовом уровне C++, пооэтому менять для меня что то в скетче это просто темный лес. Нет осциллографа нет, увы.

 

Dok321
Offline
Зарегистрирован: 26.10.2018

// Автор кода: Christian D'Aquino						
// Версия: 20150109														
// Редактор: Rodrigo Amaral				
// Перевод на Русский: CheapDrums    

// НЕОБХОДИМО УСТАНОВИТЬ СКОРОСТЬ СОМ ПОРТА НА 115200
									
//----------------------------  ННАСТРОЙКИ  ------------------------------------------------------------------------------------------------------------------------------------------//

// ФОРМА ВВОДА ЗНАЧЕНИЙ, ВВОДИМ ЗНАЧЕНИЯ ВСЕХ 16ТИ ПИНОВ В СКОБКАХ ЧЕРЕЗ ЗАПЯТУЮ, ПРИМЕР ={A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15}; 
/*                        
                        |HAT CONTROL
                        |A0  |HI-HAT
                        |    |A1  |KICK
                        |    |    |A2  |SNARE
                        |    |    |    |A3  |RACK TOM 1 (1)
                        |    |    |    |    |A4  |RACK TOM 2 (2)
                        |    |    |    |    |    |A5  |RACK TOM 3 (3)
                        |    |    |    |    |    |    |A6  |FLOOR TOM 1 (4)
                        |    |    |    |    |    |    |    |A7  |RIDE 2
                        |    |    |    |    |    |    |    |    |A8  |RIDE 2 BELL
                        |    |    |    |    |    |    |    |    |    |A9  |SYMBAL 3
                        |    |    |    |    |    |    |    |    |    |    |A10 |SYMBAL 4
                        |    |    |    |    |    |    |    |    |    |    |    |A11 |CHINA 1
                        |    |    |    |    |    |    |    |    |    |    |    |    |A12 |CHINA 2
                        |    |    |    |    |    |    |    |    |    |    |    |    |    |A13 |SPLASH
                        |    |    |    |    |    |    |    |    |    |    |    |    |    |    |A14 |SPOCK
                        |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |A15
*/                        
byte SensorType[16]   ={128, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 128 };	       // ТИП СЭНСОРА; 144 = ПЬЕЗА, 176 = КОНТРОЛЛЕР ХЭТА НА TCRT5000, 128 = ПУСТО												
byte PadNote[16]      ={44,  60,  36,  38,  48,  47,  45,  43,  108, 109,  30,  31,  27,  52,  55, 29  };	       // НОТА ПРИВЯЗАННАЯ К ПИНУ (АКТУАЛЬНО ДЛЯ SUPERIOR DRUMMER 2 / THE METAL FOUNDRY, В ДРУГИХ ПЛАГИНАХ / БИБЛИОТЕКАХ МОЖЕТ ОТЛИЧАТЬСЯ)  
int thresholdMin[16]  ={10  ,100, 100 ,100 ,100 ,100 ,100 ,100 ,100 ,100 ,100 ,100 ,100 ,100 ,100 ,100 };				 //	НИЖНИЙ ПОРОГ ЧУВСТВИТЕЛЬНОСТИ	(так же срезается нижний порог передаваемого по миди значения velocity, компенсиривать можно во вкладке utility)									
int thresholdMax[16]  ={1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023};			   //	ВЕРХНИЙ ПОРОГ ЧУВСТВИТЕЛЬНОСТИ  										
int sensorScantime[16]={10,  10,  10,  10,  10,  10,  10,  10,  10,  10,  10,  10,  10,  10,  10,  10  };			   // ЧАСТОА ОПРОСА ДАТЧИКОВ
int sensorMasktime[16]={10,  60,  60,  40,  40,  40,  40,  40,  40,  40,  40,  40,  40,  40,  40,  40  };	       // ДЛИТЕЛЬНОСТЬ ИГНОРИРОВАНИЯ ДАТЧИКА ПОСЛЕ ПЛУЧЕНИЯ С НЕГО СИГНАЛА

#define READPIN 16 // КОЛЛИЧЕСТВО ЗАДЕЙСТВОВАННЫХ АНАЛОГОВЫХ ПИНОВ ДЛЯ ВВОДА (1й пин = A0, 2й пин = A1 и так далее)						
													
//------------------------------ Глушения тарелок ---------------------------------------//	

// Ноты глушения //

#define choke1 94
#define choke2 95 
#define choke3 106
#define chokeRide 118

// Доп цифровые входы //

#define Aux1 47
#define Aux2 47
#define Aux3 47
#define Aux4 47
#define Aux5 47
#define Aux6 47
#define Aux7 47																	
																														
// !!! ДАЛЕЕ ИДЕТ КОД ПРОГРАММЫ, ИЗМЕНЕНИЯ ВНОСИТЬ ТОЛЬКО ОПЫТНЫМ ПОЛЬЗОВАТЕЛЯМ !!! //

//Определение цифровых пинов глушилок

#define Choke1_Pin 51 
#define Choke2_Pin 49
#define Choke3_Pin 47
#define ChokeRide_Pin 53 

//Определение доп. цифровых пинов

#define Aux1_Pin 33
#define Aux2_Pin 35
#define Aux3_Pin 37
#define Aux4_Pin 39
#define Aux5_Pin 41
#define Aux6_Pin 43
#define Aux7_Pin 45

//Состояние цифровых пинов

int Choke1_State = LOW;
int Choke2_State = LOW;
int Choke3_State = LOW;
int ChokeRide_State = LOW;
int Aux1_State = LOW;
int Aux2_State = LOW;
int Aux3_State = LOW;
int Aux4_State = LOW;
int Aux5_State = LOW;
int Aux6_State = LOW;
int Aux7_State = LOW;

int currentSwitchState = LOW;

// установка и сброс битов регистра
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define midichannel 0

int readSensor = 0;
int led = 13;
unsigned long previousMillis[16];
unsigned long currentMillis[16];
unsigned int sensorReads[10];
int readNumber[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
boolean playNote[16] ={true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true};

int pin = 0;

void setup()
{
  Serial.begin(115200);
  pinMode(Choke1_Pin, INPUT);
  pinMode(Choke2_Pin, INPUT);
  pinMode(Choke3_Pin, INPUT);
  pinMode(ChokeRide_Pin, INPUT);
  pinMode(Aux1_Pin, INPUT);
  pinMode(Aux2_Pin, INPUT);
  pinMode(Aux3_Pin, INPUT);
  pinMode(Aux4_Pin, INPUT);
  pinMode(Aux5_Pin, INPUT);
  pinMode(Aux6_Pin, INPUT);
  pinMode(Aux7_Pin, INPUT);
  
  digitalWrite(Choke1_Pin, HIGH);     // необходимо подтягивающее сопротивление
  digitalWrite(Choke2_Pin, HIGH);     // необходимо подтягивающее сопротивление
  digitalWrite(Choke3_Pin, HIGH);     // необходимо подтягивающее сопротивление
  digitalWrite(ChokeRide_Pin, HIGH);  // необходимо подтягивающее сопротивление
  digitalWrite(Aux1_Pin, HIGH);       // необходимо подтягивающее сопротивление
  digitalWrite(Aux2_Pin, HIGH);       // необходимо подтягивающее сопротивление
  digitalWrite(Aux3_Pin, HIGH);       // необходимо подтягивающее сопротивление
  digitalWrite(Aux4_Pin, HIGH);       // необходимо подтягивающее сопротивление
  digitalWrite(Aux5_Pin, HIGH);       // необходимо подтягивающее сопротивление
  digitalWrite(Aux6_Pin, HIGH);       // необходимо подтягивающее сопротивление
  digitalWrite(Aux7_Pin, HIGH);       // необходимо подтягивающее сопротивление
  pinMode(led, OUTPUT);
	
	while (!Serial) {
	; // ждать последовательный порт для подключения, (только для Arduino Leonardo)
	}
  
	// установить делитель на 8
	cbi(ADCSRA,ADPS2);
	sbi(ADCSRA,ADPS1);
	sbi(ADCSRA,ADPS0);
	
	Serial.flush();
  
}

void loop()

// ------------------------------------ ЦИФРОВЫЕ ВХОДЫ ----------------------------------- //

// ГЛУШИЛКА 01
{
currentSwitchState = digitalRead(Choke1_Pin);
if( currentSwitchState == LOW && Choke1_State == HIGH ) // push
MIDI_TX(144,  choke1, 127);
if( currentSwitchState == HIGH && Choke1_State == LOW ) // release
MIDI_TX(128, choke1, 127);
Choke1_State = currentSwitchState;
  
// ГЛУШИЛКА 02
{
currentSwitchState = digitalRead(Choke2_Pin);
if( currentSwitchState == LOW && Choke2_State == HIGH ) // push
MIDI_TX(144,  choke2, 127);
if( currentSwitchState == HIGH && Choke2_State == LOW ) // release
MIDI_TX(128, choke2, 127);
Choke2_State = currentSwitchState;
  
// ГЛУШИЛКА 03
{
currentSwitchState = digitalRead(Choke3_Pin);
if( currentSwitchState == LOW && Choke3_State == HIGH ) // push
MIDI_TX(144,  choke3, 127);
if( currentSwitchState == HIGH && Choke3_State == LOW ) // release
MIDI_TX(128, choke3, 127);
Choke3_State = currentSwitchState;
  
// ГЛУШИЛКА РАЙДА
{
currentSwitchState = digitalRead(ChokeRide_Pin);
if( currentSwitchState == LOW && ChokeRide_State == HIGH ) // push
MIDI_TX(144,  chokeRide, 127);
if( currentSwitchState == HIGH && ChokeRide_State == LOW ) // release
MIDI_TX(128, chokeRide, 127);
ChokeRide_State = currentSwitchState;
  
// AUX 1
{    
currentSwitchState = digitalRead(Aux1_Pin);
if( currentSwitchState == LOW && Aux1_State == HIGH ) // push
MIDI_TX(144,  Aux1, 127);
if( currentSwitchState == HIGH && Aux1_State == LOW ) // release
MIDI_TX(128, Aux1, 127);
Aux1_State = currentSwitchState;
  
// AUX 2
{    
currentSwitchState = digitalRead(Aux2_Pin);
if( currentSwitchState == LOW && Aux2_State == HIGH ) // push
MIDI_TX(144,  Aux2, 127);
if( currentSwitchState == HIGH && Aux2_State == LOW ) // release
MIDI_TX(128, Aux2, 127);
Aux2_State = currentSwitchState;

// AUX 3
{    
currentSwitchState = digitalRead(Aux3_Pin);
if( currentSwitchState == LOW && Aux3_State == HIGH ) // push
MIDI_TX(144,  Aux3, 127);
if( currentSwitchState == HIGH && Aux3_State == LOW ) // release
MIDI_TX(128, Aux3, 127);
Aux3_State = currentSwitchState;

// AUX 4
{    
currentSwitchState = digitalRead(Aux4_Pin);
if( currentSwitchState == LOW && Aux4_State == HIGH ) // push
MIDI_TX(144,  Aux4, 127);
if( currentSwitchState == HIGH && Aux4_State == LOW ) // release
MIDI_TX(128, Aux4, 127);
Aux4_State = currentSwitchState;

// AUX 5
{    
currentSwitchState = digitalRead(Aux5_Pin);
if( currentSwitchState == LOW && Aux5_State == HIGH ) // push
MIDI_TX(144,  Aux5, 127);
if( currentSwitchState == HIGH && Aux5_State == LOW ) // release
MIDI_TX(128, Aux5, 127);
Aux5_State = currentSwitchState;
  
// AUX 6
{    
currentSwitchState = digitalRead(Aux6_Pin);
if( currentSwitchState == LOW && Aux6_State == HIGH ) // push
MIDI_TX(144,  Aux6, 127);
if( currentSwitchState == HIGH && Aux6_State == LOW ) // release
MIDI_TX(128, Aux6, 127);
Aux6_State = currentSwitchState;
  
// AUX 7
{    
currentSwitchState = digitalRead(Aux7_Pin);
if( currentSwitchState == LOW && Aux7_State == HIGH ) // push
MIDI_TX(144,  Aux7, 127);
if( currentSwitchState == HIGH && Aux7_State == LOW ) // release
MIDI_TX(128, Aux7, 127);
Aux7_State = currentSwitchState;

//------------------------------------- АНАЛОГОВЫЕ ВХОДЫ -----------------------------------------------//

	for(pin = 0; pin < READPIN; pin++)
	{
		readSensor = analogRead(pin);

                if((SensorType[pin] != 128) && (readSensor > thresholdMin[pin]) && ((currentMillis[pin] - previousMillis[pin]) <= sensorMasktime[pin]))
		{
			currentMillis[pin] = millis();
			
			if (readNumber[pin] < sensorScantime[pin])
			{
				if (readSensor > sensorReads[pin])
				{
					sensorReads[pin] = readSensor;
					
				}
				readNumber[pin]++;
			} else if (playNote[pin] == true)
			{
				
				playNote[pin] = false;
				
				int velocity = normalizeSensor(sensorReads[pin], pin);
				MIDI_TX(SensorType[pin], PadNote[pin], velocity);
                                digitalWrite(led, HIGH);
                                digitalWrite(led, LOW);
			}
				
		} else if ((currentMillis[pin] - previousMillis[pin]) > sensorMasktime[pin])
		{
			playNote[pin] = true;
			readNumber[pin] = 0;
			sensorReads[pin] = 0;
			previousMillis[pin] = currentMillis[pin];
		}
	}

// =======================================================================================================================================================//
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
 void debugCode()
 {
// 	 MIDI_TX(noteOn, 38, 90);
// 	 delay(300);
 }
 
 void debugScantimeArray(int values[])
 {
	 
	 Serial.print("Scantime = {");
	 for (int m = 0; m < 10; m++)
	 {
	 	Serial.print(values[m]);
		Serial.print(", ");
	 }
	 Serial.println("}");

 }
 
 void debugScantimeValues(int pin, int time, int value)
 {
	 
	Serial.print(pin);
	Serial.print(" > ");
	Serial.print(time);
	Serial.print(" > ");
	Serial.println(value);

 }
 
 void debugMIDI(int channel, int note, int vel)
 {
	 
	 Serial.print(channel);
	 Serial.print(" > ");
	 Serial.print(note);
	 Serial.print(" > ");
	 Serial.println(vel);
	 
 }
void MIDI_TX(byte MESSAGE, byte PITCH, byte VELOCITY)
{
//status = MESSAGE + midichannel;
Serial.write((MESSAGE | midichannel));
Serial.write(PITCH);
Serial.write(VELOCITY);
}
//Возвращает самое высокое значение в Scantime
// int maxValue(int read[], int length)
// {
// 	int max = 0;
// 		
// 	for (int n=0; n < length; n++)
// 	{	
// 		if (max < read[n]) {
// 			max = read[n];
// 		}
// 	}
// 	return max;
// }

//Нормализация значения velocity, в соответствии с чувствительностью пэда. Fun��o de Gain
int normalizeSensor(int sensor, int pin)
{
	
	if (sensor < thresholdMin[pin])
	{
		sensor = thresholdMin[pin];
	} else if (sensor > thresholdMax[pin])
	{
		sensor = thresholdMax[pin];
	}
	
	if (SensorType[pin] == 176) {
		sensor = map(sensor, thresholdMax[pin], thresholdMin[pin], 1, 127);
	}
	else
	{
   /*                                           // ПРИ СРЕЗЕ НИЖНЕГО ПОРОГА velocity УСТАНОВИТЬ ОТРИЦАТЕЛЬНОЕ ЗНАЧЕНИЕ 
                                                |
   */                                            
		sensor = map(sensor, 0, thresholdMax[pin], -15, 127);                          
	}
	
	return sensor;
}

// int scanTimeBool(int pin)
// {
// 	boolean scan;
// 	unsigned long currentMillis = millis();
// // 	if ((unsigned long)(currentMillis - previousMillis) < sensorScantime[pin])
// 	{
// 		scan = true;
// 	} else {
// 		scan = false;
// 		previousMillis = currentMillis;
// 	}
// 	
// 	return scan;
// 	
	
//}

 

 

Dok321
Offline
Зарегистрирован: 26.10.2018

Вот нашел еще один скетч для барабанов в интернете(надеюсь все правильно вставил)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

ua6em, а что означают строки 234-237 по Вашему варианту из поста 12?

Так откуда же мне знать )))
Возможно там придётся тоже изменить на 7

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Dok321 пишет:

Вот нашел еще один скетч для барабанов в интернете(надеюсь все правильно вставил)

неправильно, это под мегу 2560

Dok321
Offline
Зарегистрирован: 26.10.2018

А его нельзя переделать под Леонардо?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Dok321 пишет:
А его нельзя переделать под Леонардо?

нет, там же 16 входов используется

sadman41
Offline
Зарегистрирован: 19.10.2016

Да ладно... переделать можно почти всё в почти всё, вопрос только в том , кто этим заниматься будет ))

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Если количество входов для Леонардо можно увеличить, значит и количество входов для Леонардо можно уменьшить.

Вопрос только, кто этим будет заниматься.

Dok321
Offline
Зарегистрирован: 26.10.2018

А зачем вы интересовались про асциллограф

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

Если количество входов для Леонардо можно увеличить, значит и количество входов для Леонардо можно уменьшить.

Вопрос только, кто этим будет заниматься.


В том скетче, что для mega-2560 уменьшить не получится, мой хрустальный шар говорит, что памяти в 2,5 килобайта не хватит )))
Да и смысл, брать мегу и повторять и ничего переписывать не надо
 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

Да ладно... переделать можно почти всё в почти всё, вопрос только в том , кто этим заниматься будет ))

моим внучкам и простых барабанов хватит )))

Dok321
Offline
Зарегистрирован: 26.10.2018

andriano пишет:

ua6em, а что означают строки 234-237 по Вашему варианту из поста 12?

Dok321, в статье, приведенной в исходном сообщении темы используется Arduino Uno. Почему Вы решили замиенитьее на Leonardo?

 

И еще по поводу кода: видно, что писал его человек, не очень ориентирующийся в программировании вообще и в Ардуино в частности. Я бы не рискнул использовать его в исходном виде.

 

Dok321, по поводу "ничего не получилось".  Обратите внимание на строки 29-39 по тому же посту 12. Это - настроечные коэффициенты. Автор явно настраивал их индивидуально под каждый пэд. А теперь представьте себя на его месте: Вы знаете, что эти коэффициенты настроены конкретно под Ваши пэды и ни под какие другие не подойдут, что Вы будете делать в случае публикации? Праильно, Вы перед публикацией приведете их к некоторому сренему. Что мы и наблюдаем в исходнике. 

Если бы для всех подходил один настроечный коэффициент, автор не стал бы использовать их индивидуально для каждого свой, а ввел бы один на все. И, кстати, даже это не гарантировало бы повторяемость конструкции, т.к. у Вас технология изготовления пэдов может быть другая и Вам (даже единственный) коэффициент нужно использовать свой.

В общем, без настройки это не заработает. Хотя бы потому, что указанные настроечные коэффициенты - далеко не все настройки, которые могут понадобиться. Есть такое подозрение, что все цифры в строках 68-71 тоже требуют настройки.

Ну и некоторые замеченные ошибки:

в строке 249 делается проверка. Проверка обоснованная, только ее надо делать не здесь, а гораздо раньше - в строке 150, т.к. там может произойти даже не насыщенгие, а гораздо хуже, - потеря старших разрядов. И вообще в этом месте бы был уместен индивидуальный коэффициент масштабирования.

строки 104-109 не нужны, стандарт Си обязывает обнулить глобальные переменные перед использованием.

строки 116-138 следовало бы заменить инициализацией массивов при их описании.

ввести любые номера пинов (не обязательно последовательные) можно путем введения дополнительного массива и небольшой правки строки 150.

период оцифровки не задается жестко, а сделан "как получится", это не очень хорошо само по себе, но еще и приводит к тому, что при изменении количества пэдов, так и при замене контроллера (например с Uno на Leonardo)

millis() - не очень удачное решение, т.к. в исходнике оцифровка должна происходить с шагом около 1 мс, а в millis() эти мс "шагают" не регулярно.


Да, извините, а как мне их настроить?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Dok321 пишет:
А зачем вы интересовались про асциллограф
Мне просто любопытно, как Вы без осциллографа собираетесь настраивать электронное устройство.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

В том скетче, что для mega-2560 уменьшить не получится, мой хрустальный шар говорит, что памяти в 2,5 килобайта не хватит )))

А мой хрустальный шар говорит, что как раз в память поместится. А вот пинов может не хватить.

Цитата:

Да и смысл, брать мегу и повторять и ничего переписывать не надо
 

Это другое дело.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Dok321 пишет:
Да, извините, а как мне их настроить?
Ну я же не просто так спрашивал про осциллограф.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Doc321, а Вы видели оригинал того, что повторено по Вашей ссылке? https://youtu.be/vi-w_WqJjzQ?list=PLaCGYJSDl2G_KG5hJ-WySR9g7NF22nGSo

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

Описание в виде текста: https://www.instructables.com/id/Convert-Rockband-Controller-to-MIDI-Drums/

 

Dok321
Offline
Зарегистрирован: 26.10.2018

andriano пишет:

ua6em, а что означают строки 234-237 по Вашему варианту из поста 12?

Dok321, в статье, приведенной в исходном сообщении темы используется Arduino Uno. Почему Вы решили замиенитьее на Leonardo?

 

И еще по поводу кода: видно, что писал его человек, не очень ориентирующийся в программировании вообще и в Ардуино в частности. Я бы не рискнул использовать его в исходном виде.

 

Dok321, по поводу "ничего не получилось".  Обратите внимание на строки 29-39 по тому же посту 12. Это - настроечные коэффициенты. Автор явно настраивал их индивидуально под каждый пэд. А теперь представьте себя на его месте: Вы знаете, что эти коэффициенты настроены конкретно под Ваши пэды и ни под какие другие не подойдут, что Вы будете делать в случае публикации? Праильно, Вы перед публикацией приведете их к некоторому сренему. Что мы и наблюдаем в исходнике. 

Если бы для всех подходил один настроечный коэффициент, автор не стал бы использовать их индивидуально для каждого свой, а ввел бы один на все. И, кстати, даже это не гарантировало бы повторяемость конструкции, т.к. у Вас технология изготовления пэдов может быть другая и Вам (даже единственный) коэффициент нужно использовать свой.

В общем, без настройки это не заработает. Хотя бы потому, что указанные настроечные коэффициенты - далеко не все настройки, которые могут понадобиться. Есть такое подозрение, что все цифры в строках 68-71 тоже требуют настройки.

Ну и некоторые замеченные ошибки:

в строке 249 делается проверка. Проверка обоснованная, только ее надо делать не здесь, а гораздо раньше - в строке 150, т.к. там может произойти даже не насыщенгие, а гораздо хуже, - потеря старших разрядов. И вообще в этом месте бы был уместен индивидуальный коэффициент масштабирования.

строки 104-109 не нужны, стандарт Си обязывает обнулить глобальные переменные перед использованием.

строки 116-138 следовало бы заменить инициализацией массивов при их описании.

ввести любые номера пинов (не обязательно последовательные) можно путем введения дополнительного массива и небольшой правки строки 150.

период оцифровки не задается жестко, а сделан "как получится", это не очень хорошо само по себе, но еще и приводит к тому, что при изменении количества пэдов, так и при замене контроллера (например с Uno на Leonardo)

millis() - не очень удачное решение, т.к. в исходнике оцифровка должна происходить с шагом около 1 мс, а в millis() эти мс "шагают" не регулярно.

/*
 * Copyright (c) 2015 Evan Kale
 * Email: EvanKale91@gmail.com
 * Website: www.ISeeDeadPixel.com
 *          www.evankale.blogspot.ca
 *
 * This file is part of ArduinoMidiDrums.
 *
 * ArduinoMidiDrums is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

//Piezo defines
#define NUM_PIEZOS 7
//#define SNARE_THRESHOLD 18     //anything < TRIGGER_THRESHOLD is treated as 0 (Настроичные коэффициенты)
#define LTOM_THRESHOLD 18
#define RTOM_THRESHOLD 18
#define LCYM_THRESHOLD 18
#define RCYM_THRESHOLD 18
#define KICK_THRESHOLD 18
#define KICK_THRESHOLD 18
#define START_SLOT 0     //first analog slot of piezos

//MIDI note defines for each trigger
#define SNARE_NOTE 39
#define LTOM_NOTE 71
#define RTOM_NOTE 65
#define LCYM_NOTE 50
#define RCYM_NOTE 79
#define KICK_NOTE 36
#define KICK_NOTE 36

#define PEDAL_NOTE 57

//MIDI defines
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127

//MIDI baud rate
#define SERIAL_RATE 9600

//Program defines
//ALL TIME MEASURED IN MILLISECONDS       
//(Возможно также требуется настройка) 
#define SIGNAL_BUFFER_SIZE 100                       
#define PEAK_BUFFER_SIZE 30
#define MAX_TIME_BETWEEN_PEAKS 20
#define MIN_TIME_BETWEEN_NOTES 50

//map that holds the mux slots of the piezos
unsigned short slotMap[NUM_PIEZOS];

//map that holds the respective note to each piezo
unsigned short noteMap[NUM_PIEZOS];

//map that holds the respective threshold to each piezo
unsigned short thresholdMap[NUM_PIEZOS];

//Ring buffers to store analog signal and peaks
short currentSignalIndex[NUM_PIEZOS];
short currentPeakIndex[NUM_PIEZOS];
unsigned short signalBuffer[NUM_PIEZOS][SIGNAL_BUFFER_SIZE];
unsigned short peakBuffer[NUM_PIEZOS][PEAK_BUFFER_SIZE];

boolean noteReady[NUM_PIEZOS];
unsigned short noteReadyVelocity[NUM_PIEZOS];
boolean isLastPeakZeroed[NUM_PIEZOS];

unsigned long lastPeakTime[NUM_PIEZOS];
unsigned long lastNoteTime[NUM_PIEZOS];

int pedalPin = 2;

void setup()
{
  Serial.begin(SERIAL_RATE);
  
  //initialize globals
  for(short i=0; i<NUM_PIEZOS; ++i)
  {
    isLastPeakZeroed[i] = true;
    lastPeakTime[i] = 0;
    lastNoteTime[i] = 0;    
    slotMap[i] = START_SLOT + i;
  }

  thresholdMap[0] = LCYM_THRESHOLD;
  thresholdMap[1] = SNARE_THRESHOLD;
  thresholdMap[2] = LTOM_THRESHOLD;
  thresholdMap[3] = RTOM_THRESHOLD;
  thresholdMap[4] = RCYM_THRESHOLD;
  thresholdMap[5] = KICK_THRESHOLD;
  thresholdMap[6] = KICK_THRESHOLD;
  
  noteMap[0] = LCYM_NOTE;
  noteMap[1] = SNARE_NOTE;
  noteMap[2] = LTOM_NOTE;
  noteMap[3] = RTOM_NOTE;
  noteMap[4] = RCYM_NOTE;
  noteMap[5] = KICK_NOTE;
  noteMap[6] = KICK_NOTE;

  pinMode(pedalPin, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentTime = millis();
  
  for(short i=0; i<NUM_PIEZOS; ++i)
  {
    //get a new signal from analog read
    {
  if(velocity > MAX_MIDI_VELOCITY)
    velocity = MAX_MIDI_VELOCITY;
  
  midiNoteOn(note, velocity);
  midiNoteOff(note, velocity);
}
    unsigned short newSignal = analogRead(slotMap[i]);
    signalBuffer[i][currentSignalIndex[i]] = newSignal;
    
    //if new signal is 0
    if(newSignal < thresholdMap[i])
    {
      if(!isLastPeakZeroed[i] && (currentTime - lastPeakTime[i]) > MAX_TIME_BETWEEN_PEAKS)
      {
        recordNewPeak(i,0);
      }
      else
      {
        //get previous signal
        short prevSignalIndex = currentSignalIndex[i]-1;
        if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;        
        unsigned short prevSignal = signalBuffer[i][prevSignalIndex];
        
        unsigned short newPeak = 0;
        
        //find the wave peak if previous signal was not 0 by going
        //through previous signal values until another 0 is reached
        while(prevSignal >= thresholdMap[i])
        {
          if(signalBuffer[i][prevSignalIndex] > newPeak)
          {
            newPeak = signalBuffer[i][prevSignalIndex];        
          }
          
          //decrement previous signal index, and get previous signal
          prevSignalIndex--;
          if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;
          prevSignal = signalBuffer[i][prevSignalIndex];
        }
        
        if(newPeak > 0)
        {
          recordNewPeak(i, newPeak);
        }
      }
  
    }
        
    currentSignalIndex[i]++;
    if(currentSignalIndex[i] == SIGNAL_BUFFER_SIZE) currentSignalIndex[i] = 0;
  }

  int pedalValue = digitalRead(pedalPin);
  if (pedalValue == LOW){
    // If pedal pushed
    noteMap[0] = LCYM_NOTE;
  } else {
    // Otherwise
    noteMap[0] = PEDAL_NOTE;
  }
}

void recordNewPeak(short slot, short newPeak)
{
  isLastPeakZeroed[slot] = (newPeak == 0);
  
  unsigned long currentTime = millis();
  lastPeakTime[slot] = currentTime;
  
  //new peak recorded (newPeak)
  peakBuffer[slot][currentPeakIndex[slot]] = newPeak;
  
  //1 of 3 cases can happen:
  // 1) note ready - if new peak >= previous peak
  // 2) note fire - if new peak < previous peak and previous peak was a note ready
  // 3) no note - if new peak < previous peak and previous peak was NOT note ready
  
  //get previous peak
  short prevPeakIndex = currentPeakIndex[slot]-1;
  if(prevPeakIndex < 0) prevPeakIndex = PEAK_BUFFER_SIZE-1;        
  unsigned short prevPeak = peakBuffer[slot][prevPeakIndex];
   
  if(newPeak > prevPeak && (currentTime - lastNoteTime[slot])>MIN_TIME_BETWEEN_NOTES)
  {
    noteReady[slot] = true;
    if(newPeak > noteReadyVelocity[slot])
      noteReadyVelocity[slot] = newPeak;
  }
  else if(newPeak < prevPeak && noteReady[slot])
  {
    if (slot !=5)
      noteFire(noteMap[slot], noteReadyVelocity[slot]);
    else
      noteFire(noteMap[slot], 90);
    noteReady[slot] = false;
    noteReadyVelocity[slot] = 0;
    lastNoteTime[slot] = currentTime;
  }
  
  currentPeakIndex[slot]++;
  if(currentPeakIndex[slot] == PEAK_BUFFER_SIZE) currentPeakIndex[slot] = 0;  
}

void noteFire(unsigned short note, unsigned short velocity)
{
  if(velocity > MAX_MIDI_VELOCITY)
    velocity = MAX_MIDI_VELOCITY;
  
  midiNoteOn(note, velocity);
  midiNoteOff(note, velocity);
}

void midiNoteOn(byte note, byte midiVelocity)
{
  Serial.write(NOTE_ON_CMD);
  Serial.write(note);
  Serial.write(midiVelocity);
  //Serial.println((int)midiVelocity);
}

void midiNoteOff(byte note, byte midiVelocity)
{
  Serial.write(NOTE_OFF_CMD);
  Serial.write(note);
  Serial.write(midiVelocity);
}

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

P.S. От идеи кардана решил откзаться, чтобы использовать вторую педаль в качестве педали хай хэта, поэтому барабанов 7.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Dok321, Вы тут несколько дней не появлялись и я уже решил, что либо Вы потухли с проектом, либо с кем-то договорились в разделе "Ищу исполнителя".

Собственно, одно из моих увлечений - конструирование электромузыкальных инструментов, и как раз на прошлой неделе я закончил предыдущий проект. Ну а пьезодатчиками я уже давно запасся именно с рачтетом на имитатор ударной установки.

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

с DIN5 MIDI: https://www.audiomania.ru/electronic_drum_set/alesis/alesis_percussion_pad.html

c USB MIDI: https://www.audiomania.ru/electronic_drum_set/alesis/alesis_compactkit_7.html

ну а среди профессиональной аппаратуры выбор еще шире.

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

Кстати, я так и не понял, у Вас хоть какой-то вариант, не важно, с 6, 8, 10 или 16 "барабанами" заработал?

 

Но вообще, если мы с Вами решим повзаимодействовать, то хочу предупредить сразу - это будет не очень быстро.

Тот проект, что Вы выложили, сделан азиатским блогером. Потом чуть-чуть адаптирован русскоязычным пользователем (добавлена 1 кнопка). Тут как-то в обсуждении одного из проектов проскальзывала разница медлу программистом и блогером.

В общем, посмотрите на мой последний проект: http://arduino.ru/forum/proekty/konstruktsiya-vykhodnogo-dnya-prostoi-spektranalizator-480-polos-60-db-na-stm32f103-i-

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

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

Датчики пока планирую делать примерно как в русскоязычной статье: оргстекло с приклеенным датчиком с одной стороны и резиной - с другой. Если у Вас есть другие идеи по изготовлениюб датчиков, опишите их возможно более детально, тогда я, возможно, предпочту воспользоваться вашим вариантом.

Dok321
Offline
Зарегистрирован: 26.10.2018

Привет, опробывать даже оргигинальный скетч пока не получается, потому что при загрузке на ардуинку выдается ошибка и я пока ума не приложу что с этим делать, потому что никакой конкретной ошибки он не выдает, пишет только "Ошибка при загрузке скетча".

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Пробовал только компилировать, ошибок не было

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Dok321 пишет:

Привет, опробывать даже оргигинальный скетч пока не получается, потому что при загрузке на ардуинку выдается ошибка и я пока ума не приложу что с этим делать, потому что никакой конкретной ошибки он не выдает, пишет только "Ошибка при загрузке скетча".

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

1. Делает 10 попыток залить скетч? Если "да" - это самая неприятная ошибка, которая говорит о том, что есть какая-то неисправность, которую нельзя точно идентифицировать. Если "нет" - внимательно проверьте, правильно ли Вы выбрали тип контроллера.

2. На фото все черное - ничего не видно. Можете найти в И-нете аналогичный контейнер и дать ссылку?

Dok321
Offline
Зарегистрирован: 26.10.2018

andriano пишет:

Dok321 пишет:

Привет, опробывать даже оргигинальный скетч пока не получается, потому что при загрузке на ардуинку выдается ошибка и я пока ума не приложу что с этим делать, потому что никакой конкретной ошибки он не выдает, пишет только "Ошибка при загрузке скетча".

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

1. Делает 10 попыток залить скетч? Если "да" - это самая неприятная ошибка, которая говорит о том, что есть какая-то неисправность, которую нельзя точно идентифицировать. Если "нет" - внимательно проверьте, правильно ли Вы выбрали тип контроллера.

2. На фото все черное - ничего не видно. Можете найти в И-нете аналогичный контейнер и дать ссылку?

1. Да, сколько не пытался загрузить выдает либо "Ошибка при загрузке скетча" или "exit status 1", при чем даже при загрузке пустого скетча. Пробывал с двух компьютеров, на которые сам устанавливал среду Ардуино, везде ошибка, потом попробывал загрузить с компа друга, на котором среда установлена давно и вот на нем все нормально загрузилось.

2. Вот такой вот контейнер, а черные они потому что я их покрасил для красоты.

http://upacktorg.ru/katalog-tovara/upakovka_tara/banki_vedra_pishhevye/banki/product/view/739/15079.html

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

1. Если работает на "старой" среде и не работает на "новой", вероятнее всего, что в старой есть что-то, что по умолчанию отсутствует. Например, драйвера конкретного чипа последовательного порта. Но, если я правильно понял, плату один раз все-таки удалось прошить. С барабанами это работает?

2. Мне почему-то такие не попадались. Но сегодня-завтра еще посмотрю. Судя по цене, там должен быть довольно тонкий пластик, Вы считаете, он обладает достаточной прочностью? И еще: насколько я понял, на крышке имеется кольцевой выступ, как в этм случае приклеивать резину? Ну и вообще распишите поподробнее что, куда (в какое место крышки) и чем клеили.

Dok321
Offline
Зарегистрирован: 26.10.2018

1. Когда первые разы пытался загрузить скетч, один раз у меня получилось, но ничего не заработало, даже когда я подключил просто пьезодатчик без пэда. Сейчас на плате этого скетча нет, потому что у друга на его компьютере я загружал сторонний скетч.
2. Пластик там действительно тонкий, но у меня была очень толстая резина, так что мне это не помешало. Кольцевой выступ не мешает, кроме небольшой выпуклости, которая остаётся после отливки, но я просто спилил ее надфилем. Из резины вырезал круги и приклеил просто на крышку с внешней стороны. Клеил моментом универсальным, в 150 мм тюбике

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Очень похожи на контейнеры из под селёдки (Магнит)

Dok321
Offline
Зарегистрирован: 26.10.2018

Да, они такие же, только побольше

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Объехал магазины, купил палочки, аналогичный контейнер найти не удалось.

Думаю, дальнейшее обсуждение целесообразно перенести в раздел "Проекты". http://arduino.ru/forum/proekty/midi-drums