Problem sending text from Bluetooth mobile device to Arduino (App inventory)

Hello, you can enter 3 different variables from Arduino with "|" between them. I put the sign as a separator and send it via Bluetooth. I separated them with the code prepared with App Inventory and used them without any problems. Likewise, when I send three different information from the phone to Arduino, it does not work. For example. I send the text "10|2|3" to Arduino, the code does not work. It works when you type the same text manually from the serial monitor. I couldn't find out whether there is a problem with the software I created in the App inventory or the Arduino software. I set DelimiterByte to 10, set a delay time, etc. It didn't happen. Can you help me?

if (Serial.available() > 0) 
   {
  String receivedData = Serial.readStringUntil('\n'); // Satır sonuna kadar veriyi oku
  int data1 = receivedData.substring(0, receivedData.indexOf('|')).toInt();
  receivedData = receivedData.substring(receivedData.indexOf('|') + 1);
  int data2 = receivedData.substring(0, receivedData.indexOf('|')).toInt();
  receivedData = receivedData.substring(receivedData.indexOf('|') + 1);
  int data3 = receivedData.toInt();
  delay (30);
  if (data1 >0)
  {
  set=data1;
  hys=data2;
  }
     if (data3==1)
     {
       mode="RUN";
       valve= 0;
     }
     if (data3==2)
     {
       mode="STP";
     }
     if (data3==3)
     {
       valve = 1;
     }
     
   }

`

One should post in English in the English language section. Use Translate.

I translated it to English.

As a first step you should print the characters that were received by the arduino.

if (Serial.available() > 0)  {
  String receivedData = Serial.readStringUntil('\n'); // Satır sonuna kadar veriyi oku
  Serial.print("receivedData #");
  Serial.print(receivedData);
  Serial.println("#");

to make visible what you really received

You are using

String receivedData = Serial.readStringUntil('\n');

There are multiple problems in this code

You should not use variabletype String for anything
on small microcontrollers. Sooner or later these Strings eat up all memory and then your microcontroller crashes.

There is an easy to use alternative called SafeString and SafeStringReader
The name is program. SafeStrings are safe to use.

The second thing is:
depending on to what line-ending you have adjusted the serial monitor this line-ending is
carriage return
or
carriage return and linefeed
or
linefeed

Your code

Serial.readStringUntil('\n');

does what its name says:

wait until a newline-character is received
This means you must send a newline-character from your inventor-app

Additionally if I look at your code

     if (data3==1)
     {
       mode="RUN";
       valve= 0;
     }
     if (data3==2)
     {
       mode="STP";
     }
     if (data3==3)
     {
       valve = 1;
     }

You are again using Strings
thow I am not sure because you did not post your complete sketch

The code-snippet leaves out the important information what variable-type your variable
"mode" is

It is not nescsessary to use a character-sequence like "RUN" or "STP"
You can use integerconstants for everything. And these constants shall have names that explain themselves

"data3" says only third data. But this name data3 says nothing about the purpose of this number

You are going on in your code with

     if (data3==1)
     {
       mode="RUN";
       valve= 0;
     }
     if (data3==2)
     {
       mode="STP";
     }

data3 seems to be some kind of "run" or "stop" mode.

run / stopmode of what?

The name should explain exactly this purpose. If you use self-explaining names for everything your code becomes much easier to understand and to maintain.

Same thing with

valve = 0;
valve = 1;

which number has the meaning "valve opened" ?
which number has the meaning "valvle closed"?

let's assume inverted logic

const byte opened = 0;
const byte closed = 1;

writing code like

valve = opened;
valve = closed;

makes everything clear without any comments because the code is SELF-explaining

Here is a demo-code which uses SafeString and SafeStringReader.

The advantage of SafeStringReader is its non-blocking nature.
You could send "10|2"
and then 10 minutes later send "|3" plus a newline
and then the received data will be processed.

But as the character of SafeStringReader is non-blocking
all other code will be processed continously until the delimiter (the newline) will be received

You can see this by the blinking of the onboard-LED which again works non-blocking with non-blocking timing


unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
const byte    OnBoard_LED = 13;     //  2 onboard-LEDESP32 / ESP8266
//const byte    OnBoard_LED = 25;   // 25 onboard-LED Raspberry Pi pico
//const byte    OnBoard_LED = 13;   // 13 onboard-LED uno, mega


// Example of NON-Blocking read commmands from the Arduino Monitor input and acts on them
// the available commands are start stop
// See the SafeStringReader_CmdsTimed.ino for an example using a struct to hold the commands and their functions
//
// Commands are delimited by space dot comma NL or CR
// If you set the Arduino Monitor to No line ending then the last command will be ignored until it is terminated by a space or ,
//  Use the settings Newline or Carrage Return or Both NL & CR
//
// These commands can be picked out of a line of user input
// start  stop
// The input line can be as long as you like 100's of Kb long, but only two small buffers need to parse the commands
//
// download and install the SafeString library
// with the arduino-IDE
// or from www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html


#include <SafeStringReader.h>
#include <SafeString.h>

// create an sfReader instance of SafeStringReader class
// that will handle commands upto 32 chars long
// delimited by space, comma or CarrageReturn or NewLine
// the createSafeStringReader( ) macro creates both the SafeStringReader (sfReader) and the necessary SafeString that holds input chars until a delimiter is found
// args are (ReaderInstanceName, expectedMaxCmdLength, delimiters)
createSafeStringReader(sfReader, 32, " ,\r\n");

cSF(receivedData_SS, 32); // SafeString can hold up to 32 characters
cSF(data1_SS, 8);         // SafeString can hold up to  8 characters
cSF(data2_SS, 8);         // SafeString can hold up to  8 characters
cSF(data3_SS, 8);         // SafeString can hold up to  8 characters

int data1;
int data2;
int data3;

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  PrintFileNameDateTime();

  Serial.println();
  Serial.println( F(" Set the Arduino IDE monitor to Newline, or Carriage return or Both NL & CR") );
  Serial.println("waiting to receive 3 numbers with delimiter |");

  SafeString::setOutput(Serial); // enable error messages and SafeString.debug() output to be sent to Serial
  sfReader.connect(Serial); // where SafeStringReader will read from
  //sfReader.echoOn(); // echo back all input, by default echo is off
}



void loop() {
  BlinkHeartBeatLED(OnBoard_LED, 250);

  // becomes true if a delimiter is received
  // see createSafeStringReader(sfReader, 32, " ,\r\n");
  if (sfReader.read()) {
    receivedData_SS = sfReader;

    // print received characters for analysing purposes
    Serial.print("received #");
    Serial.print(receivedData_SS);
    Serial.println("#");
    Serial.println();


    // function substring stores characters in variable named "data1_SS"
    receivedData_SS.substring(data1_SS, 0, receivedData_SS.indexOf('|'));
    Serial.print("data1_SS #");
    Serial.print(data1_SS);
    Serial.println("#");


    data1_SS.toInt(data1);
    Serial.print("INTEGER-Number: data1:");
    Serial.println(data1);
    // function substring stores characters in variable named "receivedData_SS"
    receivedData_SS.substring(receivedData_SS, receivedData_SS.indexOf('|') + 1);
    Serial.println();


    // function substring stores characters in variable named "data2_SS"
    receivedData_SS.substring(data2_SS, 0, receivedData_SS.indexOf('|'));
    Serial.print("data2_SS #");
    Serial.print(data2_SS);
    Serial.println("#");

    data2_SS.toInt(data2);
    Serial.print("INTEGER-Number data2:");
    Serial.println(data2);
    Serial.println();


    // function substring stores characters in variable named "receivedData_SS"
    receivedData_SS.substring(receivedData_SS, receivedData_SS.indexOf('|') + 1);
    Serial.print("receivedData_SS #");
    Serial.print(receivedData_SS);
    Serial.println("#");

    receivedData_SS.toInt(data3);
    Serial.print("INTEGER-Number data3:");
    Serial.println(data3);
    Serial.println();

    Serial.println();
    Serial.println();
    Serial.println("waiting to receive 3 numbers with delimiter |");
  }
}


// helper-functions
void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );
}


// easy to use helper-function for non-blocking timing
// explanation see here
// https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}



void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);

  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}

If you run the code and enter "10|2|3"

followed by a newline, or a carriage-return or a comma

this gets printed to the serial monitor

18:19:07.187 -> Setup-Start
18:19:07.187 -> Code running comes from file 
18:19:07.187 -> C:\Arduino-Pure-Portable\arduino-1.8.19\portable\sketchbook\SafeStringReader-delimiter-to-Int-002\SafeStringReader-delimiter-to-Int-002.ino
18:19:07.187 ->   compiled Mar 31 2024 18:17:19
18:19:07.187 -> 
18:19:07.187 ->  Set the Arduino IDE monitor to Newline, or Carriage return or Both NL & CR
18:19:07.187 -> waiting to receive 3 numbers with delimiter |
18:19:18.869 -> received #10|2|3#
18:19:18.869 -> 
18:19:18.869 -> data1_SS #10#
18:19:18.869 -> INTEGER-Number: data1:10
18:19:18.869 -> 
18:19:18.869 -> data2_SS #2#
18:19:18.869 -> INTEGER-Number data2:2
18:19:18.869 -> 
18:19:18.869 -> receivedData_SS #3#
18:19:18.869 -> INTEGER-Number data3:3
18:19:18.869 -> 
18:19:18.869 -> 
18:19:18.869 -> 
18:19:18.869 -> waiting to receive 3 numbers with delimiter |

best regards Stefan

Did you checked to use a common baudrate?