ESP8266IOT Projects

Arduino IOT Project: Nodemcu ESP8266 wifi Robot Car “L298N motor driver + Blynk + Joystick”

Description:

 

Wifi Robot Car- In today’s tutorial, you will learn how to control a robot car using Arduino,  Nodemcu esp8266 wifi module and Blynk application. The joystick widget will be used to control the Forward…Reverse….right …and left movement..while the slider widget will be used to control the speed of the dc motors in real-time…As this project is based on WIFI, it means this robot car can be controlled from anywhere around the world. For remote controlling, an IP camera can be used for live video streaming. I will make a separate video on how to use the IP cameras.

This is the 5th  version of the Robot Car.while in the 4th version I used an ultrasonic sensor to make a safe distance maintaining robot car. in this project, the speed of the robot car is automatically adjusted depending on the distance between the cars.


While in the 3rd version, I used the flex sensor and the joystick together to control the same robot car, in this project the flex sensor was used as the accelerator and the joystick was used to control the car’s forward, left, right and reverse movement, I named this project a wireless hand gesture + joystick robot car… While in the 2nd version, I used only the joystick to control the speed and movement of the robot Car. The program used in this project was a little bit complex, so that’s why I decided to make another version of this robot and use a separate sensor for the speed controlling. So that’s why I created version 3.

 While in the first version, I used an Android cell phone to control the Robot Car using the HC-05 Bluetooth module.

Today’s tutorial is based on my previous tutorial, in this tutorial, I explained, how to assemble the robot parts and how to use the L298N motor driver to control the forward, left, right and reverse movement. In this tutorial, I also explained how to control the speed of a dc motor using the pulse width modulation. If you are a beginner and you have never used the L298N motor driver then I highly recommend you should first watch this tutorial and then you can resume from here.

Note: this old version of the Blynk app is no more functional. For the blynk mobile App setup and Blynk.cloud dashboard setup ready my article on the New Blynk V2.0. In this article I have explained how to migrate your projects from Blynk 1.0 to the new Blynk V2.0. You can also watch the video.


Amazon Links:

Arduino Uno

Arduino Nano

Robot Car chassis kit:

L298N motor driver:

Nodemcu ESP8266 WiFi Module:

Other Tools and Components:

Top Arduino Sensors:

Super Starter kit for Beginners

Digital Oscilloscopes

Variable Supply

Digital Multimeter

Soldering iron kits

PCB small portable drill machines

*Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!

wifi robot car Circuit Diagram:

Nodemcu ESP8266

All the connections are exactly the same as explained in the L298N motor driver getting started Tutorial.The only modification is the addition of the Nodemcu esp8266 wifi module. The Nodemcu tx pin is connected with the Arduino’s pin number 2 and the Nodemcu Rx pin is connected with the Arduino’s pin number 3 while the Nodemcu ground pin is connected with the Arduino ground. For the demonstration purchases, I will power the Nodemcu module using my laptop.


wifi robot car Blynk Application:

For the Blynk Application designing watch video tutorial.

wifi robot car Programming:

This project is based on two programs, this program is written for the Arduino while this program is written for the Nodemcu ESP8266 wifi module. First, let’s start with Arduino programming.

Robot Car Arduino programming

 

#include <SoftwareSerial.h>
SoftwareSerial nodemcu(2,3);

long int data; 
int firstVal, secondVal,thirdVal;


String myString; // complete message from arduino, which consistors of snesors data
char rdata; // received charactors
String cdata; // complete data

// for L298N motor driver
int ena = 5; 
int enb = 6; 

int in1 = 8; 
int in2 = 9; 
int in3 = 10; 
int in4 = 11;


void setup()
{
Serial.begin(9600); 
nodemcu.begin(9600);

 pinMode(ena, OUTPUT); 
  pinMode(enb, OUTPUT); 

  pinMode(in1, OUTPUT); 
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  
 analogWrite(ena, 0); 
 analogWrite(enb, 0);

}

void loop()
{
  
if(nodemcu.available() == 0 )
{
 
   delay(100); // 100 milli seconds
 
}

if ( nodemcu.available() > 0 ) 
{

      rdata = nodemcu.read(); 
    myString = myString+ rdata; 
    //Serial.print(rdata);
    if( rdata == '\n')
    {
Serial.println(myString);
// new code
String l = getValue(myString, ',', 0);
String m = getValue(myString, ',', 1);
String n = getValue(myString, ',', 2); 


firstVal = l.toInt(); // for left and right
secondVal = m.toInt(); // forward and reverse
thirdVal = n.toInt(); // speed

  myString = "";


            if ( (firstVal == 2) && (secondVal == 2) ) // for joystic normal position
            {
                analogWrite(ena,0);
                analogWrite(enb,0);
                digitalWrite(in1,LOW);
                digitalWrite(in2,LOW); 
                digitalWrite(in3,LOW); 
                digitalWrite(in3,LOW);
                
            } else
            
            if ( (firstVal == 2) && (secondVal > 3) ) // Forward direction
            {
                analogWrite(ena,thirdVal);
                analogWrite(enb,thirdVal);
                  digitalWrite(in1,HIGH);
                  digitalWrite(in2, LOW); 
                  digitalWrite(in3,LOW); 
                  digitalWrite(in4,HIGH); 
            }else

            if ( (firstVal == 2) && (secondVal < 1) ) // reverse direction
            {
                analogWrite(ena,thirdVal);
                analogWrite(enb,thirdVal);
                digitalWrite(in1,LOW);
                digitalWrite(in2, HIGH); 
                digitalWrite(in3,HIGH); 
                digitalWrite(in4,LOW); 
            }else

           if ( (firstVal > 3) && (secondVal == 2) ) // Right
            {
                analogWrite(ena,thirdVal);
                analogWrite(enb,thirdVal);
                digitalWrite(in1,HIGH);
                digitalWrite(in2, LOW); 
                digitalWrite(in3,LOW); 
                digitalWrite(in4,LOW); 
            } else

            
           if ( (firstVal < 1) && (secondVal == 2) ) // left
            {
                analogWrite(ena,thirdVal);
                analogWrite(enb,thirdVal);
                digitalWrite(in1,LOW);
                digitalWrite(in2, LOW); 
                digitalWrite(in3,LOW); 
                digitalWrite(in4,HIGH); 
            }
    }
  
}

}


String getValue(String data, char separator, int index)
{
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length() - 1;

    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}


wifi robot car Nodemcu esp8266 wifi module programming

#define BLYNK_PRINT Serial


#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SoftwareSerial.h>
#include <SimpleTimer.h>

int pinValue1;
int pinValue2;
int pinValue3;
int pinValue4;

String v2arduino; // values to arduino

char auth[] = "dfb3d11fbe874cd69ab413c8bb45f613";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "ZONG MBB-E8231-6E63";
char pass[] = "08659650";

SimpleTimer timer;

String myString; // complete message from arduino, which consistors of snesors data
char rdata; // received charactors


int firstVal, secondVal,thirdVal; // sensors 
// This function sends Arduino's up time every second to Virtual Pin (1).
// In the app, Widget's reading frequency should be set to PUSH. This means
// that you define how often to send data to Blynk App.
void myTimerEvent()
{
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V1, millis() / 1000);
  
}



void setup()
{
  // Debug console
  Serial.begin(9600);

  Blynk.begin(auth, ssid, pass);

    timer.setInterval(1000L,sensorvalue1); 
     timer.setInterval(1000L,sensorvalue2); 
     timer.setInterval(1000L,sensorvalue3);
}

void loop()
{

  
  
   if (Serial.available() == 0 ) 
   {
  Blynk.run();
  timer.run(); // Initiates BlynkTimer
  toarduino();
   }
   
  if (Serial.available() > 0 ) 
  {
    rdata = Serial.read(); 
    myString = myString+ rdata; 
   // Serial.print(rdata);
    if( rdata == '\n')
    {

// new code
String l = getValue(myString, ',', 0);
String m = getValue(myString, ',', 1);
String n = getValue(myString, ',', 2); 


firstVal = l.toInt();
secondVal = m.toInt();
thirdVal = n.toInt();

  myString = "";
// end new code
    }
  }

}

void sensorvalue1()
{
int sdata = firstVal;
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V2, sdata);

}
void sensorvalue2()
{
int sdata = secondVal;
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V3, sdata);

}

void sensorvalue3()
{
int sdata = thirdVal;
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V4, sdata);

}



String getValue(String data, char separator, int index)
{
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length() - 1;

    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

// in Blynk app writes values to the Virtual Pin V3
BLYNK_WRITE(V10)
{
   pinValue1 = param.asInt(); // assigning incoming value from pin V10 to a variable


}


// in Blynk app writes values to the Virtual Pin V4
BLYNK_WRITE(V11)
{
   pinValue2 = param.asInt(); // assigning incoming value from pin V10 to a variable

}

// in Blynk app writes values to the Virtual Pin V5, this is for the slider
BLYNK_WRITE(V12)
{
   pinValue3 = param.asInt(); // assigning incoming value from pin V10 to a variable

}

void toarduino()
{
v2arduino = v2arduino + pinValue1 + "," + pinValue2 + "," + pinValue3; 
Serial.println(v2arduino); 
delay(100); 
v2arduino = ""; 
}

 

Watch Video Tutorial:

 

Some other Projects:

IoT based 3 Phase Transformer monitoring.

IoT Water Quality Monitoring using Arduino and ESP8266.

IoT Temperature monitoring system using DS18B20 and ESP8266 Nodemcu

IoT vibration monitoring system using Nodemcu ESP8266

IoT 12V battery monitoring System

 

Engr Fahad

My name is Shahzada Fahad and I am an Electrical Engineer. I have been doing Job in UAE as a site engineer in an Electrical Construction Company. Currently, I am running my own YouTube channel "Electronic Clinic", and managing this Website. My Hobbies are * Watching Movies * Music * Martial Arts * Photography * Travelling * Make Sketches and so on...

3 Comments

  1. There’s an error occurred to me while uploading the code. How to fix this error:

    Arduino: 1.8.9 (Windows Store 1.8.21.0) (Windows 10), Board: “NodeMCU 1.0 (ESP-12E Module), 80 MHz, Flash, Legacy (new can return nullptr), All SSL ciphers (most compatible), 4MB (FS:2MB OTA:~1019KB), 2, v2 Lower Memory, Disabled, None, Only Sketch, 115200”

    In file included from C:\Users\user\Documents\Arduino\libraries\Blynk\src/Blynk/BlynkApi.h:17:0,

                 from C:\Users\user\Documents\Arduino\libraries\Blynk\src/BlynkApiArduino.h:14,
    
                 from C:\Users\user\Documents\Arduino\libraries\Blynk\src/BlynkSimpleEsp8266.h:24,
    
                 from C:\Users\user\Documents\Dindin\Capstone\Codes\nodemcu_trial_1\nodemcu_trial_1.ino:6:
    

    C:\Users\user\Documents\Arduino\libraries\Blynk\src/Blynk/BlynkTimer.h:36:21: error: redefinition of ‘class BlynkTimer’

    #define SimpleTimer BlynkTimer

                     ^
    

    C:\Users\user\Documents\Arduino\libraries\SimpleTimer/SimpleTimer.h:10:7: note: in expansion of macro ‘SimpleTimer’

    class SimpleTimer {

       ^
    

    C:\Users\user\Documents\Arduino\libraries\Blynk\src/Blynk/BlynkTimer.h:36:21: error: previous definition of ‘class BlynkTimer’

    #define SimpleTimer BlynkTimer

                     ^
    

    C:\Users\user\Documents\Arduino\libraries\Blynk\src/Blynk/BlynkTimer.h:41:7: note: in expansion of macro ‘SimpleTimer’

    class SimpleTimer {

       ^
    

    exit status 1
    Error compiling for board NodeMCU 1.0 (ESP-12E Module).

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

    1. //SEE THE BOTTEM FOR INFO

      #ifndef BLYNKTIMER_H
      #define BLYNKTIMER_H

      #include <Blynk/BlynkDebug.h>

      // Replace SimpleTimer
      #define SIMPLETIMER_H
      #define SimpleTimer BlynkTimer

      typedef void (timer_callback)(void);
      typedef void (
      timer_callback_p)(void *);

      class SimpleTimer {

      public:
      // maximum number of timers
      const static int MAX_TIMERS = 16;

      // setTimer() constants
      const static int RUN_FOREVER = 0;
      const static int RUN_ONCE = 1;
      
      // constructor
      SimpleTimer();
      
      void init();
      
      // this function must be called inside loop()
      void run();
      
      // Timer will call function 'f' every 'd' milliseconds forever
      // returns the timer number (numTimer) on success or
      // -1 on failure (f == NULL) or no free timers
      int setInterval(unsigned long d, timer_callback f);
      
      // Timer will call function 'f' with parameter 'p' every 'd' milliseconds forever
      // returns the timer number (numTimer) on success or
      // -1 on failure (f == NULL) or no free timers
      int setInterval(unsigned long d, timer_callback_p f, void* p);
      
      // Timer will call function 'f' after 'd' milliseconds one time
      // returns the timer number (numTimer) on success or
      // -1 on failure (f == NULL) or no free timers
      int setTimeout(unsigned long d, timer_callback f);
      
      // Timer will call function 'f' with parameter 'p' after 'd' milliseconds one time
      // returns the timer number (numTimer) on success or
      // -1 on failure (f == NULL) or no free timers
      int setTimeout(unsigned long d, timer_callback_p f, void* p);
      
      // Timer will call function 'f' every 'd' milliseconds 'n' times
      // returns the timer number (numTimer) on success or
      // -1 on failure (f == NULL) or no free timers
      int setTimer(unsigned long d, timer_callback f, unsigned n);
      
      // Timer will call function 'f' with parameter 'p' every 'd' milliseconds 'n' times
      // returns the timer number (numTimer) on success or
      // -1 on failure (f == NULL) or no free timers
      int setTimer(unsigned long d, timer_callback_p f, void* p, unsigned n);
      
      // updates interval of the specified timer
      bool changeInterval(unsigned numTimer, unsigned long d);
      
      // destroy the specified timer
      void deleteTimer(unsigned numTimer);
      
      // restart the specified timer
      void restartTimer(unsigned numTimer);
      
      // returns true if the specified timer is enabled
      bool isEnabled(unsigned numTimer);
      
      // enables the specified timer
      void enable(unsigned numTimer);
      
      // disables the specified timer
      void disable(unsigned numTimer);
      
      // enables all timers
      void enableAll();
      
      // disables all timers
      void disableAll();
      
      // enables the specified timer if it's currently disabled,
      // and vice-versa
      void toggle(unsigned numTimer);
      
      // returns the number of used timers
      unsigned getNumTimers();
      
      // returns the number of available timers
      unsigned getNumAvailableTimers() { return MAX_TIMERS - numTimers; };
      

      private:
      // deferred call constants
      const static int DEFCALL_DONTRUN = 0; // don’t call the callback function
      const static int DEFCALL_RUNONLY = 1; // call the callback function but don’t delete the timer
      const static int DEFCALL_RUNANDDEL = 2; // call the callback function and delete the timer

      // low level function to initialize and enable a new timer
      // returns the timer number (numTimer) on success or
      // -1 on failure (f == NULL) or no free timers
      int setupTimer(unsigned long d, void* f, void* p, bool h, unsigned n);
      
      // find the first available slot
      int findFirstFreeSlot();
      
      typedef struct {
        unsigned long prev_millis;        // value returned by the millis() function in the previous run() call
        void* callback;                   // pointer to the callback function
        void* param;                      // function parameter
        bool hasParam;                 // true if callback takes a parameter
        unsigned long delay;              // delay value
        unsigned maxNumRuns;              // number of runs to be executed
        unsigned numRuns;                 // number of executed runs
        bool enabled;                  // true if enabled
        unsigned toBeCalled;              // deferred function call (sort of) - N.B.: only used in run()
      } timer_t;
      
      timer_t timer[MAX_TIMERS];
      
      // actual number of timers in use (-1 means uninitialized)
      int numTimers;
      

      };

      #endif

      // copy this code to notepad and save as BlynkTimer.h (Remember The Save Location) then erase #include<SimpleTimer.h> in the coding .. Then type(in the code)
      // #include
      //Then #define SimpleTimer BlynkTimer in the code
      //Thank You

  2. #ifndef BLYNKTIMER_H
    #define BLYNKTIMER_H

    #include <Blynk/BlynkDebug.h>

    // Replace SimpleTimer
    #define SIMPLETIMER_H
    #define SimpleTimer BlynkTimer

    typedef void (timer_callback)(void);
    typedef void (
    timer_callback_p)(void *);

    class SimpleTimer {

    public:
    // maximum number of timers
    const static int MAX_TIMERS = 16;

    // setTimer() constants
    const static int RUN_FOREVER = 0;
    const static int RUN_ONCE = 1;
    
    // constructor
    SimpleTimer();
    
    void init();
    
    // this function must be called inside loop()
    void run();
    
    // Timer will call function 'f' every 'd' milliseconds forever
    // returns the timer number (numTimer) on success or
    // -1 on failure (f == NULL) or no free timers
    int setInterval(unsigned long d, timer_callback f);
    
    // Timer will call function 'f' with parameter 'p' every 'd' milliseconds forever
    // returns the timer number (numTimer) on success or
    // -1 on failure (f == NULL) or no free timers
    int setInterval(unsigned long d, timer_callback_p f, void* p);
    
    // Timer will call function 'f' after 'd' milliseconds one time
    // returns the timer number (numTimer) on success or
    // -1 on failure (f == NULL) or no free timers
    int setTimeout(unsigned long d, timer_callback f);
    
    // Timer will call function 'f' with parameter 'p' after 'd' milliseconds one time
    // returns the timer number (numTimer) on success or
    // -1 on failure (f == NULL) or no free timers
    int setTimeout(unsigned long d, timer_callback_p f, void* p);
    
    // Timer will call function 'f' every 'd' milliseconds 'n' times
    // returns the timer number (numTimer) on success or
    // -1 on failure (f == NULL) or no free timers
    int setTimer(unsigned long d, timer_callback f, unsigned n);
    
    // Timer will call function 'f' with parameter 'p' every 'd' milliseconds 'n' times
    // returns the timer number (numTimer) on success or
    // -1 on failure (f == NULL) or no free timers
    int setTimer(unsigned long d, timer_callback_p f, void* p, unsigned n);
    
    // updates interval of the specified timer
    bool changeInterval(unsigned numTimer, unsigned long d);
    
    // destroy the specified timer
    void deleteTimer(unsigned numTimer);
    
    // restart the specified timer
    void restartTimer(unsigned numTimer);
    
    // returns true if the specified timer is enabled
    bool isEnabled(unsigned numTimer);
    
    // enables the specified timer
    void enable(unsigned numTimer);
    
    // disables the specified timer
    void disable(unsigned numTimer);
    
    // enables all timers
    void enableAll();
    
    // disables all timers
    void disableAll();
    
    // enables the specified timer if it's currently disabled,
    // and vice-versa
    void toggle(unsigned numTimer);
    
    // returns the number of used timers
    unsigned getNumTimers();
    
    // returns the number of available timers
    unsigned getNumAvailableTimers() { return MAX_TIMERS - numTimers; };
    

    private:
    // deferred call constants
    const static int DEFCALL_DONTRUN = 0; // don’t call the callback function
    const static int DEFCALL_RUNONLY = 1; // call the callback function but don’t delete the timer
    const static int DEFCALL_RUNANDDEL = 2; // call the callback function and delete the timer

    // low level function to initialize and enable a new timer
    // returns the timer number (numTimer) on success or
    // -1 on failure (f == NULL) or no free timers
    int setupTimer(unsigned long d, void* f, void* p, bool h, unsigned n);
    
    // find the first available slot
    int findFirstFreeSlot();
    
    typedef struct {
      unsigned long prev_millis;        // value returned by the millis() function in the previous run() call
      void* callback;                   // pointer to the callback function
      void* param;                      // function parameter
      bool hasParam;                 // true if callback takes a parameter
      unsigned long delay;              // delay value
      unsigned maxNumRuns;              // number of runs to be executed
      unsigned numRuns;                 // number of executed runs
      bool enabled;                  // true if enabled
      unsigned toBeCalled;              // deferred function call (sort of) - N.B.: only used in run()
    } timer_t;
    
    timer_t timer[MAX_TIMERS];
    
    // actual number of timers in use (-1 means uninitialized)
    int numTimers;
    

    };

    #endif

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button