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);
}
}
}
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.
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!