lancer2000 Posted April 30, 2017 Posted April 30, 2017 (edited) Hi I have Arduino Mega and one Arduino Nano connected via RS485. Arduino library 0.2.11 DCS-BIOS 0.5.2 Arduine IDE 1.8.2 Everything is working but problem is in very slow working with 7-segment displays. I have two MAX7219 with 14 displays. If in-game change value then in the cockpit will change after even a few seconds My sketch: #define DCSBIOS_RS485_SLAVE 1 #define TXENABLE_PIN 2 #include <DcsBios.h> #include <LiquidCrystal.h> #include "LedControl.h" #include <Wire.h> LiquidCrystal lcd(4, 5, 6, 7, 8, 9); LedControl lc = LedControl(12, 11, 10, 2); int nums[11] = { B11110110, B00100010,//B01000100, B11110001, B10110011, B00100111, B10010111, B11010111, B00110010, B11110111, B10110111, B00000000 }; byte pvi_one, pvi_two, pvi_three, pvi_four, pvi_five, pvi_six, pvi_seven; byte oldpvi_one, oldpvi_two, oldpvi_three, oldpvi_four, oldpvi_five, oldpvi_six, oldpvi_seven; byte pvi2_one, pvi2_two, pvi2_three, pvi2_four, pvi2_five, pvi2_six, pvi2_seven; byte oldpvi2_one, oldpvi2_two, oldpvi2_three, oldpvi2_four, oldpvi2_five, oldpvi2_six, oldpvi2_seven; void Led_digit(int addr, int digit, int number) { switch (number) { case 0: lc.setLed(addr, 0, digit, true); lc.setLed(addr, 1, digit, true); lc.setLed(addr, 2, digit, true); lc.setLed(addr, 3, digit, true); lc.setLed(addr, 5, digit, true); lc.setLed(addr, 6, digit, true); lc.setLed(addr, 7, digit, false); break; case 1: lc.setLed(addr, 0, digit, false); lc.setLed(addr, 1, digit, false); lc.setLed(addr, 2, digit, true); lc.setLed(addr, 3, digit, false); lc.setLed(addr, 5, digit, false); lc.setLed(addr, 6, digit, true); lc.setLed(addr, 7, digit, false); break; case 2: lc.setLed(addr, 0, digit, true); lc.setLed(addr, 1, digit, true); lc.setLed(addr, 2, digit, true); lc.setLed(addr, 3, digit, true); lc.setLed(addr, 5, digit, false); lc.setLed(addr, 6, digit, false); lc.setLed(addr, 7, digit, true); break; case 3: lc.setLed(addr, 0, digit, true); lc.setLed(addr, 1, digit, false); lc.setLed(addr, 2, digit, true); lc.setLed(addr, 3, digit, true); lc.setLed(addr, 5, digit, false); lc.setLed(addr, 6, digit, true); lc.setLed(addr, 7, digit, true); break; case 4: lc.setLed(addr, 0, digit, false); lc.setLed(addr, 1, digit, false); lc.setLed(addr, 2, digit, true); lc.setLed(addr, 3, digit, false); lc.setLed(addr, 5, digit, true); lc.setLed(addr, 6, digit, true); lc.setLed(addr, 7, digit, true); break; case 5: lc.setLed(addr, 0, digit, true); lc.setLed(addr, 1, digit, false); lc.setLed(addr, 2, digit, false); lc.setLed(addr, 3, digit, true); lc.setLed(addr, 5, digit, true); lc.setLed(addr, 6, digit, true); lc.setLed(addr, 7, digit, true); break; case 6: lc.setLed(addr, 0, digit, true); lc.setLed(addr, 1, digit, true); lc.setLed(addr, 2, digit, false); lc.setLed(addr, 3, digit, true); lc.setLed(addr, 5, digit, true); lc.setLed(addr, 6, digit, true); lc.setLed(addr, 7, digit, true); break; case 7: lc.setLed(addr, 0, digit, false); lc.setLed(addr, 1, digit, false); lc.setLed(addr, 2, digit, true); lc.setLed(addr, 3, digit, true); lc.setLed(addr, 5, digit, false); lc.setLed(addr, 6, digit, true); lc.setLed(addr, 7, digit, false); break; case 8: lc.setLed(addr, 0, digit, true); lc.setLed(addr, 1, digit, true); lc.setLed(addr, 2, digit, true); lc.setLed(addr, 3, digit, true); lc.setLed(addr, 5, digit, true); lc.setLed(addr, 6, digit, true); lc.setLed(addr, 7, digit, true); break; case 9: lc.setLed(addr, 0, digit, true); lc.setLed(addr, 1, digit, false); lc.setLed(addr, 2, digit, true); lc.setLed(addr, 3, digit, true); lc.setLed(addr, 5, digit, true); lc.setLed(addr, 6, digit, true); lc.setLed(addr, 7, digit, true); break; } } //******************** PVI 800 Display ***************************** DcsBios::StringBuffer<1> pviLine1Apostrophe1Buffer(0x1934, onPviLine1Apostrophe1Change); void onPviLine1Apostrophe1Change(char* newValue) { if (newValue[0] == ' ') { lc.setLed(0, 4, 2, false); } else { lc.setLed(0, 4, 2, true); } } DcsBios::StringBuffer<1> pviLine1Apostrophe2Buffer(0x1936, onPviLine1Apostrophe2Change); void onPviLine1Apostrophe2Change(char* newValue) { if (newValue[0] == ' ') { lc.setLed(0, 4, 4, false); } else { lc.setLed(0, 4, 4, true); } } DcsBios::StringBuffer<6> pviLine1TextBuffer(0x1924, onPviLine1TextChange); void onPviLine1TextChange(char* newValue) { int one, two, three, four, five, six; if ((newValue[0] != ' ') && (newValue[0] != oldpvi_one)) { pvi_one = newValue[0] - '0'; // lc.setColumn(0,0,nums[one]); } Led_digit(0, 0, pvi_one); oldpvi_one = pvi_one; } else { lc.setColumn(0, 0, nums[10]); } if ((newValue[1] != ' ') && (newValue[1] != oldpvi_two)) { pvi_two = newValue[1] - '0'; Led_digit(0, 1, pvi_two); oldpvi_two = pvi_two; } else { lc.setColumn(0, 1, nums[10]); } if ((newValue[2] != ' ') && (newValue[2] != oldpvi_three)) { pvi_three = newValue[2] - '0'; Led_digit(0, 2, pvi_three); oldpvi_three = pvi_three; } else { lc.setColumn(0, 2, nums[10]); } if ((newValue[3] != ' ') && (newValue[3] != oldpvi_four)) { pvi_four = newValue[3] - '0'; Led_digit(0, 3, pvi_four); oldpvi_four = pvi_four; } else { lc.setColumn(0, 3, nums[10]); } if ((newValue[4] != ' ') && (newValue[4] != oldpvi_five)) { pvi_five = newValue[4] - '0'; Led_digit(0, 4, pvi_five); oldpvi_five = pvi_five; } else { lc.setColumn(0, 4, nums[10]); } if ((newValue[5] != ' ') && (newValue[5] != oldpvi_six)) { pvi_six = newValue[5] - '0'; Led_digit(0, 5, pvi_six); oldpvi_six = pvi_six; } else { lc.setColumn(0, 5, nums[10]); } } DcsBios::StringBuffer<1> pviLine1PointBuffer(0x1930, onPviLine1PointChange); void onPviLine1PointChange(char* newValue) { int digit; if ((newValue[0] != ' ') && (newValue[0] != oldpvi_seven)) { pvi_seven = newValue[0] - '0'; Led_digit(0, 6, pvi_seven); oldpvi_seven = pvi_seven; } else { lc.setColumn(0, 6, nums[10]); } } DcsBios::StringBuffer<1> pviLine2Apostrophe1Buffer(0x1938, onPviLine2Apostrophe1Change); void onPviLine2Apostrophe1Change(char* newValue) { if (newValue[0] == ' ') { lc.setLed(1, 4, 2, false); } else { lc.setLed(1, 4, 2, true); } } DcsBios::StringBuffer<1> pviLine2Apostrophe2Buffer(0x193a, onPviLine2Apostrophe2Change); void onPviLine2Apostrophe2Change(char* newValue) { if (newValue[0] == ' ') { lc.setLed(1, 4, 4, false); } else { lc.setLed(1, 4, 4, true); } } DcsBios::StringBuffer<6> pviLine2TextBuffer(0x192a, onPviLine2TextChange); void onPviLine2TextChange(char* newValue) { int one, two, three, four, five, six; if ((newValue[0] != ' ') && (newValue[0] != oldpvi2_one)) { pvi2_one = newValue[0] - '0'; // lc.setColumn(0,0,nums[one]); } Led_digit(1, 0, pvi2_one); oldpvi2_one = pvi2_one; } else { lc.setColumn(1, 0, nums[10]); } if ((newValue[1] != ' ') && (newValue[1] != oldpvi2_two)) { pvi2_two = newValue[1] - '0'; Led_digit(1, 1, pvi2_two); oldpvi2_two = pvi2_two; } else { lc.setColumn(1, 1, nums[10]); } if ((newValue[2] != ' ') && (newValue[2] != oldpvi2_three)) { pvi2_three = newValue[2] - '0'; Led_digit(1, 2, pvi2_three); oldpvi2_three = pvi2_three; } else { lc.setColumn(1, 2, nums[10]); } if ((newValue[3] != ' ') && (newValue[3] != oldpvi2_four)) { pvi2_four = newValue[3] - '0'; Led_digit(1, 3, pvi2_four); oldpvi2_four = pvi2_four; } else { lc.setColumn(1, 3, nums[10]); } if ((newValue[4] != ' ') && (newValue[4] != oldpvi2_five)) { pvi2_five = newValue[4] - '0'; Led_digit(1, 4, pvi2_five); oldpvi2_five = pvi2_five; } else { lc.setColumn(1, 4, nums[10]); } if ((newValue[5] != ' ') && (newValue[5] != oldpvi2_six)) { pvi2_six = newValue[5] - '0'; Led_digit(1, 5, pvi2_six); oldpvi2_six = pvi2_six; } else { lc.setColumn(1, 5, nums[10]); } } DcsBios::StringBuffer<1> pviLine2PointBuffer(0x1932, onPviLine2PointChange); void onPviLine2PointChange(char* newValue) { int digit; if ((newValue[0] != ' ') && (newValue[0] != oldpvi2_seven)) { pvi2_seven = newValue[0] - '0'; Led_digit(1, 6, pvi2_seven); oldpvi2_seven = pvi2_seven; } else { lc.setColumn(1, 6, nums[10]); } } //*********** PVI-800 Display END ********************* DcsBios::StringBuffer<10> ekranTxt1Line1Buffer(0x189c, onEkranTxt1Line1Change); void onEkranTxt1Line1Change(char* newValue) { lcd.setCursor(0, 0); lcd.write(newValue[0]); lcd.write(newValue[1]); lcd.write(newValue[2]); lcd.write(newValue[3]); lcd.write(newValue[4]); lcd.write(newValue[5]); lcd.write(newValue[6]); lcd.write(newValue[7]); } DcsBios::StringBuffer<10> ekranTxt1Line2Buffer(0x18a6, onEkranTxt1Line2Change); void onEkranTxt1Line2Change(char* newValue) { lcd.setCursor(0, 1); lcd.write(newValue[0]); lcd.write(newValue[1]); lcd.write(newValue[2]); lcd.write(newValue[3]); lcd.write(newValue[4]); lcd.write(newValue[5]); lcd.write(newValue[6]); lcd.write(newValue[7]); } DcsBios::StringBuffer<10> ekranTxt1Line3Buffer(0x18b0, onEkranTxt1Line3Change); void onEkranTxt1Line3Change(char* newValue) { lcd.setCursor(0, 2); lcd.write(newValue[0]); lcd.write(newValue[1]); lcd.write(newValue[2]); lcd.write(newValue[3]); lcd.write(newValue[4]); lcd.write(newValue[5]); lcd.write(newValue[6]); lcd.write(newValue[7]); } DcsBios::StringBuffer<10> ekranTxt1Line4Buffer(0x18ba, onEkranTxt1Line4Change); void onEkranTxt1Line4Change(char* newValue) { lcd.setCursor(0, 3); lcd.write(newValue[0]); lcd.write(newValue[1]); lcd.write(newValue[2]); lcd.write(newValue[3]); lcd.write(newValue[4]); lcd.write(newValue[5]); lcd.write(newValue[6]); lcd.write(newValue[7]); } DcsBios::StringBuffer<10> ekranTxt2Line1Buffer(0x18c4, onEkranTxt2Line1Change); void onEkranTxt2Line1Change(char* newValue) { lcd.setCursor(0, 0); lcd.write(newValue[0]); lcd.write(newValue[1]); lcd.write(newValue[2]); lcd.write(newValue[3]); lcd.write(newValue[4]); lcd.write(newValue[5]); lcd.write(newValue[6]); lcd.write(newValue[7]); } DcsBios::StringBuffer<10> ekranTxt2Line2Buffer(0x18ce, onEkranTxt2Line2Change); void onEkranTxt2Line2Change(char* newValue) { lcd.setCursor(0, 1); lcd.write(newValue[0]); lcd.write(newValue[1]); lcd.write(newValue[2]); lcd.write(newValue[3]); lcd.write(newValue[4]); lcd.write(newValue[5]); lcd.write(newValue[6]); lcd.write(newValue[7]); } DcsBios::StringBuffer<10> ekranTxt2Line3Buffer(0x18d8, onEkranTxt2Line3Change); void onEkranTxt2Line3Change(char* newValue) { lcd.setCursor(0, 2); lcd.write(newValue[0]); lcd.write(newValue[1]); lcd.write(newValue[2]); lcd.write(newValue[3]); lcd.write(newValue[4]); lcd.write(newValue[5]); lcd.write(newValue[6]); lcd.write(newValue[7]); } DcsBios::StringBuffer<10> ekranTxt2Line4Buffer(0x18e2, onEkranTxt2Line4Change); void onEkranTxt2Line4Change(char* newValue) { lcd.setCursor(0, 3); lcd.write(newValue[0]); lcd.write(newValue[1]); lcd.write(newValue[2]); lcd.write(newValue[3]); lcd.write(newValue[4]); lcd.write(newValue[5]); lcd.write(newValue[6]); lcd.write(newValue[7]); } void setup() { lc.shutdown(0, false); lc.setIntensity(0, 8); lc.clearDisplay(0); lc.shutdown(1, false); lc.setIntensity(1, 8); lc.clearDisplay(1); DcsBios::setup(); } void loop() { DcsBios::loop(); } In Dcsbios.log i have lots of this: (maybe 10 or more lines per second) value -65535.000000 is too small for address 6212 mask 65535 And screen of socat: I use this MAX485: https://www.aliexpress.com/item/FREE-SHIPPING-5PCS-LOT-MAX485-module-RS485-module-TTL-turn-RS-485-module-MCU-development-accessories/32255771572.html?spm=2114.01010208.3.81.AAubEO&ws_ab_test=searchweb0_0,searchweb201602_3_10152_10065_10151_10068_10136_10137_10157_10060_10138_10155_10062_10156_10154_10056_10055_10054_10059_10099_10103_10102_10096_10148_10147_10052_10053_10142_10107_10050_10051_10171_10084_10083_10080_10082_10081_10110_10111_10112_10113_10114_10181_10182_10078_10079_10073_10070_10123_10124-10051,searchweb201603_2,ppcSwitch_5&btsid=8bc712f9-3267-4c68-a8b4-6cf08615893b&algo_expid=58944ec8-62ad-4314-8db9-45586fead0e8-10&algo_pvid=58944ec8-62ad-4314-8db9-45586fead0e8 Edited April 30, 2017 by lancer2000
FSFIan Posted April 30, 2017 Posted April 30, 2017 Does the same behavior happen in IRQ_SERIAL mode? If it works fine with IRQ_SERIAL and does not work over RS-485, your RS-485 bus might be unreliable; check your wiring. If the same behavior happens in IRQ_SERIAL mode with a direct USB connection, updating the displays and MAX219 chips takes too long. You should be using setDigit() instead of multiple calls to setLed() to optimize performance, but I don't think this would account for a lag of several seconds. A lag of several seconds usually indicates that an update has been missed entirely (either due to a transmission error or due to an overworked microcontroller where some Arduino library is blocking interrupts for too long). Another thing to look out for is if the lag is consistent. If it is always there, talking to the displays might take too long. If it sometimes reacts instantly, it's probably transmission problems over the RS-485 bus. DCS-BIOS | How to export CMSP, RWR, etc. through MonitorSetup.lua
lancer2000 Posted April 30, 2017 Author Posted April 30, 2017 I make test with IRQ_SERIAL mode and work great. I thought if RS485 works then wiring is ok. I have connection like this ( only enable pins i have pin2 instead pin8 )
lancer2000 Posted April 30, 2017 Author Posted April 30, 2017 I make videos - difference between IRQ_Serial and RS485 IRQ_Serial very fast working: RS485 Lags:
FSFIan Posted April 30, 2017 Posted April 30, 2017 (edited) If the schematic on this page matches your board, the value of the bias resistors is probably too high. Measure R5 (resistance between B and GND) and R6 (resistance between A and VCC) on your board. If they are higher than 560 ohm, this is likely the problem. If the bias resistors are the problem, you can try removing the 120 ohm termination resistors (marked "121") from both boards. Without the termination resistors, the bus should then work reliably over very short distances. EDIT: ...or simply add the external 470 ohm bias resistors shown in the schematic on that page. If you use more than one slave device, only the last slave device on the bus should have a termination resistor on the board. Here's a calculator to determine the value of bias and termination resistors. It implements the formulas given in the TI app note linked in the first paragraph. The job of the bias resistors is to make sure that the bus is in a defined state when no chip is driving the bus. This happens when the master is asking a slave device "do you have something to say?". The master then releases the bus and a short amount of time passes before the slave starts driving the bus. During that time, the two 120 ohm termination resistors essentially short the bus (so there is no voltage difference between A and B and thus no defined logic level) unless there are two sufficiently strong (i.e. low value) bias resistors to counter this. If the bus is not properly biased, the devices might read a logic 0 for a short amount of time, which signals the start of a new UART transmission. That will cause data that is sent afterwards to be misinterpreted and come out as garbage. Eventually, DCS-BIOS will notice that no one has transmitted for a while and reset the bus, so the process can start over again. I recommend the MAX487 transceiver chip. Due to its slew-rate limiting, it should work without termination resistors over distances of up to 10 meters. It also supports more devices on one bus (1/4 unit load). With the MAX485, you need termination and bias resistors if your bus is more than a few centimeters long, and with proper termination and biasing you should be able to use 10 devices (1 master, 9 slaves) per bus. With the MAX487, as long as the bus is not longer than 10 meters, you can skip termination and bias resistors and use up to 126 devices on one bus. With termination and bias resistors, the MAX487 would allow about 40 devices on one bus. Note: the information in this post is based on my understanding of RS-485, which is mostly theoretical (from reading datasheets and application notes). My tests were limited to three MAX487 chips on one bus over maybe 20 centimeter of wiring. I did not test other transceiver chips, longer bus lengths, or more devices on one bus. This is the main reason that the whole RS-485 thing is not officially documented yet. Edited April 30, 2017 by [FSF]Ian DCS-BIOS | How to export CMSP, RWR, etc. through MonitorSetup.lua
maciekish Posted October 10, 2023 Posted October 10, 2023 Sorry for necroing this, found it by accident. Its not any of the issues suggested. Its a buffer overflow caused by how the RS485 slave code is written. Was pulling my hair over this for 6 months. I have suggested a fix here which eliminates the issue. 1 1
Vinc_Vega Posted October 11, 2023 Posted October 11, 2023 Thanks, so than recieving a CDU page or the Caution Panel Lights via RS485 shouldn't be so slow anymore? Regards, Vinc Regards, Vinc real life: Royal Bavarian Airforce online: VJS-GermanKnights.de [sIGPIC][/sIGPIC]
lesthegrngo Posted October 12, 2023 Posted October 12, 2023 (edited) And for the hard of thinking like me, what is it exactly we have to do to fix it, or has some software been changed? I have an A10 warning lights panel that I made using a Mega to drive individual LED's (one LED to one pin) that worked fantastically using USB, but was not working properly using RS458, as it would only light portions of the panel at any one time. If I could get that working properly under RS485 it would definitely be a plus Cheers Les Edited October 12, 2023 by lesthegrngo
Vinc_Vega Posted October 13, 2023 Posted October 13, 2023 @maciekish Do you have any experience with your fix, running more than one RS485 bus per Mega? Regards, Vinc Regards, Vinc real life: Royal Bavarian Airforce online: VJS-GermanKnights.de [sIGPIC][/sIGPIC]
Vinc_Vega Posted October 16, 2023 Posted October 16, 2023 On 10/12/2023 at 6:22 AM, lesthegrngo said: And for the hard of thinking like me, what is it exactly we have to do to fix it, or has some software been changed? I have an A10 warning lights panel that I made using a Mega to drive individual LED's (one LED to one pin) that worked fantastically using USB, but was not working properly using RS458, as it would only light portions of the panel at any one time. If I could get that working properly under RS485 it would definitely be a plus Cheers Les No answer so far, just try to pull from here: https://github.com/DCSBIOSKit/dcs-bios-arduino-library/tree/rs485 But keep a backup of your files! Regards, Vinc Regards, Vinc real life: Royal Bavarian Airforce online: VJS-GermanKnights.de [sIGPIC][/sIGPIC]
lesthegrngo Posted October 18, 2023 Posted October 18, 2023 All, I followed Maciekish's instructions and inserted the following code into my Mega Warning Light Panel sketch #define DCSBIOS_DEFER_RS485_PROCESSING #define DCSBIOS_INCOMING_DATA_BUFFER_SIZE 512 This was in front of the #include <DcsBios.h> callout I can report that the sketch now works correctly using RS485, where previously it would only display half the panel at any one time. I had a minor issue with another sketch using this but I think that it is probably more something particular to my setup rather than a problem with Maciekish's code So, if you are experiencing issues with an RS485 sketch stuttering or slowing down, this looks like it is worth a try Cheers Les 1 1
Heling Posted December 30, 2024 Posted December 30, 2024 I hope that is the end of my suffering. Although I use a very good PC, the reliability decreases with the increasing number of connected USB ports. One USB port after another stops working during a session. I have now switched 4 out of 15 to RS485. This also brought greater stability to the USB ports too! I use the DCSbiosBridge from Charliefoxtwo, which works great under WIN11 and not only connects the COM ports, but also resets them and can display the data traffic. Helpful when looking for interference, such as volatile potentiometers. Yes, the radio displays react very slowly via RS485. I will incorporate the help mentioned above into the code and sincerely hope that the disconnection problems will come to an end.
No1sonuk Posted December 30, 2024 Posted December 30, 2024 (edited) 10 hours ago, Heling said: I hope that is the end of my suffering. Although I use a very good PC, the reliability decreases with the increasing number of connected USB ports. One USB port after another stops working during a session. I have now switched 4 out of 15 to RS485. This also brought greater stability to the USB ports too! I use the DCSbiosBridge from Charliefoxtwo, which works great under WIN11 and not only connects the COM ports, but also resets them and can display the data traffic. Helpful when looking for interference, such as volatile potentiometers. Yes, the radio displays react very slowly via RS485. I will incorporate the help mentioned above into the code and sincerely hope that the disconnection problems will come to an end. Some people have serios lag using the DCSbiosBridge. If you don't need it for debugging, it's better to use the socat options. Unfortunately, the bridge's developer pulled out of the DCS-BIOS project entirely, so the bridge is not likely to be fixed until someone takes it up again. Edited December 30, 2024 by No1sonuk
Heling Posted December 31, 2024 Posted December 31, 2024 (edited) vor 12 Stunden schrieb No1sonuk: Some people have serios lag using the DCSbiosBridge. If you don't need it for debugging, it's better to use the socat options. Unfortunately, the bridge's developer pulled out of the DCS-BIOS project entirely, so the bridge is not likely to be fixed until someone takes it up again. I know. I was one of them with freezing DCSbiosBridge. The problem was not the Software, it's the combination of lot ports, laggy Bodnar boards and bad port handling inside Windows. Since I upgraded to WIN11 and max. 15 USB-ports, the bridge is working fine for me. I also updated the Bodnar bords with new firmware. Now I've to work on the RS485 net. Edited December 31, 2024 by Heling
No1sonuk Posted December 31, 2024 Posted December 31, 2024 Interesting. I had lag in Win11 with one arduino...
Heling Posted January 5 Posted January 5 I tried a USB port expansion card in the PC and quickly removed it again. The more ports WIN had to manage, the worse they worked. Lags and diconnections increased dramatically. So I have now combined several Arduinos into one port via RS484. That was very helpful!
Recommended Posts