Jump to content

DCS-BIOS RS485 Slow working


lancer2000

Recommended Posts

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:

socat_screen.jpg.02b4499adf9ff839bc16199563e562c0.jpg

 

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 by lancer2000
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by [FSF]Ian
Link to comment
Share on other sites

  • 6 years later...

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 by lesthegrngo
Link to comment
Share on other sites

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]

Link to comment
Share on other sites

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

  • Thanks 1
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...