wzqhby 发表于 2017-3-16 20:54:37

自制玩具launchpad(arduino)。

本帖最后由 wzqhby 于 2017-8-1 11:57 编辑

//MIDI jianpan.ino

/*
模拟launchpad打击垫
1.矩阵按键为9列8行
2.矩阵键盘列线解码芯片74LS138两片或74LS164一片
    或串入并出芯片还可以矩阵键盘专用管理芯片*/
   
/*RGBled为8列8行主要是用来装的,与midi键盘无关*/

#include <MsTimer2.h>         //定时器库的头文件
#include <frequencyToNote.h>
#include <MIDIUSB.h>            //midi库
#include <pitchToNote.h>
#include <Adafruit_NeoPixel.h> //RGBled库

#ifdef __AVR__
#include <avr/power.h>
#endif

const byte column_num=9;//column,9列按键,第9列100-103为场景切换
const byte row_num=8;//row,每列8个按键,也可称之为8行。

const byte key_input_pin[]={2,3,4,5,6,7,8,9,10};//按键读取数据端
const byte key_output_pin[]={14,16,10,15};//四根列线,解码可得到16列,用0-9,10列。
const unsigned char midi_key_num[]=
{//按键输出音高数组,不了解查midi资料。
64,60,56,52,48,44,40,36,
65,61,57,53,49,45,41,37,
66,62,58,54,50,46,42,38,
67,63,59,55,51,47,43,39,
96,92,88,84,80,76,72,68,
97,93,89,85,81,77,73,69,
98,94,90,86,82,78,74,70,
99,95,91,87,83,79,75,71,
108,109,110,111,112,113,114,115,
100,101,102,103,104,105,106,107
};

const unsigned char LED_num[]=
{//RGB_led位置地址数组
   0, 1, 2, 3,17,16,15,14,
18,19,20,21,35,34,33,32,
36,37,38,39,53,52,51,50,
54,55,56,57,71,70,69,68,
   4, 5, 6, 7,13,12,11,10,
22,23,24,25,31,30,29,28,
40,41,42,43,49,48,47,46,
58,59,60,61,67,66,65,64,
63,62,45,44,27,26, 9, 8,
72,73,74,75,76,77,78,79,
};

unsigned char ROWS_numr1,ROWS_numr2,ROWS_numr3,ROWS_numr4,ROWS_numr5,ROWS_numr6,ROWS_numr7,ROWS_numr8,ROWS_numr9;
unsigned char ROW_num1,ROW_num2,ROW_num3,ROW_num4,ROW_num5,ROW_num6,ROW_num7,ROW_num8,ROW_num9;
unsigned char ROWS_num[]={ROWS_numr1=0,ROWS_numr2=0,ROWS_numr3=0,ROWS_numr4=0,ROWS_numr5=0,ROWS_numr6=0,ROWS_numr7=0,ROWS_numr8=0,ROWS_numr9=0};
unsigned char ROW_num[]={ROW_num1=0,ROW_num2=0,ROW_num3=0,ROW_num4=0,ROW_num5=0,ROW_num6=0,ROW_num7=0,ROW_num8=0,ROW_num9=0};

unsigned char variable_a=0;
unsigned char key_address;
unsigned char j;
unsigned char header_num=0;
unsigned char header_num11=0;
unsigned char byte_num1=0;
unsigned char byte_num2=0;
unsigned char byte_num3=0;

#define NUMPIXELS      80//有80个LED连接
#define LED_RGB_PIN   18//arduino连接端口18

//int delayval = 500; // delay for half a second
//#define control_pin   1//控制按键引脚

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, LED_RGB_PIN, NEO_GRB + NEO_KHZ800);
//unsigned int LED_color_num[]={(R_n,G_n,B_n)};
unsigned char r_n,g_n,b_n;

const unsigned int LED_color_num1 []=
{//RGB_led颜色库数组。
{0,0,0},{10,10,10},{20,20,20},{50,50,50},{75,50,50},{50,20,20},{20,10,10},{15,10,10},//7
{50,75,50},{20,50,20},{10,20,10},{10,15,10},{50,50,75},{20,20,50},{10,10,20},{10,10,15},//15
{0,0,0},{10,10,10},{20,20,20},{50,50,50},{75,50,50},{50,20,20},{20,10,10},{15,10,10},//23
{50,75,50},{20,50,20},{10,20,10},{10,15,10},{50,50,75},{20,20,50},{10,10,20},{10,10,15},//31
{0,0,0},{10,10,10},{20,20,20},{50,50,50},{75,50,50},{50,20,20},{20,10,10},{15,10,10},//39
{50,75,50},{20,50,20},{10,20,10},{10,15,10},{50,50,75},{20,20,50},{10,10,20},{10,10,15},//47
{0,0,0},{10,10,10},{20,20,20},{50,50,50},{75,50,50},{50,20,20},{20,10,10},{15,10,10},//55
{50,75,50},{20,50,20},{10,20,10},{10,15,10},{50,50,75},{20,20,50},{10,10,20},{10,10,15},//63
{15,10,10},{10,10,10},{20,20,20},{50,50,50},{75,50,50},{50,20,20},{20,10,10},{15,10,10},//71
{50,75,50},{20,50,20},{10,20,10},{10,15,10},{50,50,75},{20,20,50},{10,10,20},{10,10,15},//79
{15,10,10},{10,10,10},{20,20,20},{50,50,50},{75,50,50},{50,20,20},{20,10,10},{15,10,10},//87
{50,75,50},{20,50,20},{10,20,10},{10,15,10},{50,50,75},{20,20,50},{10,10,20},{10,10,15},//95
{20,20,20},{10,10,10},{20,20,20},{50,50,50},{75,50,50},{50,20,20},{20,10,10},{15,10,10},//103
{50,75,50},{20,50,20},{10,20,10},{10,15,10},{50,50,75},{20,20,50},{10,10,20},{10,10,15},//111
{10,20,10},{10,10,10},{20,20,20},{50,50,50},{75,50,50},{50,20,20},{20,10,10},{15,10,10},//119
{50,75,50},{20,50,20},{10,20,10},{10,15,10},{50,50,75},{20,20,50},{10,10,20},{10,10,15},//127
};

/***写事件函数***/
void controlChange(byte channel, byte control, byte value) {
midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
MidiUSB.sendMIDI(event);
}

/***开音符函数***/
void noteOn(byte channel,byte pitch,byte velocity)
{
midiEventPacket_t noteOn={0x09,0x90|channel,pitch,127};
MidiUSB.sendMIDI(noteOn);
}

/***关音符函数***/
void noteOff(byte channel,byte pitch,byte velocity)
{
midiEventPacket_t noteOff={0x08,0x80|channel,pitch,0};
MidiUSB.sendMIDI(noteOff);
}

/*RGBled刷新函数*/
/*Fill the dots one after the other with a color*/
void colorWipe_num(uint32_t c,uint8_t a)
{
strip.setPixelColor(a, c);
strip.show();
}

/*读取midi数据和RGBled颜色读取*/
void midi_led_date(void)
{
midiEventPacket_t rx;
do
{
    rx = MidiUSB.read();
    if (rx.header != 0)
    {
      header_num=rx.header;
      byte_num1=rx.byte1;
      byte_num2=rx.byte2;
      byte_num3=rx.byte3;
      Serial.print("input:");
      Serial.println(byte_num2);
      if(header_num==9)
      {
      r_n = LED_color_num1 ;
      g_n = LED_color_num1 ;
      b_n = LED_color_num1 ;
      colorWipe_num(strip.Color (r_n,g_n,b_n), LED_num); // Red
      }
      if(header_num==8)
      {
      colorWipe_num(strip.Color(0, 0, 0), LED_num); // Red
      }
      header_num11=header_num;
    }
}
while (rx.header != 0);
}

void setup()
{
// This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
MsTimer2::set(40, midi_led_date);    //中断设置函数,每10ms进入一次中断,刷新RGBled
MsTimer2::start();                  //定时中断开始计时
Serial1.end();                      //初始化串口
pinMode(LED_RGB_PIN,OUTPUT);
for(unsigned char i=0;i<4;i++)
{
    pinMode(key_output_pin,OUTPUT);//矩阵按键4列输出线,解码后为16条列线。
}
for(unsigned char i=0;i<8;i++)
{
    pinMode(key_input_pin,INPUT_PULLUP);//每行8个按键读取数据线初始化(上拉输入模式)
}
strip.begin();
strip.show(); // Initialize all pixels to 'off'
Serial.begin(250000);//初始化串口
}

void loop()
{
for(j=0;j<=11;j++)
{
    variable_a=0;
    digitalWrite(key_output_pin, bitRead(j, 0));//列线解码,输出
    digitalWrite(key_output_pin, bitRead(j, 1));
    digitalWrite(key_output_pin, bitRead(j, 2));
    digitalWrite(key_output_pin, bitRead(j, 3));
    for(unsigned char i=0;i<8;i++)
    {
      bitWrite(ROW_num,i,digitalRead(key_input_pin));//读取按键状态数据
    }
    variable_a=ROW_num^ROWS_num;//按键状态数据是否有变化
    if(variable_a!=0)
    {
      delay(10);
      for(unsigned char i=0;i<8;i++)
      {//如果按键有变化延时20毫秒再次读取,消抖。
      bitWrite(ROW_num,i,digitalRead(key_input_pin));
      }
      variable_a=ROW_num^ROWS_num;//按键有变化异或后不等于0
      if(variable_a!=0)
      {
      ROWS_num=ROW_num;
      }
      else
      {
      variable_a=0;
      }
      if(variable_a!=0)
      {
      key_address=1;//键值地址
      for(unsigned char a=0;a<8;a++)//作8次循环, 判断具体产生变化的键
      {
          if((variable_a&key_address)!= 0)//用指针选择被测的键
          {
            if((ROWS_num&key_address)!=0)//判断变化位,以确定是被压下还是释放
            {
            noteOff(0,(midi_key_num),0);
            Serial.print("output:");
            Serial.println(midi_key_num);
            MidiUSB.flush();
            }//关闭声音,键值=i*8+j+addition
            else
            {
            noteOn(0,(midi_key_num),127);
            Serial.print("output:");
            Serial.println(midi_key_num);
            MidiUSB.flush();
            }//开始发声,键值=i*8+j+addition
          }
          key_address=key_address<<1;
      }
      variable_a=0;
      }
    }
}
}http://v.youku.com/v_show/id_XMjYzMTgwNzE3Mg==.html

wzqhby 发表于 2017-3-18 20:56:55

自己占个坑

Ansifa 发表于 2017-3-19 23:10:20

楼主应该是做了一个MP3模块分段播放。。。按一个键播放几秒。。。这板子可是体力活啊

wzqhby 发表于 2017-3-20 19:51:01

本帖最后由 wzqhby 于 2017-3-20 19:55 编辑

Ansifa 发表于 2017-3-19 23:10
楼主应该是做了一个MP3模块分段播放。。。按一个键播放几秒。。。这板子可是体力活啊

感谢回复,这是一个midi键盘加上RGB的LED灯,仿launchpad打击乐器的键盘,是midi键盘,要配合Ableton-live软件一起使用,由于功能简单,所以是个玩具。音乐是通过按键给电脑软件发送mide键值电脑分块播放,但是灯光是电脑软件返回的参数。不是单片机独立运行的。

maxims 发表于 2017-3-28 22:37:12

感觉很不错啊~介绍一下用途?

wzqhby 发表于 2017-3-29 13:53:58

这个玩具功能简单,满足能玩就好,要和音乐编辑软件Ableton Live一起使用,网上好多的lunchpad(一种打击垫键盘,音乐键盘),灯光是RGB的LED,键盘发送到电脑的是MIDI键值,电脑发声并且同步返回的数据,包括灯光开关,颜色和亮度,这个玩具用了RGB库,MIDI库和USB库,都是用的现成库做的,程序不大,就是数组多(颜色数组,亮度数组)。http://abletive.com/这个网站里有原型的东东,功能强大。

maxims 发表于 2017-7-15 00:00:21

wzqhby 发表于 2017-3-29 13:53
这个玩具功能简单,满足能玩就好,要和音乐编辑软件Ableton Live一起使用,网上好多的lunchpad(一种打击垫 ...

你是怎么记得这个pad上的调子?

wzqhby 发表于 2017-7-16 11:46:49

和网上的launchpad一样玩的啊,在网上下载一些工程(launchpad的Ableton Live工程),在电脑里打开,连接usb到电脑,唯一不同的是在软件设置项选择arduino_Leonardo(input/output),然后在工程里也要选择arduino_Leonardo/选择通道,就可以在网上看着视频学习,自己也可以做工程,不过我Ableton Live软件不会,音乐也不好,主要看灯光比较酷试一下,可能会有用到。:)
页: [1]
查看完整版本: 自制玩具launchpad(arduino)。