Jump to content

[Hardware, Custom] KSP flight panel, with flight computer


AmeliaEatyaheart

Recommended Posts

Hey everyone! :)

I'm still new to the forums, but been playing KSP for a while now. As a space nerd and electronics nerd, I wanted to combine my two interests, and deign a flight computer, partly to clear the screen from display mods. They work great, but take up precious screen space! however, I know sweet stuff-all about how to write mods for the game.

Thankfully, there are people out there with more/greater talents, and someone had already written a plugin to add external hardware - and they wrote it for Arduino! That suited me rather well, as I've made a few Arduino projects in the past :)

So, without much further ado, the flight panel to date! :)

20140722_160355.jpg

Current flight / orbital parameters output, and proposed 7 segment board - I need to re-do that though, as those modules EAT power...

20140808_143325.jpg

Cardboardian template for the control panel

kerbal_panel_fuelgauges.jpg

Fuel gauges - won't help for ion drives, but is otherwise helpful and fun - especially when firing those lovely 3.75m engines! :D

20141112_220438.jpg

The cardboardian front panel got upgraded to "let's add some not-quite-dodgy wiring and see if it works"... I'd like to believe Jeb would approve of the bare wire and spit-polish approach :)

20141122_010559.jpg

And just this week, recieved a bunch of those playstation-type thumbsticks for flight control! I was hoping to get an old-skool gamepad joystick working, but the springs are broke, and I kept spinning out of control.

I was planning on treating this primarily as a flight readout panel, but after going through zitronen's code and realising how much spaceship controls I could add, it was too much to resist! So now I have to get/make a nice case for it all :)

-----

Also, many thanks to both zitronen for writing this awesome plugin, and Mulbin for collecting a bunch of other hardware projects that other awesome people have made, that helped to inspire me :)

http://forum.kerbalspaceprogram.com/threads/66393-Hardware-Plugin-Arduino-based-physical-display-serial-port-io-tutorial-%2808-Oct%29

http://forum.kerbalspaceprogram.com/threads/66763-Custom-hardware-simpit-repository-For-people-who-take-KSP-a-little-too-far

Link to comment
Share on other sites

Thanks guys! :)

I plan to update this thread sporadically as updates happen - while I'm more keen to make the readouts happen, I haven't been able to get the circuit boards made yet, so I've concentrated on getting the switch panel finished :)

I added some flickering lights code to the switch panel, so if the ElectricCharge drops to less than 5 units, the lights start flightering, if the power drops to 0, most of the buttons will just flat-out stop working :P

Edited by AmeliaEatyaheart
Reason: I'm bad at typing and spelling :P
Link to comment
Share on other sites

I wrote some Arduino code to calculate what SOI you fall under - I'm pretty sure it will fail if eccentricity is EXACTLY 1.00000000 (overflow error possibly?), but for any other orbit (elliptical, circular, hyperbolic) this will calculate what you're falling around :)


#define NoSOI -1
#define KerbolSOI 0
#define KerbinSOI 1
#define MunSOI 2
#define MinmusSOI 3
#define MohoSOI 4
#define EveSOI 5
#define DunaSOI 6
#define IkeSOI 7
#define JoolSOI 8
#define LaytheSOI 9
#define VallSOI 10
#define BopSOI 11
#define TyloSOI 12
#define GillySOI 13
#define PolSOI 14
#define DresSOI 15
#define EElooSOI 16
//same codes as in a savefile


double Oldecc=-1;//keep value of orbital eccentricity for comparison next loop
int currentSOI=-1;

void UpdateDisplayOnNewPacket()
{
if (Oldecc==-1 || currentSOI==-1) currentSOI=resolveSOI();//force refresh if SOI unknown.
else if (Oldecc<=1 && VData.e>1) currentSOI=resolveSOI();//force refresh of SOI if orbit jumps to hyperbolic (e.g. entering a smaller SOI)
else if (Oldecc>=1 && VData.e<1) currentSOI=resolveSOI();//e.g. jumping to solar from planetary
else if ( (VData.e>(Oldecc*1.05) ) || (VData.e<(Oldecc*0.95) ) ) currentSOI=resolveSOI();
//force refresh if the eccentricity 'jumps'; indicates an SOI change without a hyperbolic orbit (e.g. Laythe horseshoe orbit)
//'resolveSOI' could be run every loop, but conditional states used to save some processor time.


//add more display update code here
...
Oldecc=VData.e; //preserve data for next run through loop
}


//--------//


double resolveSOI()
{
//will attempt to find mu, and from that, figure out which world we're orbiting.

//eqn: mu=v^2 / ( (2/OrbRad)-(1/SMA) ) for e<>1.
//eqn: mu=(V^2 * OrbRad)/2 for e==1 aka parabolic orbit.
//all distances in this function are expressed in km, not m, hence a lot of n/1000.
//references- http://en.wikipedia.org/wiki/Hyperbolic_trajectory#Velocity
//http://en.wikipedia.org/wiki/Orbital_mechanics#Formulae_for_free_orbits

double SemiMajorKm=VData.SemiMajorAxis/1000;
double mu=0;
double _BodyRadius=0;

if (VData.e>1 && SemiMajorKm>0) SemiMajorKm=-SemiMajorKm;//SMA must be a negative figure for e>1.
//this is a catch-all - hyper orbits in KSP always have a -ive SMA.
_BodyRadius=((SemiMajorKm*2)-(VData.AP/1000)-(VData.PE/1000))/2;
double vsquared=(VData.VOrbit/1000)*(VData.VOrbit/1000);
if (VData.e!=1) mu=(vsquared)/( (2/(VData.Alt/1000 + _BodyRadius))-(1/SemiMajorKm) );
else mu=(vsquared)*(2/(VData.Alt/1000 + _BodyRadius))/2;



//value will be comparable to wiki mu values, divide 10^10 (conversion factor of m^3 -> km^3

if (mu<=0) return -1;//calculation error
if ( (3531.6*0.95)<mu && mu<(3531.6*1.05) ) return KerbinSOI;
else if ( (65.138398*0.95)<mu && mu<(65.138398*1.05) ) return MunSOI;
else if ( (1.7658*0.95)<mu && mu<(1.7658*1.05) ) return MinmusSOI;
else if ( (168.60938*0.95)<mu && mu<(168.60938*1.05) ) return MohoSOI;
else if ( (8171.7302*0.95)<mu && mu<(8171.7302*1.05) ) return EveSOI;
else if ( (301.36321*0.95)<mu && mu<(301.36321*1.05) ) return DunaSOI;
else if ( (18.568369*0.95)<mu && mu<(18.568369*1.05) ) return IkeSOI;
else if ( (282528*0.95)<mu && mu<(282528*1.05) ) return JoolSOI;
else if ( (1962*0.95)<mu && mu<(1962*1.05) ) return LaytheSOI;
else if ( (207.48150*0.95)<mu && mu<(207.48150*1.05) ) return VallSOI;
else if ( (2.4868349*0.95)<mu && mu<(2.4868349*1.05) ) return BopSOI;
else if ( (2825.2800*0.95)<mu && mu<(2825.2800*1.05) ) return TyloSOI;
else if ( (0.0082894498*0.95)<mu && mu<(0.0082894498*1.05) ) return GillySOI;
else if ( (0.72170208*0.95)<mu && mu<(0.72170208*1.05) ) return PolSOI;
else if ( (21.484489*0.95)<mu && mu<(21.484489*1.05) ) return DresSOI;
else if ( (74.410815*0.95)<mu && mu<(74.410815*1.05) ) return EElooSOI;
else if ( (1172332800*0.95)<mu && mu<(1172332800*1.05) ) return KerbolSOI;

return mu; //catch-all line - unknown value, returning calc result for analysis.


}

If I update it, it'll get reposted here. But I'm pretty happy with it, and it's worked cleanly so far :)

Edit: This function actually calculates the gravitational constant * planet mass (µ, or GM) for a given body, so who knows, this might be useful for other orbital calculations as well :)

More edit: Also calculates things like distance to CENTRE of planetary body, which comes up a lot in equations as well.

Edited by AmeliaEatyaheart
Link to comment
Share on other sites

I wrote some Arduino code to calculate what SOI you fall under - I'm pretty sure it will fail if eccentricity is EXACTLY 1.00000000 (overflow error possibly?), but for any other orbit (elliptical, circular, hyperbolic) this will calculate what you're falling around :)

...

If I update it, it'll get reposted here. But I'm pretty happy with it, and it's worked cleanly so far :)

Edit: This function actually calculates the gravitational constant * planet mass (µ, or GM) for a given body, so who knows, this might be useful for other orbital calculations as well :)

More edit: Also calculates things like distance to CENTRE of planetary body, which comes up a lot in equations as well.

I absolutely love this piece of code. Is it possible at all for you to put it on github? Even just a text file, or a gist ( https://gist.github.com/ ) would be wonderful to make sure that it get all the attention it deserves :cool:

That being said, I really might borrow / steal / adapt it for my own controller, I just hope that the Mega2560 will be fast enough to recalculate it all the time :)

Link to comment
Share on other sites

Heh, the processing power of the Atmel microprocessors is vastly underestimated usually. Don't worry, it should be fine. And besides... you don't change your SOI 99% of the time anyway, running the resolveSoi() once per second is MORE than good enough.

Link to comment
Share on other sites

Heh, the processing power of the Atmel microprocessors is vastly underestimated usually. Don't worry, it should be fine. And besides... you don't change your SOI 99% of the time anyway, running the resolveSoi() once per second is MORE than good enough.

True, I just have to put some variable somewhere in my code... lastSOICalculated() or something. Or I need to learn how to do event-based programming in C ;.;

Link to comment
Share on other sites

There are several ways to ration out how often the function is called; the code block I wrote will only call ResolveSOI() when it has changed enough to warrant a re-calc (eccentricity changes from hyperbolic to elliptical, visa-versa, makes a sudden jump, or is unknown). But it's not a really intense subroutine either. So far I have not had any false reportings of SOI with this code block, so do feel free to use it :)

I'd honestly be shocked if it slowed the mega2560 down, even if it was called every loop. It's a floating point function, sure, but... it's not super-complicated :)

I'll have to have a look at github, to be honest this is the first Arduino code I felt was of value to share, so haven't really thought of all that stuff - I consider it released on a 'have fun with it, no restrictions, just give me name credit' type basis :)

Edited by AmeliaEatyaheart
Link to comment
Share on other sites

@Amelia, yeah you're probably right. After all, Zitronen's plugin updates the Microcontroller only a few times per second (forgot how quickly, exactly), which leaves quite a lot of time for the microcontroller to "do stuff" in between.

One thing to keep in mind though is that floating point math is really expensive on an Atmel microcontroller. Not that it will be cheaper on controllers from other brands, just comparing it to integer math. Here's someone who tested it with some dramatic results:

http://www.avrfreaks.net/forum/multiply-divide-add-performance-various-data-types

He basically generated two random numbers of float, int_8, int_16, ... each, and multiplied them, measuring the time it took. Results on the bottom of the first post ;).

So yeah.. I'm a bit hesitant with floating point math since I know that but it's pretty much unavoidable in KSP where we deal with planetary masses and gravitational pulls at the same time. But beware that floating point error :D

Link to comment
Share on other sites

So I was thinking about finally implementing sending the SOI, but if people are happy with Amelia's implementation I won't need to any more?

Honestly, I would prefer the SOI to be sent from the plugin. On the KSP side, you have a much better idea of which body we are orbiting (it is the "REF" attribute of the "ORBIT" element in persistent.sfs), especially if the planetary bodies are modded in some way (Real Solar System, anyone?).

Amelia's implementation, on the other hand, without wanting to belittle the hard work that went into it, relies on quite a bit of guesswork. It might break anytime with a mod or an update to the core (0.90?)

Link to comment
Share on other sites

I'd second Hakans opinion on this. Providing the SOI from KSP itself is inherently more reliable and stable. And with "reliable" I don't mean to imply that Amelias code has issues, but that it will invariably fail is SQUAD changes a parameter on one of the bodies that is involved in the calculations whereas the KSP-side of things would simply continue to work.

Link to comment
Share on other sites

@Amelia, yeah you're probably right. After all, Zitronen's plugin updates the Microcontroller only a few times per second (forgot how quickly, exactly), which leaves quite a lot of time for the microcontroller to "do stuff" in between.

The default packet delay is 80ms, which seems fine for most things. I'm not even running any switch debouncing code with a delay like that, and not had any problems.

But beware that floating point error :D

tell me about it ;) Had a few FP projects with borked maths. I've given up testing for x==0 now, just test for x<0.001 or something like that :P

My SOI code would break if the planetary parameter for mass (GM) changed, or had two bodies with the same GM value. Otherwise, it looks up craft orbital velocity, semi-major axis, apoapsis, and periapsis from the KSPplugin :)

Edited by AmeliaEatyaheart
Link to comment
Share on other sites

Yes that's more or less the standard way of validating against zero with floating point math :)

I like using things like (fabs(result - expectedResult) < 0.0001) or something to that effect. fabs() is part of math.h

Link to comment
Share on other sites

You can easily add Fuel gauge to the ion by changing the following section


PROPELLANT
{
name = XenonGas
ratio = 0.1
}

to

PROPELLANT
{
name = XenonGas
ratio = 0.1
DrawGauge = True
}

won't help for ion drives, but is otherwise helpful and fun - especially when firing those lovely 3.75m engines!

Link to comment
Share on other sites

You can easily add Fuel gauge to the ion by changing the following section

Hmm! Maybe I'll have to modify the fuel gauge to do both after all! :D

MrOnak, ty! I do need to learn more about some (i.e. A LOT) of the internal Arduino library functions - it's not uncommon for me to write a function and find out later that there's an inbuilt version of the same thing.

Link to comment
Share on other sites

Mini update:

Been working on the PCBs of late, so I thought I'd show em off :)

Flightcomputerpaneldecember2014.png

the flight readout will have a stupid amount of 7 segment displays, a small graphic LED which I hope to use to show a navball, or a simple orbital map, and a character LCD for any extra info that doesn't fit on the 7-seg's such as current SOI, Terminal velocity indicator, various alarm statuses...

PCBpaneldecember2014.png

And the reason it's taking so long to get made :P

There's a few different projects on that panel, the two bigger boards to the upper right and the small shield lower right are for the mass 7-segment display (6 rows by 8 digits, plus indicator LEDs)

The driver board will run two of those with a bit of greenwiring :)

It's an expensive project, and it won't get done before the end of the summer break (southern hemisphere, so... end of jan maybe?) so I thought I'd make a post and show that this project may be running on slow, but not forgotten :)

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...