kpower
Published © GPL3+

Control your Arduino Car over a WiFi network

Use a browser based interface to control a Arduino Car over a WiFi network from your laptop, tablet or Smartphone.

IntermediateFull instructions provided4 hours2,445
Control your Arduino Car over a WiFi network

Things used in this project

Hardware components

Dual H-Bridge motor drivers L298
SparkFun Dual H-Bridge motor drivers L298
×1
DC Motor 5V
×2
HC-020K Encoder Module
×2
CR123 LI Battery 700 mAh
×4
UNOR3 WIFI ESP8266 CH340G Board
×1
Wireless Antenna
×1
Toggle Switch, Toggle
Toggle Switch, Toggle
×1
Car Kit
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Drill / Driver, Cordless
Drill / Driver, Cordless

Story

Read more

Schematics

Schematic

Overall car schematic

Code

HTML code for direction control page

HTML
<!DOCTYPE html>
<html>
  <head>
    <title>ESP8266 Demo</title>
    <style>
      html {font-family: Helvetica;display: inline-block;margin: 0px auto;text-align: center;}
      body {background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: black; }
      .button {border: none;color: white;padding: 16px 40px;text-decoration: none;font-size: 30px;margin: 2px;cursor: pointer;}
      .button1 {background-color: darkblue;user-select:none;-moz-user-select:none;-webkit-user-select:none;}
      table.center{margin-left: auto;margin-right: auto;}
      p.blocktext {margin-left: auto;margin-right: auto;}
      h1.text{{margin-left: auto;margin-right: auto;}
     </style>
  </head>
  <body>
  <!-- table used to postion the buttons -->
  <!-- buttons use onpointerdown and onpointerup to send requests to server -->
    <h1 class="text">Car Control</h1>
    <p class="blocktext">Use buttons to set direction</p>
    <table class="center">
    	<tr>
    	  <td></td>
    	  <td><button id="but1"class="button button1" onpointerdown="mouseDown(1)" onpointerup="mouseUp(2)">FWD</button></td>
    	  <td></td>
    	</tr>
    	<tr>
    	  <td><button id="but2" class="button button1" onpointerdown="mouseDown(3)" onpointerup="mouseUp(4)">LEFT</button></td>
    	  <td></td>
    	  <td><button id="but3" class="button button1" onpointerdown="mouseDown(5)" onpointerup="mouseUp(6)">RIGHT</button></td>
    	</tr>
    	<tr>
    	  <td></td>
    	  <td><button id="but4" class="button button1" onpointerdown="mouseDown(7)" onpointerup="mouseUp(8)">BACK</button></td>
    	  <td></td>
    	</tr>
    </table>
    <p class="blocktext">Use Slider to control speed</p>
    <div class="slidecontainer">
  	<input type="range" min="10" max="99" value="50" step="5" class="slider" id="myRange">
  	<p class="blocktext">Speed: <span id="demo"></span></p>
    </div>
    <script>
    <!-- Functions send request to ESP8266 server to alert action -->
    	function mouseDown(button) {
  		if (button == 1){document.getElementById("but1").style.background = "crimson";}
  		else if (button == 3){document.getElementById("but2").style.background = "crimson";}
  		else if (button == 5){document.getElementById("but3").style.background = "crimson";}
  		else { document.getElementById("but4").style.background = "crimson";}
  		const xhr = new XMLHttpRequest();
  		xhr.open("GET", "http://esp8266.local/"+ button);
  		xhr.send();
	}
	function mouseUp(button) {
  		if (button == 2){document.getElementById("but1").style.background = "darkblue";}
  		else if (button == 4){document.getElementById("but2").style.background = "darkblue";}
  		else if (button == 6){document.getElementById("but3").style.background = "darkblue";}
  		else { document.getElementById("but4").style.background = "darkblue";}
  		const xhr = new XMLHttpRequest();
  		xhr.open("GET", "http://esp8266.local/"+ button);
  		xhr.send();
	}
	var slider = document.getElementById("myRange");
	var output = document.getElementById("demo");
	output.innerHTML = slider.value;
	<!-- send slider value to ESP8266 via POST -->
	slider.oninput = function() {
	  output.innerHTML = slider.value;
	  var speed = new XMLHttpRequest();
	  speed.open("POST", "http://esp8266.local/speed", true);
	  speed.send(slider.value);
	}
    </script>
  </body>
</html>

ESP8266 Server and Access Point

Arduino
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>
#include <FS.h> // Include the SPIFFS library

const char *ssid = "ESP8266Network"; // The name of the Wi-Fi network that will be created
const char *password = "1234567890";   // Password for WiFi network. Must be more than 8 characters
const int led = 12; // Define pin for LED

ESP8266WebServer server(80); // Create a webserver object that listens for HTTP request on port 80

void setup() {

pinMode(led, OUTPUT);
digitalWrite(led,LOW);
Serial.begin(115200);
delay(10);

WiFi.softAP(ssid, password); // Start the access point

MDNS.begin("esp8266");
SPIFFS.begin(); // Start the SPI Flash Files System

server.onNotFound([]() {  // If the client requests any URI
if (!handleFileRead(server.uri())) // send it if it exists
server.send(404, "text/plain", "404: Not Found"); // otherwise, respond with a 404 (Not Found) error
});
server.on("/1",handleButton);
server.on("/2",handleButton);
server.on("/3",handleButton);
server.on("/4",handleButton);
server.on("/5",handleButton);
server.on("/6",handleButton);
server.on("/7",handleButton);
server.on("/8",handleButton);
server.on("/speed",handleSpeed);
server.begin(); // Actually start the server
//Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
  MDNS.update();
}

void handleButton() {
  server.send(200,"text/plain", "Thanks");
  String request = server.uri();
  //Serial.println(request);
  char but = request.charAt(1);
  //Serial.println(but);
  //Serial.println("Button request recieved");
  
  switch (but){
    // FWD Activate
    case '1':
    Serial.write(but);
    break;
    // FWD Stop
    case '2':
    Serial.write(but);
    break;
    // LEFT Activate
    case '3':
    Serial.write(but);
    break;
    // LEFT Stop
    case '4':
    Serial.write(but);
    break;
    // RIGHT Activate
    case '5':
    Serial.write(but);
    break;
    // RIGHT Stop
    case '6':
    Serial.write(but);
    break;
    // BACK Activate
    case '7':
    Serial.write(but);
    break;
    // BACK Stop
    case '8':
    Serial.write(but);
    break;
    default:
    
    break;
    Serial.flush();
  }
}

void handleSpeed() {
  
  if (server.hasArg("plain") == false){ //Check if body received
    server.send(200, "text/plain", "Body not received");
    return;
  }
  
  String message = "Body received:\n";   
  server.send(200, "text/plain", message);  
  String request = 's' + server.arg("plain");
  char speedValue[4];
  request.toCharArray(speedValue,4);
  Serial.write(speedValue);
  Serial.flush();
  
}

bool handleFileRead(String path) { // send the right file to the client (if it exists)

if (path.endsWith("/")) path += "index.html";     // If a folder is requested, send the index file
String contentType = getContentType(path);      // Get the MIME type
if (SPIFFS.exists(path)) {                    // If the file exists
  File file = SPIFFS.open(path, "r");         // Open it
  size_t sent = server.streamFile(file, contentType); // And send it to the client
  file.close(); // Then close the file again
  return true;
}

return false;
// If the file doesn't exist, return false
}

String getContentType(String filename) { // convert the file extension to the MIME type
if (filename.endsWith(".html")) return "text/html";
else if (filename.endsWith(".css")) return "text/css";
else if (filename.endsWith(".js")) return "application/javascript";
else if (filename.endsWith(".ico")) return "image/x-icon";
return "text/plain";
}

Arduino Motor Control

Arduino
// Define Motor A connections to L298N
int enA = 5;
int in1 = 4;
int in2 = 7;
// Define Motor B connections to L298N
int enB = 6;
int in3 = 8;
int in4 = 9;

int led = 13; // LED used for diagnostics (and it looks cool)
boolean toggle = false;

int motorSpeed = 120;
String incomingString;
char but;

void setup() {
  Serial.begin(115200);
  // Set all the motor control pins to outputs
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(led, OUTPUT);

  // Turn off motors - Initial state
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);

  // Set initial speed of Motors
  analogWrite(enA, motorSpeed);
  analogWrite(enB, motorSpeed);
}

void loop() {
  if (Serial.available() > 0){
    incomingString = Serial.readString();
    if (incomingString.charAt(0) == 's'){
      incomingString.remove(0,1);
      motorSpeed = (90+(incomingString.toInt()*165)/100);
      but = '0';
    }
    else {
    but = incomingString.charAt(0);    
    }
    
    switch (but){
    // FWD Activate
    case '1':
    forwardOn();    
    break;
    // FWD Stop
    case '2':
    motorsOff();
    break;
    // LEFT Activate
    case '3':
    leftOn();
    break;
    // LEFT Stop
    case '4':
    motorsOff();
    break;
    // RIGHT Activate
    case '5':
    rightOn();
    break;
    //RIGHT Stop
    case '6':
    motorsOff();
    break;
    // BACK Activate
    case '7':
    backOn();
    break;
    // BACK Stop
    case '8':
    motorsOff();
    break;
    default:
    
    break;
  }
  
  delay(5);
  }
}

void forwardOn() {

  analogWrite(enA, motorSpeed);
  analogWrite(enB, motorSpeed);

  // Turn on motor A & B
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  digitalWrite(led, HIGH);
}

void leftOn() {

  analogWrite(enA, motorSpeed);
  analogWrite(enB, motorSpeed);

  // Turn on motor A & B
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
  digitalWrite(led, HIGH);
}

void rightOn() {

  analogWrite(enA, motorSpeed);
  analogWrite(enB, motorSpeed);

  // Turn on motor A & B
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  digitalWrite(led, HIGH);
}

void backOn() {

  analogWrite(enA, motorSpeed);
  analogWrite(enB, motorSpeed);

  // Turn on motor A & B
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  digitalWrite(led, HIGH);
}

void motorsOff() {
  // Turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
  digitalWrite(led, LOW);
}

Credits

kpower

kpower

19 projects • 6 followers
Qualified Electrical Engineer with experience in software and hardware development

Comments