Go Down

Topic: Stellbereich (Wertebereich) des Joysticks anpassen (Read 247 times) previous topic - next topic

Westmaerker

Hi Peps,

ich habe mir in der vergangenen Zeit einen Regler aufgebaut, dessen Bewegung über einen Poti erfasst wird, der seine Werte an einen Arduino Leonardo weiter gibt. Der Regler hat nur einen Arbeitsbereich, nämlich die Auslenkung um 45 Grad nach vorne und hinten. Also sozusagen eine X-Achse mit zentrierter Stellung und einem Bewegungsbereich in positiver und negativer X-Richtung.

Nun stellt sich bei der Integration dieses Reglers in Games das Problem, dass der Regler nicht die maximale Auslenkung erreichen kann, die in verschiedenen Games wie FlySim etc. möglich sind. Ich arbeite da mit einer herkömmlichen Joystick-Bibliothek im Arduino. Ich habe bisher noch keine Möglichkeit gefunden, im Quelltext Anpassung vorzunehmen, um den Stellbereich des Reglers genau auf die Ingame-Stellbereiche anzupassen. Viele Spiele haben keine guten Optionen, um das präzise einzustellen. Deshalb wollte ich versuchen hier im Forum zu erfahren, welche Möglichkeiten der Anpassung es direkt im Arduino gibt.  ;)

LG
WM

HotSystems

Ich kenne deinen Joystick und deinen Sketch nicht, aber vermute, mit der Funktion "map()" könnte das funktionieren.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

zwieblum


Doc_Arduino

Hallo,

ich habe das auch schon gemacht für so einen Miniatursteuerknüppel wo zwei Potis über Kreuz verbaut sind.
Du musst dir eine Kalibrierroutine schreiben in dem du den Mittelpunkt beider Achsen erfasst und die Werte der 4 Endausschläge. Mit diesen 6 Werten kannste danach im laufenden Programm auf den gewünschten Wertebereich mappen.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Westmaerker

Danke für eure Antworten! :)

Ich kenne deinen Joystick und deinen Sketch nicht, aber vermute, mit der Funktion "map()" könnte das funktionieren.
Ja, davon habe ich auch schon gelesen. Bisher habe ich leider mit dieser Funktion noch nicht gearbeitet.

Joystick in Windoof kalibrieren?
Das reicht nicht aus. Leider. Windows erfasst nur den 'Status Quo'. Die Stellwerte der (physischen) Achsen lassen sich nicht anpassen in Windows.

Hallo,
ich habe das auch schon gemacht für so einen Miniatursteuerknüppel wo zwei Potis über Kreuz verbaut sind.
Du musst dir eine Kalibrierroutine schreiben in dem du den Mittelpunkt beider Achsen erfasst und die Werte der 4 Endausschläge. Mit diesen 6 Werten kannste danach im laufenden Programm auf den gewünschten Wertebereich mappen.
Hi! ;) Kannst du mir das vielleicht noch etwas genauer beschreiben? Evtl. auch via PN? Ich habe ja in meinem Fall nur einen Poti. Also "einen" Steuerknüppel mit einer Achse und zwei Endausschlägen. Ich nutze derzeit die MHeironimus/ArduinoJoystickLibrary und die Prozedur/Code:

void Loop () {
axelValue = analogRead(A0);
Joystick.setThrottle(axelValue);
delay(1);

...
}

HotSystems

Ja, davon habe ich auch schon gelesen. Bisher habe ich leider mit dieser Funktion noch nicht gearbeitet.
Das ist kein Problem.
Hier ist es sehr gut beschrieben.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Doc_Arduino

Hallo,

PN? Mach es einfach nicht. Dafür ist das Forum da.

Ist das jetzt ein USB Joystick oder einer der an den analogen Eingängen angeschlossen ist?
Wenn USB, dann folge einfach der Beschreibung zur Lib. Eine Kalibrierung ist laut derer vorhanden. "Game Controller Settings".
http://mheironimus.blogspot.com/2016/11/arduino-joystick-library-version-20.html
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Westmaerker

Das ist kein Problem.
Hier ist es sehr gut beschrieben.
Hallo HotSystems,

danke für den Link. Ich habe mich belesen.

Ist das jetzt ein USB Joystick oder einer der an den analogen Eingängen angeschlossen ist?
Wenn USB, dann folge einfach der Beschreibung zur Lib. Eine Kalibrierung ist laut derer vorhanden. "Game Controller Settings".
http://mheironimus.blogspot.com/2016/11/arduino-joystick-library-version-20.html
Hallo Doc_Arduino! :)

Das ist ein selbstgebauter Joystick, der auf A0, 5V und GND angeschlossen ist.

Ich habe heute über den Arduino die maximalen Stellwerte des Joystick-Potis ausgelesen. Normalerweise "schaltet" der Arduino ja von 0 bis 1023. Mein Joystick hingegen kann nicht den kompletten Stellbereich des Potis aus technischen Gründen nutzen. Die Joystickachse beginnt bei voller Auslenkung nach hinten bei einem Wert von ~18, erreicht bei ~492 die Mittelstellung und einen Höchstwert bei voller Auslenkung nach vorne bei ~942. Da fehlt also hinten und vorne was. :D

Dazu habe ich versucht mit der map-Funktion das anzupassen. Die Kompilierung zeigt keinen Fehler. Aber mein heutiger Programmierversuch löst leider mein Problem nicht. Habe ich einen Fehler gemacht?

Code: [Select]


#include "Joystick.h"

Joystick_ Joystick;

// declare variables
int axe1Value;
int StellValue = 0;

void setup() {
// Initialize Button Pins
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(A0, INPUT_PULLUP);

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

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

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

void loop() {
// Axe 1
axe1Value = analogRead(A0);
if (axe1Value > 492) {
 StellValue = map(axe1Value,512,1023,492,942);
 Joystick.setThrottle(StellValue);
}
else (axe1Value < 492); {
 StellValue = map(axe1Value,0,512,18,492);
 Joystick.setThrottle(StellValue);
}
delay(1);


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

delay(50);
}


postmaster-ino

Hi

Du hast einen Bereich von 18...942.
Um von 0 aus Werte zu bekommen, musst Du nur 18 abziehen -> 0...924
Um nun die volle Auflösung zu bekommen, musst Du nur die 924 (MAX_Wert-MIN_Wert) auf 1023 mappen.

Oder verstehe ich Dich nicht richtig?

MfG
anscheinend ist Es nicht erwünscht, einen Foren-internen Link als 'Homepage' einzubinden, damit JEDER nur einen Klick von combie's Liste zum Thema State-Maschine entfernt ist.
... dann eben nicht ...

HotSystems

#9
Sep 12, 2019, 06:22 pm Last Edit: Sep 12, 2019, 06:23 pm by HotSystems
Ja, du hast map nicht ganz verstanden.
Du musst den kompletten, eingelesenen Wert verwenden.

Beispiel:
Ergebnis=map(Axe1value, niedrister vorhandener Wert, höchster vorhandener Wert, niedrigster Sollwert, höchster Sollwert)
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Doc_Arduino

Hallo,

wenn das kein USB Joystick wozu dann die USB Lib?

Der einfachste Fall wie die anderen schon beschrieben haben in dem du die ermittelten Endwerte direkt in map einsetzt. Zusätzlich musst du zwischen hinten/vorn ab Mittelstellung unterscheiden - vorm mappen!
Weil die Mittelstellung muss nicht in der Mitte der Werte liegen, mechanisch bedingt, sieht man hier auch.

hinten = 18
mitte = 492
vorn = 942

wenn Wert kleiner 492 mappe zwischen 0 bis 512
wenn Wert größer 492 mappe zwischen 512 bis 1023
ansonsten gib mitte 512 raus.
Irgendwann bauste dir noch eine Hysterese ein.

Mit Kalibrierroutine musste nacheinander die Werte abfragen und auf Tastendruck in einer Variablen speichern und zur nächsten Endwertabfrage springen usw. Dafür brauchste einen entprellten Taster der nicht retriggert werden kann.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Westmaerker

Vielen vielen Dank an euch alle!  ;D  ;D Ihr habt mir sehr geholfen.



Soweit läuft das jetzt alles. ABER: Ich habe nun versucht den Joystick etwas zu "enthysterisieren". Bei voller Auslenkung nach Vorne und nach Hinten beginnt die Steuerung im Spiel zu zittern, weil die analoge Ungenauigkeit des Potis wieder den Wertebereich variieren lässt.

Jetzt wollte ich dafür die map-Funktion missbrauchen und ihm sagen, dass er bei Werten unterhalb von 20 dann 0 ausgeben soll, sodass die Steuerung im Spiel bei voller Auslenkung nach Hinten nicht zittert und bei Werten über 939 dann 1023 ausgegeben werden soll, um die Steuerung nicht im Spiel bei voller Auslenkung nach Vorne so stark rütteln zu lassen. Funktioniert aber nicht. :)

Habt ihr vielleicht Lösungsvorschläge dafür?  ???

Code: [Select]
#include "Joystick.h"

Joystick_ Joystick;

// declare variables
int axe1Value;
int StellValue;

void setup() {
// Initialize Button Pins
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(A0, INPUT_PULLUP);

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

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

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

void loop() {{
// Axe 1
axe1Value = analogRead(A0);
 if (axe1Value > 495) {
  StellValue = map(axe1Value,492,942,512,1023);
  Joystick.setThrottle(StellValue);
 }
 if (axe1Value > 939) {
  StellValue = map(axe1Value,939,942,1023,1023);
  Joystick.setThrottle(StellValue);
 }
 if (axe1Value < 20) {
  StellValue = map(axe1Value,15,20,0,0);
  Joystick.setThrottle(StellValue);
 }
 else (axe1Value < 487); {
  StellValue = map(axe1Value,18,492,0,512);
  Joystick.setThrottle(StellValue);
 }
}
delay(1);


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

delay(50);
}

michael_x

Quote
Code: [Select]
else (axe1Value < 487); {
  StellValue = map(axe1Value,18,492,0,512);
  Joystick.setThrottle(StellValue);
 }
Da ist nur der Teil (axe1Value < 487); die sinnlose Anweisung im else-Zweig.
Das meinst du sicher anders.

Doc_Arduino

Hallo,

die Daten prüfen und erst am Ende ausgeben.
Mach was sinnvolles daraus.

Code: [Select]

void setup(void) {
  Serial.begin(250000);
  Serial.println();

  for (unsigned int i=0; i<1024; i++)
  {
    Serial.print("Einlesewert ");
    Serial.print(i);
    Serial.print('\t');
    Serial.print("Ausgabewert ");
    Serial.print( mappen(i) );
    Serial.println();    
  }
}

void loop(void) {

}


unsigned int mappen (unsigned int joy)
{
  const unsigned int LimitMIN = 20;
  const unsigned int LimitMAX = 940;
  const unsigned int MITTE = 492;
  const byte HYST = 5;
  unsigned int value = 0;

  //axis = analogRead(A0);
  unsigned int axis = joy;

  // Werte im Limit ?
  if (axis >= LimitMIN && axis <= LimitMAX)
  {
    // kleiner Mitte inkl. Hysterese?
    if (axis <= MITTE-HYST) {
      value = map(axis, LimitMIN, MITTE-HYST, 0, 511);
    }
    // größer Mitte inkl. Hysterese?
    if (axis >= MITTE+HYST) {
      value = map(axis, MITTE+HYST, LimitMAX, 513, 1023);
    }
  }

  // in Mittelstellung inkl. Hysterese?
  if ( (axis>MITTE-HYST) && (axis<MITTE+HYST) )
  {
      value = 512;
  }

  // Werte außerhalb des Limits ?
  if (axis < LimitMIN) value = 0;
  if (axis > LimitMAX) value = 1023;

  //Joystick.setThrottle(value);
  return value;
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Westmaerker

Da ist nur der Teil (axe1Value < 487); die sinnlose Anweisung im else-Zweig.
Das meinst du sicher anders.
Upppss... Ja, du hast recht. Ich hatte da gar nicht mehr drüber nachgedacht. Danke! :)



Hallo,

die Daten prüfen und erst am Ende ausgeben.
Mach was sinnvolles daraus.

Code: [Select]

void setup(void) {
  Serial.begin(250000);
  Serial.println();

  for (unsigned int i=0; i<1024; i++)
  {
    Serial.print("Einlesewert ");
    Serial.print(i);
    Serial.print('\t');
    Serial.print("Ausgabewert ");
    Serial.print( mappen(i) );
    Serial.println();   
  }
}

void loop(void) {

}


unsigned int mappen (unsigned int joy)
{
  const unsigned int LimitMIN = 20;
  const unsigned int LimitMAX = 940;
  const unsigned int MITTE = 492;
  const byte HYST = 5;
  unsigned int value = 0;

  //axis = analogRead(A0);
  unsigned int axis = joy;

  // Werte im Limit ?
  if (axis >= LimitMIN && axis <= LimitMAX)
  {
    // kleiner Mitte inkl. Hysterese?
    if (axis <= MITTE-HYST) {
      value = map(axis, LimitMIN, MITTE-HYST, 0, 511);
    }
    // größer Mitte inkl. Hysterese?
    if (axis >= MITTE+HYST) {
      value = map(axis, MITTE+HYST, LimitMAX, 513, 1023);
    }
  }

  // in Mittelstellung inkl. Hysterese?
  if ( (axis>MITTE-HYST) && (axis<MITTE+HYST) )
  {
      value = 512;
  }

  // Werte außerhalb des Limits ?
  if (axis < LimitMIN) value = 0;
  if (axis > LimitMAX) value = 1023;

  //Joystick.setThrottle(value);
  return value;
}


Dir auch vielen Dank dafür. :) ;)


Nun funktioniert alles wie gewünscht. Ich danke euch für eure Unterstützung hier im Forum! :)

Go Up