Adrian_gc Posted January 14, 2016 Share Posted January 14, 2016 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 More sharing options...
BravoYankee4 Posted January 14, 2016 Share Posted January 14, 2016 You need to change the video security settings, since they are now "private" and can't be viewed. Link to comment Share on other sites More sharing options...
FSFIan Posted January 14, 2016 Share Posted January 14, 2016 (edited) 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 January 14, 2016 by [FSF]Ian DCS-BIOS | How to export CMSP, RWR, etc. through MonitorSetup.lua Link to comment Share on other sites More sharing options...
Gadroc Posted January 14, 2016 Share Posted January 14, 2016 You're problem is the baud rate. 500k baud is to fast for the Arduino to keep up with. Change Serial.bevin(500000h) to Serial.begin(250000) and make a similar change in the software you're using to relay dcsbios to the serial port. Link to comment Share on other sites More sharing options...
Gadroc Posted January 14, 2016 Share Posted January 14, 2016 Also you should only update the display on a frame end, unless you move to the newer library Ian posted. Link to comment Share on other sites More sharing options...
lesthegrngo Posted January 14, 2020 Share Posted January 14, 2020 Guys, is there an equivalent sketch available for I2C OLEDS? Cheers Les Link to comment Share on other sites More sharing options...
Matchstick Posted January 14, 2020 Share Posted January 14, 2020 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 More sharing options...
lesthegrngo Posted January 15, 2020 Share Posted January 15, 2020 Thanks, will have a bash at that Cheers Les Link to comment Share on other sites More sharing options...
lesthegrngo Posted January 18, 2020 Share Posted January 18, 2020 (edited) 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 January 18, 2020 by lesthegrngo Link to comment Share on other sites More sharing options...
Recommended Posts