Jump to content

Issue with A-10C altimeter display using DCS-BIOS


Adrian_gc

Recommended Posts

Hi, I need help with the representation of height in an OLED display.

I have write a code on arduino uno using DCS-BIOS to represent the height in an OLED display. When I run the program and the airplane is on the ground, the display shows up perfectly, if I turn the Rotary altimeter also perfectly synchronized shows. The problem happens when the plane is in flight. It is seen on the screen height is represented with a mix of numbers, usually the "3" ... "333" as if it were an interference. After leaving the plane on autopilot stable, the screen displays the most stable height, still, occasionally remixed numbers.

 

Here I attached a copy of the code I'm using, also 2 videos of what happens on the ground and in flight.

 

Anyone would think that might be happening? thank you.

 

Videos:

 

[ame]https://www.youtube.com/watch?v=3Q2jVzB1wVY[/ame]

[ame]

[/ame]

 

Code:

#include <DcsBios.h>

#include <Servo.h>

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

 

#define OLED_MOSI 9

#define OLED_CLK 10

#define OLED_DC 11

#define OLED_CS 12

#define OLED_RESET 13

Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

 

#if (SSD1306_LCDHEIGHT != 32)

#error("Height incorrect, please fix Adafruit_SSD1306.h!");

#endif

 

 

char primer='-';

char segundo='-';

char tercero='-';

char cuarto='0';

char quinto='0';

char writing=0;

int val=0;

 

 

 

 

/**** In most cases, you do not have to change anything below this line ****/

 

/* Instantiate a ProtocolParser object to parse the DCS-BIOS export stream */

DcsBios::ProtocolParser parser;

 

void setup() {

Serial.begin(500000);

 

 

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

 

display.clearDisplay();

}

 

 

 

/*

Your main loop needs to pass data from the DCS-BIOS export

stream to the parser object you instantiated above.

 

It also needs to call DcsBios::PollingInput::pollInputs()

to detect changes in the state of connected controls and

pass them on to DCS.

*/

void loop() {

char pepe[6];

// feed incoming data to the parser

while (Serial.available()) {

parser.processChar(Serial.read());

}

 

// poll inputs

DcsBios::PollingInput::pollInputs();

 

sprintf(pepe, "%c%c%cA%c", primer, segundo, tercero, cuarto, quinto);

 

writing=1;

 

display.clearDisplay();

display.setTextSize(3);

display.setTextColor(WHITE);

display.setCursor(30,5);

display.write(primer);

display.write(segundo);

display.write(tercero);

display.write(cuarto);

display.write(quinto);

//display.println();

display.display();

 

delay (75);

writing=0;

 

}

 

/*

You need to define

void sendDcsBiosMessage(const char* msg, const char* arg)

so that the string msg, followed by a space, the string arg

and a newline gets sent to the DCS-BIOS import stream.

 

In this example we send it to the serial port, so you need to

run socat to read the data from the serial port and send it

over UDP to DCS-BIOS.

 

If you are using an Ethernet Shield, you would probably want

to send a UDP packet from this subroutine.

*/

void sendDcsBiosMessage(const char* msg, const char* arg) {

Serial.write(msg);

Serial.write(' ');

Serial.write(arg);

Serial.write('\n');

}

 

char mapeo(unsigned int valor){

 

 

if (valor < 6553) { return '0'; }

if (valor < 13107) { return '1'; }

if (valor < 19660) { return '2'; }

if (valor < 26214) { return '3'; }

if (valor < 32767) { return '4'; }

if (valor < 39321) { return '5'; }

if (valor < 45874) { return '6'; }

if (valor < 52428) { return '7'; }

if (valor < 58981) { return '8'; }

return '9' ;

 

 

}

 

/*

This subroutine gets called every time a message is received

from the export stream (you need to define it even if it

does nothing).

 

Use this to handle outputs which are not covered by the

DcsBios Arduino library (e.g. displays).

*/

void onDcsBiosWrite(unsigned int address, unsigned int value) {

 

 

if (!writing){

if (address == 0x1080) {

primer=mapeo(value);

}

else if (address == 0x1082) {

segundo=mapeo(value);

}

else if (address == 0x1084) {

tercero=mapeo(value);

}

 

 

 

}

}

Link to comment
Share on other sites

Hint: use

 tags for source code, makes it a lot easier to read by using a monospace font and also disables smileys.

Can't view the video, but I assume what happens here is that in flight, the receive buffer fills up while you are writing to the display, which leads to incoming data being dropped on the floor, confusing the protocol parser, and ending up with garbage on the display.

It does not happen on the ground because the receive buffer is large enough to handle the smaller amount of data that is being sent (in the air, a lot more values are changing all the time).

Try using the Arduino Library in the new rs485 branch on GitHub. See [url= http://forums.eagle.ru/showpost.php?p=2636130&postcount=194]this post[/url] for more information. You can download that as a .zip archive here:
[url]https://github.com/dcs-bios/dcs-bios-arduino-library/archive/rs485.zip[/url]

You will have to change the baud rate in connect-serial-port.cmd to 250000, that's the new standard.

The new interrupt-based communication handling is designed to solve this exact problem (only works on ATMega328-based controllers at the moment).

I'll try to edit a code example into this post later.
EDIT: with the new library, you could try this code:
[code]
// tell DCS-BIOS we want interrupt-based serial comms. How to do this will probably change in the future.
#define DCSBIOS_IRQ_SERIAL

#include <DcsBios.h>
#include <Servo.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_MOSI   9
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

char* displayString = "---00";

// onDcsBiosWrite does not exist anymore, use Int16Buffers instead
DcsBios::Int16Buffer alt10000ftCounter(0x1080);
DcsBios::Int16Buffer alt1000ftCounter(0x1082);
DcsBios::Int16Buffer alt100ftCounter(0x1084);

void setup() {
 
 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  
 display.clearDisplay();
 
 DcsBios::setup();
}


void loop() {
 DcsBios::loop();
 
 if (alt10000ftCounter.hasUpdatedData()) { displayString[0] = mapeo(alt10000ftCounter.getData()); }
 if (alt1000ftCounter.hasUpdatedData()) { displayString[1] = mapeo(alt1000ftCounter.getData()); }
 if (alt100ftCounter.hasUpdatedData()) { displayString[2] = mapeo(alt100ftCounter.getData()); }
 
 display.clearDisplay();
 display.setTextSize(3);
 display.setTextColor(WHITE);
 display.setCursor(30,5);
 display.print(displayString);
 display.display();

 delay (75);

}

char mapeo(unsigned int valor){


 if (valor < 6553) { return '0'; }
 if (valor < 13107) { return '1'; }
 if (valor < 19660) { return '2'; }
 if (valor < 26214) { return '3'; }
 if (valor < 32767) { return '4'; }
 if (valor < 39321) { return '5'; }
 if (valor < 45874) { return '6'; }
 if (valor < 52428) { return '7'; }
 if (valor < 58981) { return '8'; }
 return '9' ;
 

}


Edited by [FSF]Ian
Link to comment
Share on other sites

  • 4 years later...
Guys, is there an equivalent sketch available for I2C OLEDS?

 

Cheers

 

Les

 

The Adafruit_SSD1306 supports I2C displays a well so if youre display works with that you could use the same code, just change the display definitions and constructor.

 

eg replace

 

#define OLED_MOSI 9

#define OLED_CLK 10

#define OLED_DC 11

#define OLED_CS 12

#define OLED_RESET 13

Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

 

with something like

 

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)

#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

 

To find out what your display needs I'd try the I2C demos for the SSD1306 library and see what works for you.

Link to comment
Share on other sites

Hi guys, me yet again

As usual my issue is getting the sketches to work when the hardware is slightly different. I'm using a buysdisplay 0.96" 128 x 64 display, but I also want to use a 0.87" OLED module.

Trying to use the code above this is what I got to that works OK

// tell DCS-BIOS we want interrupt-based serial comms. How to do this will probably change in the future.
#define DCSBIOS_IRQ_SERIAL

#include <DcsBios.h>

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

char* displayString = "---";

// onDcsBiosWrite does not exist anymore, use Int16Buffers instead
DcsBios::Int16Buffer alt10000ftCounter(0x1080);
DcsBios::Int16Buffer alt1000ftCounter(0x1082);
DcsBios::Int16Buffer alt100ftCounter(0x1084);

void setup() {
 
 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  
 display.clearDisplay();
 
 DcsBios::setup();
}


void loop() {
 DcsBios::loop();
 
 if (alt10000ftCounter.hasUpdatedData()) { displayString[0] = mapeo(alt10000ftCounter.getData()); }
 if (alt1000ftCounter.hasUpdatedData()) { displayString[1] = mapeo(alt1000ftCounter.getData()); }
 if (alt100ftCounter.hasUpdatedData()) { displayString[2] = mapeo(alt100ftCounter.getData()); }
 
 display.clearDisplay();
 display.setTextSize(6);
 display.setTextColor(WHITE);
 display.setCursor(5,0);
 display.print(displayString);
 display.display();

 delay (75);

}

char mapeo(unsigned int valor){


 if (valor < 6553) { return '0'; }
 if (valor < 13107) { return '1'; }
 if (valor < 19660) { return '2'; }
 if (valor < 26214) { return '3'; }
 if (valor < 32767) { return '4'; }
 if (valor < 39321) { return '5'; }
 if (valor < 45874) { return '6'; }
 if (valor < 52428) { return '7'; }
 if (valor < 58981) { return '8'; }
 return '9' ;
 

}

 

This works on the 0.96" module, with a max text size of 6, anything bigger and it clips. However the numerals displayed are very crude and blockish, presumably due to the bitmap character library being equally crude, so I would like to know if there is a better library I can use for this.

 

It also strangely will not load on a Nano board, with an error message that it is too big coming up. I have it on an Uno board, on which it works fine. Is there something that I can do to reduce it so that it fits on the Nano? **EDIT** tried on another Nano board and it compiled fine - no idea why

 

Lastly I tried with the 0.87" module, and there things get a bit weird. I can get it to display by reducing the character size, but it displays the characters back to front, by which I mean it looks like you are looking at them in a mirror. As I want to modify the sketch for use with the Fuel Quantity indication and the pressure indication, I need this to display correctly, so does anyone have any ideas what is causing it?

 

This video here shows what I would ultimately like to do

 

 

The scrolling of the digits is a great touch, and I downloaded the sketch and the bespoke libraries, and tried to reverse engineer what he had done with what I managed to get working above, this sketch being the result. I worked through a load of the error messages by installing some libraries within the Adafruit one

 

/*
Based on the Adafruit_SSD1306 library demo and the DCS-BIOS template sketch.

This is meant to be compiled with Energia and to run on a
Texas Instruments Tiva C Series Launchpad board.

It should run on an Arduino (adjust the #defines accordingly
to specify the pins you used), but I have not tested whether
the 16 MHz AVR is fast enough.
The Tiva C Launchpad has an 80 MHz ARM processor.

The fonts are not perfectly aligned because they were made
in a hurry to get a proof of concept...

*/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DcsBios.h>
#include <Servo.h>

#include "digits_32x64.cpp"
#include "digits_00_32x64.cpp"
#include "digits_1to9_32x64.cpp"

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// If using software SPI (the default case):
//#define OLED_MOSI  PE_1
//#define OLED_CLK   PE_2
//#define OLED_DC    PD_3
//#define OLED_CS    PB_7
//#define OLED_RESET PD_2
//Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

DcsBios::ProtocolParser parser;

void drawDigit(unsigned int index, unsigned int offset, unsigned char* bits) {
 //double y_offset = (double)offset / 65535.0d;
 //unsigned int y_offset_lines = y_offset * 640;
 unsigned int y_offset_lines = offset / 103;
  display.fillRect(32*index, 0, 32, 64, BLACK);
  display.drawXBitmap(32*index, 0, &bits[4*y_offset_lines], 32, 64, WHITE);
  display.display();   
}

void setup()   {                
 //Serial.begin(500000);
 
 display.begin(SSD1306_SWITCHCAPVCC);

 display.clearDisplay();
 drawDigit(0, 0, digits_1to9_32x64_bits);
 drawDigit(1, 0, digits_32x64_bits);
 drawDigit(2, 0, digits_32x64_bits);
 drawDigit(3, 0, digits_00_32x64_bits);
}


void loop() {
 while(Serial.available()) parser.processChar(Serial.read());
}

void onDcsBiosWrite(unsigned int address, unsigned int value) {
 address = address & 0xffff;
 value = value & 0xffff;
 if (address == 0x1080) {
   unsigned int alt10000ftCntValue = (value & 0xffff) >> 0;
   drawDigit(0, alt10000ftCntValue, digits_1to9_32x64_bits);
 }
 
 if (address == 0x1082) {
   unsigned int alt1000ftCntValue = (value & 0xffff) >> 0;
   drawDigit(1, alt1000ftCntValue, digits_32x64_bits);
 }
 
 if (address == 0x1084) {
   unsigned int alt100ftCntValue = (value & 0xffff) >> 0;
   drawDigit(2, alt100ftCntValue, digits_32x64_bits);
 }
}

 

Unfortunately it just gives errors at the end, saying it's unable to compile for either of the arduinos, which is a shame as it would have been great to have a working version

 

Cheers

 

Les


Edited by lesthegrngo
Link to comment
Share on other sites

  • Recently Browsing   0 members

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