• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Arduino = gamepad/joystick?
#1
Witam wszystkich, jestem nowy w temacie Arduino jak i na forum Smile



Nie znam się za bardzo na elektronice, więc szukam praktycznego rozwiązania, mam nadzieję że uzyskam pomoc.

Potrzebuję zbudować 6-ścio lub maksymalnie 8 przyciskowy kontroler usb na bazie Arduino Uno.


Podstawową wiedzę i narzędzia posiadam, znam PHP i Pawn, zauważyłem że Arduino programuje się podobnie jak ActionScript więc myślę że zaprogramowanie 6 do 8 przycisków nie będzie stanowiło problemu.


Na początek potrzebuję bardzo proste rozwiązanie które będę rozbudowywał.

Są to przyciski stosowane w grach zręcznościowych, typowy dwu stykowy przycisk, przykład:
https://botland.com.pl/duuuze-przyciski/...-eko2.html

W opisie produktu jest nawet przykładowy program napisany pod Arduino Smile



No i pytanie, czy dobrze trafiłem? Czy Arduino Uno pozwoli mi na zbudowanie kontrolera z użyciem wyżej pokazanych buttonów? A może jest prostsze rozwiązanie?

Chodzi mi dokładnie o to by po podłączeniu Arduino przez USB, system Winodws wykrył go jako kontroler gier USB i abym miał możliwość zaprogramowania go jak zwykłego kontrolera już z poziomu aplikacji/gry/softu.



Wykonałem taki kontroler z płytki od chińskiej klawiatury usb (tzw. usb keyboard hack), działa wiadomo bez zarzutu lecz ma ograniczenia - właściwie brak możliwości rozbudowy no i na ten moment szukam rozwiązania profesjonalnego z możliwością rozbudowy.


Dam radę z Arduino czy szykować 200$ na gotowca z Usa? Budował ktoś podobny emulator na bazie Arduino?

Z góry dzięki za pomoc i informacje,

Pozdrawiam, Filip.
 
Odpowiedź
#2
Znalazłem taki artykuł, myślę że sobie poradzę z 6 przyciskami.

Cytat:Out of the box the Arduino Leonardo and the Arduino Micro appear to the host computer as a generic keyboard and mouse. This article discusses how the Arduino Leonardo and the Arduino Micro can also appear as a generic Game Controller or Joystick. This project will only work with Arduino products based on the ATmega32u4 microcontroller (i.e. the Arduino Leonardo and the Arduino Micro). It will not work with the Arduino UNO, because it is based on the ATmega328 microcontroller.

The Arduino Joystick Library (a.k.a. Game Controller library) used in the Instructable provides the following:

   X, Y, and Z axis
   32 buttons
   X, Y, and Z axis rotation
   Rudder
   Throttle
   2 Point of View Hat Switches

http://www.instructables.com/id/Arduino-.../?ALLSTEPS


Ktoś ma więcej info to poproszę linki Smile

Pzdr.
 
Odpowiedź
#3
Witam ponownie, zakupiłem Arduino Leonardo.

Zainstalowałem odpowiednie biblioteki i zainstalowałem program z dostępnych przykładów:


Kod:
// by Matthew Heironimus
// 2015-11-20
//--------------------------------------------------------------------

#include <Joystick.h>

void setup() {
 // Initialize Button Pins
 pinMode(9, INPUT_PULLUP);
 pinMode(10, INPUT_PULLUP);
 pinMode(11, INPUT_PULLUP);
 pinMode(12, INPUT_PULLUP);

 // Initialize Joystick Library
 Joystick.begin();
}

// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 9;

// Last state of the button
int lastButtonState[4] = {0,0,0,0};

void loop() {

 // Read pin values
 for (int index = 0; index < 4; index++)
 {
   int currentButtonState = !digitalRead(index + pinToButtonMap);
   if (currentButtonState != lastButtonState[index])
   {
     Joystick.setButton(index, currentButtonState);
     lastButtonState[index] = currentButtonState;
   }
 }

 delay(50);
}


System Windows wykrywa Arduino jako Gamepad, w powyższym przykładzie są 4 przyciski i wszystko działa jak należy, wykorzystałem piny od 9 do 12 i GND.


Teraz jednak chcę zrobić nie 4 lecz powiedzmy 16 przycisków, wytłumaczcie mi na jakiej zasadzie będzie to podłączone skoro teraz wykorzystuje 1 pin pod 1 przycisk to pod 16 braknie pinów, wybaczcie za to pytanie, pewnie jest śmieszne ale cóż. Proszę o przykład jakiś. Nie wyobrażam sobie 32 przycisków, osi X, Y, Z itd, gdzie i jak to podpiąć?

W przykładzie USBJoystickTest.ino wykorzystane są tylko 2 piny?

Kod:
  pinMode(A0, INPUT_PULLUP);
  pinMode(13, OUTPUT);

Proszę mi to wytłumaczyć jak dziecku, dziękuję Smile

Pozdrawiam.
 
Odpowiedź
#4
1. Biblioteka nie korzysta z fizycznych pinów
2. Nigdzie nie jest napisane że 1 pin to 1 button. Poczytaj o klawiaturach matrycowych.
W dokumentacji jest napisane:
Cytat:Joystick.setButton(byte button, byte value)
Sets the state (0 or 1) of the specified button (0 - 31). The button is the 0-based button number (i.e. button #1 is 0, button #2 is 1, etc.). The value is 1 if the button is pressed and 0 if the button is released.
Pomagam za darmo więc szanuj mój czas.
Wklejaj tekst a nie jego zdjęcie.
Nie pisz następnego postu jak nie odpowiedziałeś na poprzedni.
Jak mądrze zadawać pytania
 
Odpowiedź
#5
Dzięki za odpowiedź.

Gdybym skorzystał z nakładki np: https://botland.com.pl/klawiatury/4468-k...esults=113

Mogę to zaprogramować przy użyciu bibliotek Joystick?

Będę mógł wcisnąć kilka przycisków jednocześnie? Czy jednak nie będzie możliwości prawidłowego odczytania napięcia?

Pozdrawiam.
 
Odpowiedź
#6
Z klawiaturą analogową moży być ciężko zdekodować naciśnięcie 2 przycisków jednocześnie ale na pewno można to zrobić z klawiaturą matrycową binarną: https://botland.com.pl/klawiatury/2895-k...witch.html używając bibioteki Keypad: http://playground.arduino.cc/Code/Keypad
Pomagam za darmo więc szanuj mój czas.
Wklejaj tekst a nie jego zdjęcie.
Nie pisz następnego postu jak nie odpowiedziałeś na poprzedni.
Jak mądrze zadawać pytania
 
Odpowiedź
#7
Witam ponownie, klawiatura matrycowa fajnie działa na tych bibliotekach Keypad, dzięki za radę. Idea

Zaprogramowałem 16 przycisków, użyłem biblioteki Keypad i Keyboard ponieważ chcę emulować prawdziwą klawiaturę usb, kod głównie z przykładów lekko przerobiłem.

Jest 8 klawiszy zwykłych (cyfry 1-8) oraz 8 klawiszy funkcyjnych (enter, shift itp.)

Szybki test w kilku grach i wszystko działa jak należy, teraz czeka mnie więcej testów i dołączyłem wyświetlacz by widzieć co się dzieje.

Chcę by LCD pokazywał mi dla każdego klawisza funkcyjnego osobny tekst w drugiej lini, tak jak teraz pokazuje z tablicy Data[1] dla klawiszy od 1 do 8 lecz chciał bym teraz Switch i 16 przypadków dla każdego klawisza osobny tekst.

Pomoże ktoś?

Oto kod:
Kod PHP:
#include <Keyboard.h>
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define BACKLIGHT_PIN 3

char showKey;
char Data[1]; // 2 is the number of chars it can hold

const byte ROWS 4//four rows
const byte COLS 4//three columns
char keys[ROWS][COLS] = {
{
'1','2','3','4'},
{
'5','6','7','8'},
{
KEY_ESC KEY_RETURN KEY_LEFT_ARROW KEY_RIGHT_ARROW},
{
KEY_LEFT_SHIFT KEY_LEFT_CTRL KEY_RIGHT_CTRL KEY_RIGHT_SHIFT}
};
byte rowPins[ROWS] = {5432}; //connect to the row pinouts of the kpd
byte colPins[COLS] = {9876}; //connect to the column pinouts of the kpd

Keypad kpd KeypadmakeKeymap(keys), rowPinscolPinsROWSCOLS );

unsigned long loopCount;
unsigned long startTime;
String msg;

int led 10

LiquidCrystal_I2C  lcd(0x3F,2,1,0,4,5,6,7); // 0x3F adres I2C LCD 16x2

void setup() {
 
   Serial.begin(9600);
 
   loopCount 0;
 
   startTime millis();
 
   Keyboard.begin();

 
   pinMode(ledOUTPUT);

 
   lcd.begin (16,2);
 
   lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
 
   lcd.setBacklight(HIGH);
 
   lcd.home ();
 
   lcd.print("   KEY  DEBUG   ");
}


void loop() {
 
   loopCount++;
 
   if ( (millis()-startTime)>5000 ) {
 
       Serial.print("Average loops per second = ");
 
       Serial.println(loopCount/5);
 
       startTime millis();
 
       loopCount 0;
 
       }

 
   // Fills kpd.key[ ] array with up-to 10 active keys.
 
   // Returns true if there are ANY active keys.
 
   if (kpd.getKeys())
 
   {
 
       for (int i=0i<LIST_MAXi++)   // Scan the whole key list.
 
       {
 
           if kpd.key[i].stateChanged   // Only find keys that have changed state.
 
           {
 
               switch (kpd.key[i].kstate) {  // Report active key state : IDLE, PRESSED, HOLD, or RELEASED
 
                   case PRESSED:
 
                   Keyboard.press(kpd.key[i].kchar);
 
                   analogWrite(led50);
 
                   showKey kpd.key[i].kchar;
 
                   Data[1] = showKey// store char into data array
 
                   lcd.setCursor(0,1);
 
                   lcd.print(Data[1]); // print char at said cursor
 
               break;
 
                   case HOLD:
 
                   Keyboard.press(kpd.key[i].kchar);
 
                   analogWrite(led250);
 
               break;
 
                   case RELEASED:
 
                   Keyboard.release(kpd.key[i].kchar);
 
                   analogWrite(led0);
 
               break;
 
               }
 
           }
 
       }
 
   }
 // End loop 


Pozdrawiam.
-
 
Odpowiedź
#8
Ok poradziłem sobie, jak zwykle ignorując podstawy programowania Smile

Pozostało mi tylko ostrzeżenie które nie do końca rozumiem, próbowałem zamiast KEY_ użyć hexadecymalnych i decymalnych wartości, bez skutku, pomimo 100% poprawnego działania układu, ostrzeżenie o zmianie z int na char zawsze się pokazuje.

Kod PHP:
MultiKey_to_Keyboard2.ino:26:1warningnarrowing conversion of '133' from 'int' to 'char' inside { } [-Wnarrowing

Rozumiem że tu źle definiuje wartości klawiszy funkcyjnych:

Kod PHP:
char keys[ROWS][COLS] = {
{
'1','2','3','4'},
{
'5','6','7','8'},
{
KEY_ESC KEY_RETURN KEY_LEFT_ARROW KEY_RIGHT_ARROW},
{
KEY_LEFT_SHIFT KEY_LEFT_CTRL KEY_RIGHT_CTRL KEY_RIGHT_SHIFT}
}; 

Mam dodać definicje na początku? To chyba nic nie daje, kompilator i tak za każdym razem zmienia i wywala ostrzeżenie.

Proszę wytłumaczyć.

Dzięki i pozdrawiam.
 
Odpowiedź
#9
Jest rozwiązanie 1 pin = 1 przycisk w moim mniemaniu. Mjoy jeśli dobrze pamiętam wykorzystywał to rozwiązanie. Wystarczyło użyć tanich ekspanderów. Zresztą w wielu innych projektach również są używane ekspandery jeśli trzeba zwiększyć ilość pinów. Istnieje możliwość rozszerzenia pinów do bodajże dodatkowych 127 na takich modułach(trzeba tylko pamiętać o ustawieniu odpowiednich adresów dla ekspanderów).
 
Odpowiedź
#10
Witam, rozbudowuję projekt kontrolera jako że jestem z niego zadowolony, zamówiłem kilka pustych matryc na przyszłość a teraz chcę dodać kilka opcji.

Mam problem ze zrozumieniem działania funkcji millis()

Z wiadomych przyczyn nie mogę zastosować delay() by kontrolować czas.

W kodzie mam Serial.print co 5 sekund i nawet nie potrafię tego do końca zrozumieć, dodałem opisy Smile

Kod PHP:
loopCount++;  // loop+1
    
if ( (millis()-startTime)>5000 ) {  // jeżeli (czas startu arduino(ms) odjąć czas startu funkcji(ms)) większy niż 5000(ms)
        
Serial.print("Average loops per second = ");  // print
        
Serial.println(loopCount/5);  // print ilość loopów dzielone na 5
        
startTime millis();  // nadpisujemy czas startu funkcji
        
loopCount 0//resetujemy policzone przez 5 sekund loopy
        


Jeżeli dobrze rozumiem ten prosty kod to na jego podstawie nie powinienem mieć problemów z kontrolowaniem np. ledów nie powodując opóźnień w działaniu kontrolera. Poza ledami posłuży mi to do kontrolowania silniczków wibracyjnych i przekaźników, precyzja nie jest ważna, ważniejsze jest płynne działanie kontrolera i brak opóźnień.

Dobrze rozumiem kod?

Pozdrawiam.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości