Awol, We're having exactly the issue you describe in our stepper control code.
I understand why it will fail without the delay but I'm trying to understand why it needs a >20ms delay to work correctly. if its 9600bps thats (1/9600)*8 = 0.00083s <1Ms, for the time it takes a byte to arrive at the arduino? increasing the baud rate for serial comms reduces the length of the delay needed but that obviously isn't a fix, just confirms that our code sucks slighly faster at higher baud rates.
So the code in void loop() is running faster than that hence getting a -1 as it hits between bytes but why does it need more than 20ms delay to get 5 chars. In our case 5 chars is the smallest string we send, longest string is probably a buffer full, we don't check, mainly as its not that important as our release software will be usually sending just a single command+optional data string, but random length multiple command strings are very useful while I debug and could springboard another project that they would be very useful in.
Would it be legitimate for me to use something like:
if (Serial.available() > 4)
before we start to process the serial buffer? or am I hoping that by the time its processed the command string, the data portion of the command (if it exists) will have arrived?
Our command strings take the following form, where nnnnn = 0 to 16384
:POS:nnnnn;
:SPD:nnnnn;
:STP:nnnnn;
:LMT:nnnnn;
:IN1:n; // already padded to keep the commands to 3 bytes
:OUT:n;
IN1 and OUT don't actually need a value unless you are sending a multiple command string like this:
:spd:1000;:lmt:16000;:stp:500;:in1:0;:stp:50;:out:0;:stp:60;:out:0;
We know why in and out fail with the 0; ommited, because we still check for a value which kills the string as it reads the next command in while it hunts for a ; to finish the last command, that's fine we'll fix that in a bit by moving the call to the 'get the value for the command' function into the commands that actually require a value.
some of our code:
void loop() {
int bCommandReady = false;
//If There is information in the Serial buffer read it in and start the Build command subroutine
if (usingSerial && Serial.available() > 0) { // I expect to change this to
// read the incoming byte:
incomingByte = Serial.read();
/* Build a new command. */
bCommandReady = cliBuildCommand(incomingByte);
}
delay(100); // with this lower than 20ms our code goes sporadic, the lower you go it fails (as explained by awol)
//If there is a command in the buffer then run the process command subroutine
if (bCommandReady == true) {
bCommandReady = false; // reset the command ready flag
cliProcessCommand(); // run the command
}
if (UPDATE){
UPDATE=false;
FocusPrintStepsFun(); //Print the number of steps
FocusPrintPositionFun(); //Print the Position
SerialDATAFun(); // debug mainly, gives detailed information about the current state of the machine
}
}
and the command/data building functions:
//Process Command. This searches the command table to see if the command exits if it does then the required subroutine is run
void cliProcessCommand(void)
{
int bCommandFound = false;
int idx;
/* Convert the parameter to an integer value.
* If the parameter is emplty, gParamValue becomes 0. */
gParamValue = strtol(gParamBuffer, NULL, 0);
/* Search for the command in the command table until it is found or
* the end of the table is reached. If the command is found, break
* out of the loop. */
for (idx = 0; gCommandTable[idx].name != NULL; idx++) {
if (strcmp(gCommandTable[idx].name, gCommandBuffer) == 0) {
bCommandFound = true;
break;
}
}
/* If the command was found, call the command function. Otherwise,
* output an error message. */
if (bCommandFound == true) {
(*gCommandTable[idx].function)();
}
}
//When data is in the Serial buffer this subroutine is run and the information put into a command buffer.
// The character : is used to define the end of a Command string and the start of the parameter string
// The character ; is used to define the end of the Parameter string
int cliBuildCommand(char nextChar) {
static uint8_t idx = 0; //index for command buffer
static uint8_t idx2 = 0; //index for parameter buffer
int loopchk = 0;
nextChar = Serial.read();
do
{
gCommandBuffer[idx] = TO_UPPER(nextChar);
idx++;
loopchk=loopchk+1;
nextChar = Serial.read();
}
while ((nextChar != ':') && (loopchk < 6));
loopchk=0;
nextChar = Serial.read();
do
{
gParamBuffer[idx2] = nextChar;
idx2++;
loopchk=loopchk+1;
nextChar = Serial.read();
}
while ((nextChar != ';')&& (loopchk < 5));
gCommandBuffer[idx] = '\0';
gParamBuffer[idx2] = '\0';
idx = 0;
idx2 = 0;
return true;
}