-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Serial.available() only returns 0 or 1 when sending multiple single bytes to atmega32u4 #267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
looking through the code and the data sheet it does not seem possible to get all the bytes available; only the byte count of the oldest packet. from what i can tell any subsequent packets sent do not make it into the endpoint. when bytes are read from serial it makes a call to available() to set max bytes to be retrieved. not sure if this should be changed to recheck available() after the endpoint has been emptied to see if more bytes should be fetched to attempt and read all the bytes or to the amount the sketch requested with readBytes. i think the only possibility is to document the difference in software serial and move on. :( |
Serial.available returns 1 when there is a data in the serial buffer. It is up to the rest of the code to process or count, if so desired, the characters in the buffer. This "Serial.available > 1" can be source of nasty bugs ( missing data) since your program structure often processes the serial data much faster than it is arriving. |
the online doc says it counts the number of bytes in the buffer. |
Yes, it does count the # of bytes, read my post again. " purpose of this function which is to simply detect the presence of data in buffer." |
It seems that @teliot is arguing that the purpose of this function is to count the number of bytes in the buffer, not just detect the presence of data. I agree with him on that, as does the documentation he linked. @teliot, As for the original issue, I haven't looked at the 32u4 serial code (I'm assuming you're talking about the CDC serial code, not software serial, which is usually used to refer to bit-banging serial on an I/O pin), but it would be preferable to make that behave like hardware serial as well. I don't quite follow what you're saying about this, though. Does the hardware buffer multiple USB packets and can you only access the byte count of one of them? Or does the USB host perhaps buffer the data until the 32u4 processed the packet completely? |
i looked through the 32u4 data sheet and lufa docs a good deal but was unable to find any mention of gaining access to any packet other then the current one. additionally i am unsure myself as to how exactly the endpoints work. i may be getting overly confused on the data sheet or the info just isn't there. if i were to guess, the packets come in and are buffered in DPRAM. the endpoint registers allow you to only access the first packet (FIFO). the LUFA docs did mention something about building a table, if it is talking about endpoints the overhead of accessing and decoding the dpram would be a waste of cycles. at this point i believe the best thing is to add a blurb in the docs that USB serial endpoints of the 32u4 (leonardo and variants) can only read one packet at a time. if someone more familiar with the chip knows of a way they can always chip in, users can always create a software buffer at the expense of ram if they wish. |
I am not sure why you have added "USB" . "Serial" is an instance of "HardwareSerial" class which in an essence performs UART functions - collect incoming data into a buffer via 32u4. If you code is Even the slowest processor will detect ONLY the first data and proceed into next instruction. If this is not helping, I must have missed something in your OP. |
@VaclavSal, what you describe is what happens on e.g. the Arduino Uno, which has an atmega328p running user code, and a atmega16u2 running the USB->serial conversion. This issue is about e.g. the Arduino Leonardo, which has a 32u4 that runs both user code and the virtual serial port over USB, with no separate USB part required. |
i don't think the usb serial endpoint reuses any code from the HardwareSerial files directly and has all of it's code in the board file and the usb* (mostly usbcore) files. EDIT: did not see matt's last comment above when i replied. his reply explains it better. |
came across the same issue and found just recently that several answers were correct, while not helping to understand the issue. When reciving data Serial.Available() is returning the number of bytes. Key is that the receiving and processing is so fast that the 1st byte in reception is already processed. My sequence to allow the receive queue to get all bytes, before starting to read and process the complete receive buffer is simply: |
Serial.available() never returns anything other then 0 or 1 when sending single bytes to the software serial of a mega32u4.
test code
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(Serial.available());
delay(100);
}
i can reproduce this on the client by using putty to send individual bytes.
while(Serial.available() < 4) ;
will lockup the program.
while(Serial.available() < 4) {
if (serialEventRun)
serialEventRun();
}
will not lockup the program but gets stuck in an infinite loop with single bytes being sent in. if i use the built in serial monitor sending a string of multiple bytes will exit the loop.
Example:
Serial.available() == 0
send one byte
Serial.available() == 1
send one byte
Serial.available() == 1
Restart device
Serial.available() == 0
send 4 bytes in one packet
Serial.available() == 4
send 1 byte
Serial.available() == 4
this behavior is different then a hardware serial of an uno
The text was updated successfully, but these errors were encountered: