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

April 27, 2024, 11:13:34 AM

Login with username, password and session length

PROUDLY ENDORSING


Fly Elise-ng
500 Guests, 0 Users
Members
  • Total Members: 4,154
  • Latest: xyligo
Stats
  • Total Posts: 59,641
  • Total Topics: 7,853
  • Online today: 514
  • Online ever: 582
  • (January 22, 2020, 08:44:01 AM)
Users Online
Users: 0
Guests: 500
Total: 500

COUNTDOWN TO WF2022


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 4 Guests are viewing this topic.

ame

Perfect! Now an Arduino program that looks for "<", then "G", then pulls in three characters that are digits, convert the three digits to a number, multiply by the scaling factor*, then analogWrite(). Done!

I can picture the code. If you can't find an example that is close to this don't worry, I'll write something. Unfortunately it's Monday morning here in NZ, so I don't have so much free time today.

* I am assuming a linear relationship between the applied pwm value and the markings on the gauge. If it's not linear we can look at that later.

Mach7

Hello ame,, yes...i have been searching for code on GITHUB for something similar, but so far no luck. I think a lot of this is new territory as a lot of sim's are straight glass cockpits now.

I will keep looking for an example.

Thank you again

Jim

ame

How about the examples folder in link2fs?

ame

Here's something to look at:
https://github.com/maxime-a/Airspeed-Indicator-for-flight-simulation/blob/master/Multi_Keys_with_flaps_servo.ino

I don't know why the author refers to flaps with character "G" in the comments, but "P" in the code, but you can see the general structure of how it's done.

Read the incoming data stream. Find "<", jump to LESSTHAN. Find "P" (in your case should be "G"). Pull in three more characters. Convert to a number. Do stuff. Done.

I will use that example if you like, by stripping out everything but the flaps code.

It uses the Arduino string library, which is universally disliked, but it's such a small program it won't matter.

Mach7

ok...i guess whatever happens it can be modified with trial and error.

ame

Quote from: Mach7 on August 13, 2023, 12:57:46 PMok...i guess whatever happens it can be modified with trial and error.
Software development in a nutshell.

ame

#81
Ok. Try this. I decided to removed some unused code, but not all, so you can see the general structure. You could add code in the "Do something" sections if you decide to send other elements from link2fs.

Quote/*
    This code is in the public domain
    For use with "Link2fs_Multi"
    Jimspage.co.nz

*/


int CodeIn;// used on all serial reads
String flaps;

int flaps_PWM_out_pin = 3; // Must be one of 3, 5, 6, 9, 10, or 11 for Arduino Uno


void setup()
{
 Serial.begin(115200);
 // Set up PWM pin to drive flaps gauge
 pinMode(flaps_PWM_out_pin, OUTPUT);
 // Set PWM value to zero.
 analogWrite(flaps_PWM_out_pin, 0); 
}

void loop() {
  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)
  }

}

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
      float flaps_degrees = flaps.toFloat();
      // Convert degrees to PWM 0-255.
      // 33 degrees is full scale, so multiplier is 255/33=7.727
      int PWM_out = flaps_degrees*7.727;
      // Clip output to maximum if (for some reason) it's >255
      if(PWM_out > 255) PWM_out=255;
      // Drive the gauge by writing to the PWM pin
      analogWrite(flaps_PWM_out_pin, PWM_out); 

    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
}

No, I haven't tried this code. I recommend first that you look at it and read it (even if it looks complicated). It's basically one simple step after another. Everything should fall into place when you get to the end, but keep in mind there is other stuff coming from "outside" which is what is driving the program.

ame


_alioth_

#83
The code works. I have uploaded in an Arduino Nano to test. I don't have a galvanometer here to test now, but I have tested with some serial.prints

Some things I see:

1.-  The way the serial port is read in those link2fs examples are not the best. It can happen that  "if (Serial.available())" sees incoming data, but the data is not complete yet (something like <G0, because de last two numbers 18 have not arrive yet ) and you lose that comnunication.

For this reason, a simple fix is to add a delay before reading the characters when serial.avaliable says there is something to read. In this way you are sure that the incoming data will be complete before trying to read it. (something about 10ms worked fine I remember)

This fix was commonm in link2fs days. And for one (or several) simple galvanometers will work great. But the ideal would be a diferent approach to read the data, without delays.

I think Mach7 should test the code as is, because it should work and this is a big step.

2.- Later, (only when Ame code is working for you) a smoother funtion for the needle should be coded. Because in the way the code is written, you only have 30 needle steps. Arduino can make 255 steps so going for 0 to 1 degree in flaps should go 0..1..2..3..4...5..6...7 in pwm.
But now it will go for 0 to 7, so the needle is not going to be very smooth.

3.- <G indicatesd flaps position. But It can happen flaps are really in 18 degrees, but master bus in aircraft is switch off, so the gauge should be at 0. When you switch on the master bus, the gauge (which needs energy in bus), will go to 18 position.
The way to do this is tick the box in link2fs for bus voltage, reading this data in arduino and write some conditions there in the pwm function.
Sometimes you will find a variable that indicates needle position, instead of "flaps or whatever" position. In this case you don't need to make any condition. Just use the needle position variable. But I think this is not the case. You will have to look at it.


Step by step!

Arturo.



Mach7

Hello @ame and thank you!!

will be home to test the code this afternoon...at work right now and report back!.

Thanking both of you and Arturo for all the effort you are putting into this for me...it is greatly appreciated!

Jim

Mach7

Just came home for a bit and here are what the results were.

I downloaded the script to Arduino (uno)....(ot sure if that makes a difference as Arturo said he tested the code with a nano).

I connected the said gauge wires..one to ground the other to pin 3 (as per script).

Fired up FS9 and the 146 program..booted up link2fs and selected com 1...card 1..and simconnect extractions box as before.

When I manipulated the flaps I could read the values on the traffic monitor but nothing going to the arduino board.
And the gauge needle didn't move a millimeter.


Here are some other observations

Link2fs confirmed FS9 was connected

I did not connect a second power supply to the gauge..only the USB was connected

Is there something else I need to select on linksfs that i might be missing?

Thanks guys!

Jim

_alioth_

#86
First test the arduino part:
Close link2fs
Open Arduino  IDE.
Be sure you have selected the correct com port Tools->Port
Open the Serial Monitor window (control + shift + m)
Write in the upper line    <G018    and push send. this is the data type that arduino is expecting.
-If works and needle moves, the problem is link2fs related
-If doesn't, the problem is with arduino code, or wiring

Usb power supply is fine. You tested this before.
Arduino Uno and Nano work exactly the same with this sketch.

Mach7

@_alioth

I am going to do all of that...pretty sure there is something I missed in either the hardware or the software aspect...

Will report back tonight.

jim

Mach7

i actually have gauge wire (+) set to  pin pwm 3  and the other wire i put to ground...does this sound like a viable set up...? maybe it's a simple connection error?

_alioth_

Quote from: Mach7 on August 14, 2023, 10:46:49 AMi actually have gauge wire (+) set to  pin pwm 3  and the other wire i put to ground...does this sound like a viable set up...? maybe it's a simple connection error?

+ to pin3
- to gnd

It is ok.

To be sure the wiring is fine, load the Fade example sketch (which worked days ago), change line:
int led = 9; 
to
int led = 3;

upload the sketch and see if needle moves. It should move.



Mach7

Ok...so some additional info..and I am pretty sure it is a communication problem from the com port to the io board.

a few strange things going on with port com 1.

so when i removed the gauge/ wires/ usb/ arduino and connected it up to my laptop, doing the "ctrl+shift+M" allowed me to enter <G020 and the gauge moved accordingly.

when I went to my main computer to run the same test, it DID recognise the port as com 1, but would not run the test..in other words nothing happened when I hit "send".

So...the programming is sound...the UNO board is sound..the wiring is sound, and the gauge is sound.

Our problem here is the port (I think) 0n the main computer.

I thought that the link2fs monitor was good to go as it was showing me flap register values as the flaps were selected and travelling from 0 to 33 and back to 0...but then of course it would because it is getting its info directly from FS9...has nothing to do with the com port 1.

I tried to select a number of other ports on the link2fs communication page...but none of them will go green except com port 1.

My next step is to connect it to one of my USB (powered) hubs and see what happens..(i have been using one of the spare USB plugins at the back of the computer.

Mach7

In addition....when I plug the usb into the computer with Arduino connected...i don't get the "happy" connect sound, but rather three abrupt tones...like "buh..buh.buh"

If I plug a usb stick into the same port..the tone is different.

Mach7

SUCCESS...SUCCESS..SUCCESS

Ok guys...after some troubleshooting I re-installed the drivers for the Arduino board...that is the only thing that made sense to me.

After I did this...it recognised com 3 (not com 1) and I ran the flaps successfully from 0 to 33 and back to 0.

None of my other USB items seem to be affected thus far.

The only thing that the gauge does...that does not happen in the real aircraft, is it acts like a stepper motor...in other words the needle travels fine, but it travels in little movements, lie 05..stop for a millisecond...5 to 10 etc etc...like the hands of a stop watch.

This could be a product of the program as well (QW 146)

Is there anyway to smoothin out the sweep?

Thank you again guys!!!

Jim

Mach7

i re-read your reply @_alioth

with respect to the needle smoothness....you have already addressed that so i sure there is a fix:)

_alioth_

#94
Great!

Quote from: Mach7 on August 14, 2023, 12:41:28 PMThe only thing that the gauge does...that does not happen in the real aircraft, is it acts like a stepper motor...in other words the needle travels fine, but it travels in little movements, lie 05..stop for a millisecond...5 to 10 etc etc...like the hands of a stop watch.

This could be a product of the program as well (QW 146)

Is there anyway to smoothin out the sweep?

Yes. I anticipated this would happen:

Quote from: _alioth_ on August 14, 2023, 01:47:04 AM2.- Later, (only when Ame code is working for you) a smoother funtion for the needle should be coded. Because in the way the code is written, you only have 30 needle steps. Arduino can make 255 steps so going for 0 to 1 degree in flaps should go 0..1..2..3..4...5..6...7 in pwm.
But now it will go for 0 to 7, so the needle is not going to be very smooth.


This need a little of work. The most important thing is you understand the way to do it. Code will go later.

Now:
You recieved a new position, and move instantly the needle to the new position.
And you only have 33 steps for full range movement.


How to smooth:
You need two variables. 1.- actual needle position 2.- target position
When you receive new data, put the data in target position.
Then, move the actual needle position to target, step by step, with a delay (non blocking delay, because you need the rest of the code working.
If you want to go from 0 to 255 in 5 seconds, then you should move one step every 20 miliseconds.
So, create a nonblocking flag every 20 miliseconds. And every 20 miliseconds move the needle one step from actual position to target position.

There are other ways to do it. But this is quite easy to understand.

If you want to progress, you will need to write and understand the arduino code.
First look for info about non blocking delays. It is a good point to start.

Arturo.

ame

It's morning in New Zealand. Whilst the country was asleep you guys did all the hard work. Thanks!

@Mach7 I think it's important to note exactly how you got to this point and internalise the data flow from the sim to the gauge. Every time you use the sim and change the flaps position all of the elements must be in place: sim working, link2fs working, Arduino driver working (on the same COM port), Arduino working, gauge working. It should be pretty reliable, but as you can see, anything that goes wrong in that path will stop things working.

Regarding the needle smoothing, you will need more code. You can write it yourself (remember to stash a copy of the current working code somewhere so you can go back to it if you get completely lost), or myself or maybe Arturo will suggest some code for you.

If you want to add more gauges then you can have up to six PWM pins driven by the same Arduino. You would have six different variables to record the gauge value, and six different sections of code looking for tags (like "<G") for the other data elements. Then get link2fs to export them.

If you want input from something attached to the Arduino (such as a button or a pot) back into the sim, it's possible. But, one step at a time.

Mach7

@ame, thanks for all of that.

The only extra thing I would like to include and then the sim if 100 percent finished, are the three fuel gauges...left, center, and right. They two are the same design as the flap gauge.

With respect to flap smoothing...if you could give me a bit of a head start on that I would appreciate it. If it involves just adding values to certain lines, then yes I am comfortable with that.

Right now I am just excited that it is all working...for now I will run all the sub-systems and make sure nothing is being interfered with.

With respect to the fuel gauges, I am assuming this would have to be added to the existing flap code as one long string, then reprogrammed and pin identified.

Mach7

#97
as Arturo suggested;

1.-  The way the serial port is read in those link2fs examples are not the best. It can happen that  "if (Serial.available())" sees incoming data, but the data is not complete yet (something like <G0, because de last two numbers 18 have not arrive yet ) and you lose that comnunication.

For this reason, a simple fix is to add a delay before reading the characters when serial.avaliable says there is something to read. In this way you are sure that the incoming data will be complete before trying to read it. (something about 10ms worked fine I remember)


From this I gather a delay code would have to be written before each "serial.available. line is read. would this look something like this, (for each line prior to seral.available ?

delayMicroseconds (10);

ame

Quote from: Mach7 on August 14, 2023, 02:58:35 PM@ame, thanks for all of that.

The only extra thing I would like to include and then the sim if 100 percent finished, are the three fuel gauges...left, center, and right. They two are the same design as the flap gauge.

With respect to flap smoothing...if you could give me a bit of a head start on that I would appreciate it. If it involves just adding values to certain lines, then yes I am comfortable with that.

Right now I am just excited that it is all working...for now I will run all the sub-systems and make sure nothing is being interfered with.

With respect to the fuel gauges, I am assuming this would have to be added to the existing flap code as one long string, then reprogrammed and pin identified.
Ok. Basically you need to start thinking in terms of precisely what is going on in both human timescale (compared to a microcontroller we are glacially slow) and microcontroller timescale (compared to a human they are insanely fast). Also think about basic physics, inertia, momentum, time.

This is the last step before affecting the outside world:
analogWrite(flaps_PWM_out_pin, PWM_out);

At that point a value from 0-255 is written to the PWM module, this causing the GPIO pin to be turned on and off at a certain frequency, with a variable ratio of on period to off period. The effect of this is that the average power transferred from the GPIO pin is 0% of available power to 100% of available power. We know, because we designed it that way, by varying the power transferred to the electromagnetic coil in the gauge we can get it to move anywhere as a percentage of its full range. The mechanical inertia of the coil and spring in the gauge serves to dampen the on/off signal from the PWM module so that it appears to be stable.

Consider the situation where the gauge is at zero, but the sim is at 33 degrees. link2fs sends <G033. Arduino converts this to 33.0, multiplies this by 7.727 to get 254.991, converts it to an integer (not sure if if will round it, so you might get 254, or 255. Doesn't matter. Let's use 255 for illustration) and writes it to the PWM pin. Now the output is 255 which is 100%, which is fully on.

The effect of this is the same as applying 5V from a power supply or battery. The gauge will move to full scale. You can imagine that on a micro timescale it's very slow, because the magnetic force in the gauge coil has to overcome inertia and the spring tension in the gauge mechanism (it's basically a moving-coil Galvanometer). On a human timescale it might appear instead, or quite rapid.

So, to make it slower you have to simulate inertia. Instead of writing a new value directly to the PWM module you have to calculate over time what the needle position should be, based on the elapsed time and the target position. You could use some physics equations and simulate it accurately, or you could fake it.

Arturo already outlined this, but if coding is new to you it might be tricky to know where to start. The key point is that the Arduino loop() function literally goes round in a loop forever. Sometimes it has something to do on any particular loop iteration. Sometimes it has nothing. So your code can do incremental stuff (like moving a needle by a small amount) every time around the loop.

I'll draft some code (faking it, of course. No need for accurate physics) and see how it looks.

For the other three gauges you have to go through the entire process we just did, without making any assumptions. Specifically,

Does the gauge work like a simple voltmeter from 0 to 5V?
Is the gauge scale linear?
Does link2fs have a data element for each of the three gauges?
What is the tag (like "<G") for each gauge?
What is the format of the data following the tag, and what does it represent?
What is, therefore, the relationship between the reported data and the gauge position?

That's basically what we just did.

And yes, the string of data from link2fs will just get longer because it just keeps tacking on whatever elements you choose. There's obviously a practical limit, but you won't hit it.

ame

Quote from: Mach7 on August 14, 2023, 03:09:38 PMas Arturo suggested;

1.-  The way the serial port is read in those link2fs examples are not the best. It can happen that  "if (Serial.available())" sees incoming data, but the data is not complete yet (something like <G0, because de last two numbers 18 have not arrive yet ) and you lose that comnunication.

For this reason, a simple fix is to add a delay before reading the characters when serial.avaliable says there is something to read. In this way you are sure that the incoming data will be complete before trying to read it. (something about 10ms worked fine I remember)


From this I gather a delay code would have to be written before each "serial.available. line is read. would this look something like this, (for each line prior to seral.available ?

delayMicroseconds (10);
Not sure. It might not be necessary.

I can see why the example code has been written in that way. It's clear, simple, and obvious, but it's inelegant. Doesn't matter, it works.

If you start seeing problems then we could suspect this issue and fix it, or rewrite the code so that the issue does not occur.

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