Wifi controlled car, arduino freezes, how to fix

Good afternoon, I had an idea to make wifi controlled car and see what’s happening in my room while I’m not at home.

Everything works fine while the internet connection is stable, but when the connection is lost my code crashes.

the problem is that Arduino freezes when the connection is lost, all my sensors stop working, but the car continuous to ride. And this is the big problem because, in this case, in 80 % of cases my car bump into
wall or other things that stay on the floor.

my question is: what can I do to eliminate this freeze? And after 15 seconds code starts to work again, but very slow, and 15 seconds is a lot of time. Is it possible to reduce this interval?

Thanks for the help, and sorry for mistakes (if they are present)

And maybe some advice?

this is my code(if needed)


/*
    Скетч к проекту "WiFi машинка на Arduino"
    Автор: GUGO Technologies  2020 
  /* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial


#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
//char auth[] = "CEl-cpfVJcZ0OgdjNOvKFktWlUkvGMit";
char auth[] = "";

// Your WiFi credentials.
// Set password to "" for open networks.
//char ssid[] = "";
//char pass[] = "";

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

//char ssid[] = "";
//char pass[] = "";

// Hardware Serial on Mega, Leonardo, Micro...
#define EspSerial Serial3

// or Software Serial on Uno, Nano...
//#include <SoftwareSerial.h>
//SoftwareSerial EspSerial(2, 3); // RX, TX

// Your ESP8266 baud rate:
#define ESP8266_BAUD 38400

ESP8266 wifi(&EspSerial);

///motors///
#define MOTOR_MIN 0
int  MOTOR_MAX;  // максимальный сигнал на мотор (max 255)
#define JOY_MIN 0
#define JOY_MAX 1023

#define IN1 8
#define IN2 9        // IN2 обязательно должен быть ШИМ пином!!!
#define IN3 7
#define IN4 6        // IN4 обязательно должен быть ШИМ пином!!!

#include "GyverMotor.h"
GMotor motorR(IN1, IN2);
GMotor motorL(IN3, IN4);

int X, Y;
int Speed, Sides;
int signalX0, signalY0;

////avoidance////

#include "GyverFilters.h"
#include <NewPing.h>


#define MAX_DISTANCE 150 // Maximum distance we want to ping for (in centimetres). Maximum sensor distance is rated at 400-500cm.
NewPing sonar1(3, 2, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
NewPing sonar2(4, 5, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

GMedian3 filter1, filter2 ;
GFilterRA filter3, filter4;
int distance1, distance2;
unsigned long timer1;
boolean  Flag1, Flag2, Flag3, Flag4, Flag5;


BLYNK_WRITE(V1) {
 if (Flag4 == 0){ 
X = param[0].asInt();
  
Y = param[1].asInt();
 }

}
BLYNK_WRITE(V2) {
  int MAX = param.asInt();
  MOTOR_MAX = MAX;
}

#define BLYNK_GREEN     "#23C48E"
#define BLYNK_BLUE      "#04C0F8"
#define BLYNK_YELLOW    "#ED9D00"
#define BLYNK_RED       "#D3435C"
#define BLYNK_DARK_BLUE "#5F7CD8"

WidgetLED led1(V3);
WidgetLED led2(V4);

BlynkTimer timer;

BLYNK_WRITE(V5) {
  if (Flag4 == 1){
  //acceleration force applied to axis x
   int X0 = param[0].asFloat();
  //acceleration force applied to axis y
   int Y0 = param[1].asFloat();
  
   Y0 = map((Y0), JOY_MIN, 5, MOTOR_MIN , 1023 );         // сигнал по У
   X0 = map((X0), JOY_MIN, 5, MOTOR_MIN , 1023 );

  Y = constrain(abs(Y0), MOTOR_MIN, 1023);
  X = constrain(abs(X0), MOTOR_MIN, 1023);
  

  if (X0 > 0) {
    X = -X;
  }

  if (Y0 > 0) {
    Y = -Y;
  }


  // Do something with x and y
  //Serial.print("X = ");
  //Serial.print(X);
  //Serial.print("; Y = ");
  //Serial.println(Y);
  // Serial.print("; Z = ");
  //Serial.println(z);

  }
}
BLYNK_WRITE(V6) {
 Flag4 = param.asInt();
 
}

void setup() {
  Serial.begin(38400);

  // Set ESP8266 baud rate
  EspSerial.begin(ESP8266_BAUD);
  delay(10);

  //Blynk.begin(auth, wifi, ssid, pass);
  // You can also specify server:
  //Blynk.begin(auth, wifi, ssid, pass, "blynk-cloud.com", 80);
  Blynk.begin(auth, wifi, ssid, pass, "", 8080);

  ////sonar////
  filter3.setStep(5);
  filter4.setStep(5);
  /////led part//////

  led1.on();
  led2.on();

  timer.setInterval(1000L, led);

}


void loop() {
Blynk.run();
Serial.print(Blynk.run());

avoidance();

motors();

//timer.run();
}

void avoidance(){
  if (millis() - timer1 > 80) {
    int a, c ;
    byte b, d;
    a = filter1.filtered(sonar1.ping_cm());
    c = filter2.filtered(sonar2.ping_cm());
    b = abs(sonar1.ping_cm() - a);  // расчёт изменения с предыдущим
    d = abs(sonar2.ping_cm() - c);
    if (b > 1) filter3.setCoef(0.7);   // если большое - резкий коэффициент
    else filter3.setCoef(0.2);
    if (d > 1) filter4.setCoef(0.7);
    else filter4.setCoef(0.2);
    distance1 = filter3.filteredTime(a);
    distance2 = filter4.filteredTime(c);

    Serial.print(distance1); 
    Serial.print("    "); 
    Serial.println(distance2);
    
    timer1 = millis();
  }
if (distance1 < 70 && distance1 > 40 && Y > 320 || distance1 < 70 && distance1 > 40 && Y < -320 || distance2 < 70 && distance2 > 40 && Y > 320 || distance2 < 70 && distance2 > 40 && Y < -320) Flag1 = 1; 

else Flag1 = 0; 

if (distance1 > 0 && distance1 <= 40 && Y > 320    || distance2 > 0 && distance2 <= 40  && Y < -320) Flag2 = 1; 

else Flag2 = 0; 

}

void led(){

if (distance1 > 70  )   led1.setColor(BLYNK_GREEN);

if (distance2 > 70 )   led2.setColor(BLYNK_GREEN);

if (distance1 <= 70 &&  distance1 > 40)  led1.setColor(BLYNK_YELLOW);

if (distance2 <= 70 &&  distance2 > 40 ) led2.setColor(BLYNK_YELLOW);

if (distance1 <= 40  )   led1.setColor(BLYNK_RED);

if (distance2 <= 40 )   led2.setColor(BLYNK_RED);


Blynk.virtualWrite(V7,distance1);

Blynk.virtualWrite(V8,distance2);





}


void motors() {

  if (X == 0 && Y == 0 || Flag2 == 1 || Flag5 == 0) {   // если мы в "мёртвой" зоне
    motorR.setMode(STOP);           // не двигаемся
    motorL.setMode(STOP);
    Speed = 0;
    Sides = Speed;
  }
  else {
    
    signalY0 = map((Y), JOY_MIN, JOY_MAX, MOTOR_MIN , MOTOR_MAX ); // сигнал по У
    signalX0 = map((X), JOY_MIN, JOY_MAX, MOTOR_MIN , MOTOR_MAX ); // сигнал по Х

    if (signalY0 < 0) {
      signalY0 = signalY0 * -1; //Конвертируем сигнал в положительный
    }

    if (signalX0 < 0) {
      signalX0 = signalX0 * -1; //Конвертируем сигнал в положительный
    }
    
    if (signalY0 >= signalX0) {
      Speed = signalY0 + (signalX0 / 2); //делим сигнал X  сигнал по полам для достижения большей плавности
    }

    if (signalY0 <= signalX0) {
      Speed = (signalY0 / 2) + signalX0; //делим сигнал Y  сигнал по полам для достижения большей плавности
    }

    Speed = constrain(abs(Speed), 0, MOTOR_MAX);
    Sides = Speed - signalX0;



    if ( Y < 320 && Y > -320 ) {
      Sides = -Speed;   //поворот на 360 градусов
    }
    if (Y < -320 ) {
      Speed = -Speed; // задний ход
      Sides = -Sides;
    }

    if (X < 0) {
      int swap = Speed; //переворот двух значений переменных для противоположной стороны
      Speed = Sides;
      Sides = swap;
    }
    // Serial.print(Speed);
    //Serial.print(" ");
    //Serial.println(Sides);



    if (Speed > 0) motorL.setMode(FORWARD);
    else motorL.setMode(BACKWARD);
    //управление моторами
    if (Sides > 0) motorR.setMode(FORWARD);
    else motorR.setMode(BACKWARD);

    Speed = constrain(abs(Speed), MOTOR_MIN, MOTOR_MAX);
    Sides = constrain(abs(Sides), MOTOR_MIN, MOTOR_MAX);
  }
  if (Flag1 == 0) {
    motorR.setSpeed(Sides);       // задаем скорость
    motorL.setSpeed(Speed);
  }

  if (Flag1 == 1) {
    motorR.setSpeed(Sides / 2);     // задаем скорость
    motorL.setSpeed(Speed / 2);

  }
}

I think you’ll find that the connection loss is due to Blynk timing-out, and that is happening because you have far too much stuff happening in your void loop (or in functions called by your void loop every time it executes).
In addition, your Arduino probably doesn’t have enough processing speed, and maybe not enough memory either, to cope with what you’re asking it to do.

Pete.

No, when there is a connection everything works fine, but when connection is lost code freezes(it starts to reconnect and reconnect to the local server). Is it possible to remove this check?

YES… just because it works (or so you think, and only in perfect conditions), doesn’t mean it works properly :stuck_out_tongue:

Since Blynk tends to require a constant connection, removing the “check” is a non-solution.

There are a few ways of implementing a failsafe for motor driven devices, but before you can fix the issue of signal and control loss, you need to fix your code to better support the solutions.

Lots of examples of Blynk controlled rovers (including some “fail safe timers”) in this forum… just do some searching and learn about proper void loops and timed functions.

PS a good “failsafe” is to treat your rover like it was on Mars… In other words, limit its “freedom” due to potential delays in-between commands, do not simply let it follow the last command until the end of time. Put in some timed restrictions for each action. AKA, if FORWARD, then do so until X amount of time, then STOP, unless new command arrives first, then do that command until X… etc…

2 Likes

:grinning:Ok, but how timer will start if code is stopped? The problem is that if connection is lost the whole program stops.
And all timers or other things stop working. I wanted to write something like (if nothing new in 5 seconds my robot stop driving). But no results, because no Wi-Fi.

I have also 2 sonar sensors, but they also stop working, because the Wi-Fi connection is lost.

My idea was to take second Arduino (Nano for example) it will receive all data that goes to motors, and if Nano does not receive more new information, it will block the motors. (but I don’t like this variant, because I don’t want to use 2 boards).

Not if you use the proper code and programming methods (for Blynk).

Look here for one method of continuous code operation…

I wrote this long ago and there might be even better ways, later documented in this forum… So this is also important… :innocent:

Blynk - RE-SEAR-CH

1 Like

Ok thank you for this advice :handshake:, i have read your code, and i think this should work for me.
but one thing I didn’t understand:

 WiFi.begin(ssid, pass); 

what library are you using? because i have " ‘WiFi’ was not declared in this scope" error.

It’s part of the ESP8266WiFi.h library.

The code you were looking at was written for an ESP8266 based board, not an Arduino plus ESP-01 combination, so would require modifications to work with your hardware.

I’m also sceptical about whether this will solve the problem that you’ve described, but you seem unwilling to hear the guidance that’s being offered about the root cause of the issue.

Pete.

Sorry, I might not understand you, can you repeat your advice. I will try to read more carefully.
Thanks.

True… however I only intended it to be used as a reference for the Blynk.config() and reconnection option… the OP apparently just loaded the whole thing :slight_smile: My mistake for not being clearer on which part of the code I was referring too :innocent:

@vektobus

Instead of Blynk.begin()

Blynk.config(auth, server, port);
Blynk.connect();

See here: https://docs.blynk.cc/#blynk-firmware-configuration-blynkconfig

And then the bare minimum “check test” in the void loop()

  if (Blynk.connected()) {  // If connected run as normal
    Blynk.run();
  }

@vektobus Here is another sketch (which could have been found with some searching :wink: ) that I use for an old RC car conversion… Running on an UNO and ESP-01.

Note: there is NO “keep running without connection” code in this one (no need for my uses), so you would need to add that. But it does show a (very rudimentary) “fail safe” timer solution to shut off the motors.

1 Like

Thank you so much. That is very useful information and I will try to do this also with my robot.
But one thing I didn’t understand in your code. Why I need this:

  wifi.setDHCP(1, 1, 1); //Enable dhcp in station mode and save in flash of esp8266

???

After 10 probes: I don’t know why, but if I disable my server, my code stop running for 10 seconds.
I have added these

if (Blynk.connected()) {  // If connected run as normal
   Blynk.run();
 }

Is it possible to solve it?

These 10 seconds are killing me

post your latest code so that we can see what techniques you have tried, and what you have not.

#define BLYNK_PRINT Serial

#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <Servo.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
//char auth[] = "CEl-cpfVJcZ0OgdjNOvKFktWlUkvGMit";

char auth[] = "zk9LYDsplNnxXvahKZdICKtiCVUVtZgg";



char ssid[] = "";
char pass[] = "";
char server[] = "";  // IP for your Local Server
int port = 8080;



#include <NeoSWSerial.h>  // https://github.com/SlashDevin/NeoSWSerial
NeoSWSerial EspSerial(2, 3);  // RX, TX - using Analog pins A0 & A1
#define ESP8266_BAUD 9600
ESP8266 wifi(&EspSerial);


Servo servo;

# include "GyverButton.h"
GButton but (5);

const int sensorPin = 2;

int lightVal;
BLYNK_WRITE(V3)
{
  servo.write(param.asInt());
}
int ReCnctFlag;  // Reconnection Flag
int ReCnctCount = 0;  // Reconnection counter

unsigned long lon;
void setup()
{


  // Debug console
  Serial.begin(9600);


  // Set ESP8266 baud rate
  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  //Blynk.begin(auth, wifi, ssid, pass);
  // You can also specify server:
  //Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 80);
  //wifi.setDHCP(1, 1, 1); //Enable dhcp in station mode and save in flash of esp8266
  Blynk.config(wifi, auth, server, port);
  if (Blynk.connectWiFi(ssid, pass)) {
    Blynk.connect();
  }
  servo.write(40);
  int lightCal = analogRead(sensorPin);
  servo.attach(4);
}

void loop()
{

  if (Blynk.connected()) {

    Blynk.run();
  }

  else {
    Serial.print("disconnected");
    Blynk.connect();
  }


  but.tick();

  Serial.println(lightVal);
  if (but.isHold() == 1 || lightVal < 820) {
    servo.write(40);
  }

  if (lightVal > 820 && but.isHold() == 0) {
    while (1) {
      int lightVal1 = analogRead(sensorPin);
      if (lightVal1 > 820) {
        delay(1000);
        servo.write(8);
      }

      int lightVal2 = analogRead(sensorPin);
      if (lightVal2 > 820) {
        delay(1000);
        servo.write(70);
      }
      int lightVal3 = analogRead(sensorPin);
      if (lightVal3 < 850) {
        break;
      }
    }
  }

  lightVal = analogRead(sensorPin);

}

This is my last code(not Wi-Fi car) it’s shorter, but here we can see this 10-second delay.

If you run this code with local server and after everything is connected, you disconnect the server, you will see, that Serial.print stop printing for 10 seconds.

In my rower code this is the big problem, because 10 seconds it’s enough to bump in to the wall.

You have to much code in the loop() this is will cause your disconnection issue, which in turn causes the 10-second delay (BLYNK is trying to re-establish connection to the server). You cannot get rid of this delay when BLYNK is trying to establish a connection, there is no way around it. You can shorten it by adding in a timeout, for example Blynk.connect(500);, but the best way to prevent it is by keeping the device connected to the server. This is done with:

Where should I add this?
How to add timeout?
If will be 5 or 3 seconds, it will be great.

Replace this:

The 500 after the Blynk.connect is the timeout time in milliseconds, but Blynk uses 3 times this value.

However, I don’t think that will help, as it’s not the reconnect timeout that’s the issue.

The 10 seconds is coming from the heartbeat time with the server. If the Blynk library hasn’t connected to the server for 10 seconds then Blynk.connected() will be false. If you shorten this heartbeat time then you’ll get more disconnections. If you lengthen it you’ll get fewer disconnections, but that isn’t the way to solve your problem.

As I said in my first post in this topic:

But, as I said later:

You still have far too much happening during each execution of your void loop. The loop should be executing tens, if not hundreds, of times per second and it’s not. Solve that, and you’ll solve your problem.
Ignore that, and you’ll continue to have problems.

Pete.

1 Like

Ok I have cut everything from my loop:

void loop()
{
  
 if(Blynk.connected()){

Blynk.run();
 }
Serial.println("1");
 
}

This is my loop part now, but nothing has changed.

And I do this because my Wi-Fi connection is not stable, and some times, if Wi-Fi is lost, my car steel running and bumps. With my server everything is ok, and when Wi-Fi is good, I have full controlled car.

My question is how to reduce these 10 seconds?

If your problem really is your WiFi connection, why aren’t you using WiFi.status() instead of Blynk.connected() ?

Pete.

If you can’t fix your WiFi issue, then instead of trying to change how Blynk needs to work, simply change your motor control for short intermittent movements,.so that the worst that happens is it sits there waiting until you can control it again. Not really a Blynk issue.

I think I will do so, I will check the status of the Wi-Fi, I will make the movements short and I will optimize my code.

But I’m worried about the question, there is no way to change the delay of 10 seconds? Maybe I can change something in the system files or add something?