using bluetooth communicated strings as commands

Hello people,

I’m new to Arduino , used to program in Pascal and assembly about 25 years ago.
I’m confused about how to use strings as command triggers.
Successfully used single digits

Intention is that when I send “on#” via bluetooth the command Bluetooth.println(“Device ON”) would execute.

Obviously I’m missing something basic here.
The little debug line “Serial.print(Data);” works just fine and sends what I expect

#include <SoftwareSerial.h>

SoftwareSerial Bluetooth(10, 9); // RX, TX

String Data = ""; //initialise a string to hold my message

void setup(){
  Serial.begin(9600);
  Bluetooth.begin(9600);
}
  
  
  void loop() {
  while(Bluetooth.available() ) {
     char character = Bluetooth.read();     // Receive a character from the software serial port
        Data.concat(character);             // Add the received character to the receive buffer
        if (character == '#')               // # received, continue to do with string Data
        {
         
       if(Data =="on#"){Bluetooth.println("Device ON"); Serial.println("Device ON"); }  // respond to bluetooth and serial
       if(Data =="off#"){Bluetooth.println("Device OFF"); }


         Serial.print(Data); //Output the received message to serial to see if it actually received
         
           Data =""; //clear the message
           Serial.println();
           delay(500);
      
  }
  
}
}

This thread on serial basics is a must read Serial Input Basics - Programming Questions - Arduino Forum

You want to avoid String and use native char arrays–String sucks the minimal RAM dry.

You also want AltSoftSerial rather than SoftwareSerial (but that probably has nothing to do with what you’re doing.

I use a btSerialScan() to get anything available from an AT-09:

void  btSerialScan() {
  //see if data is available and process
  // monSerial.println(btInBfrPtr);
  //  if (btSerial.available()) {
  //    monSerial.print("bt available: "); monSerial.print(btSerial.available()); monSerial.print("_:"); monSerial.println(btInBfrPtr);
  //  }
  //
  //  if (btInBfrPtr && (millis() - btCharTimeout > btLastCharMs)) {
  //    monSerial.print("timeout reached: "); monSerial.print(millis()); monSerial.print("_:"); monSerial.println(btInBfrPtr);Serial.flush();
  //  }



  //check for switching on
  if ( (btSerialStatus == BTAT) && (digitalRead(btSerialStatusPin) == HIGH)) {
    //it has connected
    monSerial.println("we are connected!");
    btSerialStatus = BTON;
  } else if ( (btSerialStatus == BTON) && (digitalRead(btSerialStatusPin) == LOW)) {
    //we have been disconnected!
    monSerial.println("we have been disconnected!!!");
    btSerialStatus = BTAT;
  }



  //check for timeout
  if ((btInBfrPtr > 0) && (millis() - btCharTimeout > btLastCharMs) ) {
    //then it's gone too longe since the last character.  pad the string with null
    //    monSerial.print("padding "); monSerial.print(  btInBfrPtr);
    //    monSerial.print("-"); monSerial.print(millis());
    //    monSerial.print("_"); monSerial.println(btLastCharMs, DEC);
    //    monSerial.println(btInBfr);
    //    Serial.flush();
    for (btInBfrPtr; btInBfrPtr < btInBfrSiz - 1; btInBfrPtr++) {
      btInBfr[btInBfrPtr] = '\0';
      // monSerial.println(btInBfrPtr);
    }
    //monSerial.println(btInBfrPtr);
  } else {



    while ((btSerial.available() ) &&  (btInBfrPtr < (btInBfrSiz - 1)) ) {
      //this means serial data available from bt.Serial and still space in buffer


      //monSerial.print("Data coming:"); monSerial.print( btInBfrPtr); monSerial.print("_:"); monSerial.println((char) btSerial.peek());

      // add it to the input buffer
      btInBfr[btInBfrPtr] = btSerial.read();
      btInBfrPtr++;

      //log when this happened
      btLastCharMs = millis();
    };        //end while available

  }       //end else

  //if we have reached maximum size in bt buffer, process the command

  if ( btInBfrPtr >= (btInBfrSiz - 1)  ) {

    // monSerial.print("full string!  "); monSerial.print(btInBfrPtr); monSerial.print("  :");
    //monSerial.println(btInBfr);
    doBtInBfr();

    //reset so that it can go again
    btInBfrPtr = 0;
    //we could re-zero the array, but why?


  }

  // relay the monSerial to the bluetooth
  while (monSerial.available()) {
    //this would mean that data is available from the serial monitor
    // monSerial.write("_"); monSerial.write(monSerial.peek());
    //monSerial.println("Sending: ");
    btSerial.write(Serial.read());
  }

}
[code]

note that monSerial is aliased to Serial with "HardwareSerial &monSerial = Serial;" due to my expectation that I'l switch chips and use the hardware for the bluetooth.

This code checks for whether or not there is bt data available, gets it if there is, and limits it to 16 characters.  

It also imposes a 100ms limit for more data.

At either timeout or full, doBtInBfr() is called to handle whatever command has been received.

(also, I don't think I need the array spot for the trailing nil, but it's harmless).
[code]

void   doBtInBfr() {
  //here we interpret the input string
  //monSerial.write("parsing : "); monSerial.println(btInBfr);
  //this needs to behave differently in command mode and once enabled

  switch (btSerialStatus) {
    case BTAT:
      //it's still in command mode

      monSerial.print(btInBfr);


    // break;
    case BTON:
      //so we are live and looking for commands
      switch (btInBfr[0]) {
#ifdef useLeds
        case 'y':
          //turn on yellow LED
          //monSerial.println("got a y");

          lightLed(0);
          break;
        case 'b':
          //      monSerial.println("B!");
          //turn on blue LED
          lightLed(1);
          break;
#endif

        case 's':
          //talk back
          monSerial.write("you said : ");
          monSerial.println(&btInBfr[1]);
          break;

        case 't':
          monSerial.println( "setting time");
          //set time in unix  seconds
          //there is a reserved space after the t command, then theunix time
          //memcpy(seconds, btInBfr[2], 4);
          unsigned long t;
          memcpy(seconds, btInBfr[2], 4);
        //setUnixTime(&
        case 'T':
          //report local tie back
          monSerial.println( "telling time");
          //send back the  time in unix  seconds
          //there is a reserved space ater the t command, then theunix time
          memcpy(seconds, btInBfr[2], 4);


          break;

        case 'k':
          // kill the connection
          btSerialKill();
          break;


      }               //the btInBfr[0] switch

  } // the btSerialSttus switch

  //reset the buffer
  btInBfrPtr = 0;
}

The general format once I have a buffer is to read the first char for a command, and then if it has arguments, parse them.

I found the y and b commands to turn on LEDs quite useful in debugging and seeing if its talking at all.

Building up to these, I have articles [/code]
[/code]
A Simple ATmega Circuit . . . – dochawk.org, and https://www.dochawk.org/2019/01/07/getting-a-response-back-from-the-atmega-to-the-pi/https://www.dochawk.org/2019/01/04/talking-to-the-atmega-from-the-pi-over-bluetooth-ble/ where I step through the whole sequence with code built up as I go along.

Im reading.
Not to worried about how much Ram im using, any program I write with this will be short.
Just baffled to why I could do this with single characters no problem, and cant with strings.
The string data passes on just fine.
Its the IF statement seems to not meet conditions.
Grumble!

I went back and looked at

Strings, as opposed to strings, are resource intensive, use heap and/or stack, fragment memory, and such in small memory implementations like Arduino.