Blynk Joystick Controlled Tracked Rover with Wemos D1 Mini Pro

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