Bluetooth and Ultrasonic don't seem to work as "expected" together

Hello people of the Arduino community. That’s my first time posting in the forums so bear with me. So i’m trying to make a bluetooth controlled 4 wheeled car which by the use of an ultrasonic sensor, when i “tell it” to go forward and there is an obstacle it should stop/or do another movement… My problem is as follows (with the current code): When i press forward the vehicle move forward as expected, in fact every move works well. So say that the distance is safe, while pressing forward the vehicle moves forward, but if the distance changes to unsafe, the vehicle still moves forward instead of stopping. So if any of you could help i would be more than grateful. If there is any part that you don’t understand please don’t hesitate to tell me. Thanks in advance.

The arduino code is as follows:

#include <Arduino.h>
#include <SoftwareSerial.h>
#include <Ultrasonic.h>
// #include <NewPing.h>
#include <Servo.h>

int bluetoothTx = 13;
int bluetoothRx = 12;

int btData;
// int btSendInfo;

SoftwareSerial bluetooth(bluetoothRx, bluetoothTx);

int rightMotorPin1 = 7;
int rightMotorPin2 = 8;

int leftMotorPin1 = 9;
int leftMotorPin2 = 10;

Servo servo;

const int TrigPinF = A5;
const int EchoPinF = A4;

const int TrigPinR = 5;
const int EchoPinR = 4;

const int TrigPinL = 3;
const int EchoPinL = 2;

// #define SAFE 15

int distanceR;
int distanceF;
int distanceL;

Ultrasonic sensorF(TrigPinF, EchoPinF), sensorR(TrigPinR, EchoPinR), sensorL(TrigPinL, EchoPinL);

void setup() {

  servo.attach(11);
  bluetooth.begin(9600);
  Serial.begin(9600);
  pinMode(rightMotorPin1, OUTPUT);
  pinMode(rightMotorPin2, OUTPUT);
  pinMode(leftMotorPin1, OUTPUT);
  pinMode(leftMotorPin2, OUTPUT);

}

void MoveForward(){
  digitalWrite(rightMotorPin1, HIGH);
  digitalWrite(rightMotorPin2, LOW);
  digitalWrite(leftMotorPin1, HIGH);
  digitalWrite(leftMotorPin2, LOW);
}

void MoveBackward(){
  digitalWrite(rightMotorPin1, LOW);
  digitalWrite(rightMotorPin2, HIGH);
  digitalWrite(leftMotorPin1, LOW);
  digitalWrite(leftMotorPin2, HIGH);
}

void servoRotateRight(){
  servo.write(155);
}

void servoRotateLeft(){
  servo.write(35);
}

void servoGoToCenter(){
  servo.write(90);
}

void MoveFR(){
  MoveForward();
  servoRotateRight();
}

void MoveFL(){
  MoveForward();
  servoRotateLeft();
}

void MoveBR(){
  MoveBackward();
  servoRotateRight();
}

void MoveBL(){
  MoveBackward();
  servoRotateLeft();
}

int sScan(Ultrasonic sensor){
  sensor.read();
  delay(50);
  Serial.println("Reads ");
  Serial.print(sensor.read());
  Serial.println();
  return sensor.read();
}

void stop() {
  digitalWrite(rightMotorPin1, LOW);
  digitalWrite(rightMotorPin2, LOW);
  digitalWrite(leftMotorPin1, LOW);
  digitalWrite(leftMotorPin2, LOW);
  servoGoToCenter();
}

void autoRight() {
  MoveForward();
  servoRotateRight();
  delay(500);
  stop();
}

void autoLeft() {
  MoveForward();
  servoRotateLeft();
  delay(500);
  stop();
}

void loop() {
  distanceF = sScan(sensorF);
  btData = bluetooth.read();
  if (distanceF>15) {
    switch (btData)
    {
    case 'F':  
      MoveForward();      
      break;
    case 'B':
      MoveBackward();
      break;
    case 'L':
      servoRotateLeft();
      break;
    case 'R':
      servoRotateRight();
      break;
    case '0':
      stop();
      break;
    default:
      break;
    }
  }
  else if (distanceF<=15) {
    switch (btData)
    {
    case 'F':
      stop();
      break;
    case '0':
      stop();
    default:
    break;
    
    }
  }
  
}

Your code decides what to do based on the distance and the bluetooth input. If the distance is safe, and the bluetooth device says go forward, the device will start moving forward. Then, loop ends, and repeats.

Suppose that there is no input from the bluetooth device for 10 minutes, then. The device, moving forwards, gets within 15 undefined units from some obstacle. What do you do? Well, that depends on the current bluetooth input. There isn't any, so you do nothing.

That hardly seems like the right thing to do.

Maybe you want to do something based on the last thing you got from the bluetooth device, in which case you should replace the value in btData only if there is something available().

Maybe what to do has nothing to do with input from the bluetooth device. Maybe you should stop.

Only you really know what you want to do when there is something in front of the device and there is no current bluetooth input.

Let me rephrase what my goal is. In very simplistic manner, i want to control this vehicle (this thing works), but in the case of finding an obstacle (say safe distance is smaller or equal than/to 15) i want it to do something like stop OR use the autoRight/autoLeft function. What i don't get is what "path" to follow on the programming side since the code given above doesn't work as expected. (I fear that instead of you not understanding me, it's me having the problem to understand)

but in the case of finding an obstacle (say safe distance is smaller or equal than/to 15) i want it to do something like stop OR use the autoRight/autoLeft function.

So, when the distance is less than 15, what you want to do does not depend on bluetooth input. Why does your code think it does?

PaulS:
So, when the distance is less than 15, what you want to do does not depend on bluetooth input. Why does your code think it does?

No, it is dependable on the bluetooth input. If i'm pressing forward and there is an obstacle in front i want the vehicle to stop. (If my code is right, that what should happen i guess)

We need to understand what you are sending to the Arduino, and when.

It sounds like you are sending "forward" over and over as long as the forward key is pressed.

What you SHOULD be sending is one value when the forward switch becomes pressed and another value when it becomes released.

But, you've said nothing about what you are actually sending, or when.

On the android app, all the buttons have the same function. While pressed send 'F' (or 'B'/'R'/'L') and when released send 0. But I can't really see how this is related. (sorry)

I don’t see any Serial.print() statements in your code to let you know what distance has been detected.

I get the feeling that your attempted interaction between distance measured and command inputs is too simple - and maybe that is also what @PaulS is getting at.

I think you need to separate the use of the distance data from the commands so that, even if there is no command the detection of an obstacle will cause the robot to stop. Something as simple as this may work

if (distanceF <= 15) {
    forwardMovesAllowed = false;
}
else
   forwardMovesAllowed = true;
}

But now comes the interesting bit - how do you stop forward moves (including one that is already happening) while allowing a backward move.

I think you need a variable that records the direction of motion (F, R and S could mean Fwd Rev and Stopped)

And then you would have code like this

if (forwardMovesAllowed == false and robotDirection == 'F') {
   // code to stop the motor
   robotDirection = 'S';
}

and your present moveForward() function could be modified like this

void MoveForward(){
    if (forwardMovesAllowed == false) {
        return;
    }
    digitalWrite(rightMotorPin1, HIGH);
    digitalWrite(rightMotorPin2, LOW);
    digitalWrite(leftMotorPin1, HIGH);
    digitalWrite(leftMotorPin2, LOW);
    robotDirection = 'F';
}

…R

PS … in your PM to me you were critical of @Pauls’s style - and you are not the first. However if you ignore the style you will find that the advice is always very sound.

Robin2:
I don’t see any Serial.print() statements in your code to let you know what distance has been detected.

I get the feeling that your attempted interaction between distance measured and command inputs is too simple - and maybe that is also what @PaulS is getting at.

I think you need to separate the use of the distance data from the commands so that, even if there is no command the detection of an obstacle will cause the robot to stop. Something as simple as this may work

if (distanceF <= 15) {

forwardMovesAllowed = false;
}
else
  forwardMovesAllowed = true;
}



But now comes the interesting bit - how do you stop forward moves (including one that is already happening) while allowing a backward move.

I think you need a variable that records the direction of motion (F, R and S could mean Fwd Rev and Stopped)

And then you would have code like this


if (forwardMovesAllowed == false and robotDirection == ‘F’) {
  // code to stop the motor
  robotDirection = ‘S’;
}




and your present moveForward() function could be modified like this


void MoveForward(){
    if (forwardMovesAllowed == false) {
        return;
    }
    digitalWrite(rightMotorPin1, HIGH);
    digitalWrite(rightMotorPin2, LOW);
    digitalWrite(leftMotorPin1, HIGH);
    digitalWrite(leftMotorPin2, LOW);
    robotDirection = ‘F’;
}




...R

PS ... in your PM to me you were critical of @Pauls's style - and you are not the first. However if you ignore the style you will find that the advice is always very sound.

Hey there Robin, thanks for your reply. I’ll try to move along these lines and inform you about how everything goes. Once again thanks for the help.

As far as it goes for Paul, I kind of get how he replies. I guess what he wants to do is to make me think of the many variables that affect my code and/or how those variables also affect the way that my “vehicle” moves around or so… Anyhow…

@Robin, tried to follow what you proposed, but to no avail.
Just a little heads up. The only way i kind of got to work, was through this code but the problem is that the vehicle stops for every movement (and that’s totally understandable through the code). But when I try to narrow it down just to the forward movement, that’s when everything goes wrong:

void loop() {
  distanceF = sScan(sensorF);
  
  if (distanceF<= SAFE){
    stop();
  } else if (distanceF > SAFE) {   
    if (bluetooth.available()) { 
      btData = bluetooth.read();
      
      if (btData =='F') {
        MoveForward(); //Serial.println(sensor1.read());
      } else if (btData == 'B'){
          MoveBackward(); //Serial.println(sensor1.read());
      } else if (btData == 'L') {
          servoRotateLeft(); //Serial.println(sensor1.read());
      } else if (btData == 'R') {
          servoRotateRight(); //Serial.println(sensor1.read());
      } else {
        stop(); //Serial.println(sensor1.read());
      } 
    }
  }
}

the rest of the code (except for the main loop) is as posted in my initial post