ButtonBox SimRacing - Kippschalter und Drucktaster

Hallo Forengemeinde,

um es vorweg zu nehmen, ich bin Neu hier und auf dem Gebiet Arduino und Programmierung ein Neuling. Als kleines Winterprojekt habe mir in den Kopf gesetzt, eine BottonBox fürs SimRacing selber zu bauen. Die Box ist fertig, alle Schalter und Knöpfe platziert und verdrahtet, aber leider komme ich an einer Stelle nicht weiter obwohl ich inzwischen einige Videos zum Thema DIY-ButtonBox gesehen habe.

Die Box besteht aus:

7 Drucktaster

(1x Start/Stopp-Knopf als PushButton, 6x PushButtons zum verstellen von z.B. ABS, Traktionskontrolle o.ä.)

5 Kippschalter

(1x Zündung AN-AUS, 4x z.B. zum An- und Ausschalten von Scheibenwischer, Licht o.ä.)

Das Ganze habe ich als 4x4 Matrix aufgebaut, Matrix siehe Bilder. Ich verwende ein Arduino Micro Pro.

Die Kippschalter haben 2 Funktion – AN und AUS. Ebenso die Drucktaster. Welche Kippschalter und Drucktaster ich verwendet habe, siehe Bilder.

Nun mein Problem: Wenn ich die Kippschalter betätige, bspw. ich möchte mit Kippschalter 1 die Scheibenwischer und mit Kippschalter 2 das Licht AN-schalten, leuchten im Windows-Gamecontroller 2 der 12 Kontrolllampen. Das passt, siehe Abbildung 1. Sobald ich jetzt aber mittels PushButton bspw. ABS erhöhen möchte, leuchten 6 der 12 Kontrolllampen, obwohl nur 3 leuchten dürften. (1x Scheibenwischer, 1x Licht, 1x ABS erhöhen), siehe Abbildung 2.

Ich habe sowohl mit SimHub als auch mit dem beigefügten Quell-Code die Box versucht zum laufen zu bringen. Ich habe mich jedoch für den beigefügten Quell-Code entschieden, da er mir transparenter erscheint.

Ich hoffe mein Problem verständlich geschildert zu haben und wäre um jede Unterstützung dankbar. Vermutlich liegt es am Quell-Code, der vermutlich angepasst werden muss aber ich weiß leider nicht an welcher Stelle und wie.

#include <Joystick.h>

//BUTTON BOX 
//USE w ProMicro
//Tested in WIN10 + Assetto Corsa
//AMSTUDIO
//20.8.17

#include <Keypad.h>
#include <Joystick.h>

#define ENABLE_PULLUPS
#define NUMROTARIES 24
#define NUMBUTTONS 12
#define NUMROWS 4
#define NUMCOLS 4


byte buttons[NUMROWS][NUMCOLS] = {
  {0,1,2,3},
  {4,5,6,7},
  {8,9},
  {10,11}
};

struct rotariesdef {
  byte pin1;
  byte pin2;
  int ccwchar;
  int cwchar;
  volatile unsigned char state;
};

rotariesdef rotaries[NUMROTARIES] {
  {0,1,24,25,0},
  {2,3,26,27,0},
  {4,5,28,29,0},
  {6,7,30,31,0},
};

#define DIR_CCW 0x10
#define DIR_CW 0x20
#define R_START 0x0

#ifdef HALF_STEP
#define R_CCW_BEGIN 0x1
#define R_CW_BEGIN 0x2
#define R_START_M 0x3
#define R_CW_BEGIN_M 0x4
#define R_CCW_BEGIN_M 0x5
const unsigned char ttable[6][4] = {
  // R_START (00)
  {R_START_M,            R_CW_BEGIN,     R_CCW_BEGIN,  R_START},
  // R_CCW_BEGIN
  {R_START_M | DIR_CCW, R_START,        R_CCW_BEGIN,  R_START},
  // R_CW_BEGIN
  {R_START_M | DIR_CW,  R_CW_BEGIN,     R_START,      R_START},
  // R_START_M (11)
  {R_START_M,            R_CCW_BEGIN_M,  R_CW_BEGIN_M, R_START},
  // R_CW_BEGIN_M
  {R_START_M,            R_START_M,      R_CW_BEGIN_M, R_START | DIR_CW},
  // R_CCW_BEGIN_M
  {R_START_M,            R_CCW_BEGIN_M,  R_START_M,    R_START | DIR_CCW},
};
#else
#define R_CW_FINAL 0x1
#define R_CW_BEGIN 0x2
#define R_CW_NEXT 0x3
#define R_CCW_BEGIN 0x4
#define R_CCW_FINAL 0x5
#define R_CCW_NEXT 0x6

const unsigned char ttable[7][4] = {
  // R_START
  {R_START,    R_CW_BEGIN,  R_CCW_BEGIN, R_START},
  // R_CW_FINAL
  {R_CW_NEXT,  R_START,     R_CW_FINAL,  R_START | DIR_CW},
  // R_CW_BEGIN
  {R_CW_NEXT,  R_CW_BEGIN,  R_START,     R_START},
  // R_CW_NEXT
  {R_CW_NEXT,  R_CW_BEGIN,  R_CW_FINAL,  R_START},
  // R_CCW_BEGIN
  {R_CCW_NEXT, R_START,     R_CCW_BEGIN, R_START},
  // R_CCW_FINAL
  {R_CCW_NEXT, R_CCW_FINAL, R_START,     R_START | DIR_CCW},
  // R_CCW_NEXT
  {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START},
};
#endif

byte rowPins[NUMROWS] = {18,19,20,21}; 
byte colPins[NUMCOLS] = {7,8,14,15}; 

Keypad buttbx = Keypad( makeKeymap(buttons), rowPins, colPins, NUMROWS, NUMCOLS); 

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, 
  JOYSTICK_TYPE_JOYSTICK, 12, 0,
  false, false, false, false, false, false,
  false, false, false, false, false);

void setup() {
  Joystick.begin();
  rotary_init();}

void loop() { 

  CheckAllEncoders();

  CheckAllButtons();

}

void CheckAllButtons(void) {
      if (buttbx.getKeys())
    {
       for (int i=0; i<LIST_MAX; i++)   
        {
           if ( buttbx.key[i].stateChanged )   
            {
            switch (buttbx.key[i].kstate) {  
                    case PRESSED:
                    case HOLD:
                              Joystick.setButton(buttbx.key[i].kchar, 1);
                              break;
                    case RELEASED:
                    case IDLE:
                              Joystick.setButton(buttbx.key[i].kchar, 0);
                              break;
            }
           }   
         }
     }
}


void rotary_init() {
  for (int i=0;i<NUMROTARIES;i++) {
    pinMode(rotaries[i].pin1, INPUT);
    pinMode(rotaries[i].pin2, INPUT);
    #ifdef ENABLE_PULLUPS
      digitalWrite(rotaries[i].pin1, HIGH);
      digitalWrite(rotaries[i].pin2, HIGH);
    #endif
  }
}


unsigned char rotary_process(int _i) {
   unsigned char pinstate = (digitalRead(rotaries[_i].pin2) << 1) | digitalRead(rotaries[_i].pin1);
  rotaries[_i].state = ttable[rotaries[_i].state & 0xf][pinstate];
  return (rotaries[_i].state & 0x30);
}

void CheckAllEncoders(void) {
  for (int i=0;i<NUMROTARIES;i++) {
    unsigned char result = rotary_process(i);
    if (result == DIR_CCW) {
      Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0);
    };
    if (result == DIR_CW) {
      Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0);
    };
  }
}



Warum gibt es dann im Quellcode rotary encoder wenn du gar keine hast?

Achja mal wieder so ein Fall von
Noch gar keine Ahnung vom Programmieren
Ein ähnliches Projekt her genommen und nur pi mal Daumen angepasst
und jetzt funktioniert es auch nur pi mal daumen.

Schnellschuss ohne sorgfältige Analyse des Quellcodes

ein array aus ungleichmäßig langen Zeilen funktioniert wahrscheinlich nicht
Und Tastaturmatrixen werden mit Dioden ausgestattet damit kein ghosting stattfindet

vgs

1 Like

7+5=12, Pro Micro hat 18 Pins. Mein Fazit: du brauchst keine Matrix, damit wird auch dein Ghosting Problem weg und überflüssige Encoders auch.
schau

//BUTTON BOX
#include <Joystick.h>
#define NUMBUTTONS 12
byte buttons[NUMBUTTONS] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15};

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,
                   JOYSTICK_TYPE_JOYSTICK, NUMBUTTONS, 0,
                   false, false, false, false, false, false,
                   false, false, false, false, false);

void setup() {
  Joystick.begin();
  for (byte i = 0; i < NUMBUTTONS; i++)pinMode(buttons[i], INPUT_PULLUP);
}

void loop() {
  for (byte i = 0; i < NUMBUTTONS; i++)Joystick.setButton(i, !digitalRead(buttons[i]));
}

Hatte erwähnt das ich in Sachen Quellcode unwissend bin und mir hier Hilfe erhoffe. Trotzdem Danke für den wenig konstruktiven Beitrag

Die Matrix möchte ich beibehalten da ich so die ButtonBox flexibel erweitern kann.

Dann solltest Du auch die Hinweise von @StefanL38 beachten:

Dein Schaltbild der Matrix verstehe ich auch nicht - Da sind auch Lampen drin ???
Du solltest eine korrektes Schaltbild deiner Matrix posten.

Dann mach doch.

Oder sollen wir für dich den Sketch programmieren und testen?

Kippschalter #5 und Taster #6 haben LED-Lampen eingebaut @MicroBahner, daher die Lampen in der Matrix. Können ignoriert werden, die sind ganz sicher nicht die Ursache

Ihr seid Fachleute auf dem Gebiet, ich hingegen verstehe nur Bahnhof. Falls mir also jemand helfen mag dann wäre es hilfreich so zu erklären, dass es ein Laie versteht. Auf irgenwelche Seiten mit Fachchinesisch zu verlinken ist verschwendete Zeit.

Die Tatsache, dass die Schalter Lampen eingebaut haben, heißt ja nicht, dass die auch in der Matrix verschaltet sind. Oder hast Du das so gemacht?

Du hast deine Button-Box doch verdrahtet oder? Dann musst Du doch auch wissen, was Du da gemacht hast. Und genau das müssen wir wissen, damit wir helfen können. Nicht mit einem Prinzipbildchen, sondern exakt so wie Du die Drähte und Schalter verbunden hast. Sonst ist das alles nur Raterei.

Aufgrund deiner Beschreibung vermute ich mal, dass Du keine Dioden eingebaut hast. Dann kann das schonmal prinzipiell mit Schaltern nicht funktionieren.

P.S. Und wo der Rotary-Encoder ist, der im Sketch vorkommt sollten wir auch wissen. ( hat ja auch (@StefanL38 schon angesprochen).

lieber weiter unten
vgs

ich bin schlecht in Erziehung. bin raus.

Die Matrix habe ich selbst erstellt, die Verkabelung entspricht genau der abgebildeten Matrix. Dioden sind keine verbaut. Die verbauten Kipp- und Druckschalter habe ich ebenfalls oben abgebildet und entsprechend der Lage in der Matrix nummeriert. Ein Rotary-Encoder ist nicht verbaut auch wenn er im Quell-Code aufgeführt ist.

Also ein bisschen mehr eigenes Engagement ist schon notwendig.
Bis jetzt machst du hier den Eindruck

Schreibt mir entweder

ein fertiges Programm
oder
schreibt mir einen auf meine Anwendung zugeschnittenen kompletten Elektronik kurs

Und das ist von deiner Seite aus sehr viel verlangt bei minimalem eigenem Engagement.

Du wirst einen ganz anderen Eindruck hinterlassen wenn du konkrete Fragen stellst.

Um mit gutem Beispiel voranzugehen

"Wo finde ich grundlegende Informationen / eine für Elektroniklaien einfach verständliche Einführung wie man eine Tastaturmatrix abfragt?"

nächstes Beispiel:

"Mit was für Stichworten muss ich denn suchen damit ich einführende Informationen finde
die zu meinem Projekt passen?"

Antwort: "Arduino Democode Tastaturmatrix"

Und hier gleich der Link dazu

https://www.google.com/search?q=arduino+democode+tastaturmatrix

googeln kriegste doch wohl hin oder?
So viel Eigenengagement wird hier schon erwartet.

Und dann könnte die nächste Frage lauten:
"welcher von den Links die ich jetzt per googeln gefunden habe ist dann am besten geeignet?

Der hier

Das ist kein Schaltbild, und speziell im Falle der Lampen kann man die wirkliche Verdrahtung nicht erkennen.

Dann wird es nicht funktionieren.

Ein wenig Elektrotechnik Grundlagen wirst Du dir dazu schon aneignen müssen.

Auch ich bin dieser Meinung. (hab aber den Sketch nicht angeschaut.)
Bei einer normalen Tastaturmatrix kann man nicht zweifelsfrei mehrere Taster gleichzeitig detektieren.
Schalter sind prinzipiell Taster die lange Zeit in einer Stellung bleiben. Taster werden nur kurz betätigt.
Wenn jeder taster /Schalter eine Diode in Reihe bekommt kann man mehrere Taster/Schalter gleichzeitig betätigen und auch auslesen.

Hier Tastenmatrix an Mikrocontrollern eine Erklährung.

Grüße Uwe

Hm.

Ich würde das Ganze als eine normale 4 x 4 Matrix machen.

Wenn man in einer (z.b. 4x4) Matrix nicht alle Taster braucht, kann man die, bei richtiger Programmierung, auch mit 10 Tasten verwenden.

Da Taster 11 bis 16 NIE ausgelöst werden (weil bei dir nicht da), ist auch keine Reaktion erforderlich.
ABER Schalt-technisch und auch Software-Seitig sollten sie vorhanden sein.

Im Code oben und auch in den Link im Beispiel wird eine Matrix definiert.
Die liefert das Ergebnis des Tastendruck. Da körperlich einige Tasten diese Matrix NIE gedrückt werden können, wird auch nicht der WERT der Matrix (A) ausgegeben.

Solltest du später mal (wie du sagtest) deine Matrix erweitert, musst du halt ein Taster an die Stelle setzen und den Wert (im Beispiel A) auswerten.

Was Bedeutet : du brauchst entweder 2 x 4 Pins am Board, oder eine PCF-8574 wo die Matrix angeschlossen wird. Schaltbeispiele inc. Code findest du im Netz.

Nun noch 2 Pins gegen GND wie in deiner Schaltung für die in deinen Schaltbild ROT-Markierten Teile (die mit den LED).

Fertig ist das ganze.

Hier ein Link wie das mit der 4x4er Matrix funktioniert.
https://draeger-it.blog/arduino-lektion-68-4x4-matrix-tastatur/

Was deine Schalter im Gehäuse angeht. Die würde ich (um Pins zu sparen) auch an einen PCF-8574 hängen (Adresse beachten). Dann im Code einfach den Zustand den passenden BIT abfragen. Auch Fertig.

Ist zwar nicht die feine Art, aber du kannst sogar die beiden LED'S an den selben PCF-8574 hängen.

Ich denke mit meinen Hinweisen sollte deine Tastatur funktionieren.

Gruß

Pucki

Dein Link zeigt ein 4x4 Tasterfeld.
Taster werden für gewöhnlich nur kurz und einzeln betätigt.

Der TO hat aber Schalter die für längere Zeit auf Stellung "Schalter geschlossen" stehen.
Ohne Dioden ist dann das Auslesen der anderen Schalter / Taster nicht möglich,
weil der geschlossene Schalter für das sogenannte Ghosting sorgt.

Ein PCF8574 hat 8 Pins.

Ein SX1509 hat 16 pins und noch besser: bereits einen Tastatur-Scanner im Chip selbst. Man muss das Zeilen-/Spalten-Umschalten also gar nicht mehr programmieren.

Nichts desto trotz braucht auch diese Lösung Dioden gegen das Ghosting und eine Programmanpassung weil sowohl ein PCF8574 als auch ein SX1509 natürlich anders abgefragt wird wie eine µC-internes Zeilen-/Spalten-Umschalten.

Es ist wie in 98% der DIY-Projekte.
Entweder der Nachbau passt 100,0000% oder man muss Anpassungen am Code vornehmen.

Es gibt einfach zu viele Chips auf den Plani :wink: Den von dir genannten kannte ich noch nicht. Da muss ich mich selbst mal schlau machen. Ich habe halt meine Kenntnisse zum großen Teil aus Fachbüchern und den Rest "sammele" ich im Internet, je nach Problem wenn ich zu den Problem keine Lösung kenne.

OK. Den Einbau von Dioden ist sicher von Vorteil.

Aber wie vermutlich nicht richtig erwähnt. Ich würde Tasten und Schalter GETRENNT betreiben.

Weshalb ich auch bei den PCF den Hinweis auf die Adresse geschrieben habe.

Den kann ich zu 1000 % :wink: zustimmen. Ich lern(t)e auch nur durch die Beispiele die ich dann für meine Projekte anpasse. Einfach nur 1:1 nachbauen ist mir eh zu langweilig.

Aber 1 habe ich schnell gelernt. Es gibt immer ganz viele Lösungen zum Ziel.

Bei nur 5 Tastern würde sogar noch die "Widerstandslösung" funktionieren. Aber der TO hat ja geschrieben das er mal das Feld erweitern möchte. Und dann wirds mit der Lösung langsam ziemlich eng. Weshalb ich sie nicht erwähnt habe.

Gruß

Pucki

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.