极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14146|回复: 7

自制玩具launchpad(arduino)。

[复制链接]
发表于 2017-3-16 20:54:37 | 显示全部楼层 |阅读模式
本帖最后由 wzqhby 于 2017-8-1 11:57 编辑
  1. //MIDI jianpan.ino

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

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

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

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

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

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

  47. unsigned char ROWS_numr1,ROWS_numr2,ROWS_numr3,ROWS_numr4,ROWS_numr5,ROWS_numr6,ROWS_numr7,ROWS_numr8,ROWS_numr9;
  48. unsigned char ROW_num1,ROW_num2,ROW_num3,ROW_num4,ROW_num5,ROW_num6,ROW_num7,ROW_num8,ROW_num9;
  49. 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};
  50. 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};

  51. unsigned char variable_a=0;
  52. unsigned char key_address;
  53. unsigned char j;
  54. unsigned char header_num=0;
  55. unsigned char header_num11=0;
  56. unsigned char byte_num1=0;
  57. unsigned char byte_num2=0;
  58. unsigned char byte_num3=0;

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

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

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

  66. const unsigned int LED_color_num1 [][3]=
  67. {//RGB_led颜色库数组。
  68.   {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
  69.   {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
  70.   {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
  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},//31
  72.   {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
  73.   {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
  74.   {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
  75.   {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
  76.   {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
  77.   {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
  78.   {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
  79.   {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
  80.   {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
  81.   {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
  82.   {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
  83.   {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
  84. };

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

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

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

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

  109. /*读取midi数据和RGBled颜色读取*/
  110. void midi_led_date(void)
  111. {
  112.   midiEventPacket_t rx;
  113.   do
  114.   {
  115.     rx = MidiUSB.read();
  116.     if (rx.header != 0)
  117.     {
  118.       header_num=rx.header;
  119.       byte_num1=rx.byte1;
  120.       byte_num2=rx.byte2;
  121.       byte_num3=rx.byte3;
  122.       Serial.print("input:");
  123.       Serial.println(byte_num2);
  124.       if(header_num==9)
  125.       {
  126.         r_n = LED_color_num1 [byte_num3][0];
  127.         g_n = LED_color_num1 [byte_num3][1];
  128.         b_n = LED_color_num1 [byte_num3][2];
  129.         colorWipe_num(strip.Color (r_n,g_n,b_n), LED_num[byte_num2-36]); // Red
  130.       }
  131.       if(header_num==8)
  132.       {
  133.         colorWipe_num(strip.Color(0, 0, 0), LED_num[byte_num2-36]); // Red
  134.       }
  135.       header_num11=header_num;
  136.     }
  137.   }
  138.   while (rx.header != 0);
  139. }

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

  162. void loop()
  163. {
  164.   for(j=0;j<=11;j++)
  165.   {
  166.     variable_a=0;
  167.     digitalWrite(key_output_pin[0], bitRead(j, 0));//列线解码,输出
  168.     digitalWrite(key_output_pin[1], bitRead(j, 1));
  169.     digitalWrite(key_output_pin[2], bitRead(j, 2));
  170.     digitalWrite(key_output_pin[3], bitRead(j, 3));
  171.     for(unsigned char i=0;i<8;i++)
  172.     {
  173.       bitWrite(ROW_num[j],i,digitalRead(key_input_pin[i]));//读取按键状态数据
  174.     }
  175.     variable_a=ROW_num[j]^ROWS_num[j];//按键状态数据是否有变化
  176.     if(variable_a!=0)
  177.     {
  178.       delay(10);
  179.       for(unsigned char i=0;i<8;i++)
  180.       {//如果按键有变化延时20毫秒再次读取,消抖。
  181.         bitWrite(ROW_num[j],i,digitalRead(key_input_pin[i]));
  182.       }
  183.       variable_a=ROW_num[j]^ROWS_num[j];//按键有变化异或后不等于0
  184.       if(variable_a!=0)
  185.       {
  186.         ROWS_num[j]=ROW_num[j];
  187.       }
  188.       else
  189.       {
  190.         variable_a=0;
  191.       }
  192.       if(variable_a!=0)
  193.       {
  194.         key_address=1;//键值地址
  195.         for(unsigned char a=0;a<8;a++)//作8次循环, 判断具体产生变化的键
  196.         {
  197.           if((variable_a&key_address)!= 0)//用指针选择被测的键
  198.           {
  199.             if((ROWS_num[j]&key_address)!=0)//判断变化位,以确定是被压下还是释放
  200.             {
  201.               noteOff(0,(midi_key_num[j*8+a]),0);
  202.               Serial.print("output:");
  203.               Serial.println(midi_key_num[j*8+a]);
  204.               MidiUSB.flush();
  205.             }//关闭声音,键值=i*8+j+addition
  206.             else
  207.             {
  208.               noteOn(0,(midi_key_num[j*8+a]),127);
  209.               Serial.print("output:");
  210.               Serial.println(midi_key_num[j*8+a]);
  211.               MidiUSB.flush();
  212.             }//开始发声,键值=i*8+j+addition
  213.           }
  214.           key_address=key_address<<1;
  215.         }
  216.         variable_a=0;
  217.       }
  218.     }
  219.   }
  220. }
复制代码
回复

使用道具 举报

 楼主| 发表于 2017-3-18 20:56:55 | 显示全部楼层
自己占个坑
回复 支持 反对

使用道具 举报

发表于 2017-3-19 23:10:20 | 显示全部楼层
楼主应该是做了一个MP3模块分段播放。。。按一个键播放几秒。。。这板子可是体力活啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 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键值电脑分块播放,但是灯光是电脑软件返回的参数。不是单片机独立运行的。
回复 支持 反对

使用道具 举报

发表于 2017-3-28 22:37:12 | 显示全部楼层
感觉很不错啊~介绍一下用途?
回复 支持 反对

使用道具 举报

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

使用道具 举报

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

你是怎么记得这个pad上的调子?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-7-16 11:46:49 | 显示全部楼层
和网上的launchpad一样玩的啊,在网上下载一些工程(launchpad的Ableton Live工程),在电脑里打开,连接usb到电脑,唯一不同的是在软件设置项选择arduino_Leonardo(input/output),然后在工程里也要选择arduino_Leonardo/选择通道,就可以在网上看着视频学习,自己也可以做工程,不过我Ableton Live软件不会,音乐也不好,主要看灯光比较酷试一下,可能会有用到。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-23 17:52 , Processed in 0.039497 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表