-
Notifications
You must be signed in to change notification settings - Fork 26
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
RS485 Data Dropping #52
base: master
Are you sure you want to change the base?
Conversation
#define DCSBIOS_INCOMING_DATA_BUFFER_SIZE 512 #define DCSBIOS_ALTERNATIVE_RS485_PROCESSING
…s up another character, the tail end of a partial new message may end up in the incomingDataBuffer.
DCSBIOS_DEFER_RS485_PROCESSING
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job diagnosing this. I like your approach.
The only thing I'd ask it that your excellent PR description be made available to all for after the PR closes. You can decide where. Could be in readme. Could be on the wiki. I often find it best to make a sketch in the example and comment it well.
Hi, sorry for taking forever. I was cleaning up my branches and realized this was never merged. I have pushed an example called RS485Deferred. Please let me know if it looks ok. How do i make changes to the wiki? Can't find any fork/edit function there. |
@maciekish to make changes to the wiki you should just be able to click the edit or new page buttons on any page in the top left. I've just opened up edit access to the wiki - let me know if you have any issues |
I have added a page explaining the alternate processing mode but haven't touched the menu because i'm not sure how you want to organize it as there is no RS485 page or menu. https://github.com/DCS-Skunkworks/dcs-bios-arduino-library/wiki/RS485-Processing-Modes. There is also an example i added before: https://github.com/DCSBIOSKit/dcs-bios-arduino-library/blob/rs485/examples/RS485Deferred/RS485Deferred.ino Please let me know how you would like to proceed |
I have no strong opinions about the wiki structure (I'm not too involved in this project) so I'd say take whatever action you see fit. It's a community wiki and things can always be moved in the future - the important part is just getting the data there in the first place |
RS485 Data Dropping
This PR addresses the data dropping issues encountered when RS485 slaves are too busy to process incoming data.
The problem
RS485 slaves drop incoming export data if the user sketch runs too slow. It happens when drawing to a slow display, but also in cases where it should work a lot faster, such as writing to a Nextion display (UART2, 250000 baud). Additionally, if you map 48LEDs on an Arduino Mega, even with direct register writes, it triggers the same issue.
Videos
These examples run on the exact same hardware, code and data. The only difference are the
#defines
for USB or RS485 mode. I have made a dev-board for tracking down this particular issue, and it includes the same amount of LED as the A-10C Caution Panel, and a Nextion header for easy testing.Before
Expand
CautionPanel-Broken.mp4
CDU-Broken.mp4
After
Expand
CautionPanel-Fixed.mp4
CDU-Fixed.mp4
Changes
I have done extensive testing and found the following changes fix the issue. Each change improves the situation, and together, RS485 slaves behave like USB devices.
processCharISR()
has been modified to only store the received byte ifDCSBIOS_RS485_SLAVE
is defined.processChar()
has been moved toloop()
.unit8_t availableForWrite()
added toRingBuffer
.incomingDataBuffer
is checked for space to avoid a buffer overflow.incomingDataBuffer
is user-configurable with#define DCSBIOS_INCOMING_DATA_BUFFER_SIZE 512
.Rationale
processCharISR()
. This function directly calls out to individual ESLs, which in turn run all user code in any DCS-BIOS callbacks. In practice, pretty much the whole sketch runs in ISR context, with nested interrupts. There is barely any prioritization because everything runs from the ISR. So when new data arrives, it has to contest for resources. While it may seem like callingprocessChar()
is important, the full picture must be considered. IfprocessChar()
takes a bit longer because it´s now called inloop()
and may be interrupted, the only downside is that the external update (LED, display, servo etc) will happen slightly later. But ifprocessCharISR()
doesn't run fast enough, we start dropping data randomly, sync is invalidated because we don't know what, or how much was dropped, and the wholeincomingDataBuffer
becomes a mess.incomingDataBuffer
which is aRingBuffer
. What this means in practice, is that if an ESL is busy reading data from theRingBuffer
, and an interrupt causes a write longer than available space, the new data will overwrite old data that hasn't been processed yet. This causes all sorts of weird issues, like the sync sequenceUUUU
appearing as text on displays, or the wrong LEDs lighting up/extinguishing on a caution panel. So, if the buffer cannot fit the new data, it has to be discarded.User impact
All changes only affect AVR MCUs in RS485 mode. USB mode is not affected. To enable the new processing mode, use
DCSBIOS_DEFER_RS485_PROCESSING
: