Here’s a video of the car in action:

Gallery of all the pictures I took.

The most recent project I decided to work on was a line following robot. However, as I was testing it to make sure the direction code was working, I decided to develop something that I can control from my smartphone. It turned out much better than I was expecting, so I figured I should make a blog post about it.

As you can clearly see, I pieced together the parts for my car. It’s a block of wood, with a caster on the front, and a couple of brackets on the back to hold the motor/wheels. All of those parts cost about $7.50 total off of AliExpress. In hindsight, I see that I should have just bought a car kit, which would do the same thing, for a dollar more, and is much less of a headache to put together.

Part List:

I just used a portable charger to power the Wemos. You may want to use batteries with a battery holder(3 AA batteries in series, with positive on the 5v pin, and negative on Ground). Either way will work, the portable charger was just easier.

The first step is to put the car together. I don’t have the kit, but I don’t think people should waste their time rigging it together like I did, so I’m not going to go into any detail on putting it together. The kit seems pretty easy to assemble from some of the videos I have seen.

Next, you need to wire up the TB6612FNG motor controller to the Wemos and to the motor. To do that, refer to the schematic below. Keep in mind that if one or both motors get wired backwards, the code will cause them to go in reverse. You can either rewire them, or you can just edit the code appropriately. I have put in a comment in the code indicating what you would need to change:

WiFi Car Schematic


Once you have the everything connected, you need to upload the HTML and Javascript files for the web based joystick. The code for the Joystick came from HERE. I modified the code for those to send the joystick coordinates to the ESP.

These 2 files need to be uploaded to SPIFFS. I use the instructions located HERE. Download the zip file from the first step in that link. For the first step of the instructions, go to your preferences in Arduino IDE, and look at your sketchbook folder. Browse to that folder, and create a folder names ‘tools’ if it’s not already there. Unzip that file into this tools directory. For me, my sketchbook folder was C:\Users\<username>\Documents\Arduino , and after unzipping, I had a file located at C:\Users\<username>\Documents\Arduino\tools\ESP8266FS\tool\esp8266fs.jar . Restart Arduino IDE.

Now, go ahead and create the sketch/ino file you will be putting this project into and save it. Go to the folder you saved it in, and create a folder under there called ‘data’. DOWNLOAD THE MODIFIED HTML/JS FILES. Unzip the HTML/JS files into this ‘data’ folder. You may need to restart Arduino IDE, and then go to ‘Tools->ESP8266 Sketch Data Upload’. This will upload the files in the data folder to SPIFFS. If you are on mobile, and just want to view the code, click here.

Upload the code to the Wemos/ESP. Be sure to modify the SSID and Password. :

#include <ESP8266WebServer.h>
#include <FS.h>
#include <ESP8266WiFi.h>

//Set Wifi ssid and password
char ssid[] = "<SSID>";
char pass[] = "<password>";

//Define the pins
int STBY = 12; //standby
//Motor A
int PWMA = 5; //Speed control
int AIN1 = 14; //Direction
int AIN2 = 16; //Direction
//Motor B
int PWMB = 4; //Speed control
int BIN1 = 15; //Direction
int BIN2 = 13; //Direction

ESP8266WebServer server (80);

//This function takes the parameters passed in the URL(the x and y coordinates of the joystick)
//and sets the motor speed based on those parameters. 
void handleJSData(){
  boolean yDir;
  int x = server.arg(0).toInt() * 10;
  int y = server.arg(1).toInt() * 10;
  int aSpeed = abs(y);
  int bSpeed = abs(y);
  //set the direction based on y being negative or positive
  if ( y < 0 ){
    yDir = 0; 
  else { 
    yDir = 1;
  //adjust to speed of each each motor depending on the x-axis
  //it slows down one motor and speeds up the other proportionately 
  //based on the amount of turning
  aSpeed = constrain(aSpeed + x/2, 0, 1023);
  bSpeed = constrain(bSpeed - x/2, 0, 1023);

  //use the speed and direction values to turn the motors
  //if either motor is going in reverse from what is expected,
  //just change the 2 digitalWrite lines for both motors:
  //!ydir would become ydir, and ydir would become !ydir
  digitalWrite(STBY, HIGH);  
  digitalWrite(AIN1, !yDir);
  digitalWrite(AIN2, yDir);
  analogWrite(PWMA, aSpeed);
  digitalWrite(BIN1, !yDir);
  digitalWrite(BIN2, yDir);
  analogWrite(PWMB, bSpeed);

  //return an HTTP 200
  server.send(200, "text/plain", "");   

void setup()
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {

  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  //set the pins as outputs
  pinMode(STBY, OUTPUT);

  pinMode(PWMA, OUTPUT);
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);

  pinMode(PWMB, OUTPUT);
  pinMode(BIN1, OUTPUT);
  pinMode(BIN2, OUTPUT);  
  // Debug console
  //initialize SPIFFS to be able to serve up the static HTML files. 
  if (!SPIFFS.begin()){
    Serial.println("SPIFFS Mount failed");
  else {
    Serial.println("SPIFFS Mount succesfull");
  //set the static pages on SPIFFS for the html and js
  server.serveStatic("/", SPIFFS, "/joystick.html"); 
  server.serveStatic("/virtualjoystick.js", SPIFFS, "/virtualjoystick.js");
  //call handleJSData function when this URL is accessed by the js in the html file
  server.on("/jsData.html", handleJSData);  

void loop()

Once the code is uploaded, you can open up any recent web browser on your computer or mobile, and go to http://<ESP IP Address>/ and you should get a gray screen. Just touch or click on the screen and drag to move the joystick. The car should move accordingly. Again, if the direction of the car isn’t behaving as expected, then make the changes in the code by following the directions in the code comments around line 45.

As always, if you have any comments or feedback post in the comments. It should be fairly easy to leave a comment. Feel free to use a fake email. You just won’t get any notifications of a reply.


15 Replies to “WiFi Controlled Car with a Self Hosted HTML/JS Joystick Using a Wemos D1 Mini/ESP8266

  1. Hi! Thanks a lot,

    It works, was too much delay between issued command and car response, so I have changed to AP mode, and now seems to work really good,

    I have modified pinouts for nodemcu and also added html and js in code, so no need to use SPIFFS.

    Anyways, nice tutorial, thanks a million.

    1. Any chance you can share your AP code? I tried and could not get it to work in AP.

      I want to use without internet connection.


  2. I need a little help, i am relatively new to esp 8266 and i want to know how you work with the x and y variables from javascript to arduino sketch. To pass the values from one to another

    Sorry for the bad english.

  3. Hi Simit,

    Very nice to meet you.  I saw your project WiFi Controlled Car with a Self Hosted HTML/JS Joystick on

    Would you be interested working on a project to make the HTML/JS Joystick work with the following:

    Arduino Yun
    Sabertooth 2×32
    2 motors

    Let me know your thoughts upon review.

    We can chat on Skype

    All the best – Scott

  4. Hello Simit,
    I uploaded your code to a node MCU 1.0 and it worked without any fiddling.
    Kudos on a well written example with clear instructions.
    I have been attempting this for awhile now but I didn’t realize it was so easy to use the file system, so I never jumped down that rabbit hole.

    You have given me breadcrumbs to help with other projects I’m working on.

    WHERE is your “buy me a cup of coffee” donation button!?


    Cheers, Martin

    1. Martin, I’m happy to hear that my work was able to help you out. I never thought anyone would ever want to just give me money for this, so I never thought to add a ‘Donate’ button until now. I’ve added one to the sidebar on the right though PayPal.

  5. Hi,

    Is it possible to change the code to work with two joysticks/fingers and thus four channels? I would like to use this for controlling a drone.

Leave a Reply