Hobby Science&Experiment

愛と工作の日々

趣味でやっている工作や勉強したことのメモ書きです。

【Arduino MIDIドラムシーケンサ③】LCD追加とトリムポットでBPM変更

前回作成したドラムシーケンサBPMが固定であったため、BPMをトリムポットによって調整する機能を付けました。またLCD(液晶ディスプレイ)を追加することで現在のBPMを確認できるようにしました。

配線

A0:トリムポット(50kΩ等)
A5:LCD1602のSCL端子
A4:LCD1602のSDA端子
LCD1602には5Vの電源を供給します。写真では関係ないものもブレッドボードに載ってます(^^;)
f:id:tara-chang:20210516115137p:plain

コード

BPMは拍と拍の間のインターバル(delay)で調整します。トリムポットのAnalogRead値(0~1023)をインターバルの値(200ms~1000ms)でmapを使用して規格化しています。

// Arduino MIDI Drum sequencer 
// Sending MIDI messages to the host PC.
// DAW: Waveform Free
//
// Author: Tara-chang
// 
// Revision History:
// Date        |    Author    |  Change
// ---------------------------------------------------
// 2021-05-09  |  Tara-chang  |  Initial Release
// 2021-05-09  |  Tara-chang  |  Added LCD and Trimpot to tempo control 

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include <MIDI.h> 
MIDI_CREATE_DEFAULT_INSTANCE();

#define CRUSH 49 //C#3
#define KICK 36 //C2
#define CLAP 39 //D#2
#define SNARE 38 //D2
#define RIDE 51 //D#3
#define HITOM 50 //D3
#define MIDTOM 48 //C3
#define LOWTOM 45 //A2
#define OPHIHAT 46 //A#2
#define CLHIHAT 42//F#2

int DRUM[] = {SNARE, KICK, CLHIHAT, RIDE};
const byte NUM_DRUM = sizeof(DRUM)/sizeof(DRUM[0]);
const byte NUM_BEAT = 8;
boolean RTM[NUM_DRUM][NUM_BEAT] = {
  {0,0,1,0,0,0,1,0},//SNARE
  {1,1,0,0,1,1,0,0},//KICK
  {1,1,1,1,1,1,1,1},//CLHIHAT
  {1,0,0,0,1,0,0,0}//RIDE
  };
//in order of SNARE, KICK, CLAP, CRUSH
byte nt = 0;
byte in = 0;
int BPM = 0; //X beats/60sec = 60/X sec/beat
int interval = 295;//60/double(BPM)*(NUM_BEAT/4)*1000; // 

boolean changed = 1;
int trimpot = 300;
int now_trimpot = 300;
#define INT_MIN 200
#define INT_MAX 1000
#define TRM_MIN 0 
#define TRM_MAX 1023

void setup()
{   
  Serial.begin(115200);
  MIDI.begin(4); //
  lcd.init();
  lcd.backlight();
  lcd.clear();
  pinMode(0, INPUT);
}

void loop(){

  for (nt = 0; nt < NUM_BEAT; nt++){
    for (in = 0; in < NUM_DRUM; in++){    
      //String text = "(in,nt)=("+String(in)+","+String(nt)+")"+String(RTM[in][nt]);
      
      if (RTM[in][nt]){
      MIDI.sendNoteOn(DRUM[in],127,1);  // (pitch, velocity, channel)         
      MIDI.sendNoteOff(DRUM[in],0,1);   //        
      }
    }
    delay(now_trimpot*(4/double(NUM_BEAT))); 
    }

    now_trimpot = map(analogRead(0), TRM_MAX, TRM_MIN, INT_MAX, INT_MIN);
    if (now_trimpot == trimpot){  
    }
    else{
      trimpot = now_trimpot;
      changed = 1;
      //Serial.println("trimpot changed");
    }         

    if(changed){
        BPM = 1/double(trimpot)*60*1000;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("BPM");
        lcd.setCursor(0, 1);
        lcd.print(BPM);
        changed=0;
    }  

}

動作

課題

・ワンパターンのリズムしか演奏できないのは悲しいので、ボタンで切り替えられるようにしたいと思います。
・トリムポットのAnalogRead値にややふら付きがあるのでここも改善必要です。