среда, 24 февраля 2016 г.

Подключение джойстика от приставки Денди к к компьютеру через USB при помощи Arduino (Digispark)

    В данной статье я подробно опишу вариант переделки джойстика от игровой приставки Денди для подключения к USB порту компьютера, используя Arduino-совместимый модуль Digispark ATTINY85 стоимостью менее 1.5$.
    Сначала я покажу  как выглядит готовый (переделанный под USB) джойстик:

Заинтересовал? Тогда прошу продолжить чтение данной статьи про вариант его адаптации для ПК:



Нам понадобится:
1) Джойстик от 8-битной игровой приставки Денди. Валялся он у меня дома лет 10 и считался нерабочим, т.к. был поврежден шнур. Но на переделку это не повлияло.
2) Модуль ATTINY85 Digispark. Покупал у по этой ссылке на Aliexpress. На момент покупки стоил 1.42$
3) Провод с USB разъемом на конце. Я использовал доставшийся мне бесплатно провод от нерабочей мышки. Вы же можете использовать любой имеющийся у Вас в наличие: от мышки, клавиатуры, принтера, мобильного телефона и т.д.

   В моем джойстике была установлена плата типа SB8321. Если у Вас такая же - то схему подключения можете использовать мою. Если другая - расположение выводов придется искать самостоятельно.

  Для начала нужно соединить 5-ю проводами плату с модулем DigiSpark. Расположение выводов на плате SB8321 следующее (слева-направо со стороны дорожек):  +5В, GND (общий),  Latch, Clock, Data














  Если Вам придется искать расположение выводов самостоятельно, то имейте ввиду, что общий провод (GND, минус питания) разведен по плате и подключен к одному из контактов кнопок.
  После того, как будет найден найден общий контакт, с одной стороны от него будет подряд три информационных вывода. Считая от вывода GND (общего) они расположены в следующем порядке: Latch, Clock, Data. С другой стороны от общего вывода (относительно Latch, Clock, Data) расположен вывод подключения питания +5В.
 Такое расположение обычно на всех джойстиках клонов приставки от NINTENDO: Dendy, Subor, Simba's и др.
  Если у Вас джойстик от оригинальной приставки NES Nintendo - тогда распайку джойстика можно посмотреть в этой статье.
   Также можно определить расположение выводов "прозвонив" тестером провода от разъема до платы, используя следующую подсказку:
Далее при помощи 5-ти коротких проводков нужно соединить плату джойстика с модулем DigiSpark:
 























Для удлинения USB разъема используется провод от мышки:
























Далее необходимо собрать джойстик (прикрутить заднюю крышку)

Переходим к заливке программы в Digispark:
1) Скачиваем и устанавливаем на ПК драйвера для платы Digispark.
2) Скачиваем последнюю версию Arduino c официального сайта www.arduino.cc (на момент написания статьи это версия 1.6.7).

Подойдет любая сборка Arduino не ниже версии 1.6.5.
3) Устанавливаем и запускаем.

4) Выбираем Файл-Настройка


5) В поле "Дополнительные ссылки для Менеджера плат" вписываем строку
http://digistump.com/package_digistump_index.json и нажимаю ОК

6) Далее в меню “Инструменты” выбираем  “Плата: "Arduino....” и далее пункт “Менеджер плат


7) В открывшемся менеджере плат выбираем тип отображаемых плат "Внесены"

8) Выбираем "Digistump AVR board by Digistump" и нажимаем "Установка"

9) Убеждаемся, что появился список плат Digispark и выбираем тип своей платы (у меня Digispark Pro (default 16Mhz))

10) Вставляем в Arduino следующий скетч:

//Simple DigiSpark NES Joystick Adapter  
 //I purposfully made the program read all NES buttons the traditional way   
 //then store them into the Buffer so that its easy to follow what the program is doing  
 //I could have just read the correct bits directly into the buffer but then   
 //the functionality would be obfuscated  
 #include <DigiJoystick.h>  
 #define NES_Clock 1  
 #define NES_Latch 0  
 #define NES_Data  2  
 #define NES_RIGHT 1  
 #define NES_LEFT  2  
 #define NES_DOWN  4  
 #define NES_UP   8  
 #define NES_START 16  
 #define NES_SELECT 32  
 #define NES_B   64  
 #define NES_A   128  
 #define XAXIS 0  
 #define YAXIS 1  
 //we need someplace to store our button reads...  
 byte NESButtons = 0;  
 //  x, y, xrot, yrot, zrot, slider, buttonLowByte, buttonHighByte  
 char JoyBuffer[8];  
 void setup() {  
  NESinit();  
 }  
 void loop() {  
  NESButtons = NESRead(); // Store our NES Button Data  
  JoyBuffer[0] = GetAxis(XAXIS); // get the X Axis (left/right buttons)  
  JoyBuffer[1] = GetAxis(YAXIS); // get the Y axis (up/down buttons)  
  JoyBuffer[6] = NESButtons >> 4; //shift button bytes over by 4 so we lose the 4 directions and make the buttons show up as buttons 1-4 instead of 5-8  
  DigiJoystick.setValues(JoyBuffer);  
  //DigiJoystick.update(); //Send a USB Keep Alive(only sends data on change or as needed to keep usb alive) Not Needed if using regular(every 50ms or less) interval of DigiJoystick.delay();  
  DigiJoystick.delay(10); //wait 10 milliseconds because whynot? :p since we use this every 10ms we dont need to call DigiJoystick.update(); as this does it for us.  
 }  
 void NESinit() {  
  pinMode(NES_Clock,OUTPUT);  
  pinMode(NES_Latch,OUTPUT);  
  pinMode(NES_Data,INPUT);  
  digitalWrite(NES_Latch,LOW);  
  digitalWrite(NES_Clock,HIGH);  
  digitalWrite(NES_Data, HIGH); // turn on pullup  
 }  
 byte NESRead(){  
   byte ret = 0;  
   digitalWrite(NES_Latch,HIGH);  
   delayMicroseconds(12); //seems to work without the delay but this is how NES works  
   digitalWrite(NES_Latch,LOW);  
   ret = shiftIn(NES_Data,NES_Clock,MSBFIRST);  //shift in the button data
   digitalWrite(NES_Clock,HIGH); //set clock high after shift in so we catch the first bit  
   return ~ret; //bit flip our results because the NES buttons are active low  
 }  
 byte GetAxis(int Axis){  
  byte ret = 0;  
  switch(Axis) {  
   case YAXIS:  
    if (NESButtons & NES_UP) {  
     ret = 0;  
    }  
    else if (NESButtons & NES_DOWN) {  
     ret = 250;  
    }  
    else {ret = 127;} //center joystick  
    break;  
   case XAXIS:  
    if (NESButtons & NES_LEFT) {  
     ret = 0;  
    }  
    else if (NESButtons & NES_RIGHT) {  
     ret = 250;  
    }  
    else {ret = 127;} //center joystick  
    break;  
   }  
  return ret;  
 }  


11) При отключенном модуля DigiSpark (отключенном джойстике) в программе Arduino 1.6.* нажимаем на кнопку "Загрузка". Происходит компиляция скетча и программа в течение 60 секунд ожидает подключения модуля DigiSpark.

12) Подключаем наш собранный джойстик к USB порту компьютера. После заливки скетча в модуль DigiSpark джойстиком можно пользоваться.

Если возникнут дополнительные вопросы - пишите их в комментариях. Постараюсь ответить.

UPD 12.08.2017: Для Windows 10 драйвера не нужны, в подтверждение привожу скриншоты:


      UPD 14.02.2020:
     Как подключить два таких джойстики к ПК, они определяются системой как один Можно им как-то задать разную идентификацию?
      Допустим, один джойстик у нас уже прошит. Далее, открываем файл конфигурации USB по адресу наподобие этого (из-за разности версий путь может немного отличаться):

"C:\Users\'имя_пользователя'\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\libraries\DigisparkJoystick\usbconfig.h".

Находим строку
"#define USB_CFG_DEVICE_ID 0xdc, 0x27"
и немного меняем это ID. Я сделал так:
"#define USB_CFG_DEVICE_ID 0xdd, 0x27".

Далее по желанию, но я ещё изменил имя устройства:
#define USB_CFG_DEVICE_NAME 'D','i','g','i','K','e','y','2'
#define USB_CFG_DEVICE_NAME_LEN 8

Всё, сохраняем. Перезагружаем Arduino IDE, прошиваем второй джойстик и мы имеем второе устройство, которое и визуально по имени отличается от первого, и не конфликтует с ним из-за одинаковых адресов. (Спасибо MedAleks)

      UPD 26.03.2020:
Еще раз проверил. Вставил код в Arduino IDE и проверил - ошибок нет

Скачать скетч можете здесь 

Update 20.02.2021
      Вариант печатной платы адаптера размером 35х40мм от Alexnvg  что чтобы не разбирать джойстик:




Скачать архив можно на Яндекс диске автора или у меня на google диске.


Литература:
1) Подключение джойстика Nintendo NES к USB при помощи DigiSPARK
2) Ремонт джойстиков Dendy.Форум Emu-Land.net
3)  NES USB Controller using DigiSPARK

Upd 02.05.2022:  Выложил файлы в первых комментариях к данной статье на нашем телеграмм канале. Не забудьте подписаться на канал!



67 комментариев:

  1. А вот интересно если такой джойстик преределанный под USB подключить не к компу а к Raspberry Pi (RETROPI - внутри Raspbian - Debian ) он будет работать ?

    ОтветитьУдалить
    Ответы
    1. Теоретически - должен работать. Я через OTG-переходник подключал к своему android-телефону - прицепился и работал без проблем.

      Удалить
  2. Интересно ... обязательно попробую , заказал Digispark на али по вашей ссылке.

    ОтветитьУдалить
  3. А как заставить ПК видеть ардуино уно как геймпад или руль?

    ОтветитьУдалить
    Ответы
    1. Используя соответствующие библиотеки для Arduino. Например https://github.com/NicoHood

      Удалить
  4. Этот комментарий был удален автором.

    ОтветитьУдалить
  5. Вячеслав, как заставить винду 10 видеть digispark, драйвера не подходят вообще

    ОтветитьУдалить
    Ответы
    1. В чем проблема? Напишите как у Вас определяется джойстик в диспетчере устройств (vid-pid)? Постараюсь помочь.

      Удалить
    2. Еще раз проверил, для windows 10 драйвера не нужны, система определяет джойстик автоматически. В конце статьи добавил скриншоты.

      Удалить
  6. Турбо кнопки будут работать?

    ОтветитьУдалить
  7. А будут ли работать все кнопки если подключить джойстик от SNES т.к. они почти похожи только от SNES больше кнопок.

    ОтветитьУдалить
    Ответы
    1. Джойстики SNES разве совместимы NES?

      Удалить
    2. ту так то если распаять джойстик от nes под snes то он будет работать. только не будут работать работать кнопки x,a и shift-ы т.к. их просто нет этих кнопок на джойстике. В джойстике от snes применяются таже микруха что и в nes (4021) только их там две

      Удалить
  8. не пашет. При компиляции выдает Arduino: 1.8.5 (Windows 10), Плата:"Arduino/Genuino Uno"

    C:\Users\Дарина\Documents\Arduino\sketch_dec21a\sketch_dec21a.ino:6:29: fatal error: DigiJoystick.h: No such file or directory

    compilation terminated.

    exit status 1
    Ошибка компиляции для платы Arduino/Genuino Uno.

    Этот отчёт будет иметь больше информации с
    включенной опцией Файл -> Настройки ->
    "Показать подробный вывод во время компиляции"

    не знаю че делать

    ОтветитьУдалить
  9. И в компе тоже:
    Arduino: 1.8.5 (Windows 7), Плата:"Arduino/Genuino Uno"

    C:\Users\Андрей\Documents\Arduino\sketch_dec22a\sketch_dec22a.ino:6:29: fatal error: DigiJoystick.h: No such file or directory

    compilation terminated.

    exit status 1
    Ошибка компиляции для платы Arduino/Genuino Uno.

    Этот отчёт будет иметь больше информации с
    включенной опцией Файл -> Настройки ->
    "Показать подробный вывод во время компиляции"

    ОтветитьУдалить
    Ответы
    1. Не подключилась библиотека

      Удалить
    2. А что это может быть? Установил Arduino 1.6.7 - то же самое:
      Arduino: 1.6.7 (Windows 7), Плата:"Arduino/Genuino Uno"

      C:\Users\Андрей\Documents\Arduino\sketch_dec23a\sketch_dec23a.ino:6:29: fatal error: DigiJoystick.h: No such file or directory

      compilation terminated.

      exit status 1
      Ошибка компиляции.

      Это сообщение будет содержать больше информации чем
      "Отображать вывод во время компиляции"
      включено в Файл > Настройки

      Удалить
    3. Пункты 4-9 данной статьи выполнены?
      Плата на Attiny85?

      Удалить
    4. то-то и обидно, что все по "инструкции" делаю. Плата такая, только ее же вроде надо только после компиляции скетча подключать. Пока ни комп ни планшет ее "не видели".

      Удалить
    5. после установки драйверов на семерке диспетчер устройств видит джойстик как какой-то Digispark Botloader

      Удалить
    6. Меня смущает это "Плата:"Arduino/Genuino Uno"
      Точно 9 пункт "инструкции" выполнили? Должен быть быть выбран какой то из Digispark (у меня Digispark Pro (default 16Mhz)).
      ЗЫ: По поводу прошивки все верно. Плата для заливки скетча подсоединяется после компиляции.

      Удалить
    7. да, спасибо. все залилось нормально. ...
      > Press CTRL+C to terminate the
      Правда джойстик все равно не заработал, но это уже наверное проблемы с самим джойстиком

      Удалить
    8. странно одно. Почему диспетчер устройств после всех манипуляций видит digispark bootloader, а не джойстик?

      Удалить
  10. Здравствуйте. Спасибо за хорошую инстуркции, все работает. Но у меня есть потребность подключить два таких джойстики к ПК, но сейчас они определяются системой как один Можно им как-то задать разную идентификацию?

    ОтветитьУдалить
    Ответы
    1. Здравствуйте. Присоединяюсь к благодарностям за хорошую статью, дал новую жизнь старым джойстикам!
      Два джойстика можно подключить, вот только что разобрался, как это можно сделать.
      Допустим, один джойстик у нас уже прошит. Далее, открываем файл конфигурации USB по адресу наподобие этого (из-за разности версий путь может немного отличаться):

      "C:\Users\'имя_пользователя'\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\libraries\DigisparkJoystick\usbconfig.h".

      Находим строку
      "#define USB_CFG_DEVICE_ID 0xdc, 0x27"
      и немного меняем это ID. Я сделал так:
      "#define USB_CFG_DEVICE_ID 0xdd, 0x27".

      Далее по желанию, но я ещё изменил имя устройства:
      #define USB_CFG_DEVICE_NAME 'D','i','g','i','K','e','y','2'
      #define USB_CFG_DEVICE_NAME_LEN 8

      Всё, сохраняем. Перезагружаем Arduino IDE, прошиваем второй джойстик и мы имеем второе устройство, которое и визуально по имени отличается от первого, и не конфликтует с ним из-за одинаковых адресов.

      Удалить
    2. Спасибо за ценную информацию. Обязательно добавлю ее в статью.

      Удалить
    3. Приветствую.
      Способ не работает. Вероятно: забыли ещё какую-то настройку подкрутить?
      Вижу в свойствах двух уже прошитых и подключенных устройств разные PID и разные имена, однако совместно устройства работать отказываются, только по одному. При попытке подключить второй джойстик - он определяется как Unknown Device. При этом нет разницы, в какой последовательности производить подключение: всегда первый из двух подключенных будет работать, а второй определяться как неизвестное устройство. Если поменять их местами, т.е. сначала подключить "второй", а потом "первый", то "второй" будет работать, а первый не определится. Также сразу отмечу, что подмена VID не решает проблему. Т.е. два устройства, прогруженных одинаковым скетчем, но имеющих разные имена, разные PID и разные VID, совместно не работают :(

      Удалить
    4. upd: симптоматически решил "раскидыванием" на разные порты. Оказалось, что на ноутбуке, на котором происходило тестирование, все три USB-разъёма - это на самом деле один USB-порт. На целевом стационарнике, на котором будет крутиться эмулятор, USB-разъёмы на задней панели подключены к разным контроллерам на мат.плате, и всё работает. Разрулить ситуацию таким образом, чтоб оно работало на одной шине, у меня скиллов не хватает, поэтому я для своей ситуации успокаиваюсь на признании необходимости работы через разные порты аппаратным ограничением.

      Удалить
  11. Здравствуйте! при попытке настроить джойстик в JNES, постоянно срабатывают кнопки турбо. Как это отключить??

    ОтветитьУдалить
  12. Добрый день не получается загрузить на digispark скетч, после нажатия на загрузка пишет выберите порт до загрузки, как это исправить?

    ОтветитьУдалить
  13. как загрузить ваш скетч. копирую вставляю при загрузки выдает какую то ошибку???

    ОтветитьУдалить
    Ответы
    1. Все по инструкции сделали? Библиотеку подключили? Драйвера digispark установили? Какая ошибка?

      Удалить
    2. напишите номер вайбера

      Удалить
    3. библиотеку подключил а вот драйвера почему то не устанавливаются

      Удалить
  14. как подключить библиотеку?

    ОтветитьУдалить
  15. или же скиньте ссылку скетча попробую еще раз

    ОтветитьУдалить
  16. Простите, но в личной переписке помощь не оказываю. Скетч если найду (статья писалась 4 года назад) то выложу. По поводу установки драйвера - проще поискать на профильных сайтах - форумах по digispark.

    ОтветитьУдалить
    Ответы
    1. постарайтесь найти скетч. плохо что здесь нельзя скиншоты показать об ошибке

      Удалить
  17. Не знаю, почему у Вас не получается установить драйвер, но возможно решение проблемы здесь: https://m.habr.com/ru/post/413927/

    ОтветитьУдалить
  18. при проверки выдает такую ошибку:redefinition of void setup

    ОтветитьУдалить
  19. зашел в расположения файлов ардуино.открыл папку драйвера и нажал установщик пакетов драйверов. в установщике написано что драйвера установились. у меня виндовс 8.1

    ОтветитьУдалить
  20. Вітаю, Вячеславе! Мені вдалося повторити Ваш успіх. Все запрацювало з першого разу і тепер я маю два чудових джойстики, що чудово пасують до емулятора Dendy на комп'ютері. Дякую за статтю!

    ОтветитьУдалить
  21. З приводу скетчу. Хотілося б додати, що на файл скетчу Arduino 1.8.13 справді "плюється" при перевірці, та якщо брати текст скетчу зі статті й вставляти напряму - все ок.

    ОтветитьУдалить
  22. Здравствуйте. А пистолет так можно зацепить? Есть скетч под него.

    ОтветитьУдалить
    Ответы
    1. В данной статье описана переделка ДЖОЙСТИКА денди в ДЖОЙСТИК для ПК. Для ПК пистолетов я не видел, поэтому пистолет от денди переделывать не во что. Да и в пистолете кроме фотоэлемента и кнопки других деталей нет.

      Удалить
    2. Дельное замечание. Но в том и вопрос можно ли так же подцепить пистолет к ПК чтобы играть на эмуляторе в тех же уток например...

      Удалить
    3. Как я писал ранее пистолет представляет собой фотоэлемент с кнопкой, а функция стрельбы реализована в самой программе стрельбы по уткам. И параметры экрана жестко привязаны к параметрам кинескопа. Поэтому пистолет не будет ни на чем другом работать кроме кинескопного телевизора даже при подключении приставки Денди.

      Удалить
  23. Возникла проблема припаенный джостик к такой же плате как у вас на фото вставляю в юсб он его обнаруживает(издает звук) и сразу теряет(издает звук) так и на семерке и на 10-ке. В чем может быть проблема???

    ОтветитьУдалить
    Ответы
    1. Прошейте Digispark правильно

      Удалить
    2. решил проблему покупкой платы у продавца другого из вашей темы, теперь всё работает, правда два вместе нехотят работать

      Удалить
    3. Чуть выше в комментариях был описан способ подключения двух джойстиков: https://mynobook.blogspot.com/2016/02/usb-arduino-digispark.html?showComment=1581426118465#c3913441188061516913

      Удалить
  24. Доброго времени суток.
    Не работает, увы. Припаял к дигиспарку db9 разъем и выставил все пины в коде в соответствии с распиновкой разъёма, но никакого отклика от геймпада нет.
    Пробовал другой код и сигнал есть, но он какой-то неправильный (в той прошивке через digikeyboard делали).
    Что могло пойти не так?
    Просто не могу уже понять.

    ОтветитьУдалить
    Ответы
    1. Возможно перепутаны выводы на джойстике...
      Или же Вы задействовали для подключения к джойстику выводы на Digispark 3, 4 (зарезервированы под USB) или 5 (Reset)

      Удалить
    2. Ещё раз здравствуйте. Всё сделал правильно, это я дурак. :)
      Оказалось, что эмулятор тупо не поддерживал дигиспарк.

      Удалить
  25. Сделал по-быстрому переходник, чтобы не лезть в джойстик, кому интересно - плата: https://disk.yandex.ru/d/mJljyqpAP6gqdQ

    ОтветитьУдалить
    Ответы
    1. Спасибо. Отличная работа! Добавил в статью.
      Поделитесь, где можно взять штырьки которые вы устанавливали на плату?

      Удалить
    2. Этот комментарий был удален автором.

      Удалить
    3. А те, на которых припаян digispark - с материнки от компа

      Удалить
    4. Те, к которым подключается разъем джойстика...

      Удалить
    5. Мне попались штырьки на плате от старого советского телика, можно накусать из проволоки диаметром 1,5 мм

      Удалить
  26. Можно поподробнее про то, можно ли сделать все тоже самое но используя вместо digispark, ардуино nano?(я в даном вопросе совершенно не продвинут)

    ОтветитьУдалить
    Ответы
    1. Библиотека DigiJoystick работает только с Digispark. Для Аrduino нужна другая библиотека (например, https://github.com/MHeironimus/ArduinoJoystickLibrary/tree/version-1.0) и другой скетч. Так что просто так переделать не получится.

      Удалить