yes, I agree, but I want to point out, that timing issues and code optimization are a 2nd problem, the original question was just: what's wrong with "== operator in conditional statement".
RayLivingston:
The correct way to handle it is by looking at the characters AS THEY COME IN, and finding the beginning and end of each packet, discarding any invalid messages. Anything else will simply not be robust.
Which is what I did in my solution I think? Consider each byte as it comes in and deal with it in terms of your expectations? In MIDI '144' is a note on command byte and you shoud expect two bytes to follow, one for note and the other for velocity. I could obviously add some kind of error handling, velocity for example should only be in the range 0-127, if it's outside that you can assume something's gone wrong and abort the command, for example.
However this does raise an important consideration. I'm assuming Serial.available DOESN'T wait? My assumption is if there's something in the buffer get it otherwise continue with program execution. Correct me if I'm wrong as this sketch will develop into a sequencer so timing will be critical.
@ArthurD - I feel you did answer my original question. Thank you!
correct, Serial.available DOESN'T wait!
it just looks into the Serial buffer and counts the bytes which are filled in and then returns the number of it, nothing else.
ArthurD:
correct, Serial.available DOESN'T wait!
it just looks into the Serial buffer and counts the bytes which are filled in and then returns the number of it, nothing else.
Good! That's what I want ... if there's a byte to be had, get it and do something with it, otherwise, move along nothing to see here etc
Serial.available() just subtracts two indices modulo buffersize, no wait, no looking into or counting.
int HardwareSerial::available(void)
{
return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE;
}
ok counting not one by one but by computing 2 indices, but thats finally the same, isn't it?
The result of counting and computing will be equal if the computation is correct.
But the process is very different, counting scales linear with the elements, computation is fixed.
Do you remember the story of the kids that had to add the numbers from 1 to 1000 as a penalty?
Computing (1000+1)*500 was a quick way to get the correct value.
Admitted, the result is equivalent.
the result is what the user wants to know, either by counting or by calculating, it does not alter the fact that
Serial.available looks into the Serial buffer and counts (or calculates) the bytes which are filled in and then returns the number of it, and nothing else.
OTOH, what is "subtracts two indices" acually doing? perhaps something like counting bytes or ints or longs between both indices? But finally that's subtleties, not to say: hairsplitting.
ArthurD:
Serial.available looks into the Serial buffer and counts (or calculates) the bytes which are filled in and then returns the number of it, and nothing else.
No.
No looking into buffer, no counting.
It returns the difference of two bytes modulo some value. (As you can see in the source.)
You are free to rename 'subtraction' in 'counting' and
'subtracting two bytes modulo buffersize' to 'looking into buffer',
but you better publish that list of renames or nobody will be able to communicate with you.
as I said, finally that's subtleties, not to say: hairsplitting.
my paraphrase should simply describe understandably what happens in the end.
I you see it that way, you are free to.
Programming is an exact science and like in mathematics there are words with special meaning.
So counting has a special meaning (the linear complexity) that makes a big difference to subtraction,
and pointing out that fact is far away from knitpicking.
dcjim:
Doesn't the surrounding while loop chunk the incoming data into three bytes though?do{
if (Serial.available()) {
commandByte = Serial.read();
noteByte = Serial.read();
velocityByte = Serial.read();
...
}
while (Serial.available() > 2);
No. The do-while does the check after the body of the loop. The body always executes once, which is what makes it different from a while loop. The body checks for one or more characters, reads up to three characters if they are available, and the do-while repeats that if there are three or more characters in the buffer after the 1-to-3 have been removed.
dcjim:
And how does that explain why it works without the noteByte condition?
commandByte = Serial.read(); // Reads the noteOn value
noteByte = Serial.read(); // Returns -1 which gets turned to 255 in an unsigned char
velocityByte = Serial.read(); // Returns -1 which gets turned to 255 in an unsigned char
if (velocityByte > 0) { // WORKS because 255 > 0
if (noteByte == 36 && velocityByte > 0) { // FAILS because 255 != 36
Vaclav:
Plain and true - if you expect 3 bytes - wait for three.My view is that there is a major "urban legend" how "available" works due to two "false doctrines" - never use delay() or any kind of wait for "available" in you code - use loop() and if( available) so the processor is kept busy irregardless if it is required or not.
Different styles exist with pros and cons. That doesn't make them "urban legends" or "false doctrines".
It is well understood that delay() should be avoided if possible, especially when it's not necessary. For example, it's not necessary at all to use delay() when waiting for bytes to be available in the serial buffer. What is the point in twiddling your thumbs between checking to see if you received any data? Wouldn't you want to do something with data immediately as it arrives? If you use delay() the data could be sitting in the receive buffer for up to the full length of your delay. So it's pointless and completely avoidable.
And the processor is "kept busy" with your techniques too--you keep the processor spinning in circles doing nothing useful with code like this:
while (!Serial.available());
A program could do something else while it waits to receive data over the slow serial port, such as with the "if (Serial.available())" technique, but it can't if it's stuck inside your empty "while (!Serial.available())" loop.
Vaclav:
( And add millis() to convolute the code more - famous blink without delay())) .
What's convoluted about the Blink Without Delay example? It shows a very straightforward way to perform some task without twiddling the processor's thumbs doing nothing with delay(). It's useful to show beginners how to educate and elevate themselves up from their beginner state. You can look at it as a stepping stone to more advanced techniques like pseudo-multitasking (see examples like "Several Things at the Same Time") or a state machine. Those advanced techniques cannot be used if one "task" is spinning around doing nothing inside a delay() or an empty "while" loop while other tasks could be doing something useful.
Still, if you want to be a perpetual beginner or don't ever care about doing more than one thing "at the same time", go ahead and use your techniques to wait for serial data and the like. Most everyone else wants to write a program that can do more than one thing at a time (eg, do something while waiting for serial data).
christop:
Still, if you want to be a perpetual beginner or don't ever care about doing more than one thing "at the same time", go ahead and use your techniques to wait for serial data and the like. Most everyone else wants to write a program that can do more than one thing at a time (eg, do something while waiting for serial data).
He just likes to complain.... a LOT!
Regards,
Ray L.
RayLivingston:
He just likes to complain.... a LOT!Regards,
Ray L.
I know it, but I wouldn't feel as compelled to respond to his complaints if they were founded in facts.