This commit is contained in:
2026-08-13 13:04:44 +02:00
parent aa76c1b274
commit d77e7f49e0
@@ -0,0 +1,554 @@
/*
* Simple car controlled by any wifi device with browser.
* Nodemcu with L293D driver and 6V battery pack.
* Nodemcu will act as AccessPoint.
* After connecting to AP, open 192.168.4.1
*
*/
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#define IN1 D1 // left motor
#define IN2 D2 // left motor
#define IN3 D5 // right motor
#define IN4 D6 // right motor
const char* ssid = "RobotV1";
const char* password = "12345678";
ESP8266WebServer server(80);
// =============================
// Motor control
// =============================
void leftForward() {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
}
void leftBackward() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
}
void rightForward() {
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
}
void rightBackward() {
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
}
void stopRobot() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
}
// =============================
// Drive
// =============================
void drive(int left, int right) {
// Left motor
if (left > 0) {
leftForward();
}
else if (left < 0) {
leftBackward();
}
else {
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
}
// Right motor
if (right > 0) {
rightForward();
}
else if (right < 0) {
rightBackward();
}
else {
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
}
}
// =============================
// Web page
// =============================
const char webpage[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<meta name="viewport"
content="width=device-width,
initial-scale=1.0,
maximum-scale=1.0,
user-scalable=no">
<title>Robot Control</title>
<style>
body {
margin: 0;
background: #111;
color: white;
font-family: Arial;
text-align: center;
overflow: hidden;
touch-action: none;
}
h2 {
margin-top: 25px;
}
#joystick {
width: 280px;
height: 280px;
background: #333;
border: 3px solid #555;
border-radius: 50%;
margin: 40px auto;
position: relative;
touch-action: none;
}
#stick {
width: 100px;
height: 100px;
background: #2196F3;
border-radius: 50%;
position: absolute;
left: 90px;
top: 90px;
box-shadow: 0 0 20px #2196F3;
}
#status {
font-size: 20px;
color: #aaa;
}
</style>
</head>
<body>
<h2>🤖 Robot</h2>
<div id="joystick">
<div id="stick"></div>
</div>
<div id="status">
STOP
</div>
<script>
const joystick = document.getElementById("joystick");
const stick = document.getElementById("stick");
const status = document.getElementById("status");
let active = false;
const center = 140;
const maxDistance = 90;
// --------------------------------
// Send motor command
// --------------------------------
function sendCommand(x, y) {
// Up = positive
let forward = -y / maxDistance;
let turn = x / maxDistance;
// Tank steering
let left = forward + turn;
let right = forward - turn;
// Limit values
left = Math.max(-1, Math.min(1, left));
right = Math.max(-1, Math.min(1, right));
let leftCmd = Math.round(left * 100);
let rightCmd = Math.round(right * 100);
fetch(
"/drive?left=" +
leftCmd +
"&right=" +
rightCmd
);
// Status
if (Math.abs(leftCmd) < 5 &&
Math.abs(rightCmd) < 5) {
status.innerText = "STOP";
}
else if (forward > 0.3 &&
Math.abs(turn) < 0.3) {
status.innerText = "FORWARD";
}
else if (forward < -0.3 &&
Math.abs(turn) < 0.3) {
status.innerText = "BACKWARD";
}
else if (turn > 0.3) {
status.innerText = "RIGHT";
}
else if (turn < -0.3) {
status.innerText = "LEFT";
}
else {
status.innerText = "DRIVING";
}
}
// --------------------------------
// Move joystick
// --------------------------------
function moveStick(clientX, clientY) {
const rect = joystick.getBoundingClientRect();
let x = clientX - rect.left - center;
let y = clientY - rect.top - center;
let distance =
Math.sqrt(x * x + y * y);
if (distance > maxDistance) {
x =
x / distance *
maxDistance;
y =
y / distance *
maxDistance;
}
stick.style.left =
(center - 50 + x) + "px";
stick.style.top =
(center - 50 + y) + "px";
sendCommand(x, y);
}
// --------------------------------
// Reset joystick
// --------------------------------
function resetStick() {
active = false;
stick.style.left = "90px";
stick.style.top = "90px";
fetch("/stop");
status.innerText = "STOP";
}
// --------------------------------
// Touch
// --------------------------------
joystick.addEventListener(
"touchstart",
function(e) {
e.preventDefault();
active = true;
const touch = e.touches[0];
moveStick(
touch.clientX,
touch.clientY
);
}
);
joystick.addEventListener(
"touchmove",
function(e) {
e.preventDefault();
if (!active)
return;
const touch = e.touches[0];
moveStick(
touch.clientX,
touch.clientY
);
}
);
joystick.addEventListener(
"touchend",
function(e) {
e.preventDefault();
resetStick();
}
);
// --------------------------------
// Mouse support
// --------------------------------
joystick.addEventListener(
"mousedown",
function(e) {
active = true;
moveStick(
e.clientX,
e.clientY
);
}
);
document.addEventListener(
"mousemove",
function(e) {
if (active) {
moveStick(
e.clientX,
e.clientY
);
}
}
);
document.addEventListener(
"mouseup",
function() {
if (active)
resetStick();
}
);
</script>
</body>
</html>
)rawliteral";
// =============================
// Web server
// =============================
void handleRoot() {
server.send(
200,
"text/html",
webpage
);
}
void handleDrive() {
int left =
server.arg("left").toInt();
int right =
server.arg("right").toInt();
drive(left, right);
server.send(
200,
"text/plain",
"OK"
);
}
void handleStop() {
stopRobot();
server.send(
200,
"text/plain",
"STOP"
);
}
// =============================
// Setup
// =============================
void setup() {
Serial.begin(115200);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
stopRobot();
// Create WiFi network
WiFi.softAP(
ssid,
password
);
Serial.println();
Serial.println("Robot WiFi started");
Serial.print("IP address: ");
Serial.println(
WiFi.softAPIP()
);
// Web server routes
server.on(
"/",
handleRoot
);
server.on(
"/drive",
handleDrive
);
server.on(
"/stop",
handleStop
);
server.begin();
Serial.println(
"Web server started"
);
}
// =============================
// Main loop
// =============================
void loop() {
server.handleClient();
}