صنع لوحة مفاتيح MIDI من مركب أطفال قديم

صورة

ذات يوم ، عندما عدت إلى المنزل ، بالقرب من شلال القمامة في المدخل ، رأيت مُركِّب لعب أطفال قديم. مرت ، لأنه كان من "الخطيئة" أخذه من القمامة ، ولكن في قلبي أردت سحبه من هناك. في وقت متأخر من الليل ، في حوالي الساعة 2 ، قررت أن أرى ما إذا كانت لا تزال واقفة هناك. ونعم ، كانت لا تزال هناك! في المظهر ، كانت كاملة ونظيفة تمامًا ، لذلك لم يكن هناك أي شفقة حتى لا تأخذها. لذا نعم ، لقد أخذتها.

لطالما كنت أرغب في العزف على البيانو ، لست موسيقيًا محترفًا ، ولكن فقط لأستمتع - لماذا لا؟ شراء شيء "من أجل التدليل" كنت "خنقا من الضفدع" ، وهنا - لعبة مجانية. عندما أخذتها من سلة المهملات ، لم أفكر حتى في استخدامها كلعبة أطفال ، فكرت على الفور: "Ohhhh ... قاعدة جيدة لمحاولة إنشاء لوحة مفاتيح MIDI".
نظرًا لأن لدي بالفعل بعض الخبرة في التواصل مع لوحات المفاتيح الاحترافية ولوحات المفاتيح MIDI ، فقد فهمت على الفور جميع عيوب فكرتي. أي أن اللعبة في الواقع ستظل لعبة. على أساس ذلك ، سيكون من المستحيل تحقيق قوة ضغطات المفاتيح. إن المفاتيح البلاستيكية "خفيفة الوزن" نفسها ، والتي هي أيضًا غير مكتملة ، لن تجعل من الممكن القيام بشيء يستحق ذلك.

بادئ ذي بدء ، تم تفكيك جهاز مزج الألعاب "إلى المسمار" ، وتم غسل كل البلاستيك جيدًا بالصابون. كما يتم تنظيف الألواح ومجموعات مفاتيح الاتصال.

بعد التفكيك ، جاء تفهم سبب رمي الناس له. لعبة (لا أعرف السبب: من وقت لآخر ، من جودة المكونات الصينية أو التشغيل الصعب) أولاً: السماعات المدمجة تنهار ، وثانيًا: موصل مكسور منهم عالق في مقبس سماعة الرأس ، لذلك لم يكن هناك أي طريقة عمليًا لسحبها للخارج . على الأرجح ، بعد أن توقفت اللعبة عن اللعب بمكبرات الصوت المدمجة ، استخدموها مع سماعات الرأس ، وبعد أن كسروا الموصل هناك ، قاموا برميها بعيدًا.

في الداخل ، يتكون مُركب الألعاب من ثلاث ألواح مترابطة بحلقة كبل. المجلس المركزي ، الذي كان مسؤولاً عن توليد الصوت وأشياء أخرى ، تم فصله على الفور من اللوحين الآخرين وتم وضعه جانباً. على اللوحين الآخرين كانت هناك اتصالات للأزرار الموجودة على اللوحة الأمامية للعبة ومفاتيح البيانو نفسها. لقد قمت بلحام موصلات PBS لهم ، خاصة وأن طبقة الثقب على الألواح كانت 2.54 ملم فقط.





بعد ذلك ، قضيت بضع ساعات في رسم الرسوم البيانية لهذه اللوحات باستخدام المفاتيح. كما اتضح ، فإن المخطط عبارة عن لوحة مفاتيح مصفوفة بسيطة.



في الصورة في دوائر صفراء ، الأرقام هي أرقام جهات الاتصال "الأفقية" ، والأرقام الموجودة على المفاتيح هي أرقام جهات الاتصال "الرأسية" في موصل PBS-13 على لوحة المفاتيح.







بعد ذلك ، تم إلقاء كل هذا في زاوية وغبار لمدة عام. ثم بدأت فترة العزلة الذاتية ... أصبحت مملة وأردت أن أفعل شيئًا بيدي ، خاصةً لأنه لا يوجد مكان أذهب إليه ، وهو أمر مستحيل ...

في النهاية ، قررت أن أحاول إنهاء هذه اللعبة على الأقل قليلاً. تم أخذ لوحة Arduino كأساس لجهاز التحكم ، وبما أن عدد سلاسل المفاتيح أكبر من عدد دبابيس Arduino UNO ، فقد قررت استخدام سجلات التحول 74HC595 و 74HC165. ونتيجة لذلك ، حصلنا على مثل هذا المخطط.



تم تجميع الدائرة في الأصل على لوحة توصيل بدون لحام. لاختبار قابلية تشغيل الدائرة (أنه لا توجد أخطاء في التوصيلات في أي مكان) ، تم تطوير برنامج اختبار أظهر أن كل شيء يبدو جيدًا. كانت خوارزمية برنامج الاختبار بسيطة: يتم تشغيل أحد مخرجات رقاقة إخراج التحول ويتم قراءة القيم في دورة من شريحة إدخال التحول ، مع الضغط على المفاتيح. للوهلة الأولى ، لم يكن هناك ما ينذر بالمشاكل ... وبدا كل شيء على ما يرام ...



في الأيام القليلة التالية ، عملت ببطء على "الواجبات المنزلية" ، أي لحام جميع مكونات اللوحة بعناية على لوح توصيل. جمعت كل شيء مما كان في مكاني. تولى Arduino NANO كلوحة تحكم.



يرجع هذا "السندويتش" من الألواح إلى حقيقة أن لوحتي اللعبة (واحدة بأزرار والأخرى مع لوحة المفاتيح) تقعان على مستويات مختلفة ، وقبل أن ألحمها كلها فكرت: "هل من الممكن توصيلها معًا بطريقة ما باستخدام المكونات الموجودة في المنزل لتبدو جيدة أو أقل؟ " وهكذا اتضح هذا التصميم للوحين مترابطين بواسطة الموصلات. من وجهة نظري ، بالنسبة لخيار المنزل ، عندما نجلس في عزلة ذاتية ، اتضح أنه جيد جدًا. كل ما كان علي فعله هو قطع اللوح وتعديل جسم اللعبة بشكل طفيف حتى تتمكن من توصيل كابل USB بلوحة Arduino.



جاء الإدراك بأن الجهاز لا يعمل تمامًا كما أردت عندما أنهيت برنامج الاختبار. كانت الخوارزمية بسيطة: قم بتشغيل كل ناتج من رقاقة 74HC595 ، مع مراعاة حالة مدخلات رقاقة 74HC165 ، وكتابة النتيجة في متغيرات منفصلة. في المجموع ، يتم توصيل 5 مخرجات من 74HC595 بلوحة المفاتيح ، لذلك في النهاية حصلت على 40 بت (5 * 8) من البيانات بعد هذا الاستطلاع. تم إخراج سلسلة من 40 بت إلى وحدة التحكم ، وتم الضغط على المفاتيح لمعرفة كيفية تعامل الجهاز مع ضغطات المفاتيح المتزامنة لعدة مفاتيح.



هذا هو المكان الذي ظهرت فيه المشكلة: إذا ضغطت على مفتاح واحد ، كان كل شيء على ما يرام ، ولكن عند محاولة الضغط على أكثر من مفتاحين في نفس الوقت ، ظهر موقف عندما كان من المستحيل التنبؤ بما سيتم قراءته. يمكن أن تكون النتيجة صحيحة مع مجموعة واحدة ، ومع مجموعة أخرى يمكن أن تكون غير متوقعة تمامًا. كانت المشكلة أن ميزة هذا المخطط لم تؤخذ بعين الاعتبار. عندما يتم الضغط على العديد من المفاتيح في نفس الوقت ، لا يتم فقط قفل العديد من القطاعات الرأسية لمسح لوحة المفاتيح (وهذا أمر مقبول) ، ولكن يمكن إغلاق العديد من الخطوط الأفقية من خلال المفاتيح (وهو أمر غير مقبول على الإطلاق). يمكنك قراءة المزيد عن هذه المشكلة وكيفية حلها هنا.

اخترت "الحل الأساسي" للمشكلة ، وهو: قررت أنه سيكون هناك صمام ثنائي لكل مفتاح في لوحة المفاتيح.

في رأسي ، بدأت بالفعل في التفكير عقليًا كيف سأضطر إلى قطع المسارات على اللوحة ووضع الصمام الثنائي في حالة SMD في الفجوة. تسلقت إلى غرف التخزين الخاصة بي ورأيت أنني ببساطة لم يكن لدي الكثير من الثنائيات في حالة SMD (لا تنس أن كلنا نجلس على العزلة الذاتية والذهاب إلى المتجر لمكونات الراديو غير ممكن - لأن هذه بالتأكيد ليست سلعًا أساسية). منزعج قليلاً ، قررت أن ألقي نظرة عن كثب على اللوحة: قد يكون من الممكن وضع الثنائيات الناتجة على بعض المسارات (لدي أيضًا بعض منها). ثم رأيت أن كل مفتاح يحتوي على وصلة مرور (اللوحة أحادية الجانب) والدائرة مصنوعة بحيث أنه بدلاً من هذا الطائر يمكنك وضع الصمام الثنائي. فكرت على الفور - ليس عليك حتى قطع أي شيء ، عليك فقط وضع الثنائيات الناتجة بدلاً من الوثب في كل مكان.كما لم يكن لدي هذا العدد من الثنائيات الإخراج. تومض فكر في رأسي: "ربما مصابيح LED؟" تعمل الدائرة عند +5 فولت ، وإذا قمت بوضع مصابيح LED حمراء بها حد أدنى من انخفاض الجهد (من بين مصابيح LED) ، فيجب أن يكون هناك في النهاية مستوى منطقي للتحديد الصحيح: يتم الضغط على المفتاح أم لا.



مع وضع ذلك في الاعتبار ، صعدت إلى الأسهم الخاصة بي مرة أخرى وأمسكت مصابيح LED الحمراء من أي مكان ممكن. كان هناك بالضبط عدد المفاتيح الموجودة على لوحة المفاتيح! هذه علامة ، كما أعتقد ، ملحومة بالعديد من مصابيح LED بدلاً من وصلات العبور للاختبار. أظهرت نتائج الاختبار أن الحل يعمل. بعد ذلك ، قمت بلحام مؤشرات LED المتبقية بدلاً من وصلات العبور. أظهر برنامج الاختبار أنه يمكنك الضغط على جميع المفاتيح على الأقل في نفس الوقت ، وتتم قراءتها جميعًا بشكل صحيح.



قررت عدم وضع الثنائيات على الأزرار الإضافية الموجودة في اللعبة ، لأنه من غير المحتمل أن يتم الضغط عليها بعدة قطع في وقت واحد. علاوة على ذلك ، في البرنامج ليس لدي معالجة للنقر على هذه الأزرار. حسنًا ، لم أقرر بعد كيفية استخدامها.

لقد حان الوقت لمعرفة كيفية جعل هذا الجهاز يظهر على جهاز الكمبيوتر الخاص بك كلوحة مفاتيح MIDI وبالتنسيق الذي تحتاجه لإرسال البيانات.

أخبرتني المعلومات الموجودة على الإنترنت أنه من الممكن إنشاء لوحة مفاتيح MIDI من Arduino بسهولة شديدة وببساطة عن طريق صب البرامج الثابتة فيها ، مما يجعل الكمبيوتر يراها ليس كمنفذ COM ، ولكن كلوحة مفاتيح MIDI. في البداية ، استرشدت بهذا القرار ، ولا أخوض بشكل خاص في كيفية تنفيذه.

الآن ، عندما وصلت إليه وقرأته بعناية ، أدركت أن لوحة Arduino NANO الخاصة بي لن تكون مناسبة لهذا الحل ، نظرًا لأنه يحتوي على منفذ COM يعتمد على شريحة CH340. لاستخدام البرامج الثابتة من الرابط أعلاه ، تكون هذه البطاقات فقط مناسبة حيث يكون منفذ USB موجودًا بالفعل على وحدة التحكم (على سبيل المثال: AtMega32u4) أو لم يتم الاتصال عبر منفذ COM على رقائق التحويل من نوع FT232RL أو ما شابه ، ولكن على وحدات التحكم الدقيقة AtMega. لذلك ، يجب أن ترسل البرامج الثابتة في اللوحة البيانات بتنسيق MIDI إلى منفذ COM ، وعلى جهاز الكمبيوتر ، سيتعين عليك تثبيت وتكوين البرامج التي تعترض هذه البيانات ونقلها إلى منفذ MIDI الظاهري.
كانت خوارزمية قراءة المفاتيح وإنشاء أوامر MIDI كما يلي:



يبدو برنامج وحدة تحكم Arduino NANO الآن على هذا النحو.
//    +5V
//   ST_CP  74HC595
#define latchPin      11
//   SH_CP  74HC595
#define clockPin      13
//   DS  74HC595
#define dataPin       12

//     +5V
#define latchPin_IN   9
#define clockPin_IN   10
#define dataPin_IN    8

// ,       1-16    
#define BUT_OUT0      7
#define BUT_OUT1      6
#define BUT_OUT2      5
#define BUT_OUT3      4

byte but_out[4] = {BUT_OUT0, BUT_OUT1, BUT_OUT2, BUT_OUT3};
//       
byte kbd_in[5] = {0, 0, 0, 0, 0};
byte kbd_in_new[5] = {0, 0, 0, 0, 0};

//       
byte btn_in[4] = {0, 0, 0, 0};
byte btn_in_new[4] = {0, 0, 0, 0};

//  3  -   (1 - , 0 - )
byte kbd_out = 0b11100000;

//  
void init_electronics() {
  //  ,   +5V
  //  OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  //  ,   +5V
  pinMode(latchPin_IN, OUTPUT);
  pinMode(clockPin_IN, OUTPUT);
  pinMode(dataPin_IN, INPUT);

  //          
  for (byte i = 0; i < 4; i++) pinMode(but_out[i], OUTPUT);
}

//      74HC595
void write_5V(byte a) {
    digitalWrite(latchPin, LOW);
    //    dataPin
    shiftOut(dataPin, clockPin, MSBFIRST, a); 
     //"" ,      
    digitalWrite(latchPin, HIGH); 
}

void read_5V(byte *btn, byte *kbd) {
  digitalWrite(clockPin_IN, HIGH);
  digitalWrite(latchPin_IN, LOW);
  digitalWrite(latchPin_IN, HIGH);
  
  //    -    
  *btn = shiftIn(dataPin_IN, clockPin_IN, LSBFIRST);
  
  //    -    
  *kbd = shiftIn(dataPin_IN, clockPin_IN, LSBFIRST);
}

void setup() {
  init_electronics();
  write_5V(kbd_out);
  Serial.begin(115200);
}

//       ,   
void read_kbd_and_btn_state(byte *btn, byte *kbd) {
 byte tmp;
  for (byte i = 0; i < 5; i++) {
    write_5V(kbd_out | (1 << i));
    read_5V(&tmp, &kbd[i]);
  }
}

void noteOn(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}

//     num  ,   
// 0 -  0,  0
// 1 -  0,  1
// 2 -  1,  1
// 3 -  1,  0
byte compare_bit(byte old_state, byte new_state, byte num) {
  byte tmp_old, tmp_new;
  tmp_old = (old_state >> num) & 1;
  tmp_new = (new_state >> num) & 1;
  if ((tmp_old == 0) && (tmp_new == 0)) return 0;
  if ((tmp_old == 0) && (tmp_new == 1)) return 1;
  if ((tmp_old == 1) && (tmp_new == 1)) return 2; 
  if ((tmp_old == 1) && (tmp_new == 0)) return 3;  
}

void loop() {
  read_kbd_and_btn_state(btn_in_new, kbd_in_new);
  for (byte i = 0; i < 5; i++) {
    for (byte j = 0; j < 8; j++) {
      switch (compare_bit(kbd_in[i], kbd_in_new[i], 7 - j)) {
        //  
        case 1: noteOn(0x90, 0x1D + (8 * i + j), 0x7F);
                break;
        //  
        case 2: //noteOn(0x00, 0x1D + (8 * i + j), 0x7F);
                break;
        //  
        case 3: noteOn(0x90, 0x1D + (8 * i + j), 0x00);
                break;
      }
    }
    kbd_in[i] = kbd_in_new[i];
  }
} 


ليس من المنطقي أن ترسم بالتفصيل كيفية العمل مع بيانات MIDI ، لأنه يمكن قراءتها هنا.

سوف أسهب في مزيد من التفاصيل حول برنامج الكمبيوتر والمشاكل التي واجهتها. نشأت مشاكل ، وذلك ببساطة بسبب عدم وجود وثائق عادية لهذا البرنامج. لذلك ، حتى يتمكن الكمبيوتر من استقبال بيانات MIDI بنجاح من جهاز مثل الجهاز الخاص بي ، ستحتاج إلى برنامجين: loopMIDI و Serial-Midi Converter . بالنسبة إلى Serial-MIDI Converter ، تحتاج أيضًا إلى تثبيت Java إذا لم يكن مثبتًا على جهاز الكمبيوتر.

نبدأ برنامج loopMIDI وننشئ منفذين افتراضيين. اتصلت بهم Arduino IN و Arduino OUT. سيكون هذا البرنامج عبارة عن جهاز MIDI افتراضي.



بعد ذلك ، قم بتشغيل Serial-MIDI Converter وعند بدء التشغيل ، نبدأ في عملية إعداده. لسوء الحظ ، يجب عليك القيام بذلك في كل مرة تبدأ فيها ، ولكنها ليست مخيفة للغاية ، ويتم ذلك حرفياً في أربعة ضغطات على لوحة المفاتيح. قد يكون رقم منفذ COM مختلفًا ؛ يظهر على الكمبيوتر عند توصيل لوحة Arduino NANO. يتم تعيين سرعة المنفذ في البرامج الثابتة Arduino NANO. تشير الأسهم الحمراء إلى الإعدادات الخاصة بي ، والتي يعمل فيها كل شيء بالنسبة لي.



في الواقع ، تم الانتهاء من عملية الإعداد ويمكنك بالفعل استخدام بعض البرامج التي ستقوم بتشغيل الأصوات عن طريق قبول ضغطات المفاتيح من الجهاز. في إعدادات البرنامج ، يجب عليك تحديد "Arduino_OUT" كمدخل. في الصورة أدناه ، مثال على تكوين Kontakt Player.



يعمل في النهاية مثل هذا:


ماذا بعد؟ ثم حدث كل شيء تمامًا كما توقعت - تظل اللعبة لعبة مع جميع أوجه القصور التي ذكرتها في البداية. على الأرجح ، سيلعب الطفل هذه اللعبة في ضجة ، ولكن بالنسبة للبالغين ، بعد لوحات المفاتيح العادية ... من الأسهل شراء أي لوحة مفاتيح MIDI مستخدمة بسعر رخيص وسيكون أفضل بكثير من هذه اللعبة. قررت ترك هذه اللعبة كما هي ، لكنني أجري بعض التعديلات عليها:

  1. اترك الحالة الأصلية.
  2. ضع مكبرات صوت عاملة وقم بعمل مضخم لهم.
  3. اجعلها تعمل في وضع "لعبة الأطفال" دون الاتصال بجهاز كمبيوتر ، أي حتى يمكنها تشغيل الأصوات نفسها.
  4. اجعل من الممكن توصيل FootSwitch (نفس الدواسة على البيانو أدناه) حتى تتمكن من الإمساك بالصوت بعد تحرير المفاتيح ، كما هو الحال في الآلات العادية.
  5. , .
  6. , -, .



لا يمكنني تنفيذ معظم النقاط ، بينما نحن جميعًا معًا "في المنزل" ، لأنني لا أملك جميع المكونات المطلوبة لذلك في المنزل.

لتنفيذ الفقرة 3 على الإنترنت ، تم العثور على حل يسمى SamplerBox . جوهر المشروع هو أنه يمكنك توصيل أي لوحة مفاتيح MIDI بلوحة Raspberry Pi ، التي تعالج أوامر MIDI من لوحة المفاتيح وتقوم بتشغيل الأصوات أو تبديل الأدوات ، إلخ. يبقى فقط وضع لوحة Raspberry Pi داخل جسم اللعبة ، دون إمكانية استبدال بطاقة SD (بدون تفكيك العلبة) ، وتكوين الأزرار الموجودة على جسم اللعبة حتى يتم تبديل الأدوات وهذا سيكون كافيًا لترك هذا المشروع في هذا الشكل.

لكن كل هذا سيحدث بعد انتهاء فترة العزلة الذاتية.

آمل أن يجد شخص ما تجربتي مفيدة.

All Articles