Het WebJoystick voorbeeld maakt een virtuele joystick-interface die toegankelijk is via elke webbrowser. Ontwikkeld voor het ESP32 educatieve platform met verbeterde robotica mogelijkheden, ingebouwde motorbesturing en naadloze integratie met robotica educatiemodules. Perfect voor het aansturen van robots, voertuigen of elk systeem dat 2D-positie-invoer nodig heeft.
Of u kunt de volgende kits kopen:
Openbaarmaking: Sommige van de links in deze sectie zijn Amazon-affiliate links. We kunnen een commissie ontvangen voor aankopen die via deze links worden gedaan, zonder extra kosten voor u. We waarderen uw steun.
Volg deze stappen nauwkeurig:
Verbind de ESP32 met uw computer via een USB-kabel.
Start de Arduino IDE op uw computer.
Selecteer het juiste ESP32 board (bijvoorbeeld ESP32 Dev Module) en de juiste COM-poort.
Ga naar het Libraries icoon in de linker balk van de Arduino IDE.
Zoek op "DIYables ESP32 WebApps" en vind de DIYables ESP32 WebApps Library van DIYables.
Klik op de Install knop om de library te installeren.


#include <DIYables_ESP32_Platform.h>
#include <DIYablesWebApps.h>
const char WIFI_SSID[] = "YOUR_WIFI_SSID";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
static ESP32ServerFactory serverFactory;
DIYablesWebAppServer webAppsServer(serverFactory, 80, 81);
DIYablesHomePage homePage;
DIYablesWebJoystickPage webJoystickPage(false, 5);
int currentJoystickX = 0;
int currentJoystickY = 0;
void setup() {
Serial.begin(9600);
delay(1000);
Serial.println("DIYables ESP32 WebApp - Web Joystick Example");
webAppsServer.addApp(&homePage);
webAppsServer.addApp(&webJoystickPage);
webAppsServer.setNotFoundPage(DIYablesNotFoundPage());
if (!webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD)) {
while (1) {
Serial.println("Failed to start WebApp server!");
delay(1000);
}
}
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
currentJoystickX = x;
currentJoystickY = y;
Serial.println("Joystick - X: " + String(x) + ", Y: " + String(y));
}
});
webJoystickPage.onJoystickValueToWeb([]() {
webJoystickPage.sendToWebJoystick(currentJoystickX, currentJoystickY);
Serial.println("Web client requested values - Sent to Web: X=" + String(currentJoystickX) + ", Y=" + String(currentJoystickY));
});
}
void loop() {
webAppsServer.loop();
delay(10);
}
const char WIFI_SSID[] = "YOUR_WIFI_NETWORK";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
DIYables WebApp - Web Joystick Example
INFO: Added app /
INFO: Added app /web-joystick
DIYables WebApp Library
Platform: ESP32
Network connected!
IP address: 192.168.0.2
HTTP server started on port 80
Configuring WebSocket server callbacks...
WebSocket server started on port 81
WebSocket URL: ws://192.168.0.2:81
WebSocket server started on port 81
==========================================
DIYables WebApp Ready!
==========================================
📱 Web Interface: http://192.168.0.2
🔗 WebSocket: ws://192.168.0.2:81
📋 Available Applications:
🏠 Home Page: http://192.168.0.2/
🕹️ Web Joystick: http://192.168.0.2/web-joystick
==========================================
Als u niets ziet, herstart dan de ESP32.
Noteer het IP-adres dat verschijnt en typ dit adres in de adresbalk van een webbrowser op uw smartphone of computer.
Bijvoorbeeld: http://192.168.0.2
U ziet de startpagina zoals hieronder:
U kunt ook direct de pagina openen door het IP-adres te gebruiken gevolgd door /web-joystick. Bijvoorbeeld: http://192.168.0.2/web-joystick
Probeer de virtuele joystick te bedienen door te klikken en te slepen binnen het joystickgebied en observeer de X/Y coördinaten (-100 tot +100) in de Seriële Monitor.
De joystick kan met verschillende parameters worden ingesteld:
DIYablesWebJoystickPage webJoystickPage;
DIYablesWebJoystickPage webJoystickPage(false, 5);
De joystick-interface biedt:
Joystick Pad: Cirkelvormig bedieningsvlak voor touch/muis invoer
Positie-indicator: Toont de huidige joystickpositie
Coördinatenweergave: Realtime X/Y waardes (-100 tot +100)
Middelpunt: Visuele referentie voor neutrale positie
Klik en sleep: Klik op de joystick en sleep om te bewegen
Loslaten: Joystick keert terug naar het midden (als autoReturn=true)
Klikpositie: Direct klikken om joystickpositie in te stellen
Aanraken en slepen: Raak joystick aan en sleep met vinger om te bewegen
Multitouch: Gebruik een vinger voor nauwkeurige besturing
Loslaten: Automatisch terug naar midden (indien ingeschakeld)
De joystick geeft coördinaten in een standaard Cartesian systeem:
X-as: -100 (volledig links) tot +100 (volledig rechts)
Y-as: -100 (volledig omlaag) tot +100 (volledig omhoog)
Midden: X=0, Y=0 (neutrale positie)
Hoeken: Diagonale posities combineren X/Y waardes
void setup() {
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
currentJoystickX = x;
currentJoystickY = y;
Serial.println("Joystick - X: " + String(x) + ", Y: " + String(y));
});
}
const int MOTOR_LEFT_PIN1 = 2;
const int MOTOR_LEFT_PIN2 = 3;
const int MOTOR_RIGHT_PIN1 = 4;
const int MOTOR_RIGHT_PIN2 = 5;
const int MOTOR_LEFT_PWM = 9;
const int MOTOR_RIGHT_PWM = 10;
void setup() {
pinMode(MOTOR_LEFT_PIN1, OUTPUT);
pinMode(MOTOR_LEFT_PIN2, OUTPUT);
pinMode(MOTOR_RIGHT_PIN1, OUTPUT);
pinMode(MOTOR_RIGHT_PIN2, OUTPUT);
pinMode(MOTOR_LEFT_PWM, OUTPUT);
pinMode(MOTOR_RIGHT_PWM, OUTPUT);
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
controlRobot(x, y);
});
}
void controlRobot(int x, int y) {
int leftSpeed = y + x;
int rightSpeed = y - x;
leftSpeed = constrain(leftSpeed, -100, 100);
rightSpeed = constrain(rightSpeed, -100, 100);
if (leftSpeed > 0) {
digitalWrite(MOTOR_LEFT_PIN1, HIGH);
digitalWrite(MOTOR_LEFT_PIN2, LOW);
analogWrite(MOTOR_LEFT_PWM, map(leftSpeed, 0, 100, 0, 255));
} else if (leftSpeed < 0) {
digitalWrite(MOTOR_LEFT_PIN1, LOW);
digitalWrite(MOTOR_LEFT_PIN2, HIGH);
analogWrite(MOTOR_LEFT_PWM, map(-leftSpeed, 0, 100, 0, 255));
} else {
digitalWrite(MOTOR_LEFT_PIN1, LOW);
digitalWrite(MOTOR_LEFT_PIN2, LOW);
analogWrite(MOTOR_LEFT_PWM, 0);
}
if (rightSpeed > 0) {
digitalWrite(MOTOR_RIGHT_PIN1, HIGH);
digitalWrite(MOTOR_RIGHT_PIN2, LOW);
analogWrite(MOTOR_RIGHT_PWM, map(rightSpeed, 0, 100, 0, 255));
} else if (rightSpeed < 0) {
digitalWrite(MOTOR_RIGHT_PIN1, LOW);
digitalWrite(MOTOR_RIGHT_PIN2, HIGH);
analogWrite(MOTOR_RIGHT_PWM, map(-rightSpeed, 0, 100, 0, 255));
} else {
digitalWrite(MOTOR_RIGHT_PIN1, LOW);
digitalWrite(MOTOR_RIGHT_PIN2, LOW);
analogWrite(MOTOR_RIGHT_PWM, 0);
}
}
#include <Servo.h>
Servo panServo;
Servo tiltServo;
void setup() {
panServo.attach(9);
tiltServo.attach(10);
panServo.write(90);
tiltServo.write(90);
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
controlServos(x, y);
});
}
void controlServos(int x, int y) {
int panAngle = map(x, -100, 100, 0, 180);
int tiltAngle = map(y, -100, 100, 180, 0);
panServo.write(panAngle);
tiltServo.write(tiltAngle);
Serial.println("Pan: " + String(panAngle) + "°, Tilt: " + String(tiltAngle) + "°");
}
const int LED_UP = 2;
const int LED_DOWN = 3;
const int LED_LEFT = 4;
const int LED_RIGHT = 5;
const int LED_CENTER = 13;
void setup() {
pinMode(LED_UP, OUTPUT);
pinMode(LED_DOWN, OUTPUT);
pinMode(LED_LEFT, OUTPUT);
pinMode(LED_RIGHT, OUTPUT);
pinMode(LED_CENTER, OUTPUT);
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
updateLEDIndicators(x, y);
});
}
void updateLEDIndicators(int x, int y) {
digitalWrite(LED_UP, LOW);
digitalWrite(LED_DOWN, LOW);
digitalWrite(LED_LEFT, LOW);
digitalWrite(LED_RIGHT, LOW);
digitalWrite(LED_CENTER, LOW);
if (abs(x) < 10 && abs(y) < 10) {
digitalWrite(LED_CENTER, HIGH);
return;
}
if (y > 20) digitalWrite(LED_UP, HIGH);
if (y < -20) digitalWrite(LED_DOWN, HIGH);
if (x > 20) digitalWrite(LED_RIGHT, HIGH);
if (x < -20) digitalWrite(LED_LEFT, HIGH);
}
void setup() {
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
handleJoystickInput(x, y);
});
webJoystickPage.setAutoReturn(false);
webJoystickPage.setSensitivity(10.0);
}
void handleJoystickInput(int x, int y) {
static bool precisionMode = false;
if (abs(x) > 95 && abs(y) > 95) {
precisionMode = !precisionMode;
if (precisionMode) {
webJoystickPage.setSensitivity(1.0);
Serial.println("Precision mode ON");
} else {
webJoystickPage.setSensitivity(10.0);
Serial.println("Precision mode OFF");
}
}
}
void processJoystickWithDeadZone(int x, int y) {
const int DEAD_ZONE = 15;
int filteredX = (abs(x) < DEAD_ZONE) ? 0 : x;
int filteredY = (abs(y) < DEAD_ZONE) ? 0 : y;
if (filteredX != 0) {
filteredX = map(abs(filteredX), DEAD_ZONE, 100, 0, 100);
filteredX = (x < 0) ? -filteredX : filteredX;
}
if (filteredY != 0) {
filteredY = map(abs(filteredY), DEAD_ZONE, 100, 0, 100);
filteredY = (y < 0) ? -filteredY : filteredY;
}
controlDevice(filteredX, filteredY);
}
class SpeedController {
private:
int targetX = 0, targetY = 0;
int currentX = 0, currentY = 0;
unsigned long lastUpdate = 0;
const int RAMP_RATE = 5;
public:
void setTarget(int x, int y) {
targetX = x;
targetY = y;
}
void update() {
if (millis() - lastUpdate > 20) {
if (currentX < targetX) {
currentX = min(currentX + RAMP_RATE, targetX);
} else if (currentX > targetX) {
currentX = max(currentX - RAMP_RATE, targetX);
}
if (currentY < targetY) {
currentY = min(currentY + RAMP_RATE, targetY);
} else if (currentY > targetY) {
currentY = max(currentY - RAMP_RATE, targetY);
}
applyControlValues(currentX, currentY);
lastUpdate = millis();
}
}
void applyControlValues(int x, int y) {
Serial.println("Ramped - X: " + String(x) + ", Y: " + String(y));
}
};
SpeedController speedController;
void setup() {
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
speedController.setTarget(x, y);
});
}
void loop() {
server.loop();
speedController.update();
}
void setupRobotCar() {
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
int leftMotor = y + (x / 2);
int rightMotor = y - (x / 2);
leftMotor = constrain(leftMotor, -100, 100);
rightMotor = constrain(rightMotor, -100, 100);
setMotorSpeed(9, 2, 3, leftMotor);
setMotorSpeed(10, 4, 5, rightMotor);
});
}
void setMotorSpeed(int pwmPin, int dir1Pin, int dir2Pin, int speed) {
if (speed > 0) {
digitalWrite(dir1Pin, HIGH);
digitalWrite(dir2Pin, LOW);
analogWrite(pwmPin, map(speed, 0, 100, 0, 255));
} else if (speed < 0) {
digitalWrite(dir1Pin, LOW);
digitalWrite(dir2Pin, HIGH);
analogWrite(pwmPin, map(-speed, 0, 100, 0, 255));
} else {
digitalWrite(dir1Pin, LOW);
digitalWrite(dir2Pin, LOW);
analogWrite(pwmPin, 0);
}
}
#include <Servo.h>
Servo panServo, tiltServo;
int panOffset = 90, tiltOffset = 90;
void setupCameraGimbal() {
panServo.attach(9);
tiltServo.attach(10);
panServo.write(panOffset);
tiltServo.write(tiltOffset);
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
int panPos = panOffset + map(x, -100, 100, -45, 45);
int tiltPos = tiltOffset + map(y, -100, 100, -30, 30);
panPos = constrain(panPos, 0, 180);
tiltPos = constrain(tiltPos, 0, 180);
panServo.write(panPos);
tiltServo.write(tiltPos);
});
}
const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;
void setupRGBControl() {
pinMode(RED_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
int red = map(abs(x), 0, 100, 0, 255);
int green = map(abs(y), 0, 100, 0, 255);
int blue = map(abs(x + y), 0, 141, 0, 255);
if (x > 0 && y > 0) {
blue = 0;
} else if (x < 0 && y > 0) {
red = 0;
} else if (x < 0 && y < 0) {
green = 0;
} else if (x > 0 && y < 0) {
green = blue = 0;
}
analogWrite(RED_PIN, red);
analogWrite(GREEN_PIN, green);
analogWrite(BLUE_PIN, blue);
});
}
1. Joystick reageert niet
Controleer de WebSocket verbinding in de browser console
Controleer netwerkconnectiviteit
Vernieuw de browsertab
Controleer de Seriële Monitor op foutmeldingen
2. Schokkerige of inconsistente beweging
Verhoog de gevoeligheid om minder frequente updates te ontvangen
Implementeer dead zone filtering
Voeg snelheidsopbouw toe voor vloeiende overgangen
Controleer mogelijke netwerkvertraging
3. Auto-terugkeer werkt niet
Controleer instelling: webJoystickPage.setAutoReturn(true)
Controleer browsercompatibiliteit (sommige touch apparaten verschillen)
Test met verschillende invoermethoden (muis vs touch)
4. Waardes bereiken niet het volledige bereik
Controleer joystick calibratie in de webinterface
Controleer coördinatenberekening in callback
Test met verschillende browsers en apparaten
Voeg uitgebreide debugging toe:
void debugJoystickState(int x, int y) {
Serial.println("=== Joystick Debug ===");
Serial.println("X: " + String(x) + " (" + String(map(x, -100, 100, 0, 100)) + "%)");
Serial.println("Y: " + String(y) + " (" + String(map(y, -100, 100, 0, 100)) + "%)");
Serial.println("Distance from center: " + String(sqrt(x*x + y*y)));
Serial.println("Angle: " + String(atan2(y, x) * 180 / PI) + "°");
Serial.println("=====================");
}
Gebruik joystick voor richting en sliders voor snelheid/intensiteit:
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
int maxSpeed = getSliderValue();
int scaledX = map(x, -100, 100, -maxSpeed, maxSpeed);
int scaledY = map(y, -100, 100, -maxSpeed, maxSpeed);
controlRobot(scaledX, scaledY);
});
Gebruik joystickposities om digitale pinstatussen te triggeren:
webJoystickPage.onJoystickValueFromWeb([](int x, int y) {
webDigitalPinsPage.setPinState(2, x > 50);
webDigitalPinsPage.setPinState(3, x < -50);
webDigitalPinsPage.setPinState(4, y > 50);
webDigitalPinsPage.setPinState(5, y < -50);
});
Na het beheersen van het WebJoystick voorbeeld kunt u proberen:
WebSlider - Voor extra analoge bediening
WebDigitalPins - Voor discrete aan/uit besturing
WebMonitor - Voor debugging van joystickwaardes
MultipleWebApps - Combineren van joystick met andere bedieningselementen