I have written a piece of code for arduino. I am giving command on serial port for LED at pin 13 to toggle. I need two type of swtching, one is continuous and other is once for each time command is sent. The code is attached below:
arihant122:
It means I have to clear the serial buffer everytime before sending next command. Am I getting it right?
No, because when there is something in the serail buffer you read it (thus clearing it). It's string that's not empty And you don't clear that... So still the same problem.
arihant122:
I have implemented changes as per your suggestions. I think they are fine now.
You didn't fix the problem... You only gave it another name. But let me see:
You indeed gave it a better name, made it a const byte, removed command from global and removed the delay() from the Serial.read(). But that still leaves 4 other points And of course the real problem
The answer is, clear the String/string. But when you want to clear it is up to you.... Because that can make all the difference
For string/String, search for "arduino string vs String". String is an object which has some problems... A real C/C++ style string is a NULL terminated char array
And for the indentation, just press Ctrl+T and see how that looks.
I could reach upto this much only. When I send the "JOG" command, LED blinks once (as required) and blink continuously on sending "CONT" command.
But I have to send "JOG" first as you mentioned in your first reply. I am not able to figure a way out.
Here is the sketch:
BUTTTTT, this has a lot of disadvantages... First, you use the wasteful String. Second, if you send anything other then "JOG" or "CONT" it stuck. And you use delay()s. In the second a blink takes new actions are ignored. That might not be very bad but it means you can't expand the program very easy. If you want to blink, you can only blink. Do nothing else. Which is a shame...
Sorry I was away so could not reply. I will implement your suggestions and post it here for your suggestions.
Thanks for your continuous guidance.
Now I understood after looking at your program what you meant when you said
"don't rely on the string containing "CONT" if you want to blink continues. Just know (aka save in a variable) you want to do that".
I feel stupid now.
I am using string because I want to control the LED from LabVIEW based program. Writing that String makes it easier for user to understand. I will post that also after completion.
When labView sends a string lets say its "JOG". Does it send anything after the G? Typically it will. A EOL char or a newline char, return or something. Find out what that is. Then, don't just blindly read everything. Read each character one by one into a string until you see the end character. Lastly, add a '\0' to terminate the command you got. Now you know you have a complete command in your command buffer(string). Go look to see what it is.
arihant122:
Now I understood after looking at your program what you meant when you said
"don't rely on the string containing "CONT" if you want to blink continues. Just know (aka save in a variable) you want to do that".
I feel stupid now.
Wise lesson learned
arihant122:
I am using string because I want to control the LED from LabVIEW based program. Writing that String makes it easier for user to understand. I will post that also after completion.
I don't say you can't send strings to the Arduino. But that's something different then using Strings (with a capital) on the Arduino. A normal C/C++ style string is a NULL-character terminated char array
char myString[14] = "A string in C"
And did you already think about what should happen if you would send "Hello" and then "JOG"? Or "JO" followed by "CONT"? Or "Jog"? Aka anything else then exactly "CONT" or "JOG"?
I have made some changes in the program as below. The blinking interval is set as a variable.
Sorry for using too many "delay()" as I am yet to get used to "millis()" . I will change that afterwards.
I will display a message about wrong command input when anything other than required string is entered.
String mode;
const byte ledPin = 13;
bool blinkContinues = false;
unsigned long interval = 500; //default interval is 500 milliseconds
void setup()
{
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.println("Enter C for continuous blink");
Serial.println("Enter J for single blink");
}
void loop()
{
while (Serial.available() > 0)
{
char command = (Serial.read());
mode += command;
command = 0;
}
if (mode == "C") // COMMAND FOR CONTINUOUS PULSE
{
delay(2000);
if(Serial.available() > 0)
{
Serial.println("");
Serial.println("set blink interval");
interval= Serial.parseInt(); //set blinking interval
Serial.println("Blink interval is ");
Serial.println(interval);
blinkContinues = true;
mode = "";
}
}
else if (mode == "J") // COMMAND FOR SINGLE BLINK
{
blinkContinues = false;
digitalWrite(ledPin, !digitalRead(ledPin));
delay(500);
mode = "";
}
else
{
digitalWrite(ledPin, LOW); //this is default state
mode = "";
}
if(blinkContinues){
doBlink();
}
}
void doBlink(){
digitalWrite(ledPin, HIGH);
delay(interval);
digitalWrite(ledPin, LOW);
delay(interval);
}
jimLee:
When labView sends a string lets say its "JOG". Does it send anything after the G? Typically it will. A EOL char or a newline char, return or something. Find out what that is. Then, don't just blindly read everything. Read each character one by one into a string until you see the end character. Lastly, add a '\0' to terminate the command you got. Now you know you have a complete command in your command buffer(string). Go look to see what it is.
Hope this helps.
-jim lee
Thank you Jim. I will keep that in mind.
I will add termination characters to identify start and end of string.
I have made some changes. I am not using String anymore in this program.
//String mode;
char command;
const byte ledPin = 13;
bool blinkContinues = false;
unsigned long interval = 500; //default interval is 500 milliseconds
void setup()
{
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.println("Enter C or c for continuous blink");
Serial.println("Enter J or j for single blink");
}
void loop()
{
while (Serial.available() > 0)
{
command = (Serial.read());
//command = 0;
}
if (command == 'C' || command == 'c') // COMMAND FOR CONTINUOUS PULSE
{
delay(2000);
Serial.println("");
Serial.println("set blink interval");
if (Serial.available() > 0)
{
interval = Serial.parseInt(); //set blinking interval
Serial.println("Blink interval is ");
Serial.println(interval);
blinkContinues = true;
command = 0;
}
}
else if (command == 'J' || command == 'j') // COMMAND FOR SINGLE BLINK
{
blinkContinues = false;
digitalWrite(ledPin, !digitalRead(ledPin));
delay(500);
command = 0;
}
else
{
//delay(2000);
//Serial.println("Enter valid command");
digitalWrite(ledPin, LOW); //this is default state
command = 0;
}
if (blinkContinues) {
doBlink();
}
}
void doBlink() {
digitalWrite(ledPin, HIGH);
delay(interval*.5);
digitalWrite(ledPin, LOW);
delay(interval*.5);
}
Now I want to enter continuous mode blink rate along with 'c' command. Something like C200 which would imply continuous blink with 200 blinks per second.
You can use toLower() so you don't have to check for the small letter and the capital letter.
if (command == 'C' || command == 'c') // COMMAND FOR CONTINUOUS PULSE
{
if (Serial.available() > 0)
Is not a good idea. The program runs faster then the serial does (especially at only 9600) so there is a big change only 'c' is received yet. Granted, the delay will probably fix that but you don't want to use delay().
Myself, I'm not even a fan of parseInt() because it's a blocking function I would just remember I saw a command that needed folowing by number and just collect them as I see new serial data. And start using it the moment I see a not-ascii number (like a line end '\n')