Code
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
ESP8266WebServer server(80);
// motor control pins
const int motorThrottle = D1; // vertical lift
const int motorForwardBack = D2; // forward/backward
const int motorLeftRight = D3; // left/right
// throttle ramp globals
int throttleValue = 0;
bool isRamping = false;
int rampStartValue = 0;
int rampTargetValue = 0;
int rampDuration = 0;
unsigned long rampStartTime = 0;
// movement globals
int movementFB = 0;
int movementLR = 0;
int speedValue = 0;
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
pinMode(motorThrottle, OUTPUT);
pinMode(motorForwardBack, OUTPUT);
pinMode(motorLeftRight, OUTPUT);
analogWriteFreq(1000);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("IP: "); Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, handleWebpage);
server.on("/command", HTTP_GET, handleCommand);
server.begin();
}
void loop() {
handleRamping();
server.handleClient();
}
// smoothly step throttle from rampStartValue → rampTargetValue over rampDuration ms
void handleRamping() {
if (!isRamping) return;
float t = float(millis() - rampStartTime) / rampDuration;
if (t >= 1.0) {
throttleValue = rampTargetValue;
analogWrite(motorThrottle, throttleValue);
isRamping = false;
} else {
int v = rampStartValue + (rampTargetValue - rampStartValue) * t;
analogWrite(motorThrottle, v);
}
}
void startRamp(int target, int duration) {
rampStartValue = throttleValue;
rampTargetValue = target;
rampDuration = duration;
rampStartTime = millis();
isRamping = true;
// throttleValue will be updated in handleRamping()
}
// web‑page
void handleWebpage() {
String html = R"rawliteral(
<!DOCTYPE html><html><head>
<title>Helicopter Control</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body{background:#111;color:#fff;font-family:Arial;text-align:center;padding:20px}
button{background:#00aaff;color:#fff;border:none;padding:15px;margin:5px;border-radius:8px;cursor:pointer}
button:hover{background:#007acc}
.grid{display:grid;grid-template-columns:80px 80px 80px;gap:10px;justify-content:center;margin-bottom:20px}
input[type=range]{width:300px;margin:10px}
</style>
</head><body>
<h1>Helicopter Control</h1>
<h2>Direction</h2>
<div class="grid">
<div></div><button onclick="cmd('move',0,-30)">↑</button><div></div>
<button onclick="cmd('move',-30,0)">←</button><div></div><button onclick="cmd('move',30,0)">→</button>
<div></div><button onclick="cmd('move',0,30)">↓</button><div></div>
</div>
<h2>Throttle</h2>
<button onclick="cmd('throttle',30)">↑ Throttle</button>
<button onclick="cmd('throttle',-30)">↓ Throttle</button>
<h2>Speed</h2>
<input type="range" min="0" max="100" id="speed" oninput="fetch(`/command?type=speed&value=${this.value}`)">
<h2>Actions</h2>
<button onclick="fetch('/command?type=takeoff')">Takeoff</button>
<button onclick="fetch('/command?type=land')">Land</button>
<button onclick="fetch('/command?type=stop')">Stop</button>
<script>
function cmd(t,x,y=0){ fetch(`/command?type=${t}&x=${x}&y=${y}`) }
document.addEventListener('keydown',e=>{
if(e.key=='ArrowUp') cmd('move',0,-30);
if(e.key=='ArrowDown') cmd('move',0,30);
if(e.key=='ArrowLeft') cmd('move',-30,0);
if(e.key=='ArrowRight') cmd('move',30,0);
if(e.key=='w'||e.key=='W') cmd('throttle',30);
if(e.key=='s'||e.key=='S') cmd('throttle',-30);
if(e.key=='k'||e.key=='K') fetch('/command?type=takeoff');
if(e.key=='l'||e.key=='L') fetch('/command?type=land');
});
</script>
</body></html>
)rawliteral";
server.send(200, "text/html", html);
}
// handle incoming commands
void handleCommand() {
String type = server.arg("type");
if (type=="throttle") {
throttleValue = constrain(throttleValue + server.arg("x").toInt(), 0, 1023);
analogWrite(motorThrottle, throttleValue);
}
else if (type=="move") {
movementFB = server.arg("y").toInt();
movementLR = server.arg("x").toInt();
analogWrite(motorForwardBack, map(movementFB,-50,50,0,1023));
analogWrite(motorLeftRight, map(movementLR,-50,50,0,1023));
}
else if (type=="speed") {
speedValue = server.arg("value").toInt();
// you could scale other outputs by speedValue here
}
else if (type=="takeoff") {
startRamp(800, 2000); // ramp up to 800/1023 in 2 s
}
else if (type=="land") {
startRamp(0, 3000); // ramp down to 0 in 3 s
}
else if (type=="stop") {
throttleValue = 0;
analogWrite(motorThrottle,0);
analogWrite(motorForwardBack,0);
analogWrite(motorLeftRight,0);
isRamping = false;
}
server.send(200, "text/plain", "OK");
}
1. Overall Power & Ground
-
Motor supply (e.g. 7.4 V Li‑Po) → both L298N “VCC”
-
L298N GND ⟷ NodeMCU GND ⟷ Battery GND (common ground)
-
NodeMCU VIN (or 5 V USB) → L298N “5 V” logic supply (only if your board doesn’t onboard 5 V regulator—otherwise leave 5 V jumper in place)
2. NodeMCU → L298N Driver #1 (Main Blades)
L298N Pin | Connect to NodeMCU | Drives Motor… |
---|---|---|
ENA | +5 V (jumper ON) | enable channel A |
IN1 | D1 (GPIO 5) | Blade 1 direction A |
IN2 | D2 (GPIO 4) | Blade 1 direction B |
IN3 | D3 (GPIO 0) | Blade 2 direction A |
IN4 | D4 (GPIO 2) | Blade 2 direction B |
OUT1/OUT2 | → Motor 1 leads | Main blade motor 1 |
OUT3/OUT4 | → Motor 2 leads | Main blade motor 2 |
3. NodeMCU → L298N Driver #2 (Tail)
L298N Pin | Connect to NodeMCU | Drives Motor… |
---|---|---|
ENB | +5 V (jumper ON) | enable channel B |
IN1 | D5 (GPIO 14) | Tail direction A |
IN2 | D6 (GPIO 12) | Tail direction B |
OUT1/OUT2 | → Tail motor leads | Tail rotor motor |
Physically hook up & program the NodeMCU
-
Power & USB
-
Plug a Micro‑USB cable from the NodeMCU into your PC. This powers the board and gives you a serial port for uploading.
-
If Windows doesn’t see it, install the CP210x/CH340 USB‑serial driver (depending on your clone).
-
-
In Arduino IDE
-
Select Tools → Board → “NodeMCU 1.0 (ESP-12E Module)”
-
Select the COM port that appeared when you plugged in.
-
Click Upload.
-
When it’s done, open the Serial Monitor at 115200 baud.
-
-
Read the IP
-
In the Serial Monitor you’ll see something like:
-
That is the address your PC will use to control the helicopter.
-
2. Put your PC on the same Wi‑Fi
‑ Your PC (or laptop) must be connected to the same SSID (e.g. “YOUR_SSID”) that the NodeMCU joined.
3. Open the web interface in your browser
-
In Chrome/Firefox on your PC, type the ESP’s IP into the address bar:
-
The control page will load.
4. Control with mouse or keyboard
‑ Click any of the on‑screen buttons to move, throttle, take‑off (“Takeoff”) or land (“Land”).
‑ Or give the page keyboard focus (click once in the gray area) and use:
Key | Action |
---|---|
Arrow Up | Move forward |
Arrow Down | Move backward |
Arrow Left | Move left |
Arrow Right | Move right |
W or w | Throttle up (increase lift) |
S or s | Throttle down (decrease lift) |
K or k | Takeoff (smooth ramp up) |
L or l | Land (smooth ramp down) |
Space | Stop all motors immediately |
Circuit wiring summary
NodeMCU Pin | L298N IN pin | Motor function |
---|---|---|
D1 (GPIO5) | IN1 & IN2 | Throttle (vertical) |
D2 (GPIO4) | IN3 & IN4 | Forward / Backward |
D3 (GPIO0) | IN5 & IN6 | Left / Right |
GND | GND | Common ground |
VIN or 5V | 5V | Logic power (if needed) |
-
All GNDs (NodeMCU, motor‑driver, battery) must be tied together.
-
Motor supply (e.g. 7.4 V LiPo) goes to the L298N motor‑power input.
With this sketch and wiring, you get a web‑page you can open in any browser on your LAN. Click buttons or press:
-
Arrow keys for movement
-
W / S for throttle up/down
-
K for take‑off ramp
-
L for landing ramp
1 Comments
hi
ReplyDelete