BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

Remote car Tank drive

Alright, just made a 3 wheeled 2 wheel drive car. My searches didn’t bring up any satisfactory joystick code, so I headed in and tried my own. Maps the y axis so that it starts counting back up below center but leaves a buffer in the middle. Maps the x axis and subtracts that speed from the proper wheel. Some code and observations. I first got all the code running and virtual writing the wheel speeds to the app. I noticed that the app would get way behind with the numbers. I had decided before I started I would run this one on local server because our internet has bad latency. Once I got it running on local server it was better but it still was slow. When I commented out the virtual writes BAMB!! works fine. I would love to hear criticisms on the code.

Setup
-three wheeled car from Banggood or Ebay includes 4- AA battery pack and L298N motor driver (also included an Uno and shield)
-Instead of the Uno I am using the trusty NodeMcu
-virtual Joystick

Additions for future
-Battery voltage off the analog pin
-Ordered a IR bar to try line following

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
 

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
// Use your own WiFi settings
char auth[] = "==";
char ssid[] = "==";
char pass[] = "==";
 
bool reverseFlag = false;
bool drivingFlag = false;
bool leftTurnFlag = false;
bool rightTurnFlag = false;

#define RightSpeedPin   D5
#define RightMotorDir   D6  
#define RightMotorDir1  D7  
#define LeftSpeedPin    D8  
#define LeftMotorDir    D1
#define LeftMotorDir1   D0

int leftMotorSpeed = 0;
int rightMotorSpeed = 0;

void setup()
{
  // initial settings for motors off and direction forward
   pinMode(RightMotorDir1, OUTPUT);
   pinMode(RightMotorDir, OUTPUT);
   pinMode(LeftMotorDir1, OUTPUT);
   pinMode(LeftMotorDir, OUTPUT);
   pinMode(RightSpeedPin, OUTPUT);
   pinMode(LeftSpeedPin,  OUTPUT);
   
   digitalWrite(RightMotorDir1,LOW);
   digitalWrite(RightMotorDir,LOW);
   digitalWrite(LeftMotorDir1, LOW);
   digitalWrite(LeftMotorDir,LOW);
   Serial.begin(9600);
   
  Blynk.begin(auth, ssid, pass, IPAddress(192,168,0,97), 8080);
    Blynk.connect();
    ArduinoOTA.setHostname("car");
    ArduinoOTA.begin();

   Serial.println("setup");
 }
 
 
void loop()
{
  Blynk.run();
  ArduinoOTA.handle(); 
}
 
 
BLYNK_WRITE(V1)
{
  int x = param[0].asInt();
  int y = param[1].asInt();
  int y1;
  int factor;

//maps forward, stop and backward (speed)

  if((y > 123)&&(y < 131))
  {
    drivingFlag = false;
    //Blynk.virtualWrite(V6,"stop1");
    Serial.println("stop");
  }
  else if(y < 129)                         
  {
    y1 = map(y,0,125,1030,500);                     
    reverseFlag = true;
    drivingFlag = true;
    //Blynk.virtualWrite(V6,"reverse");
    Serial.println("reverse");
  }
  else{
    y1 = map(y,131,255,500,1030);
    reverseFlag = false;
    drivingFlag = true;
    //Blynk.virtualWrite(V6,"forward");
    Serial.println("forward");
  }

//maps left and right speed

  if(x < 110)
  {
    factor = map(x,0,110,400,20);
    leftTurnFlag = false;
    rightTurnFlag = true;
  }
  else if (x > 144){
    factor = map(x,144,255,20,400);
    leftTurnFlag = true;
    rightTurnFlag = false;
  }
  else
  {
   factor = 128;
   leftTurnFlag = false;
   rightTurnFlag = false;
  }

//driving functions
  if (drivingFlag == true)
  {
///////////reverse
    if (reverseFlag == true)
    {
      ////////reverse left turn
      if (leftTurnFlag == true)
      {
        rightTurnFlag = false;
        rightMotorSpeed = y1;
        leftMotorSpeed = (y1 - factor);
        if (leftMotorSpeed < 500){
          leftMotorSpeed = 0;
        }
        driveBackward();
        //Blynk.virtualWrite(V4, "ReverseLeft");
        //Blynk.virtualWrite(V3, leftMotorSpeed);
        //Blynk.virtualWrite(V2, rightMotorSpeed);
        Serial.print("reverseleft");
      }
      else if (rightTurnFlag == true){
        leftTurnFlag = false;
        leftMotorSpeed = y1;
        rightMotorSpeed = (y1 - factor);
        if (rightMotorSpeed < 500){
          rightMotorSpeed = 0;
        }
        driveBackward();
        //Blynk.virtualWrite(V4, "ReverseRight");
        //Blynk.virtualWrite(V3, leftMotorSpeed);
        //Blynk.virtualWrite(V2, rightMotorSpeed);
        Serial.print("reverseRight");
      }
      else
      {
        leftMotorSpeed = y1;
        rightMotorSpeed = y1;
        driveBackward();
        //Blynk.virtualWrite(V4, "ReverseStraight");
        //Blynk.virtualWrite(V3, leftMotorSpeed);
        //Blynk.virtualWrite(V2, rightMotorSpeed);
        
      }
     }
    //////////////////////////////forward
    if (reverseFlag == false)
    {
      if (leftTurnFlag == true)
      {
        rightTurnFlag = false;
        rightMotorSpeed = y1;
        leftMotorSpeed = (y1 - factor);
        driveForward();
        //Blynk.virtualWrite(V4, "ForwarLeft");
        //Blynk.virtualWrite(V3, leftMotorSpeed);
        //Blynk.virtualWrite(V2, rightMotorSpeed);
      }
      else if (rightTurnFlag == true){
        leftTurnFlag = false;
        leftMotorSpeed = y1;
        rightMotorSpeed = (y1 - factor);
        driveForward();
        //Blynk.virtualWrite(V4, "ForwardRight");
        //Blynk.virtualWrite(V3, leftMotorSpeed);
        //Blynk.virtualWrite(V2, rightMotorSpeed);
      }
      else
      {
        leftMotorSpeed = y1;
        rightMotorSpeed = y1;
        driveForward();
        //Blynk.virtualWrite(V4, "ForwardStraight");
        //Blynk.virtualWrite(V3, leftMotorSpeed);
        //Blynk.virtualWrite(V2, rightMotorSpeed);
      }
    }
  }
  else
  {
    driveStop();
    //Blynk.virtualWrite(V6, "stopped");
    //Blynk.virtualWrite(V4, "Stopped");
    leftMotorSpeed = 500;
    rightMotorSpeed = 500;
    //Blynk.virtualWrite(V3, leftMotorSpeed);
    //Blynk.virtualWrite(V2, rightMotorSpeed);
  }
}

void driveForward()
{
   analogWrite(RightSpeedPin, rightMotorSpeed);
   analogWrite(LeftSpeedPin,  leftMotorSpeed);
   digitalWrite(RightMotorDir, LOW);
   digitalWrite(RightMotorDir1, HIGH);
   digitalWrite(LeftMotorDir, LOW);
   digitalWrite(LeftMotorDir1, HIGH);
   Serial.print("now driving forward ");
   Serial.print(rightMotorSpeed);
   Serial.println(leftMotorSpeed);
}

void driveBackward()
{
   analogWrite(RightSpeedPin, rightMotorSpeed);
   analogWrite(LeftSpeedPin,  leftMotorSpeed);
   digitalWrite(RightMotorDir1,LOW);
   digitalWrite(RightMotorDir,HIGH);
   digitalWrite(LeftMotorDir1, LOW);
   digitalWrite(LeftMotorDir,HIGH);
   Serial.print("now driving backward");
   Serial.print(rightMotorSpeed);
   Serial.println(leftMotorSpeed);
}

void driveStop()
{
   digitalWrite(RightMotorDir1,LOW);
   digitalWrite(RightMotorDir,LOW);
   digitalWrite(LeftMotorDir1, LOW);
   digitalWrite(LeftMotorDir,LOW);
   Serial.print("now stoppppped ");
   Serial.print(rightMotorSpeed);
   Serial.println(leftMotorSpeed);
}
3 Likes

Hi @daveblynk,
Please, upload video and pictures!!!

Thanks for sharing!!!

1 Like

Will do… in the meantime I tried out some 10k resistors between my 6v battery and A0. It doesn’t read anything, but if I jump the 3v pin to A0 it works. You electrical engineers out there, is the current to low with the resistors?

You need to create a voltage divider using two resistors. Read this for more info…

Note that a bare ESP8266 chip can accept a maximum of 1v on the analogue pin, but the NodeMCU/Wemos D1Mini dev boards have an onboard voltage divider that changes the range from 0-1v to 0-3.3v, so the calculations used in the above link are correct for the board you’re using.

Pete.

Should work for 6v readings as well.

Sorry I didn’t state clearly. I did the resistor voltage divider so my volt meter shows 1.5v. You think it is the internal step up that is causing Blynk display to show a 0 for 1.5 and 3.3 when I jump the 1.1 (software calculation) pin? I was wondering if my 10k resistor step down was not letting enough current through…

Edit. Bang head I’m thinking I did my calculations the wrong way. I’ll check when I get home… thanks for now

If you’re using a 6v battery then you’ll probably want to use a voltage divider that gives an output of 3.3v for an input of around 6.5v (it depends what your multimeter says when it’s fully charged).

When you read the digital pin you’ll get a value between 0 and 1023 (as the NodeMCU has a 10 bit ADC), so you’ll want to map 0,1023 to 0,6.5

You can then do a bit of tweaking of the 6.5 value in the map command to give you a value that matches what your multimeter says when the setup is in its idle mode.

Pete.

1 Like