Send special data via app to arduino

Hi.
I built an app that is able to send the number 1 or 2 by means of the push of 2 buttons. When Arduino reads 1 then the servo attached did something. When the Arduino reads 2 then the servo will be turned off and doesn't move more.
My servo is a dynamixel. This means that it has a pid behaviour inside itself. What I want is, at this point, to add to the app the possibility to change the parameters of PID before the move of dynamixel. This means that I have to send 3 parameters(P,I,D) in the same time. I did it! But I am not able to add it in the same code where I switch the on/off of the servo with the reading of "1" OR "2".
I hope that I explained myself quite good.
What I can say more is that when the number 1 is sent, then the imu starts to read accelerations and basing on them, the dynamixel did some moves.

#include <SoftwareSerial.h>
SoftwareSerial BTSerial(7,8);
#include <Arduino_LSM6DS3.h>
#include <DynamixelShield.h>

const uint8_t DXL_ID = 1;
const float DXL_PROTOCOL_VERSION = 2.0;

DynamixelShield dxl;
//This namespace is required to use Control table item names
using namespace ControlTableItem;
#define DEBUG_SERIAL Serial


int walk_state=0;
int read_acc=0;

float Object_position_X = 170; 
float Object_position_Y = 60;  

float Athr =  0.22;
float Bthr =  -0.1; 

void setup(){
  DEBUG_SERIAL.begin(57600);
   delay(2000);
  BTSerial.begin(57600);
  delay(2000);
    IMU.begin();
    delay(2000);
  

  
  dxl.begin(57600);
  // Set Port Protocol Version. This has to match with DYNAMIXEL protocol version.
  dxl.setPortProtocolVersion(DXL_PROTOCOL_VERSION);

  // Turn off torque when configuring items in EEPROM area
  dxl.torqueOff(DXL_ID);
  dxl.setOperatingMode(DXL_ID, OP_POSITION);
  dxl.torqueOn(DXL_ID);
  DEBUG_SERIAL.print("Connect the device via bluetooth") ; 
}


String Data;


void loop(){
  if (BTSerial.available()>0){
    Data=BTSerial.readString();
   }



   ///WALK///
      
if(walk_state==0 && Data == "1"){
           DEBUG_SERIAL.println("FUNZIONE WALKING ABILITATA");
           walk_state=1;
           read_acc=1;
      
              }
                    if(read_acc==1){
                         float x,y,z;
                
                    IMU.readAcceleration(x, y, z);
                    DEBUG_SERIAL.print(y);
                    DEBUG_SERIAL.print("\t");
                              if (y>Athr){
                              dxl.setGoalPosition(DXL_ID, 170,UNIT_DEGREE);
                                DEBUG_SERIAL.println("stance");
                              }
                              else if(y<Bthr){
                                dxl.setGoalPosition(DXL_ID, 60,UNIT_DEGREE);
                                DEBUG_SERIAL.println("swing");
                              }
                              else {
                              DEBUG_SERIAL.println();
                              }
                              }
if(walk_state==1 && Data == "2"){

DEBUG_SERIAL.println("FUNZIONE WALKING DISABILITATA");
walk_state=0;
read_acc=0;

Data = "nothing";
    delay(1000);
    dxl.setGoalPosition(DXL_ID, 90,UNIT_DEGREE);
    
            
   
}

////HOW TO ENTER IN THE MODALITY TO SEND PID VALUES//// 
///In the app I putted a textbox where I write 3 numbers divided ////
///each one by a comma and that have at the end an asterisk. //////

if(Data == "3"){
    
    char caracter="";
String palabra="";
int ind1="";
int ind2="";
int ind3=""; 
String  P="";
String  I="";
String  D="";

   DEBUG_SERIAL.println("Define PID");
   delay(1000);
            DEBUG_SERIAL.print(Data);
           caracter = BTSerial.read();
          palabra = palabra + caracter;
          DEBUG_SERIAL.print(palabra);
           DEBUG_SERIAL.print(caracter);
                      if(caracter == '*') {    
                        palabra = palabra.substring(0, palabra.length() - 1); // Delete last char *
                            
                                ind1 = palabra.indexOf(',');
                                P = palabra.substring(0, ind1);
                               DEBUG_SERIAL.print("P = ");
                               DEBUG_SERIAL.println(P.toInt());
                               
                                ind2 = palabra.indexOf(',', ind1+1 );
                                I = palabra.substring(ind1+1, ind2);
                                DEBUG_SERIAL.print("I = ");
                               DEBUG_SERIAL.println(I.toInt());
                               
                                ind3 = palabra.indexOf(',', ind2+1 );
                                D = palabra.substring(ind2+1);
                                DEBUG_SERIAL.print("D = ");
                               DEBUG_SERIAL.println(D.toInt());
                                    
                           
                      dxl.writeControlTableItem(POSITION_P_GAIN, DXL_ID, P.toInt());
                      dxl.writeControlTableItem(POSITION_I_GAIN, DXL_ID, I.toInt());
                      dxl.writeControlTableItem(POSITION_D_GAIN, DXL_ID, D.toInt());
                       }
           caracter="";
           palabra="";
         
           
           }

}
   
  

   

I would suggest to study Serial Input Basics to handle this

What Arduino board are you using?

I would be surprised if you can get reliable communication with software serial at 57600 baud. The fastest that I have had software serial work reliably is 38400 baud.

+1 for the serial input basics tutorial.

What is the sender? What, exactly, is it sending?

Hi I am using an Arduino uno WiFi Rev 2. In the same time I am using a Bluetooth communication with an HC06 module. What I want to send is only numbers to differentiate the way on, the way off and the way of sending pid values.

you need to craft a small protocol for sending your command may be something like "<P, I, D, val>" where P, I and D are the PID values and val is 0 or 1.

then use the technique described in Serial Input Basics to parse this

Thank you for the tip about serial input basics. I ll try to built another structure...the fact is that I can receive and distinguish the tree pid values with the final asterisk, but I can't put it with the other 2 cases ther I turn on and off the servo. Indeed it's like there is a double read of data and this will work badly.

what's the format of what you are sending? "P,I,D,Val*" ➜ that could work too and the tutorial can help you write a proper way to receive a command and deal with it

arduino reads in serial monitor a string. If this is equal to 1 than the servo is turned on, otherwise if it reads 2 then the servo is turned off. If it reads 3 then it has to read again and stop at the asterisk. What is before the asterisk are the three values of pid, that were sent after the sending od 3 and with the format #,#,#*

what happens if the Arduino starts in the middle of a data transmission "312,3,10*" and has missed the 3 ➜ you'll see the 1 of 12 that was supposed to be P, then the 2 so you'll complete two orders that are unintended, then you'll have to ignore the comma and then you have a 3 but no data afterwards, just a comma...

➜ having a start marker helps with synchronisation ( you could have a consistent end marker like sending "1*" "2*" or "312,3,10*" that could help get in sync by ignoring the first command)

mmm Nice tip. I did't think completely about it because it's for my use. Then I know that I have to send the right numbers

OK if you make the assumption that the data is always coming when the arduino is ready to receive then you can simplify. I would still use Serial Input Basics to handle receiving "P,I,D*"

that's an example how to do this:

const byte numChars = 64;
char receivedChars[numChars];
boolean newData = false;

void setup() {
  Serial.begin(115200);
  Serial.println("\n<Arduino is ready>");
}

void loop() {
  recvWithEndMarker();
  showNewData();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  static bool waitingForPID = false;
  const char endMarker = '*';
  char rc;

  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();
    if (waitingForPID) {
      if (rc != endMarker) {
        if (!isspace(rc)) {
          receivedChars[ndx++] = rc;
          if (ndx >= numChars) ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        ndx = 0;
        waitingForPID = false;
        newData = true;
      }
    } else {
      switch (rc) {
        case '1':
        case '2':
          receivedChars[0] = rc;
          receivedChars[1] = '\0';
          ndx = 0;
          newData = true;
          break;
        case '3':
          waitingForPID = true;
          break;
      }
    }
  }
}

void showNewData() {
  if (newData == true) {
    Serial.print("This just in ... ");
    Serial.println(receivedChars);
    newData = false;
  }
}

send through the Serial Monitor (at 115200 bauds)
12345,67,89*12345,67,89*12345,67,89*12345,67,89*12345,67,89*

and you'll see the commands being handled ➜ Serial Monitor (@ 115200 bauds) will show

This just in ... 1
This just in ... 2
This just in ... 45,67,89
This just in ... 1
This just in ... 2
This just in ... 45,67,89
This just in ... 1
This just in ... 2
This just in ... 45,67,89
This just in ... 1
This just in ... 2
This just in ... 45,67,89
This just in ... 1
This just in ... 2
This just in ... 45,67,89