In this sketch I'm receiving data from an Android, and I get stuck in the while loop. Once the sketch gets into the while loop, it never reads the button to see if the state has changed. I tested it by changing the "while" to "if" and that allows the state to change. But then the sketch doesn't read the incoming data. Any ideas how I can fix this? thanks in advance.
char myChar = 'a';
String string;
char LorR;
int M2INA = 8; //left
int M2INB = 7;
int M2PWM = 9;
int M1INA = 11; //right
int M1INB = 12;
int M1PWM = 10;
int ledB = A2;
int ledR = A3;
int button = 2;
int buttonState;
int val;
int mode = 0;
void setup() {
pinMode(M1INA, OUTPUT);
pinMode(M1INB, OUTPUT);
pinMode(M2INA, OUTPUT);
pinMode(M2INB, OUTPUT);
pinMode(M1PWM, OUTPUT);
pinMode(M2PWM, OUTPUT);
pinMode(ledB, OUTPUT);
pinMode(ledR, OUTPUT);
Serial.begin(57600); //230400 460800 921600
buttonState = digitalRead(button); // read the initial state
}
void loop() {
val = digitalRead(button); // read input value and store it in val
if (val != buttonState) { // the button state has changed!
if (val == LOW) { // check if the button is pressed
if (mode == 0) { // light is off
mode = 1; // light is on!
} else {
mode = 0; // light is on!
}
}
}
buttonState = val; // save the new state in our variable
if (mode == 0) {
btMode();
}
if (mode == 1) {
followMode();
}
}
void followMode() {
digitalWrite (ledR, HIGH);
digitalWrite (ledB, LOW);
}
void btMode() {
digitalWrite (ledR, LOW);
digitalWrite (ledB, HIGH);
string = "";
//Add to string
while (true) {
myChar = Serial.read();
if (32 <= myChar && myChar <= 127) {
string += myChar;
}
if (myChar == ':'){
break;
}// While End
}
//Analyse string
if (string != "off:" && string != "on:") {
if (string != "L0:" && string != "R0:") {
//code for setting motor left or right
if (string[0] == 'L') {
LorR = 'L';
} else {
LorR = 'R';
}
string.remove(0, 1);
//code for putting it in reverse
if (string[0] == '-') {
string.remove(0, 1);
string.remove((string.length() - 1), 1);
//Serial.println(string);
if (LorR == 'L') {
//digitalWrite(M2EN, HIGH);
digitalWrite (M2INA, LOW);
digitalWrite (M2INB, HIGH);
analogWrite(M2PWM, string.toInt());
} else { //Reverse left
//digitalWrite(M1EN, HIGH);
digitalWrite (M1INA, LOW);
digitalWrite (M1INB, HIGH);
analogWrite(M1PWM, string.toInt());
}
} else {
string.remove((string.length() - 1), 1);
if (LorR == 'L') {
//digitalWrite(M2EN, HIGH);
digitalWrite (M2INA, HIGH);
digitalWrite (M2INB, LOW);
analogWrite(M2PWM, string.toInt());
} else {
digitalWrite (M1INA, HIGH);
digitalWrite (M1INB, LOW);
analogWrite(M1PWM, string.toInt());
}
}
} else {
allStop();
}
}//End of long if statment
if (string == "on:") {
}
if (string == "off:") {
}
}
void allStop () { //coast
analogWrite(M1PWM, 0);
analogWrite(M2PWM, 0);
digitalWrite(M1INA, HIGH);
digitalWrite(M2INA, HIGH);
digitalWrite(M1INB, HIGH);
digitalWrite(M2INB, HIGH);
}
yes, a colon is received. The data from the android looks like this:
L178:
R215:
L-125:
R-115:
The android app computes the PWM positive or negative
PWM data is sent for both the L and R motors
While the Android app is running, I can see on the phone screen the same data that is sent to the Arduino.
With respect, seeing the data on the 'phone is not the same as seeing what is received.
You're right. In earlier versions of the code, I used SoftwareSerial to read the incoming data to the
Monitor. So I assumed the sketch is still reading the ":"
Does the break; end the code block for the if test or for the while ?
ends the while loop (or it's intended to)
I don't even know what that while(true) meant in the sketch as I first posted it. while what was true? (This sketch was found on a tutorial)
Anyway, It works fine exactly how you suggested. Thanks!!!
I spoke too soon when I said that this sketch works. Unfortunately the button only switches modes when bluetooth is connected. I would like the button mode to be able to switch when the bluetooth is not connected. Any ideas where this is getting stuck?
Yes, I have tried Robin's method. You even helped me with it here. The incoming data still freezes using that method. This method does not. This method works other than if the bluetooth is not connected, then the button never gets read to check the state.
Maybe if I add this: if (Serial.available() > 0) to the while loop, it will never get into the while loop when the bluetooth is not connected; therefore the button will be read. I will have to try it when I get home.
void btMode() {
digitalWrite (ledR, LOW);
digitalWrite (ledB, HIGH);
string = "";
if (Serial.available() > 0){
while (true) {
myChar = Serial.read();
if (32 <= myChar && myChar <= 127) {
string += myChar;
}
if (myChar == ':') {
break;
}
} // While End
}
//analyse string
}
Your code is wrong. You must never call Serial.read() without first checking that there is at least one
character available using Serial.available(). Otherwise read() will return nonsense to you.
In general if you use a while loop, nothing else can progress, you have blocked stuff.
If you use just an if within the loop function for each aspect of your project, they can all progress
as fast as they individually need, but you need to manage state explicitly - google "state-machine"
Its more compicated to code, but it then makes combining parts of a sketch really easy.
Your code is wrong. You must never call Serial.read() without first checking that there is at least one
character available using Serial.available(). Otherwise read() will return nonsense to you.
Isn't that what I have in reply #10? I may have snuck that post in before you posted your reply.
if (Serial.available() > 0){ // check once for incoming data
while (true) {
myChar = Serial.read(); // read over and over and over and over
if (32 <= myChar && myChar <= 127) {
string += myChar;
}
if (myChar == ':') {
break;
}
} // While End
}
//analyse string
}
while (Serial.available() > 0){
myChar = Serial.read(); // read over and over and over and over
if (32 <= myChar && myChar <= 127) {
string += myChar;
}
if (myChar == ':') {
break;
}
}
//analyse string
}