Welcome to Cockpitbuilders.com. Please login or sign up.

December 12, 2024, 07:49:58 AM

Login with username, password and session length

PROUDLY ENDORSING


Fly Elise-ng
24 Guests, 0 Users
Members
Stats
  • Total Posts: 59,698
  • Total Topics: 7,866
  • Online today: 23
  • Online ever: 831
  • (May 03, 2024, 12:39:25 PM)
Users Online
Users: 0
Guests: 24
Total: 24

COUNTDOWN TO WF2024


WORLDFLIGHT TEAM USA

Will Depart in...

Recent

Welcome

flap indicator interface with Fs9

Started by Mach7, August 03, 2023, 04:23:14 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ame

I hope it works, but keep the old code around just in case.

Mach7

Sorry @ame, had some issues logging on last nite

The flaps work perfectly!! Absoulutley smooth as glass, with zero stutter.

Is there a line in the code I can change to make the fuel gauges move even slower to there requested values? they could actually move as slow as the flaps.

Thank you again!!

Jim

ame

I'm glad to hear the improvement to flaps actually works. I wasn't sure how it would look.

I used two different damping techniques. One for flaps, one for fuel. So there's not really anything you can change that will make them act the same way. Sorry.

What I can do is rewrite the code so that I am using the same technique for both.

You can see in the code there is the routine that gets new data from link2fs coming in via the serial port. This updates the target value that the gauge will point to. Then there is some other code that does something every tenth of a second.

For flaps there is a limit for how far the needle can move in a tenth of a second. It is set so that the needle can only move the equivalent of reaching the 33 degree position in 35 seconds.

For fuel you said that they jumped up to the target position too quickly. I took that to mean if you had 8000 lbs of fuel and you started the simulator the needle would jump straight to 80. What I did here is to have a running average filter so that the needle is only allowed to jump one quarter of the way every tenth of a second.

So, at 0.1s it jumps to 20 (which is quarter of 80). At 0.2s it jumps to 35 (the remaining distance is 60, so a quarter is 15). At 0.3s it jumps to 46. At 0.4s it jumps to 55, and so on. The idea being that it slows down as it reaches the target. The needle will take about one second to hit the target, instead of jumping straight there.

But, if a real fuel gauge moves from zero to 80 very linearly, and very slowly, I can do that. If you want it to move in the same manner as the flaps gauge, I can do it.

Mach7

Hello ame...yes...Slowing the gauge movement would be a perfect example or what they would indicate whilst pressure re fuelling, they would move about as fast as the flap gauge moves now...that would actually be a plus because it would simulate a real scenario.

Thank you again

Jim

ame

You probably got a notification of a new message, although maybe not because it's not working for me.

Anyway, I've been a bit busy, sorry, but I will do this, and soon.

Just wanted to drop a note to say so.

Mach7

No problem ame...actually just sending a note to thank you for all your work and effort on this project. It is so nice to have functional..real time fuel gauges in the sim!!

I will post some video's soon.

Jim

ame

Ok. Try this.

Quote/*
    This code is in the public domain
    For use with "Link2fs_Multi"
    Jimspage.co.nz (via archive.org)
*/

int CodeIn;// used on all serial reads

String flaps;
String fuel;    // Re-use this variable for all fuel gauges as we only do one at a time

// PWM pins for gauges.
// Must be one of 3, 5, 6, 9, 10, or 11 for Arduino Uno
// Flaps
int flaps_PWM_out_pin = 3;
// Fuel
int fuel_L_PWM_out_pin = 5; // Left fuel gauge
int fuel_C_PWM_out_pin = 6; // Centre fuel gauge
int fuel_R_PWM_out_pin = 9; // Right fuel gauge

// Variables for fuel gauges
float fuel_L_lbs;
float fuel_C_lbs;
float fuel_R_lbs;
// Record last needle position for damping
float filtered_fuel_L_lbs;
float filtered_fuel_C_lbs;
float filtered_fuel_R_lbs;
// Can be reused for each gauge as we do one at a time.
float fuel_percent;
int fuel_PWM_out;

// Variables for flaps
float flaps_degrees;
float filtered_flaps_degrees;
int flaps_PWM_out;

     
// Variables to support incremental update of gauges
unsigned long currentMillis;
unsigned long previousMillis;
unsigned long period = 100; // 100millis = 0.1s, 10 updates per second

// Variables for damping gauges
// The gauge on the simulator travels from 0 to 33 degrees in about 35 seconds
// But the simulator only reports integer degrees.
// Introduce fractional degrees for the physical gauge so that it
// moves smoothly between integer degree positions.
// Similarly, the simulator reports integer percentage of tank full.
// We convert to lbs, and allow the lbsx100 gauge to move at limited speed.
const float flaps_max_degrees_per_period = 0.0943; // Maximum amount we can move in 0.1s
const float fuel_max_lbs_per_period = 3000; // Maximum amount we can move in 0.1s


void setup()
{
  Serial.begin(115200);
 
  // Set up PWM pins.
  pinMode(flaps_PWM_out_pin, OUTPUT);

  pinMode(fuel_L_PWM_out_pin, OUTPUT);
  pinMode(fuel_C_PWM_out_pin, OUTPUT);
  pinMode(fuel_R_PWM_out_pin, OUTPUT);

  // Set PWM values to zero.
  analogWrite(flaps_PWM_out_pin, 0);

  analogWrite(fuel_L_PWM_out_pin, 0);
  analogWrite(fuel_C_PWM_out_pin, 0);
  analogWrite(fuel_R_PWM_out_pin, 0);
 
  // Start all filtered values at zero.
  // If the simulator is already running, or the initial value
  // reported is not zero then it will take a while for the
  // gauges to match reality.
  filtered_flaps_degrees = 0;

  filtered_fuel_L_lbs = 0;
  filtered_fuel_C_lbs = 0;
  filtered_fuel_R_lbs = 0;

}


void loop() {
  // Deal with incoming data from link2fs
  if (Serial.available()) {
    CodeIn = getChar();
    if (CodeIn == '=') {EQUALS();} // The first identifier is "="
    if (CodeIn == '<') {LESSTHAN();}// The first identifier is "<"
    if (CodeIn == '?') {QUESTION();}// The first identifier is "?"
    if (CodeIn == '/') {SLASH();}// The first identifier is "/" (Annunciators)
  }

  // Other tasks
  // Smooth the needle output.
  currentMillis = millis(); // store the current time
  if (currentMillis - previousMillis >= period) { // check if 100ms passed
    // We're on a 100ms boundary
    previousMillis = currentMillis;   // update the time we were here

    // flaps_degrees is updated elsewhere when new data arrives.
    // Filter the gauge needle position slowly over time.

    if (flaps_degrees > filtered_flaps_degrees) {
      filtered_flaps_degrees += flaps_max_degrees_per_period;
      if (filtered_flaps_degrees > flaps_degrees) filtered_flaps_degrees=flaps_degrees;
    }
    else if (flaps_degrees < filtered_flaps_degrees) {
      filtered_flaps_degrees -= flaps_max_degrees_per_period;
      if (filtered_flaps_degrees < flaps_degrees) filtered_flaps_degrees = flaps_degrees;
    }
    else {
      // target and current are equal. Nothing to do.
    }
   
    // Convert degrees to PWM 0-255.
    // 33 degrees is full scale, so multiplier is 255/33=7.727   
    flaps_PWM_out = filtered_flaps_degrees*7.727;
   
    analogWrite(flaps_PWM_out_pin, flaps_PWM_out);
   
    // Now update the fuel gauges.
    // Yes, this should be done as an array...

    // Left
    if (fuel_L_lbs > filtered_fuel_L_lbs) {
      filtered_fuel_L_lbs += fuel_max_lbs_per_period;
      if (filtered_fuel_L_lbs > fuel_L_lbs) filtered_fuel_L_lbs = fuel_L_lbs;
    }
    else if (fuel_L_lbs < filtered_fuel_L_lbs) {
      filtered_fuel_L_lbs -= fuel_max_lbs_per_period;
      if (filtered_fuel_L_lbs < fuel_L_lbs) filtered_fuel_L_lbs = fuel_L_lbs;
    }
    else {
      // target and current are equal. Nothing to do.
    }

    // Centre
    if (fuel_C_lbs > filtered_fuel_C_lbs) {
      filtered_fuel_C_lbs += fuel_max_lbs_per_period;
      if (filtered_fuel_C_lbs > fuel_L_lbs) filtered_fuel_C_lbs = fuel_C_lbs;
    }
    else if (fuel_C_lbs < filtered_fuel_C_lbs) {
      filtered_fuel_C_lbs -= fuel_max_lbs_per_period;
      if (filtered_fuel_C_lbs < fuel_C_lbs) filtered_fuel_C_lbs = fuel_C_lbs;
    }
    else {
      // target and current are equal. Nothing to do.
    }

    // Right
    if (fuel_R_lbs > filtered_fuel_R_lbs) {
      filtered_fuel_R_lbs += fuel_max_lbs_per_period;
      if (filtered_fuel_R_lbs > fuel_R_lbs) filtered_fuel_R_lbs = fuel_R_lbs;
    }
    else if (fuel_R_lbs < filtered_fuel_R_lbs) {
      filtered_fuel_R_lbs -= fuel_max_lbs_per_period;
      if (filtered_fuel_R_lbs < fuel_R_lbs) filtered_fuel_R_lbs = fuel_R_lbs;
    }
    else {
      // target and current are equal. Nothing to do.
    }

    fuel_PWM_out = ((filtered_fuel_L_lbs * 1.8) / 10000.0) + 75.0;
    if(fuel_PWM_out > 255) fuel_PWM_out = 255;
    analogWrite(fuel_L_PWM_out_pin, fuel_PWM_out);

    fuel_PWM_out = ((filtered_fuel_C_lbs * 1.8) / 10000.0) + 75.0;
    if(fuel_PWM_out > 255) fuel_PWM_out = 255;
    analogWrite(fuel_C_PWM_out_pin, fuel_PWM_out);

    fuel_PWM_out = ((filtered_fuel_R_lbs * 1.8) / 10000.0) + 75.0;
    if(fuel_PWM_out > 255) fuel_PWM_out = 255;
    analogWrite(fuel_R_PWM_out_pin, fuel_PWM_out);

  }

}


char getChar()// Get a character from the serial buffer
{
  while(Serial.available() == 0);// wait for data
  return((char)Serial.read());// Thanks Doug
}


void EQUALS(){      // The first identifier was "="
  CodeIn = getChar(); // Get another character
  switch(CodeIn) {// Now lets find what to do with it
    case 'A'://Found the second identifier
       //Do something
    break;
     
    case 'B':
       //Do something
    break;
     
    case 'C':
       //Do something
    break;
  }
}


void LESSTHAN(){    // The first identifier was "<"
  CodeIn = getChar(); // Get another character
  switch(CodeIn) {// Now lets find what to do with it
    case 'A'://Found the second identifier
       //Do something
    break;
     
    case 'B':
       //Do something
    break;
     
    case 'G': //Found the second identifier ("G" Flaps position)
      // Next three characters should be numeric
      flaps = "";
      flaps += getChar();
      flaps += getChar();
      flaps += getChar();
      // convert 3-character numeric string to a float
      // Expected range is 000 to 033
      flaps_degrees = flaps.toFloat();
      // Moving the needle will be done in the main loop.
    break;
   
    case 'X': // "X" left fuel gauge
      // Next three characters should be numeric
      fuel = "";
      fuel += getChar();
      fuel += getChar();
      fuel += getChar();
      // convert 3-character numeric string to a float
      // It's a percentage of full, where full is 9200 lbs (left)
      // Expected range is 000 to 100
      fuel_percent = fuel.toFloat();
      fuel_L_lbs = fuel_percent * 9200;
      // Moving the needle will be done in the main loop.
    break;

    case 'Y': // "Y" centre fuel gauge
      // Next three characters should be numeric
      fuel = "";
      fuel += getChar();
      fuel += getChar();
      fuel += getChar();
      // convert 3-character numeric string to a float
      // It's a percentage of full, where full is 4400 lbs (centre)
      // Expected range is 000 to 100
      fuel_percent = fuel.toFloat();
      fuel_C_lbs = fuel_percent * 4400;
      // Moving the needle will be done in the main loop.
    break;

    case 'Z': // "Z" right fuel gauge
      // Next three characters should be numeric
      fuel = "";
      fuel += getChar();
      fuel += getChar();
      fuel += getChar();
      // convert 3-character numeric string to a float
      // It's a percentage of full, where full is 9200 lbs (left)
      // Expected range is 000 to 100
      fuel_percent = fuel.toFloat();
      fuel_R_lbs = fuel_percent * 9200;
      // Moving the needle will be done in the main loop.
    break;
   
  }
 
}

void QUESTION(){    // The first identifier was "?"
CodeIn = getChar(); // Get another character
  switch(CodeIn) {// Now lets find what to do with it
    case 'A'://Found the second identifier
       //Do something
    break;
     
    case 'B':
       //Do something
    break;
     
    case 'C':
       //Do something
    break;
     }
}
void SLASH(){    // The first identifier was "/" (Annunciator)
  //Do something
}

Mach7

Thank you ame!!!

I will upload and test it out when I get home on Sat.. on another 4 day rotation:(

ame

No worries. I checked that it compiles and does something...

Mach7

@ame, thank you again for the code...it works perfectly, of course!

I have included a video...it starts off slow because I needed time to get back to the instructors panel and enter the fuel particulars.

https://www.youtube.com/watch?v=Fs60OvaKla4


Thank you again!!

Jim

ame

Excellent. I changed a couple of things, but the end result is what's important, so if you're happy then it's done!

This line can be altered to allow the needles to move faster:
const float fuel_max_lbs_per_period = 3000; // Maximum amount we can move in 0.1s

Do you want to do analog input for the flaps lever, or is the project done now?

Mach7

ame,

I think we can call this project complete! Everything works perfectly..thank  you again!.


Like the Website ?
Support Cockpitbuilders.com and Click Below to Donate