I have been trying to figure out a way to send a full word from the serial monitor to the Arduino to turn something on or off. In this case, I am trying to turn an LED on or off by entering true or false. I successfully did this with a single character. Also, what if you want to include a second criteria, say PWM data following true or false. I.e. true, 255.
You need to define a command packet, and a piece of code that reads a complete packet. How do you know its complete? The trick is to add a separator that is no part of the command. Example
true,255#
false,113#
Note that the , functions as separator
You need something like this readCommand() [not tested] to read one complete command; then you can split command into fields ( search for strtok() example )
int readCommand()
{
char lastchar = ''';
int i= 0;
while (lastchar != '#')
{
if (Serial.available()>0)
{
lastchar = Serial.Read();
if (lastchar == #)
{
command[i] = '\0';
} else command[i++] = lastchar;
}
}
}
The below is for servos, but you should be able to modify it to your needs. Send your info in a string to the arduino, and then using the string functions, parse out the info you want to use. The number part of the string is captured and is turned into an integer to control a servo (you would do similar for PWM).
// zoomkat 11-22-10 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 0019 and later
// Powering a servo from the arduino usually DOES NOT WORK.
// two servo setup with two servo commands
// send eight character string like 15001500 or 14501550
#include <Servo.h>
String readString, servo1, servo2;
Servo myservo1; // create servo object to control a servo
Servo myservo2;
void setup() {
Serial.begin(9600);
myservo1.attach(6); //the pin for the servo control
myservo2.attach(7);
Serial.println("servo-test-21"); // so I can keep track of what is loaded
}
void loop() {
while (Serial.available()) {
delay(1);
if (Serial.available() >0) {
char c = Serial.read(); //gets one byte from serial buffer
readString += c; //makes the string readString
}
}
if (readString.length() >0) {
Serial.println(readString); //see what was received
// expect a string like 07002100 containing the two servo positions
servo1 = readString.substring(0, 4); //get the first four characters
servo2 = readString.substring(4, 8); //get the next four characters
Serial.println(servo1); //print to serial monitor to see results
Serial.println(servo2);
int n1; //declare as number
int n2;
char carray1[6]; //magic needed to convert string to a number
servo1.toCharArray(carray1, sizeof(carray1));
n1 = atoi(carray1);
char carray2[6];
servo2.toCharArray(carray2, sizeof(carray2));
n2 = atoi(carray2);
myservo1.writeMicroseconds(n1); //set servo position
myservo2.writeMicroseconds(n2);
readString="";
}
}
Awesome! Thanks.
That answers my question about multiple parameters. Does anybody know about how to send a single word from the serial monitor to do something? What would data type would it be?
Does anybody know about how to send a single word from the serial monitor to do something?
You need to give an example of "a single word". The word "word" has multiple meanings, including some that are specific to Microslop operating systems.
You mean an array of characters like "on" or "off".
First question to ask yourself is how will you know, when reading the characters one at a time from the serial port, using Serial.read(), that you have read the last character in the "word"?
And end-of-packet marker will be essential to know when to stop reading and when to start parsing what you have read.
char inData[10];
byte index = 0;
char EOP = ';';
void loop()
{
while(Serial.available() > 0)
{
char inByte = Serial.read();
if(index < 10)
{
inData[index] = inByte;
inData[index+1] = '\0';
}
}
if(inData[index] == EOP)
{
// Parse and use the data
if(strcmp(inData, "on")
// Do whatever on means
else if(strcmp(inData, "off")
// Do whatever off means
inData[0] = '\0';
index = 0;
}
}
// zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later
String readString;
void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
Serial.println("serial test 0021"); // so I can keep track of what is loaded
}
void loop() {
while (Serial.available()) {
delay(1);
char c = Serial.read();
readString += c;
}
if (readString.length() >0) {
Serial.println(readString);
if (readString == "on") {
digitalWrite(13, HIGH);
Serial.println("Led On");
}
if (readString == "off") {
digitalWrite(13, LOW);
Serial.println("Led Off");
}
readString="";
}
}
OK. I have integrated the strcmp into my RC car code. My question is, I'd like to add to other criteria to be entered in—a pwm speed, and an amount of time (in milliseconds). How would I set this up?
(As you can see, I already set up a byte for the speed, and an int for the duration. I understand that I'll probably have to do a little math to convert the duration to milliseconds for the delay function.)
This code won't work. The range of indices for the allMotors array is 0 to 3. 4 is not in that range. The other indices are wrong, too.
If you want to send something like "forward, 10, 100;" to make the device move forward at a speed of 10 for 100 milliseconds, you'll need to collect all the data into the array (which will obviously need to be larger), and then use strtok() to parse the inData array. Each token will be used for a different purpose. The atoi() function will bear looking into, too.
I tried making the array controlSet[4], but it won't let me. The reason I have the control set is to encompass the four main functions—forward, backward, and turning.
It's not the size of controlSet that is a problem. The array is currently sized to hold 3 objects of type AF_DCMotor.
4 is not a valid index into the allMotors array, so whatever follows the allMotors array in memory, which is most likely NOT a AF_DCMotor object is what will be stored in the first position of the controlSet array. That block of memory will most likely NOT respond correctly to an attempt to invoke its run function.
ControlSet is basically encompassing the three different arrays. I thought that it would be used for one of the criteria—forward, backward, right, left—but it may not be needed.
ControlSet is basically encompassing the three different arrays. I thought that it would be used for one of the criteria—forward, backward, right, left—but it may not be needed.
You've only got 4 motors, and they are already all defined in allMotors, and some are duplicated in rightSide and leftSide.
I can't see a use for controlSet. As a result, I can't see how to define or initialize it.
You're definitely right. I thought that I would need controlSet in the array that I am pulling data from. But I want to make allMotors = "forward" or "backward".
Could you please explain WHAT index, EOP, and inData[9] are actually doing? How would I implement extra criteria like the speed and time in the strcmp function?
OK. I think I might be on to something, but I'm getting a lot of error messages saying things like "invalid conversion from 'char' to 'const char*'.
Also, does EOP stand for the separator between criteria?
Here is my code:
The strcmp() function takes two arguments - the strings to compare. You are trying to call it with 4 arguments.
Once you have the complete string (and, no, EOP is not the separator - it is the end of packet marker. You need a different separator), you need to call strtok() to extract the tokens (the strings that contain the command, the speed, and the duration). Once you have the tokens, you need to see if the command is something ("forward" or "backward"). If so, you might need to convert the speed and duration tokens to ints (using atoi()). I would not expect all commands to have speed and duration associated with them. "stop" hardly needs to know how fast to stop.
allMotors[4].setSpeed(inputSpeed);
You only have 4 motors. The indices (the values in the []) are 0 to 3. You can't make all 4 motors do something using a command like this. You need 4 separate statements to make all 4 motors do something.