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

Blynk Joystick Controlled Tracked Rover with Wemos D1 Mini Pro

#1

This is going to be a “work in progress” topic… mainly because I do things slowly, as clarity and energy allow, so if I wait until it is finished, well… we may be into a new millennium :wink:

I am using a Wemos D1 Mini Pro. I am using the Pro becasue it has an external antenna option… for better range, should I get adventurous.

Right now I just have the Wemos mounted on a battery shield, sitting on the rover’s battery, and wired ONLY to the motor controller without PWM control.

As this progresses (i.e. as I learn how to use some of the more nitpicky pins on the Wemos), I will wire in the servo controlled Low/High gear transmission and the transistor controlled LED headlamp… as well as PWM variable control of the motors.

This will task the Mini’s limited pins as it is, so not sure if I will have any pins left to connect the UNO as a secondary “slave” device or not (or even if it is necessary).

There will be the RX/TX pins, but I haven’t yet figured out if they are readily available, since I am using OTA for programming.

So much to learn :slight_smile:

I will update this topic with sketches, App QR, detailed pictures and build info as I go along. If you have any questions or wish to see something in more detail, let me know.

7 Likes

Loosing connection with iOS app
HM10 to arduino Uno to run a motor shield
Esp8266 as Uno WiFi shell in home robot
Control motor with blynk but motor stops when it hits either (of the 2) push buttons
Wemos D1 R2 & mini blinkcloud timeout
Display data from NodeMCU ESP8266 on cloud server to Raspberry Pi local server on android app
Please help
Desire to run more than one Video Widget at a time in a single tab
#2

The basic code so far…

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

#include <ESP8266mDNS.h>  // For OTA
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA

ADC_MODE(ADC_VCC);  // For monitoring of internal voltage levels

// Setup L298N Motor Controller Input Pins
int IN1 = D6;  // Motor 2
int IN2 = D5;  // Motor 2
int IN3 = D2;  // Motor 1
int IN4 = D1;  // Motor 1

int Flag = 1;
char incomingByte;

char auth[] = "xxxxxxxxxx";
char ssid[] = "xxxxxxxxxx";
char pass[] = "xxxxxxxxxx";

BlynkTimer timer;



void setup()
{
  // setup L298N Motor Controller Input Pins
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

  Serial.begin(115200);

  Blynk.begin(auth, ssid, pass, "10.10.3.13", 8442);  // Set for Local Server

  timer.setInterval(1000L, VCCInput);

  ArduinoOTA.setHostname("Wemos D1 Mini Pro");  // For OTA
  ArduinoOTA.begin();  // For OTA
}



BLYNK_WRITE(V6)  // Joystick Widget Input
{
  Flag = 1;
  int y = param[1].asInt();
  int x = param[0].asInt();
  if (y > 750 && Flag == 1) {  // Forward
    Flag = 0;
    incomingByte = '1';
    ControlOutput();
  }
  if (y < 250 && Flag == 1) {  // Backward
    Flag = 0;
    incomingByte = '2';
    ControlOutput();
  }
  if (x < 250 && Flag == 1) {  // Left
    Flag = 0;
    incomingByte = '3';
    ControlOutput();
  }
  if (x > 750 && Flag == 1) {  // Right
    Flag = 0;
    incomingByte = '4';
    ControlOutput();
  }
  if (y == 512 && y == 512) {  // Full Stop
    incomingByte = '0';
    ControlOutput();
  }
}



// Button Widgets Input
BLYNK_WRITE(V2) {  // Forward
  if (param.asInt() == 1) {
    incomingByte = '1';
  } else {
    incomingByte = '0';
  }
  ControlOutput();
}
BLYNK_WRITE(V3) {  // Backward
  if (param.asInt() == 1) {
    incomingByte = '2';
  } else {
    incomingByte = '0';
  }
  ControlOutput();
}
BLYNK_WRITE(V4) {  // Left
  if (param.asInt() == 1) {
    incomingByte = '3';
  } else {
    incomingByte = '0';
  }
  ControlOutput();
}
BLYNK_WRITE(V5) {  // Right
  if (param.asInt() == 1) {
    incomingByte = '4';
  } else {
    incomingByte = '0';
  }
  ControlOutput();
}



//  Take inputs and direct motor control functions
void ControlOutput() {
  switch (incomingByte) {
    case '1': {
        motor1Forward();
        motor2Forward();
        Blynk.virtualWrite(V1, "Forward");
      }
      break;
    case '2': {
        motor1Backwards();
        motor2Backwards();
        Blynk.virtualWrite(V1, "Backward");
      }
      break;
    case '3': {
        motor1Backwards();
        motor2Forward();
        Blynk.virtualWrite(V1, "Spin Left");
      }
      break;
    case '4': {
        motor1Forward();
        motor2Backwards();
        Blynk.virtualWrite(V1, "Spin Right");
      }
      break;
    default: {
        Blynk.virtualWrite(V1, "Full Stop");
        motor1Stop();
        motor2Stop();
        Flag = 1;
      }
      break;
  }
}



// Functions to control L298N Motor Controller Input Pins
void motor1Forward() {
  digitalWrite(IN4, HIGH);
  digitalWrite(IN3, LOW);
}
void motor1Backwards() {
  digitalWrite(IN4, LOW);
  digitalWrite(IN3, HIGH);
}
void motor1Stop() {
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}
void motor2Forward() {
  digitalWrite(IN2, HIGH);
  digitalWrite(IN1, LOW);
}
void motor2Backwards() {
  digitalWrite(IN2, LOW);
  digitalWrite(IN1, HIGH);
}
void motor2Stop() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
}



void VCCInput() {  // Simple monitoring of internal voltage levels
  Blynk.virtualWrite(V0, ESP.getVcc() * 0.001);
}



void loop()
{
  Blynk.run();
  timer.run();
  ArduinoOTA.handle();  // For OTA
}
0 Likes

#3

Hello sir nice project
I try to play the video nothing appear ?

0 Likes

#4

I fixed the link… try again. And thank you!

0 Likes

#5

Very nice!!!
Tesla will copy your vehicle for sure…!

( I really like it )

0 Likes

#6

What chassis do you use?

0 Likes

#7

It was the base from an old broken remote control “robot” toy called the RAD 1.0


0 Likes

#8

It has gone through a few stages of development… before I scaled it back to its current slim state with easier access to the control circuitry.


3 Likes

#9

So, a few updates… I now have it working entirely on Blynk and the Wemos D1 Mini Pro; Gear change, LED, Motion and even Video.

Right now the voltage display is the ESP’s internal voltage… next is to switch that over to the 12v battery level with a voltage divider.

Current code:

#include <Servo.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

// For OTA:
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

ADC_MODE(ADC_VCC);  // For monitoring of internal voltage levels

// Setup L298N Motor Controller Input Pins:
int IN1 = D6;  // Motor 2
int IN2 = D5;  // Motor 2
int IN3 = D2;  // Motor 1
int IN4 = D1;  // Motor 1
int servoPin = 0;
int Flag = 1;
char incomingByte;

//Setup WiFi:
char auth[] = "xxxxx";
char ssid[] = "xxxxx";
char pass[] = "xxxxx";
char server[] = "blynk-cloud.com";
int port = 8080;

BlynkTimer timer;

Servo myservo;



void setup()
{
  // setup L298N Motor Controller Input Pins:
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(2, OUTPUT);

  // Set to LOW gear:
  myservo.attach(servoPin);
  myservo.write(0);
  timer.setInterval(1000L, StopServo);

  Blynk.begin(auth, ssid, pass, server, port);  // Set for Local Server

  timer.setInterval(1000L, VCCInput);  // Battery Check timer

  // For OTA:
  ArduinoOTA.setHostname("Gunnerator - Wemos D1 Mini Pro");
  ArduinoOTA.begin();
}



// Servo controlled gearing:
BLYNK_WRITE(V8) {
  if (param.asInt() == 1) {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
    myservo.attach(servoPin);
    myservo.write(175); // High gear
    timer.setTimeout(1500L, StopServo);
  } else {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
    myservo.attach(servoPin);
    myservo.write(0);  // Low gear
    timer.setTimeout(1500L, StopServo);
  }
}



// Headlamp Control:
BLYNK_WRITE(V9) {
  if (param.asInt() == 1) {
    digitalWrite(2, HIGH); // Headlamp ON
  } else {
    digitalWrite(2, LOW); // Headlamp OFF
  }
}



void StopServo() {
  myservo.detach();
}



// Joystick Widget Input:
BLYNK_WRITE(V6)
{
  Flag = 1;
  int y = param[1].asInt();
  int x = param[0].asInt();
  if (y > 750 && Flag == 1) {  // Forward
    Flag = 0;
    incomingByte = '1';
    ControlOutput();
  }
  if (y < 250 && Flag == 1) {  // Backward
    Flag = 0;
    incomingByte = '2';
    ControlOutput();
  }
  if (x < 250 && Flag == 1) {  // Left
    Flag = 0;
    incomingByte = '3';
    ControlOutput();
  }
  if (x > 750 && Flag == 1) {  // Right
    Flag = 0;
    incomingByte = '4';
    ControlOutput();
  }
  if (y == 512 && y == 512) {  // Full Stop
    incomingByte = '0';
    ControlOutput();
  }
}



// Button Widgets Input:
BLYNK_WRITE(V2) {  // Forward
  if (param.asInt() == 1) {
    incomingByte = '1';
  } else {
    incomingByte = '0';
  }
  Blynk.virtualWrite(V7, "Forward");
  ControlOutput();
}

BLYNK_WRITE(V3) {  // Backward
  if (param.asInt() == 1) {
    incomingByte = '2';
  } else {
    incomingByte = '0';
  }
  Blynk.virtualWrite(V7, "Backward");
  ControlOutput();
}

BLYNK_WRITE(V4) {  // Left
  if (param.asInt() == 1) {
    incomingByte = '3';
  } else {
    incomingByte = '0';
  }
  Blynk.virtualWrite(V7, "Spin Left");
  ControlOutput();
}

BLYNK_WRITE(V5) {  // Right
  if (param.asInt() == 1) {
    incomingByte = '4';
  } else {
    incomingByte = '0';
  }

  Blynk.virtualWrite(V7, "Spin Right");
  ControlOutput();
}



//  Take inputs and direct motor control functions:
void ControlOutput() {
  switch (incomingByte) {
    case '1': {
        motor1Forward();
        motor2Forward();
        Blynk.virtualWrite(V1, "Forward");
      }
      break;
    case '2': {
        motor1Backwards();
        motor2Backwards();
        Blynk.virtualWrite(V1, "Backward");

      }
      break;
    case '3': {
        motor1Backwards();
        motor2Forward();
        Blynk.virtualWrite(V1, "Spin Left");
      }
      break;
    case '4': {
        motor1Forward();
        motor2Backwards();
        Blynk.virtualWrite(V1, "Spin Right");
      }
      break;
    default: {
        Blynk.virtualWrite(V1, "Full Stop");
        Blynk.virtualWrite(V7, "Full Stop");
        motor1Stop();
        motor2Stop();
        Flag = 1;
      }
      break;
  }
}



// Functions to control L298N Motor Controller Input Pins:
void motor1Forward() {
  digitalWrite(IN4, HIGH);
  digitalWrite(IN3, LOW);
}
void motor1Backwards() {
  digitalWrite(IN4, LOW);
  digitalWrite(IN3, HIGH);
}
void motor1Stop() {
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}
void motor2Forward() {
  digitalWrite(IN2, HIGH);
  digitalWrite(IN1, LOW);
}
void motor2Backwards() {
  digitalWrite(IN2, LOW);
  digitalWrite(IN1, HIGH);
}
void motor2Stop() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
}



// Simple monitoring of internal voltage levels:
void VCCInput() {
  Blynk.virtualWrite(V0, ESP.getVcc() * 0.001);
}



void loop()
{
  Blynk.run();
  timer.run();
  ArduinoOTA.handle();  // For OTA
}
3 Likes

Use smartphone for FPV camera and GPS tracking smartcar robot 4WD
Video Streaming Widget Instructions
#10

Since the Wemos is plugged into a battery board, at the time for easy velcro mounting in the rover, I added a little battery just to keep it running even if the 12v battery somehow runs low enough to cause brownouts.

1 Like

#11

That is seriously the coolest Blynk robot yet!!

Camera and all! So awesome!

Next I hope we will see a roaming video and a range test? :smiley:

0 Likes

#12

Thank you!

Already range and reliability far exceeds the previous bluetooth, but that’s of course a normal benefit of WiFi vs BT.

That was a very old Android phone… and extremely laggy… very much a >Mars Rover< :wink: type driving experience, wherein I guess my target based on what I see, drive a few seconds, then wait to see what it hit :stuck_out_tongue: (I will eventually add sensors for semi autonomous action).

1 Like

#13

ADC pin must be floating for ESP.getVcc() to read correctly.

You can’t use this function with Wemos D1 or NodeMCU because ADC pin is connected to ground with 100 k Ohm resistor and you will always get a wrong reading. (< 3v)

voltage divider

The NodeMCU and the Wemos D1 mini have this network already in place

R2= 100 k ohms
R1= 220 k ohms

the Vout is connected to the ADC pin of the ESP-12 module and Vin is connected to the A0 pin on the NodeMCU or Wemos board.

instead I use this function for 3.3 V

void VCCInput() {  
     float sensorData = analogRead(A0); //reading the sensor on A0
    Blynk.virtualWrite(vPIN_VCCInput, (sensorData/1024) * 3.3);}

& this function for 5 V after adding a 180 k ohms to A0 pin

R2= 100 k ohms
R1=180 k + 220 k =400 k ohms

void VCCInput() {  
     float sensorData = analogRead(A0); //reading the sensor on A0
    Blynk.virtualWrite(vPIN_VCCInput, (sensorData/1024) * 5);}
0 Likes

#14

Old topic… and that was only for (attempted) simple monitoring of the Wemos power as it was running on battery. But even then was limited as the step up converter (not to mention the internal 5v-3.3v regulator circuit) would keep the voltage indication artificially high until just before shutdown, floating ADC or not.

End result, I never really used it anyhow… :wink:

… and I have long since switched to a voltage divider (basically added a 1.1M resistor in-line between the ADC and the battery+ to account for up to 14.8vdc) and direct 12v battery monitoring.

// Simple monitoring of internal voltage levels:
void VCCInput() {
  //Blynk.virtualWrite(V0, ESP.getVcc() * 0.001);
  Blynk.virtualWrite(V0, analogRead(A0)*0.0145);  // ADC range up to 14.8v
}

image

And I already knew about all the rest… was recently explaining it to another user :stuck_out_tongue_winking_eye:

1 Like

Reading battery voltage
split this topic #15

A post was split to a new topic: Need some help with battery reading

0 Likes

closed #16
0 Likes