All, I have an OLED display which shows the numerical output from a computer program, which gives values ranging from 0 to 65535. It is supposed to be a linear progression, however the OLED shows that there is some erratic noise being injected somewhere, which causes the numbers to corrupt for a split second.
In itself the noise is not an issue for most of the time, as it is used for a signal to a stepper motor driving a pointer representing an altimeter gauge, however the OLED display is supposed to represent the digital version of the gauge and it flickers and jumps, an annoyance.
Is there a way of smoothing the signal within the arduino sketch?
For reference here is the sketch (sorry, sketch didn't copy correctly)
#define DCSBIOS_DEFAULT_SERIAL
#include <DcsBios.h>
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
U8G2_SSD1306_128X64_ALT0_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
void setup() {
u8g2.begin();
DcsBios::setup();
}
void onAlt100ftChange(unsigned int newValue) {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_fub20_tn );
//u8g2.setTextSize(2);
u8g2.setCursor(0, 24);
u8g2.print(newValue);
u8g2.sendBuffer();
delay (5);
}
DcsBios::IntegerBuffer alt100ftBuffer(0x107e, 0xffff, 0, onAlt100ftChange);
void loop() {
DcsBios::loop();
}
Cheers
Les
What code?
You could use averaging.
Or a complimentary filter.
Thanks, looking up averaging right now!
Cheers
Les
A simple solution would be to store the altitude value and check that the new value isn't too different by some margin. If it is, ignore it.
Hi Wildbill, if it is simpler it would be better. Is it similar to averaging? I've just printed off the code showing the averaging to digest it
Cheers
Les
Can the noise not be eliminated? More info on your setup would be helpful.
You might tray a capacitor/filter on the analog input.
Or, [u]Smoothing Example[/u] (moving average).
You'll probably want a longer delay and if delay() causes problems in your application you can use a millis() delay. (See the Blink Without Delay Example.)
You can update the display more slowly than you run the smoothing loop. You wouldn't want to update the digital display more than a few times per second because it becomes impossible to read.
You could also use some "fuzzy logic" to throw-away outlier readings or to limit the change between two adjacent readings, etc.
MK1888:
Can the noise not be eliminated? More info on your setup would be helpful.
The intent is to use the output from a program called DCS BIOS, which reads in game data from DCS World aircraft simulator in order to output a stream of data to an Arduino that can be used to drive stepper motors for gauges, LCD displays, OLED displays, LED's TFT's, etc in order to simulate real world gauges. Here's the site if you are interested
http://dcs-bios.a10c.de/
The problem is that I have no way of getting in between the signal from the PC and the Arduino, as it is a direct USB connection
I've attached a picture of the cockpit I'm building, and here you can see the effect https://youtu.be/xn44cSU3Gfc
the OLED number is glitching as it is able to display the numbers faster than the LCD
And here is the effect it has on the Altimeter when it is working (about 30 seconds in)
If I can smooth the signal that is being used by the Arduino to output the number to the OLED, I am hoping it will cure the glitching
Apologies for not being super informed on how it works, DSC BIOS was written by some clever guys for us to be able to use for stuff like this, but it was an amateur project and I believe development on it has stopped, so we have what we have. Engineers like me can use it as they generally made it simple to incorporate, but when it has issues we struggle.
It is easy enough though that most of the gauges and displays you see in the picture actually work
Cheers
Les
wildbill:
A simple solution would be to store the altitude value and check that the new value isn't too different by some margin. If it is, ignore it.
Edited for clarity
After reading up on the smoothing, to my engineers mind the idea of ignoring corrupt numbers seems a better solution; averaging would still have the display just to a higher or lower reading then back again, whereas ignoring a value out of a certain range would simply delay the step to the next number, which would be unnoticeable if all it did was delay the change by 0.1 of a second or less
Cheers
Les
If you're getting updates at 10Hz, you know from the max rate of climb and descent how much it's feasible for the altitude to have changed in a tenth of a second. Add a bit of extra margin and just check against those two numbers to see whether what DCS sent you is credible.
Is this a known issue to DCS users? Is it just the 100ft change that's broken? If so, perhaps you can drive the display off one of the other altitude packets.
From what I gather, I believe that the signal is refreshed much faster than that, it's just that 5 milliseconds seems to be used in many sketches as the refresh rate for many displays.
Other DCS Bios users have reported this and replicated what I see - but of course there are not that many that are as mad as me, many utilise LCD monitors to replicate the Altimeter as it has a constantly rotating pointer, as opposed to a limited range one. This means that the gauge has to be fitted with something to zero the pointer ( in my case an IR optocoupler), and the complications mean that it is easier to use a program like Ikarus or Helios and a small monitor. That allows them to display the gauge virtually on their dash, and of course that incorporates a virtual digital gauge too. As it is essentially just a second screen, it replicates the on screen information on a secondary display - hence no issues with OLEDS.
I am having to use LCD monitors for the two MFCD's (Multi Function Centralised Displays) as they really are monitors in real life, and for the attitude indicator (artificial horizon) and radar warning indicators, hence the two smaller monitors in the centre and just left of centre. Both the latter items would be light years ahead of my engineering skills to manufacture.
Where I can I want to try and replicate the real thing though.
So the idea of the sketch comparing and ignoring values interests me, is there a tutorial available or sample sketch I can look at to help me see if I can splice it in?
Cheers
Les
Something like this:
const unsigned int AltitudeChangeThreshold=100; // Tweak this
void onAlt100ftChange(unsigned int newValue)
{
static bool HaveAltitude=false;
static unsigned int Altitude;
if(HaveAltitude)
{
if(abs(newValue-Altitude) <= AltitudeChangeThreshold)
{
Altitude = newValue;
}
}
else
{
Altitude = newValue;
HaveAltitude=true;
}
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_fub20_tn );
//u8g2.setTextSize(2);
u8g2.setCursor(0, 24);
u8g2.print(Altitude);
u8g2.sendBuffer();
delay (5);
}
Not compiled or tested.
Thanks, let me play around with this and see if it helps!
Cheers
Les
It occurs to me that relying abs when using unsigned quantities was a little... foolish.
This should be better:
const unsigned int AltitudeChangeThreshold=100; // Tweak this
unsigned int difference(unsigned int a,unsigned int b)
{
if(a>b)
return a-b;
else
return b-a;
}
void onAlt100ftChange(unsigned int newValue)
{
static bool HaveAltitude=false;
static unsigned int Altitude;
if(HaveAltitude)
{
if(difference(newValue,Altitude) <= AltitudeChangeThreshold)
{
Altitude = newValue;
}
}
else
{
Altitude = newValue;
HaveAltitude=true;
}
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_fub20_tn );
//u8g2.setTextSize(2);
u8g2.setCursor(0, 24);
u8g2.print(Altitude);
u8g2.sendBuffer();
delay (5);
}
Thanks again - I am still working on getting the original code into the sketch I'm using so once I've figured that out I'll try both to compare
Cheers
Les
All, another guy with the same problem as me has been helping with this, and we have been doing some more in depth testing.
We now believe that the output from the DCS bios program is stable and correct, and that whatever is happening to the display is a result of how the sketches process the data or the interaction between the sketch and the OLED devices.
We did a battery of tests to try and isolate where the source of the glitching could be, after trying various things including trying to average the signal. One point that appeared was that we noticed the OLED display glitching even when the signal was static.
The unstable output appears to be a false lead, as when multiple instances of the same display device are put in, both reading the same output signal, they behave differently and display different data.
One was moved from a Nano to a Mega to see if it was memory issues, but it made no difference.
As a result we are forced to conclude that the glitch resides somewhere in the sketches, and not with the output from DCS Bios
I'd like to say thanks to those who tried to help here, and that ultimately we appeared to be asking the wrong questions, nonetheless there was some great help given
If we come back to this we have to make sure we aren't being fooled into chasing erroneous assumptions
Thanks again
Les
As ever, it will probably help to write something simpler to test what you've discovered. Not easy in this case as it's pretty minimal already.
Can you reduce the frequency of the DCS update and drop the LCD and just echo to serial whatever DCS sends you?
The output from DCS is what it is at the moment, and as you state the sketch itself is pretty simple so it's difficult to simplify it further.
The guys who is helping me look into this problem has the working theory that the transmission rate and the needs of the of the conversion sketch are such that it is overwhelming the capabilities of the Arduino. He's working on trying to split up the duties by using one Arduino to process the signal and reduce it so that a second Arduino can be fed a lower data rate stream that it can then process more easily into the OLED output. That's a bit out of my league, thankfully he has a better idea of what he is doing than I do!
Interestingly, a similar sketch applied to an LCD character module doesn't have any issues, it does seem to be an OLED specific issue (and affects all the resolution modules we tried, those being 64 x 32, 128 x 32 and 128 x 64). Unfortunately the LCD modules are ill suited to this application, the OLED modules being perfect for what we are trying to achieve, with the minor drawback of not doing it properly....
Again I thank you for the input, and if we do manage to define a solution, or at least identify the cause I'll put it here for reference
Cheers
Les
Lesthegringo:
The guys who is helping me look into this problem has the working theory that the transmission rate and the needs of the of the conversion sketch are such that it is overwhelming the capabilities of the Arduino. He's working on trying to split up the duties by using one Arduino to process the signal and reduce it so that a second Arduino can be fed a lower data rate stream that it can then process more easily into the OLED output. That's a bit out of my league, thankfully he has a better idea of what he is doing than I do!
Rather than introduce a two CPU solution, I'd be inclined to fix it on the one. It sounds as though the OLED display (or at least its library) is slow. I'd try to make your solution a bit more clever.
If DCS is spamming you, the first thing to do is only update if the value has changed. If that's not enough, only update the OLED every tenth of a second or whatever frequency gets you to stable readings; which is what your colleague is going to do for you with the second Arduino.
Another consideration is that it's likely that not all the digits of the altitude have changed. It may be possible to only touch those that have.
Well, we (I say we, I actually mean a clever chap in Sweden) resolved it. I said I would report it here if we did.
It was indeed a data issue, changing the following line
#define DCSBIOS_DEFAULT_SERIAL
to
#define DCSBIOS_IRQ_SERIAL
basically cleaned it up. The explanation given was that "using DCSBIOS_DEFAULT_SERIAL will work on the vast majority of Arduino-compatible boards, but you can get corrupted data if you have too many or too slow outputs (e.g. when you have multiple character displays), because the receive buffer can fill up if the sketch spends too much time updating them.
If you can, use the IRQ Serial connection instead."
So we have smooth data flow and OLED displays now
Cheers
Les