Виноградный мультитач

    Наткнулся на интересную штуку под названием MaKey MaKey.

    http://makeymakey.com/

    Вот за что уважаю американцев — так это за талант красиво преподнести и довести до промышленного производства всякую простейшую штуку.



    Посмотрел видео, порадовался за ребят. Но где-то сразу зудеть начало. Полез за резюками. Через 15 минут (из которых пять минут ушло на перекур) получился вот такой девайс:



    UPD>… спустя некоторое время. Новый видеоролик с практическим применением виноградного мультитача :-) Исходник софтинки на C# и нового скетча для ардуины выложены внизу.



    Реализация проста до неприличия. Нужны лишь резисторы номиналом 1-50 Мом (по одному на каждый контакт). Я использовал резюки на 1 Мом, в результате чего засекаются только касания. Если поставить 10Мом и больше — будет срабатывать на расстоянии, бесконтактно.

    В скетче использовал библиотеку CapSense, которая, собссно, всю работу и делает.

    Схема подключения:



    На базе сэмпла набросал простейший скетч

    #include <CapSense.h>

    #define SND_PIN 12 // пин, к которому подключён спикер

    CapSense  key1 = CapSense(7, 5); // клавиша 1 между 7-м и 5-м пинами
    CapSense  key2 = CapSense(7, 4); // клавиша 2 между 7-м и 4-м пинами
    CapSense  key3 = CapSense(7, 3); // клавиша 3 между 7-м и 3-м пинами

    int range = 200; // пороговое значение, определяющее нажатие, подбирается экспериментально
    byte button; // побитовое обозначение нажатых клавиш
    int freq; // частота звука для воспроизведения на спикер

    void setup()          
    {
     // выключает автокалибровку на 1-й клавише.
     // Пока фиг знает зачем, советуют в примерах либы
     key1.set_CS_AutocaL_Millis(0xFFFFFFFF);
    }

    void loop()          
    {
      long total1 = key1.capSense(30);
      long total2 = key2.capSense(30);
      long total3 = key3.capSense(30);

      button = 0;
      if (total1 > range) button |= 1;
      if (total2 > range) button |= 2;
      if (total3 > range) button |= 4;
      
      switch (button) {
       case 1: freq = 200; break;
       case 2: freq = 300; break;
       case 3: freq = 400; break;
       case 4: freq = 500; break;
       case 5: freq = 600; break;
       case 6: freq = 700; break;
       case 7: freq = 800; break;
       default: freq = 0;
      }
      
      freq? tone(SND_PIN, freq) : noTone(SND_PIN); // воспроизводим или останавливаем звук
    }

    * This source code was highlighted with Source Code Highlighter.


    Если прошить нечто типа такого — ардуина с клавишами-виноградинами будет в роли HID-клавиатуры (ещё не пробовал). Но для этого не всякая Ардуинка подойдёт, нужна с чипом atmega8u2 в качестве USB контролера (новая Arduino UNO как раз с ним). Жаль, под рукой нет ничего подходящего, а хотелось поиграть в бамбермена-онлайн с виноградной клавиатуры :-) Можно, конечно, набросать софтинку которая будет через COM-порт читать с ардуины сигнали о нажатиях и транслировать их в события клавиатуры, но это уже не то (через HID всё-таки интереснее).

    UPD> Получил работающий девайс, зудеть перестало, расслабился. Почитал про МакиМаки поподробнее — оказывается, там как раз на ардуине и сделано :-)

    UPD> Просто пищать спикером неинтересно, надо бы для дочи развлекуху сделать :-) Может быть следующий топик как раз об этом и будет, если получится что-нибудь интересное.

    UPD> Нашёл интересный проект — Виртуальная USB клава, без использования atmega8u2. Надо будет попробовать подцепить.

    UPD> Вопрос к хабровчанам — мож кто подскажет софтинку (желательно под винду или кросс-платформенную) которая читала бы COM-порт, принимала сообщения в каком-нибудь формате и формировала события нажатий клавиш? А то сам я быстро такое не склепаю.

    UPD> Экстренно заказал ардуину уно дабы HID-девайс получился «из коробки». Надеюсь, доставка не подведёт и сегодня доставят. Пока не сыграю в бамбермена — не успокоюсь (а ещё со вчерашнего дня даж спать не ложился).

    UPD> Сейчас подключено 8 виноградин, одновременно все восемь отрабатываются, но с провалами. Стабильно работают 5 одновременных касаний. HID сегодня отменяется ибо доставка только завтра будет :-(

    UPD> Так… С помощью советов кореша удалось набросать простенькую софтинку на C#. Читает ардуинский COM-порт, принимает нажатия на виноградины, эмулирует нажатия клавиатуры. Щас попробую все восемь виноградин подцепить и тогда новый видеоролик сниму. Впервые писал что-то на C# :-)

    UPD> Исходный код (VS2010, C#). Я в C# не шарю, так что как получилось — так получилось :-) Огромное спасибо Leonardo за подсказки, иначе вообще нифига бы не получилось. И спасибо хабраюзеру GreenGo за наводку на библиотеку InputSimulator.

    Софтина слушает указанный COM-порт (никаких настроек нет, имя порта жёстко прописано в исходнике (COM11). Это тот порт, по которому доступна Ардуина. Задействованы только 6 клавиш.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using WindowsInput;
    
    using System.IO;
    using System.IO.Ports;
    
    namespace WindowsFormsApplication1
    {
    
        public partial class Form1 : Form
    
        {
            System.IO.Ports.SerialPort newPort;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
    
            }
    
    
            private void button2_Click(object sender, EventArgs e)
            {
                newPort = new SerialPort("COM11", 57600, Parity.None, 8, StopBits.One);
                newPort.Open();
                newPort.DataReceived += new SerialDataReceivedEventHandler(GetArduinoBytes);
            }
    
            public void GetArduinoBytes(object sender, SerialDataReceivedEventArgs e)
            {
                string data = newPort.ReadExisting();
                string [] arr;
                int key = 0;
                arr = data.Split('\r');
                try
                {
                    key = Convert.ToInt32(arr[0]);
                }
                catch (System.FormatException)
                {
                    // ничего не делаем
                }
    
                int key1 = key & 1;
                int key2 = (key >> 1) & 1;
                int key3 = (key >> 2) & 1;
                int key4 = (key >> 3) & 1;
                int key5 = (key >> 4) & 1;
                int key6 = (key >> 5) & 1;
                int key7 = (key >> 6) & 1;
                int key8 = (key >> 7) & 1;
    
                if (key1 == 1) WindowsInput.InputSimulator.SimulateKeyDown(VirtualKeyCode.DOWN);
                else WindowsInput.InputSimulator.SimulateKeyUp(VirtualKeyCode.DOWN);
    
                if (key2 == 1) WindowsInput.InputSimulator.SimulateKeyDown(VirtualKeyCode.UP);
                else WindowsInput.InputSimulator.SimulateKeyUp(VirtualKeyCode.UP);
    
                if (key3 == 1) WindowsInput.InputSimulator.SimulateKeyDown(VirtualKeyCode.LEFT);
                else WindowsInput.InputSimulator.SimulateKeyUp(VirtualKeyCode.LEFT);
    
                if (key4 == 1) WindowsInput.InputSimulator.SimulateKeyDown(VirtualKeyCode.RIGHT);
                else WindowsInput.InputSimulator.SimulateKeyUp(VirtualKeyCode.RIGHT);
    
                if (key5 == 1) WindowsInput.InputSimulator.SimulateKeyDown(VirtualKeyCode.SPACE);
                else WindowsInput.InputSimulator.SimulateKeyUp(VirtualKeyCode.SPACE);
    
                if (key6 == 1) WindowsInput.InputSimulator.SimulateKeyDown(VirtualKeyCode.VK_Z);
                else WindowsInput.InputSimulator.SimulateKeyUp(VirtualKeyCode.VK_Z);
    
            }
    
        }
    }
    


    UPD> А вот новый скетч для Ардуины. Воспроизведение писка спикером закомментил, просто передаём состояние клавиш в консоль.

    #include <CapSense.h>
    
    #define SND_PIN  12 // пин, к которому подключён спикер
    
    CapSense   key1 = CapSense(5, 2); // клавиша 1 между 5-м и 5-м пинами
    CapSense   key2 = CapSense(5, 3); // клавиша 2 между 5-м и 4-м пинами
    CapSense   key3 = CapSense(5, 4); // клавиша 3 между 5-м и 3-м пинами
    CapSense   key4 = CapSense(5, 6); // клавиша 4 между 5-м и 3-м пинами
    CapSense   key5 = CapSense(5, 7); // клавиша 5 между 5-м и 3-м пинами
    CapSense   key6 = CapSense(5, 8); // клавиша 6 между 5-м и 3-м пинами
    CapSense   key7 = CapSense(5, 9); // клавиша 7 между 5-м и 3-м пинами
    CapSense   key8 = CapSense(5, 11); // клавиша 8 между 5-м и 3-м пинами
    
    int range = 100; // пороговое значение, определяющее нажатие
    unsigned int button = 0, oldButton = 0; // побитовое обозначение нажатых клавиш
    int freq; // частота звука для воспроизведения на спикер
    byte sense = 30;
    long total1, total2, total3, total4, total5, total6, total7, total8;
    
    void setup()                    
    {
      //key1.set_CS_AutocaL_Millis(0xFFFFFFFF);
      Serial.begin(57600); // стартуем консоль
    }
    
    void loop()                    
    {
        total1 =  key1.capSense(sense);
        total2 =  key2.capSense(sense);
        total3 =  key3.capSense(sense);
        total4 =  key4.capSense(sense);
        total5 =  key5.capSense(sense);
        total6 =  key6.capSense(sense);
        total7 =  key7.capSense(sense);
        total8 =  key8.capSense(sense);
    
        button = 0;
        if (total1 > range) button |= 1;
        if (total2 > range) button |= 2;
        if (total3 > range) button |= 4;
        if (total4 > range) button |= 8;
        if (total5 > range) button |= 16;
        if (total6 > range) button |= 32;
        if (total7 > range) button |= 64;
        if (total8 > range) button |= 128;
        
       if (button != oldButton) {
         Serial.println(button);
         oldButton = button;     
       }
    
       /*
       if (button) freq = button * 10 + 200; else freq = 0;
       if (freq) {
         Serial.println(freq);
         tone(SND_PIN, freq);
       } else noTone(SND_PIN); // воспроизводим или останавливаем звук
       */
    }
    


    UPD> Про МакиМаки по телику показали. Меня звали поучаствовать в программе с этим моим «виноградным мультитачем», но пришлось отказаться по политическим причинам :-)

    Поделиться публикацией
    Комментарии 46
      0
      нетерпится посмотреть видео )))
        +5
        эээ… а кто мешает?? Или вы про какое именно видео?
          +1
          я про Ваше видео )))
        0
        Круто! Даже не верится, что такое можно сделать за 15 минут… Моё почтение!
          0
          Ну на самом деле примитивно всё. Я тут щас ещё MIDI прикручиваю, чтоб доча могла на виноградинках поиграть что-то более прилично звучащее чем спикер :-)
            0
            А тем, кто вообще ни разу не занимался подобным, будет сложно собрать такое же устройство? Я бы хотел попробовать — самому интересно, да ещё и друзей удивлю!

            В-общем, жду продолжения истории с подробным how-to. Сделаю себе барабаны из арбузов :-)
              0
              Я вот с ёмкостными контактами сам впервые столкнулся, если честно. Как видите, всё заработало сразу же. Если таки соберу что-то в законченом виде — выложу, конечно. Результат самому понравился, так что точно соберу.
            0
            минус 5 минут перекур был :-D
              0
              с первого видео еще забавный момент, когда дорожки для пакмановского джойстика рисвались карандашом на бумаге. Вспомнилось, как я когда-то, еще в начальных класах, так, наслюнявив жирный карандаш, наводил дорожки на монтажной плате картриджа после того как, то ли залил, то ли затер дорожки резко вытаскивая его с приставки(уже не помню точно). Главное, что после этого всё отлично работало и я был рад =)
                +5
                графит — он такой, ага
                  0
                  Одна проблема у графитовых сопротивление высокое порядка 1к Ом получается, им хорошо делать подтяжки)

                  а тут он просто не чувствуется по сравнению с МОм…
              +1
              У вас идеально подходящая к внешности аватарка) Девайсина интересная получилась. Судя из этого видео, можно ещё менять тональность звука в зависимости от площади нажатия.
                0
                Аватарку делал когда с бородёнкой был, вот тогда и правда идеально подходила :-) Насчёт возможностей улучшения девайса — простор неограниченный.
                  0
                  Ну, сейчас звук это лишь для демонстрации нажатий. Вообще, конечно, это будет именно клавиатура, как у америкосов. Сейчас уже 8 «клавиш» функционируют, но вот эмуляция HID откладывается до завтра.
                  +2
                  Чувак, тебе бы порядок навести.
                    +9
                    Гм, у половины хабровчан что-то подобное, имхо.
                      +1
                      чувак, это творческий бардак
                        +1
                        Возможно, творческий порядок?
                          +7
                          Не, творческий порядок у меня начинается когда у жены до моей «лаборатории» руки доходят. Я всячески препятствую, но не всегда удаётся предотвратить уборку.
                          0
                          Творческий беспорядок — более каноническое словосочетание)
                        0
                        Забавная фигня получается, если распознавание голоса во втором ролике включить. Прям misheard lyrics.
                          +1
                          Так… С помощью советов кореша удалось набросать простенькую софтинку на C#. Читает ардуинский COM-порт, принимает нажатия на виноградины, эмулирует нажатия клавиатуры. Щас попробую все восемь виноградин подцепить и тогда новый видеоролик сниму. Впервые писал что-то на C# :-)
                            0
                            Интересно, а в Игры «нажатие» проходит? Т.е. DirectInput проглатывает «эмуляцию»?

                            Может вообще сделать WM_Touch эмуляцию виноградную?
                              0
                              Уже приходит, но DirectInput не осилил. Для начала хоть с обычной эмуляцией немного разобрался, используя библиотеку InputSimulator (спасибо GreenGo за наводку). Говорю ж, впервые C# использовал. Новое демонстрационное видео снял, ща на Ютубу заливается
                            +2
                            ну все, я созрел! Спасибо автору за вдохновение! :)
                              +1
                              *пошел покупать пульт от денди
                                +1
                                лучше кило винограда купите :-) и поиграть можно, и скушать
                                  +1
                                  В напряженные моменты рискуете перепачкать руки в остатках виноградин.
                                0
                                Добавил видеоролик с практическим применением :-)
                                  +1
                                  Со злости можно ударить кулаками по виноградинам, протереть стол, взять новые и снова играть:)))
                                    +1
                                    А можно и скушать, если проголодался :-) Ну, виноград просто под рукой был, вот его и задействовал чтоб интересней было. А вообще можно экспериментировать с разными продуктами/материалами. Американцы много вариантов опробовали, но всё равно что-нить оригинальненькое придумать можно.
                                    +3
                                    Хе, засветился наш бомбер =D
                                    совершенно случайно заметил же, видюху сначала даже не запускал.
                                      +2
                                      Ваш бамбер у меня теперь каждый день по часику съедает :-) Как говорится, респект и уважуха!
                                      +1
                                      Круто!
                                      Это такой намёк, чтобы следующими сделали танчики, да? :)
                                        +1
                                        Про танчики я в топике про бамбера уже писал :-) Даёшь мультиплеерную Battle City!
                                          +4
                                          ДЫАААА!
                                            +2
                                            сначала довести до ума бомбера, после этого танчики долго себя ждать не заставят.
                                          +6
                                          image
                                            –2
                                            Из ролика я понял только это

                                            image
                                              +2
                                              я тут с апельсинкой сделал)
                                              www.youtube.com/watch?v=Wo7PPpn-c8k
                                                0
                                                клёво :-)
                                                  0
                                                  резюк на сколько мегаом поставил?
                                                  0
                                                  Чтобы сделать USB HID-клавиатуру, подойдет практически любой чип AVR.

                                                  Если это будет простой чип, без аппаратного интерфейса USB (типа ATmega8, ATmega16, ATmega32,… ATmega128), то нужно просто взять примеры HID-клавиатур, основанные на библиотеке V-USB [1]. Библиотека V-USB хорошо документирована, есть даже её перевод на русский язык (переведены комментарии в коде библиотеки).

                                                  Если использовать чип AVR с аппаратным интерфейсом USB (AT90USB1286, AT90USB1287, AT90USB162, AT90USB646, AT90USB647, AT90USB82, ATmega16U2, ATmega16U4, ATmega32U2, ATmega32U4, ATmega8U2), то лучше всего взять за основу примеры USB HID клавиатуры из библиотеки LUFA [2], или взять пример USB HID клавиатуры Atmel [3]. Лично мне больше по душе пример LUFA, так как написан он логичнее, его легко перекомпилировать на любой микроконтроллер AVR USB, и также есть переведенная на русский язык версия библиотеки LUFA (переведены комментарии в коде библиотеки и примерах кода).

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

                                                  [Ссылки]

                                                  1. Примеры USB HID устройств на библиотеке V-USB, в том числе и клавиатур.
                                                  2. LUFA клавиатура USB HID.
                                                  3. AVR271: USB Keyboard Demonstration.
                                                    0
                                                    Ну, слава богу, геморроя при встраивании кода пока не имел ни разу, тьфу-тьфу :-) Я ж не говорю что «забейте на всё, остальное, делайте только на ардуине». Мне вот влом возиться с пайкой, гораздо удобнее взять готовую плату дабы быстренько опробовать на ней что-либо новенькое.
                                                      0
                                                      Я ж не говорю что «забейте на всё, остальное, делайте только на ардуине».
                                                      Никто Вас не собирается обвинять, что Вы это говорите. И хорошо, что не говорите =).

                                                      Мне вот влом возиться с пайкой, гораздо удобнее взять готовую плату дабы быстренько опробовать на ней что-либо новенькое.
                                                      Не поверите — я абсолютно такой же лентяй, как и Вы. Но переплачивать за Ардуино не собираюсь, когда есть более дешевые (и более удобные лично для меня) макетные платы.
                                                    0
                                                    Добавил видеоролик эфира Россия-2, показывали про МакиМаки и мой виноград :-)

                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                    Самое читаемое