Joystick analogowy jako symulator myszy

Joystick analogowy jako symulator myszy

Joystick analogowy jest doskonałym manipulatorem do zdalnego kontrolowania ruchu obiektu, którym może być zarówno ramię robota jak i kursor na ekranie. Choć sterowanie z jego pomocą może być mniej precyzyjne to w wielu sytuacjach – gdy brakuje miejsca, a warunki są trudne, joystick jest jedynym wyborem. Dodatkowo przy odpowiednim oprogramowaniu może dość dobrze symulować działanie myszy komputerowej.

Joystick dostarcza na wyjściu dwa sygnały napięciowe, których poziomy są proporcjonalne do wychylenia jego elementu sterującego: czy to drążka czy przesuwnego ślizgacza. Do wytworzenia sygnałów służą zamontowane w joysticku potencjometry. Każdy potencjometr reaguje na ruch elementu sterującego w jednej z dwu osi: X lub Y. W ten sposób sygnały na wyjściu mogą odwzorowywać kierunek ruchu na dwuwymiarowej płaszczyźnie.

Fotografia 1. Joystick analogowy różne wykonania

Na fotografii 1 zostały pokazane przykładowe miniaturowe joysticki analogowe. Element oznaczony literą A jest sterowany przy pomocy drążka zakończonego nasadką, pozwalającą na wygodną manipulację palcami.

Rysunek 1. Joystick z dźwignią wyprowadzenia sygnałów

Sygnały joysticka wyprowadzone są na 5-stykowym złączu. Funkcje poszczególnych wyprowadzeń zostały pokazane na rysunku 1. Wyprowadzenie GND łączy się z masą układu a +V z napięciem odniesienia np. 5 V. Sygnały wyjściowe są dostępne na stykach VRx i VRy. Wyjście SW połączone jest z dodatkowym przyciskiem. Przycisk zwiera do masy po przyciśnięciu drążka joysticka i może być użyty jako sygnał zatwierdzenia.

Na fotografii 1B pokazany został typ joysticka, w którym ścieżki potencjometrów zostały napylone bezpośrednio na płytce stanowiącej część obudowy. Elementem sterującym zamiast drążka jest przesuwana palcem płytka, połączona mechanicznie ze ślizgaczami poruszającymi się po ścieżkach potencjometrów.

Rysunek 2. Joystick przesuwny wyprowadzenia sygnałów

Na rysunku 2 pokazano widok elementu od dołu wraz z rozmieszczeniem sygnałów na złączu. Do GND i +V doprowadza się napięcie odniesienia, a sygnały wyjściowe są dostępne na stykach VRx i VRy.

Joystick zamiast myszki

Taki analogowy joystick można przystosować do poruszania kursorem po ekranie komputera. Potrzebny jest do tego moduł ESP32 z odpowiednim oprogramowaniem. Tym razem część radiowa modułu nie będzie pracowała w trybie Wi-Fi lecz zostanie użyta jako bezprzewodowy interfejs Bluetooth LE. Litery LE oznaczają, że będzie uruchomiony tryb pracy z niskim poborem mocy (moduł ESP32 może także pracować w trybie „starego” Bluetootha, oba rozwiązania nie są ze sobą kompatybilne).

Rysunek 3. Połączenia joysticka z płytką ESP32

Sposób połączenia joysticka analogowego z modułem ESP32 został pokazany na rysunku 3. Napięcie odniesienia pobierane jest z wyprowadzenia modułu dostarczającego napięcie 3,3 V. Wybrano tą wartość ponieważ wewnętrzny przetwornik ADC modułu pracuje z takim poziomem, a wyprowadzenia joysticka VRx i VRy podłączone są do wejść tego przetwornika.

Całą pracę przekształcania zmian poziomów napięć odczytywanych z wyjść joysticka na ruch kursora wykonuje oprogramowanie. Jego główną część stanowi biblioteka dla systemu Arduino o nazwie ESP32-BLE-Mouse, można ją pobrać tu [1]. Biblioteka realizuje obsługę typowych zdarzeń związanych z myszą komputerową: reaguje na kliknięcie lewym, środkowym, prawym przyciskiem myszy, a także na naciskanie przycisków wstecz i dalej. Jest obsługiwane kółko przewijania no i oczywiście ruch myszy przekładany na ruch kursora na ekranie. Składnia poleceń biblioteki ESP32-BLE-Mouse jest podobna do składni języka Arduino w bibliotece dla myszy USB, którą opisano tutaj [2].

Przykładowa komenda poruszająca kursorem o żądaną ilość pikseli w stosunku do pozycji bieżącej wygląda tak:

BleMouse bleMouse;
bleMouse.move(xVal, yVal, wheel);

gdzie:

  • xVal – wartość przesunięcia wzdłuż osi X, dozwolona jest wartość typu char dodatnia lub ujemna,
  • yVal – wartość przesunięcia wzdłuż osi Y, dozwolona jest wartość typu char dodatnia lub ujemna,
  • wheel – wartość przesunięcia kółkiem, dozwolona wartość typu char dodatnia lub ujemna.

W ogólnym zarysie program dla joysticka symulującego działanie myszy komputerowej może wyglądać tak jak na listingu 1.

Listing 1. Pgólny zarys programu dla joysticka symulującego działanie myszy komputerowej

#include <BleConnectionStatus.h>
#include <BleMouse.h>

BleMouse bleMouse;
const int VRxPin = 34;//wejście ADC, wyjscie joysticka VRx
const int VRyPin = 35;//wejście ADC, wyjscie joysticka VRy
int potValueX = 0, potValueY = 0;//wartosci po konwersji ADC
char wektorX=0, wektorY=0;//wartosci przesuniec kursora
int pauza;

void setup() {
 // put your setup code here, to run once:
 Serial.begin(115200);
 bleMouse.begin();
 Serial.println(“Start BLE!”);
 delay(500);
}

void loop() {
 // put your main code here, to run repeatedly:

 potValueX = analogRead(VRxPin);
 potValueY = analogRead(VRyPin);
/*
 tutaj procedura konwersji poziomow napiec odczytanych
 z wyjsc joysticka na przesuniecie kursora
 bool stat_poz = KonwersjaADC_przesuwKursora(
 &pauza, &wektorX,   &wektorY, potValueX, potValueY);
*/
 
if (bleMouse.isConnected())
{
   bleMouse.move(wektorY,wektorX);
}

 delay(pauza);
}

W rzeczywistości trzeba go rozbudować o kilka dodatkowych procedur: rozpoznawania bezruchu – gdy joystick pozostaje w pozycji środkowej, detekcji kierunku ruchu kursora oraz szybkości jego przesuwania co zamyka się w głównej procedurze konwersji sygnałów odczytywanych z joysticka na wartości X, Y jego przesunięcia.

Listing 2. Kompletne oprogramowanie dla środowiska Arduino

/* Program symulujący mysz przy pomocy joystika analogowego
* podłączenie za pośrednictwem ESP32 BlueTooth LE
* v.1-04 */
#include <BleConnectionStatus.h>
#include <BleMouse.h>

BleMouse bleMouse;
const int VRxPin = 34;
const int VRyPin = 35;
int potValueX = 0, potValueY = 0;
int centrum_PortX, centrum_PortY, licznik_usrednienia;
#define ILE_USREDNIEN 50
bool stat_centr;
int pauza;
int wektorX=0, wektorY=0;

static double przesuw_x_ulamek=0, przesuw_y_ulamek=0;
bool WyliczCentrumXY(int ValueX, int ValueY);
bool KonwersjaADC_przesuwKursora(
int *p_pauza, int *p_wektorX, int *p_wektorY, int ValueX, int ValueY);
double ObliczPrzesuw(int przesuw,bool przesuw_plus,double przesuw_ulamek);
//double ObliczPrzesuw1(int przesuw,bool przesuw_plus,double przesuw_ulamek);

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Starting BLE work!");
bleMouse.begin();
centrum_PortX = 0;
centrum_PortY = 0;
licznik_usrednienia = 0;
delay(500);
}

void loop() {
// put your main code here, to run repeatedly:
potValueX = analogRead(VRxPin);
potValueY = analogRead(VRyPin);
stat_centr = WyliczCentrumXY(potValueX, potValueY);

if (stat_centr==false) {
pauza =10;
} else {
bool stat_poz = KonwersjaADC_przesuwKursora(
&pauza, &wektorX, &wektorY, potValueX, potValueY);
Serial.println("pauza, x, y, potX, potY");
Serial.print(pauza); Serial.print(" ;");
Serial.print(wektorX); Serial.print(" ;");
Serial.print(wektorY); Serial.print(" ;");
Serial.print(potValueX);Serial.print(" ;");
Serial.println(potValueY);
if (bleMouse.isConnected()) {
bleMouse.move(wektorY,wektorX);
}

delay(pauza);
}

/* wyliczanie centrum X,Y poprzez uśrednione pomiary
we: wartości odczytane z przetwornika dla portów X i Y joystika
wy: true -centra XY wyliczone */
bool WyliczCentrumXY(int ValueX, int ValueY) {
if (licznik_usrednienia >= ILE_USREDNIEN) return true;

centrum_PortX += ValueX;
centrum_PortY += ValueY;
licznik_usrednienia++;
if (licznik_usrednienia >= ILE_USREDNIEN) {
centrum_PortX = centrum_PortX / licznik_usrednienia;
centrum_PortY = centrum_PortY / licznik_usrednienia;
return true;
} else return false;
}

/* konwersja wartości ADC X i Y na przesunięcie kursora
wy: true -ruch kursora */
bool KonwersjaADC_przesuwKursora(int *p_pauza, int *p_wektorX,
int *p_wektorY, int ValueX, int ValueY) {
#define PAUZA_MS_MAX 50
#define PAUZA_MS_MIN 10
#define CENTRUM_ZERO_ADC 300

bool przesuw_plus_x, przesuw_plus_y;
int przesuw_x, przesuw_y;
double wspolcz;

//wyznaczanie kierunku ruchu kursora w osi X i Y
przesuw_x = centrum_PortX - ValueX;
//odwrócenie kierunku przesuwu w osi X
if (przesuw_x < 0) przesuw_plus_x = true;
//dla joystika analogowego typu Thumb Slide Joystick
//- SparkFun COM-09426
else przesuw_plus_x = false;
przesuw_y = centrum_PortY - ValueY;
if (przesuw_y < 0) przesuw_plus_y = false;
else przesuw_plus_y = true;

//określenie czy pozycja absolutna przesunięć obu wektorów
//znajduje się w obszarze centrum
przesuw_x = abs(przesuw_x);
przesuw_y = abs(przesuw_y);
if ((przesuw_x <= CENTRUM_ZERO_ADC) && (przesuw_y <= CENTRUM_ZERO_ADC)) {
//pozycja joystika w strefie zerowego ruchu
*p_pauza = 50;
*p_wektorX = 0;
*p_wektorY = 0;
przesuw_x_ulamek=0;
przesuw_y_ulamek=0;
return false;
} else {
if (przesuw_x>CENTRUM_ZERO_ADC) {
/* to procedura symulacji dla testów
* if (przesuw_plus_x==false) *p_wektorX =-1 *2;
* else *p_wektorX =1 *2;
*/
przesuw_x_ulamek =ObliczPrzesuw(przesuw_x,przesuw_plus_x,przesuw_x_ulamek);
*p_wektorX =przesuw_x_ulamek;
przesuw_x_ulamek-=*p_wektorX;
} else *p_wektorX =0;

if (przesuw_y>CENTRUM_ZERO_ADC) {
/*
* to procedura symulacji dla testów
* if (przesuw_plus_y==false) *p_wektorY =-1 *2;
* else *p_wektorY =1 *2;
*/
przesuw_y_ulamek =ObliczPrzesuw(przesuw_y,przesuw_plus_y,przesuw_y_ulamek);
*p_wektorY =przesuw_y_ulamek;
przesuw_y_ulamek-=*p_wektorY;
}
else *p_wektorY =0;

*p_pauza =1;
return true;
}
}

/* obliczanie przesuwu w funkcji wychylenia joystika */
double ObliczPrzesuw(int przesuw,bool przesuw_plus,double przesuw_ulamek) {
const int delta_stopien_tab[]={CENTRUM_ZERO_ADC+300,CENTRUM_ZERO_ADC+700,
CENTRUM_ZERO_ADC+800,CENTRUM_ZERO_ADC+1000};
const double delta_mnoznik_tab[]={0.33,0.66,1,1.5,2.0};
const char ile_delta=4;
char x;
double ulamek;

for (x=0;x<ile_delta;x++) {
if (przesuw <delta_stopien_tab[x]) break;
}
ulamek =delta_mnoznik_tab[x];
if (przesuw_plus==false) ulamek =0-ulamek;

return przesuw_ulamek+ulamek;
}

Takie kompletne oprogramowanie dla środowiska Arduino zostało pokazane na listingu 2 i jest dostępne do pobrania tu [3].

Ryszard Szymaniak
biuro@ars.info.pl

[1] źródła biblioteki ESP32-BLE-Mouse: https://bit.ly/3spEERC
[2] opis składni poleceń arduinowej biblioteki myszy: https://bit.ly/3GYOkXa
[3] strona internetowa z programem demonstracyjnym: https://bit.ly/32kKxVk

Artykuł ukazał się w
Elektronika Praktyczna
styczeń 2022

Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik sierpień 2022

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio lipiec - sierpień 2022

Świat Radio

Magazyn krótkofalowców i amatorów CB

Automatyka Podzespoły Aplikacje lipiec 2022

Automatyka Podzespoły Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna sierpień 2022

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Elektronika dla Wszystkich sierpień 2022

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów