Categories
Uri_ba's pit

DED Adventures – Part 2 – Tech post

Let’s talk about a bit about the technical stuff. I think that going over the technical aspects will make some sense, and naturally help others in their quest.

I’ll have posts like that from time to time, covering technical aspects of the project. Which means that code examples, circuit schematics and random technical mambo jumbo are all legit in this type of posts.

So lets begin….

As all things in life, our challange is made out of 3 parts.
1. Getting the data out of the game.
2. Getting the data to the Arduino.
3. Display the data visually (i.e Driving the hardware).

let’s start from item 1.
Falcon for a long time has supported exported data via Shared Memory. there is a library for C# written by Lightning using it will save me a lot of tinkering with things I know nothing about (I’m not a programmer).

the SharedMem data structure is described on the “FlightData.h” file located in BMS doc folder – But we will go over that in a future post.

For simplicity I’ll focus on the FuelFlow in this post, as the solution for the DED is a bit more complex and I want to cover the basics here.
FuelFlow is easy and straight forward

float fuelFlow; // Ownship fuel flow (Lbs/Hour)

Now Let’s get  the data.

We will need to define the Objects that will interact with the sharedMem:

public F4SharedMem.Reader BMSreader = new F4SharedMem.Reader();
public FlightData BMSdata = new FlightData();

Then we will just get the relevant data,
Fuelflow is easy, but it’s in float, so we’ll need to convert it to a string to be sent over.
That means sending 5 bytes and not one (unsinged int) but that’s a tread off for displaying the data – well get to that.

public string FuelFlowConvert(float FuelFlow)
  {
    return (Math.Round(Convert.ToDecimal(FuelFlow) / 10) * 10).ToString();
  }

Now we will continue to “step 2” getting the data over to the Arduino.
let’s talk about how we use Serial communication to get the data over.
ALL the tutorials I’ve found about that all revolved around using interrupts, finding end of strings and so on. that works fine, on small scale of data, but as we will get more and more data, your will find that this technique have some major draw back, the first is the need to know what piece of data goes where, the second, the computer is much faster then the arduino, and this is based on data push, which means the Arduino will be overwhelmed with data, and will not be able to do anything.

instead I opted to use a different technique using a pull, the arduino will request a specific set of data using a control character, and recive the data it expects.  exactly what we expect. that is done by using the readBytes() command which allows us to specify the exact number of bytes we want to receive.

// Define FuelFlow Global variable
char FuelFlow[5];

void readFF() {
  Serial.print('F');
  Serial.flush();
  Serial.readBytes(FuelFlow, 5) ;
}

On the other side there is a function that sends out the fuelflow data

void dedDevice_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
                SerialPort sp = (SerialPort)sender;
                string s = sp.ReadExisting();

                bool PowerOn = hsiBits[31]; // test isFlying bit
                char mode;
                try
                {
                    mode = s[0];
                }
                catch
                {
                    return;
                }

                switch (mode)
                {
                    case 'F':
                        if (PowerOn)
                        {
                            sendLine(FuelFlowConvert(BMSdata.fuelFlow).PadLeft(5, '0'), 5);
                        }
                        else
                        {
                            sendLine("0".PadRight(6, '0'), 5); // if we are not flying send "00000"
                        }
                        break;
                }

        }

private void sendLine(string sendThis, int length)
  {
    byte[] sendBytes = Encoding.GetEncoding(1252).GetBytes(sendThis); // Encoding must be changed to allow the ANSI.
    dedDevice.Write(sendBytes, 0, length);
  }

now that the Arduino has the data, we can display it.
we can use any screen now, I chose Adafruit 1.3″ OLED because it’s in the correct size, and it will allow me to create the fuelflow scroll animation.
it’s using u8glib library and this is the code to drive it.

void drawFF() {
  // break FuelFlow to segments for scroll animation
  // the thousands are static entries. insert them to their own char array
  char FFT[2];
  FFT[0] =  FuelFlow[0];
  FFT[1] =  FuelFlow[1];

  // get hundred digit
  char FFh = FuelFlow[2];
  // Now for the animation  find the previous next two digits.
  char FFhPriv;
  if (FuelFlow[2] == 48) {
    FFhPriv = 57;
  } else {
    FFhPriv = FuelFlow[2] - 1;
  }

  char FFhNext;
  if (FuelFlow[2] == 57) { //a
    FFhNext = 48;
  } else {
    FFhNext = FuelFlow[2] + 1;
  }

  char FFhTwoOver;
  if (FFhNext == 57) {
    FFhTwoOver = 48;
  } else {
    FFhTwoOver = FFhNext + 1;
  }

  // use tens digit to calculate the off set for animation (tens and singles are alway 0 on the guage)
  short offset = short((FuelFlow[3] - 48) * FF_CHAR_H / 10); //it's a char - Ascii value of '0'
  /// Begin Picture loop ///
  ffDisp.firstPage();
  do {
    // thousands and tens of thousands
    ffDisp.drawStr((FF_CHAR_W * 1) + FF_H_CONST, short(FF_CHAR_H * 1) + FF_V_CONST, FFT);

    // print the animation
    ffDisp.setPrintPos((FF_CHAR_W * 3) + FF_H_CONST, short((FF_CHAR_H * -1)) + offset + FF_V_CONST);
    ffDisp.print(FFhTwoOver);
    ffDisp.setPrintPos((FF_CHAR_W * 3) + FF_H_CONST, short((FF_CHAR_H * 0)) + offset + FF_V_CONST);
    ffDisp.print(FFhNext);
    ffDisp.setPrintPos((FF_CHAR_W * 3) + FF_H_CONST, short((FF_CHAR_H * 1)) + offset + FF_V_CONST);
    ffDisp.print(FFh);
    ffDisp.setPrintPos((FF_CHAR_W * 3) + FF_H_CONST, short((FF_CHAR_H * 2)) + offset + FF_V_CONST);
    ffDisp.print(FFhPriv);

    ffDisp.drawStr((FF_CHAR_W * 4) + FF_H_CONST, short(FF_CHAR_H * 1) + FF_V_CONST, "00");
  } while ( ffDisp.nextPage() );
  /// End Picture loop ///
}

And That’s it for this part. I hope it helped – and I’ll see you on the next post 🙂

Leave a Reply