Bluetooth remote control car transmits ultrasonic waves back to the APP

I am developing an app to control my Arduino car. I have successfully managed to control the motor, but I also want the app to display a message when the ultrasonic sensor on the car detects an object. However, I have been trying for a long time without success. Could you help me check what the problem is?

#include <Servo.h> // Include Servo library to control the servo motor
#include <SoftwareSerial.h> // Include SoftwareSerial library

// Ultrasonic sensor pins
int trigPin = 5;
int echoPin = 6;
long duration, dist;

Servo servo;

// L298N motor control pin definitions
const int IN1 = 7;
const int IN2 = 8;
const int IN3 = 13;
const int IN4 = 12;
const int ENA = 3; // Use a different PWM pin to control the left motor
const int ENB = 11; // Control the speed of the right motor

// Define motor speeds
int motorSpeed = 150;
int fastSpeed = 180; // Higher speed for turning
int slowSpeed = 120; // Lower speed for turning

// Define Bluetooth module RX and TX pins
const int rxPin = 2;
const int txPin = 4;
const int statePin = 1; // Bluetooth state pin

// Create a SoftwareSerial object
SoftwareSerial bluetooth(rxPin, txPin);

// Define variables to control message display intervals
unsigned long previousMillis = 0;
const long interval = 500;

// Define movement status variable
bool isMoving = false;

void setup() {
servo.attach(9); // Change servo control pin to avoid conflict with motor PWM
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
servo.write(0);
delay(100);

pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);

pinMode(ENA, OUTPUT);
pinMode(ENB, OUTPUT);

Serial.begin(9600);
bluetooth.begin(9600);
pinMode(statePin, INPUT);

Serial.println("Bluetooth module ready, waiting for messages...");
}

void loop() {
unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;

if (digitalRead(statePin) == HIGH) {
  Serial.println("Connected, waiting for data");

  if (bluetooth.available()) {
    Serial.println("Message received:");

    while (bluetooth.available()) {
      char receivedChar = bluetooth.read();  

      Serial.print("Character (Hex representation): ");
      Serial.print(receivedChar, HEX);  
      Serial.print(" (ASCII: ");
      Serial.print(receivedChar);  
      Serial.println(")");

      switch (receivedChar) {
        case 1: 
          moveBackward();
          break;
        case 2: 
          moveForward();
          break;
        case 4: 
          turnLeft();
          break;
        case 8: 
          turnRight();
          break;
        default:
          stopMovement();
          break;
      }
    }
  }
} else {
  Serial.println("Bluetooth not connected");
}

detectObstacle();

}
}

// Detect ultrasonic distance
void detectObstacle() {
if (!isMoving) { // Only detect and open the trash can lid when the car is stopped
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);
dist = (duration / 2) / 29.1;

if (dist < 8) {
  bluetooth.println("DETECTED");
  servo.write(90);   
  delay(3000);       
  servo.write(0);    
  delay(300);
}

}
}

// Move forward with both wheels
void moveForward() {
analogWrite(ENA, motorSpeed);
analogWrite(ENB, motorSpeed);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
isMoving = true; // Set car to moving state
Serial.println("Moving forward: motorSpeed = " + String(motorSpeed));
}

// Move backward with both wheels
void moveBackward() {
analogWrite(ENA, motorSpeed);
analogWrite(ENB, motorSpeed);
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
isMoving = true; // Set car to moving state
Serial.println("Moving backward: motorSpeed = " + String(motorSpeed));
}

// Turn left (right side moves forward faster, left side moves backward slower)
void turnLeft() {
analogWrite(ENA, slowSpeed); // Left side moves backward
analogWrite(ENB, fastSpeed); // Right side moves forward
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
isMoving = true; // Set car to moving state
Serial.println("Turning left: Right side moves forward (fast), left side moves backward (slow)");
}

// Turn right (left side moves forward faster, right side moves backward slower)
void turnRight() {
analogWrite(ENA, fastSpeed); // Left side moves forward
analogWrite(ENB, slowSpeed); // Right side moves backward
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
isMoving = true; // Set car to moving state
Serial.println("Turning right: Left side moves forward (fast), right side moves backward (slow)");
}

// Stop all movement
void stopMovement() {
analogWrite(ENA, 0);
analogWrite(ENB, 0);
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
isMoving = false; // Set car to stopped state
Serial.println("Stopping all movement");
}

You made 3 errors

  • You captured the length of the incoming text instead of the text
  • You put it in a local variable then closed the scope of the variable before using the variable for testing
  • You compared two constant different pieces of text, ignoring the variable.

Here is a simple BlueTooth text receiver sample, for single value per line:
blocks
initialize global message to


1 Like

Be sure to use println() at the end of each message to send from the sending device, to signal end of message.

Only use print() in the middle of a message.

Be sure not to println() in the middle of a message, or you will break it into two short messages and mess up the item count after you split the message in AI2.

Do not rely on timing for this, which is unreliable.

In the AI2 Designer, set the Delimiter attribute of the BlueTooth Client component to 10 to recognize the End of Line character.
BlueToothClient1_Properties
Also, return data is not immediately available after sending a request,
you have to start a Clock Timer repeating and watch for its arrival in the Clock Timer event. The repeat rate of the Clock Timer should be faster than the transmission rate in the sending device, to not flood the AI2 buffers.

In your Clock Timer, you should check

  Is the BlueTooth Client still Connected?
  Is Bytes Available > 0?
     IF Bytes Available > 0 THEN
       set message var  to BT.ReceiveText(-1) 

This takes advantage of a special case in the ReceiveText block:

ReceiveText(numberOfBytes)
Receive text from the connected Bluetooth device. If numberOfBytes is less than 0, read until a delimiter byte value is received.

If you are sending multiple data values per message separated by | or comma, have your message split into a local or global variable for inspection before trying to select list items from it. Test if (length of list(split list result) >= expected list length) before doing any select list item operations, to avoid taking a long walk on a short pier. This bulletproofing is necessary in case your sending device sneaks in some commentary messages with the data values.

Some people send temperature and humidity in separate messages with distinctive prefixes like "t:" (for temperature) and "h:" (for humidity).
(That's YAML format.)

The AI2 Charts component can recognize these and graph them. See Bluetooth Client Polling Rate - #12 by ABG

To receive YAML format messages, test if the incoming message contains ':' . If true, split it at ':' into a list variable, and find the prefix in item 1 and the value in item 2.

1 Like

Dear @_018,
the simple block that you have posted is far from being enough to help you.
In other words : the clock block you posted seems not in degree to receive nothing from Arduino. (i.e. what code is filling the variable "data" ?)
You'd better do a search on the forum tagging Arduino or Bluetooth. There are so many topics related to the same matter. Or you can have a look to the FAQ managed by @ABG. (pay particular attention to the "message delimiter" detail).
Other sources of information are the web sites (for example) of @ChrisWard (professorcad.co.uk) or @Juan_Antonio (kio4.com). But also @Taifun (puravidapps.com) and many others.
In any case, to have more possibilities to get a help, post also your .aia.

In the meanwhile, if your clock1 is the one dedicated to the BT receiving, you shall modify it in a way similar to the following:
image
Where L_BT_TOUT is your
image

1 Like

A1 (1).aia (242.7 KB)
Thank you for your reply. I followed your picture and still can't run it. Here is my AIA file

Dear @_018, just at a first sight I see that I've been not clear:
when I've said to modify your clock1, I intended:

Then, once the connection is fine, you have to configure and start the clock1 (otherwise it will never work)


The variable "Comment" is just to let me explain you the meaning of any single instruction (this approach can be useful also for you: you might embed those "comments" within your code, for future reference . The same as when you write a comment in Arduino, introduced by a //.

Also, take care of the following:
image

As @ABG has said in his posts: be aware to set the delimiter byte to 10 (LINEFEED character in the ASCII coding). This means that your last message to the APP via BT shall be made by means of a bluetooth.println();
In your Arduino code it seems that this requirement is already accomplished since I see that you transmit to the APP by using this line of code:
bluetooth.println("DETECTED");
But pay attention not to transmit elsewhere in your code without using such method.
And do not force the secure comm's: this requires to exchange a PIN between the car and the APP to establish the connection. Make your life simpler avoiding this.

Some other weird things :

Why "sendbyte" and "sendtext" ?
You'd better use always the same type of data. Probably text is less prone to misinterpretation

If you use text, you shall change your switch case in Arduino to take care of the character instead of a number (number if you send bytes) like:
switch (receivedChar) {
case '1':
moveBackward();
break;
case '2':
moveForward();
break;
case '4':
turnLeft();
break;
case '8':
turnRight();
break;
default: // receiving 88 ?
stopMovement();
break;
}

In any case, please remember that the touchdown event is raised only once, it is not raised many times until you keep pressed the button, so if you want to have a continuos movement, you shall verify periodically (with a clock) the button status. Or in the Arduino code the movement shall be maintained autonomuosly until an "88" is received.

Last hint is: before trying to put together the Arduino HW and SW plus an APP whose behaviour is still unknown, to verify if your Arduino BT Tx and Rx work fine, you can use a general purpose and ready made app that allows you to check the BT comm's like SerialBluetoothTerminal (SBT). This app (free on Google Playstore) runs on the Android device and allows you to debug easily the Arduino side. When you are done with SBT, and you are sure that Arduino is receiving and sending correctly the data on the BT line, you can try to connect your app.
I reckon that it seems a long way wasting time approach, but by doing short, but secure steps, you can arrive vary far....

EDIT: by crawling my folders, I've found a working code. You can find here below a super-simple example that, on APP side, sends some characters (A,B,C), and on Arduino side, when it receives A, it lights up the internal LED (AKA pin 13), when it receives B, it switches it off. When it receives C, it does nothing, but in all cases it sends back to the app an R+the character received.. My HW is Arduino UNO + HC06.

CREDITS: Please note that inside my app I use the @Taifun extension ( :+1:) TaifunTools to keep the screen awake.

Hoping it helps.
BT_to_Arduino.aia (26.2 KB)
BT_Send_Monitor.ino (2.0 KB)

3 Likes

-1, not 1

2 Likes

:fearful: :fearful: :fearful:
Terrible fault...
Dear @_018 please take care of the following correction.
image

Thanks @ABG .

1 Like

Also receive text, not receive signed bytes.

Did you know that you can buy a car now on Amazon?

That doesn't mean it has to arrive in a thousand boxes, though.

3 Likes

I am trying your suggestion. Fortunately, I have successfully made the APP display feedback, but the remaining problem is that the APP will not jump back to the default text after displaying it, and can only display it all the time. This may also be because English is not My native language leads to errors in understanding your suggestions, but I will continue to try.

I'm not a native English speaker either (I'm Italian). :grinning: so most probably it's difficult also for me to explain myself. Anyway, I hope that my aia and my ino could help you (they are written in AI2 and in "C" , so they are internatiomal" :rofl:).
Now, if I have correctly understood what you mean, the following if-then-else should solve:
image

In other words: when the BT transmits "Detected" the label 6 shows the positive message, if nothing arrives from the BT the label6 shows "No objects...."..
I see anyway a possible problem: since the clock1 has a period of 10 milliseconds (if you have set it as I told to that short time) possibly the positive message "There is an object" will last only 10 milliseconds.. If so, you can raise the clock1 period to (for example) 500 milliseconds. This will allow the positive message to be seen (500 ms) but on the opposite side, the reaction time will have a delay of 500 ms.
Another solution could be to have the Arduino sending two messages: "DETECTED" and, after a sufficent delay (and only if the ultrasonic sensor is not detecting any longer an obstacle) to send a new message, something like "PATH FREE". in this case your app will have no doubts:
image

Please also note that there is a third "else": if the received message isn't recognized, the label6 issues a warning.
Play with the if-then-else according to what you want to obtain, and choose which is most suitable to your needs.
Best wishes.

2 Likes

Thank you Yonglie for your various suggestions. After all my attempts, I finally realized the function I mentioned. :laughing: My 12 credits will not be taken away :sob: :sob: :sob:!!!!!!!!!!!! The following are the modified parts. :
The ARDUINO side adds the newline symbol "\n" after the text sent, and the APP is as follows:
image

1 Like

Nice to read that it works !
Best wishes for your "credits" :rofl: :rofl: :rofl:

1 Like