zitronen

[Hardware, Plugin] Arduino based physical display + serial port io+ tutorial (27-08-19)

Recommended Posts

Ok the problem is say you have a switch that turns the lights on, but what if your lights are already on? If you flip the switch to on the lights will turn off.

Ahhhhh... ok, I see why :) Yes my method would require you to set all your switches to starting position before loading the flight, yours could ignore the switch being moved to ON if it is already ON and vice versa... very clever. You may be able to bypass the current bug with landing gear (the first time you use landing gear in KSP you have to hit the button twice!)... with my setup the way round would be to set the gear to "UP" before launch to get it in sync with the bug.

Edit: If you guys want to put together a list of data you want sent from KSP that would be nice too. I will start on that when I get basic inputs working.

I'm working at the moment but I can put a list together a bit later, if eveyone does a list you wont miss anything and can merge them together :)

Share this post


Link to post
Share on other sites

I thought that sending commands through the arduino program rather than emulating a keyboard would be good for a few reasons.

- it seems a bit kludge-y. If we've got a direct route between the arduino and the game, why go the roundabout route.

- arduino limitations: I was under the impression that if you started the arduino-keyboard mode, you would have trouble doing other things. I could be completely off base on this one, though.

- non-mapped keys: going directly through the arduino lets you use commands that currently aren't mapped to the keyboard (for instance RCS on, rather than RCS toggle)

I am interested in the joystick command sending because I found a pair of (relatively) cheap 3-axis potentiometer joysticks, but that means they're not really plug-and-play compatible. Also, just for simplicity's sake, it would be nice to have everything go through the arduino.

As far as a list of variables to pass back to the arduino, my wishlist is (with the ones you've already implemented marked with an X):

- Flight Time

- Time to Node

- Real Time (from the system clock, just for the heck of it)

X Time to Apo

X Time to Peri

- Time to Sphere of Influence Switch

- Current Stage Number

- Current Throttle

X Current G Force

- Heading

- Pitch

- Roll

- Orbital Velocity

X Surface Velocity

- Target Velocity

- Altitude (normal)

X Radar Altitude

- Target Distance

X Apoapsis

- Target Apoapsis

X Vertical Velocity

X Periapsis

- Target Periapsis

- Horizontal Velocity (lazy to ask for both instead of computing it... but there's a lot more spare power in the computer than in the arduino)

- Liquid Fuel Total

- Liquid Fuel on Current Stage

- Liquid Fuel Consumption

- Electric Charge Total

- Solid Fuel Total

- Solid Fuel on Current Stage

- Mono Propellant Total

- Oxidizer Total

- Xenon Total (?)

- Current Time Warp

- Current time warp state (physical or not)

- Max Time Warp State (I guess you could also just get this from altitude)

- SAS, RCS, Precision Mode, Lights, Gear and Brakes: Current Status

- Whether action groups 1-10 have any actions assigned to them (maybe just on startup, does't really need to be polled at any frequency)

I've crossed off the ones that I think you've already got.

Looking at this list, there are a lot of variables, hopefully that stays in your 255 bytes limit. I'm sure there are important ones that I've completely forgotten to consider.

Share this post


Link to post
Share on other sites

Nice list, just finished my first draft too :) Also probably forgotten things...

Resources

Total Fuel (percentage)

Total Oxidizer (Percentage)

Stage Fuel (Percentage)

Stage Oxidizer (Percentage)

Total Monopropellant (Percentage)

Stage Monopropellant (Percentage)

Total Electricity (Percentage)

Stage Electricity (Percentage)

Electric drain/charge rate (-100.00 to +100.00?)

Flight data

Current MET (Numeric, time)

AP (numeric)

PE (Numeric)

Time to AP/PE (Numeric, Time)

Inclination (+/- Numeric)

Excentricity (+/- Numeric)

Altitude, sea level (Numeric)

Radar Altitude (Numeric)

Air pressure

Temperature

Gravity

Speed, surface

Speed, Orbit

Speed, Target

Pitch (Degrees)

Roll (Degrees)

Yaw (Degrees)

Heading/prograde (degrees)

Data to control dashboard lights..

These could be tied in with coresponding inputs.

RCS ON/OFF?

SAS ON/OFF?

Gear UP/Down?

Stage

Stage lock

Normal/fine control

Lights ON/OFF?

Brakes

Translation/rotation mode

Share this post


Link to post
Share on other sites

I can see things that are on one but not the other (and vice versa!)... xitronen might need to set up a spreadsheet :D

I may not be much use with electronics... but I'm a proffessional designer. Hurry up and think of a cool name for your plugin xitronen and I'll see if I have time for a logo. Least I can do after all the noob herding you have done to get me on track!

Share this post


Link to post
Share on other sites
I thought that sending commands through the arduino program rather than emulating a keyboard would be good for a few reasons.

- it seems a bit kludge-y. If we've got a direct route between the arduino and the game, why go the roundabout route.

- arduino limitations: I was under the impression that if you started the arduino-keyboard mode, you would have trouble doing other things. I could be completely off base on this one, though.

- non-mapped keys: going directly through the arduino lets you use commands that currently aren't mapped to the keyboard (for instance RCS on, rather than RCS toggle)

I am interested in the joystick command sending because I found a pair of (relatively) cheap 3-axis potentiometer joysticks, but that means they're not really plug-and-play compatible. Also, just for simplicity's sake, it would be nice to have everything go through the arduino.

Cool, I suspected I might be missing something... all good reasons! It might also offer a way to have multiple joysticks without them conflicting now I think about it...

Share this post


Link to post
Share on other sites
Cool, I suspected I might be missing something... all good reasons! It might also offer a way to have multiple joysticks without them conflicting now I think about it...

To be perfectly honest, I fear that getting the joysticks working through the arduino is going to be way more trouble than it's worth - in hindsight I wish I'd just gone with some normal ones. :)

Share this post


Link to post
Share on other sites

Guys I have the basics of inputs working. I have a question about how you guys would like the input packet to look like. We can go the easy and inefficient rout:


struct ControlPacket {
byte SAS;
byte RCS;
...
}

Which means we are using a whole byte for each switch button, which limits us to 255 buttons (minus bytes needed for analogue axes). But this is really easy to use, you just do ControlPacket.SAS = 1; in arduino. The alternative is to use the full byte with bit math (http://playground.arduino.cc/Code/BitMath).


struct ControlPacket {
byte ControlByte1;
byte ControlByte2;
...
}

This is much more efficient (8 times!), we can do up to 2048 buttons, but it will be more difficult to use, you will have to remember which bit is for what, i.e. bit 1 of byte 1 is SAS, and you will have to do something like ControlPacket.ControlByte1 |= (1 << 7); (turns highest bit to 1).

Share this post


Link to post
Share on other sites

That is excellent progress zitronen! Very exciting stuff :)

As for the options, I would definitely prefer the second one (one bit per toggle, keeping as much space as possible for options that will need more degrees of resolution).

I am curious about why you've chosen this way of sending commands. It is a nice counterpoint to the data-to-arduino sending (and maybe having both structured in the same way makes it easier to keep track of), but I was wondering why you would need to send all the commands all the time. For the display data (in the other direction), it makes sense, because you don't want to make the arduino have to ask for particular variables, but I don't know how often you'll be sending more than a handful of commands at a time. Would there be any benefit in limiting yourself to say 16 commands at once (probably a safe assumption?), and having the variables be passed as:


struct ControlPacket {
byte VariableNumber1;
byte VariableValue1;
byte VariableNumber2;
byte VariableValue2;
...
}

Where you could define a list of variables that are changeable (RCS = 1, SAS = 2, throttle = 3, etc.), and then pass them whatever value you want to be assigned to that particular one. If you had a max of 16 variables (per packet), that would cut down your packet size to 32 bytes, instead of 255 (or something around there, with checksums and whatnot). That way you could have thousands of possible variables (which is total overkill), and I think it would make it easier to add new ones later on. This would also make it so you wouldn't have to keep track of (and retransmit) the state of all the variables every time. Of course, the down-side is that if you somehow managed to miss a packet, it wouldn't be fixed on subsequent ones.

Just a thought, I am still super excited about your way, I don't mean to sound unappreciative. The work that you've been doing is amazing!

Share this post


Link to post
Share on other sites

Well there are many different ways to do this, but there are some down sides to what you are suggesting. First the arduino will have to keep track of which input changed, which was sent and manage the queue of what to send next. This seems like more work than just sending some bytes at regular intervals. Secondly, now you need 2 bytes to send 1 bit. The 32 byte structure you are proposing is used to send 16 bits, but the same 32 byte structure can easily be used to send 32 bits or 256 bits. So you might as well just send everything. (edit: this is how USB joysticks work, everything in one frame)

Also I am not sending 255 bytes, 255 bytes is the maximum size of the structure, the actual size of the packet depends on what's in it. So it may only be 50 bytes. If we run out of space in one structure we can simply make a new one, e.g. we could have one struct for switches and one for axes.

Share this post


Link to post
Share on other sites

That makes sense, I hadn't thought of it that way. Thanks for the patient explanation :)

Well there are many different ways to do this, but there are some down sides to what you are suggesting. First the arduino will have to keep track of which input changed, which was sent and manage the queue of what to send next. This seems like more work than just sending some bytes at regular intervals. Secondly, now you need 2 bytes to send 1 bit. The 32 byte structure you are proposing is used to send 16 bits, but the same 32 byte structure can easily be used to send 32 bits or 256 bits. So you might as well just send everything. (edit: this is how USB joysticks work, everything in one frame)

Also I am not sending 255 bytes, 255 bytes is the maximum size of the structure, the actual size of the packet depends on what's in it. So it may only be 50 bytes. If we run out of space in one structure we can simply make a new one, e.g. we could have one struct for switches and one for axes.

Share this post


Link to post
Share on other sites

I like the sound of the simpler version ;) but only if it doesn't cause problems with the limitation. I'll leave it up to those who know more about coding!

Great news on the progress!

I now have my control board up and running but I'm really starting to appreciate the limitations of the system I have used (an off the peg board designed for flightsims... don't ask me how much I could have saved building it myself - hindsight is a wonderful thing) - I frequently get tripped up by the switch positions not matching the game state, particularly if I switch ships, quickload etc.

It would be great if your plugin constantly checks the switch state and matches the game to it! For example If I load a game up and the RCS switch on my board is already set to "ON" I'd like the plugin to instantly read this state and turn the RCS on... without me having to touch the switch or reset its position. At present my board simply sends a keystroke pulse each time the switch is moved from one state to the other... ksp cant tell the difference between switching to "ON" or switching to "OFF" it simply toggles exactly the same for either.

Share this post


Link to post
Share on other sites
I like the sound of the simpler version ;) but only if it doesn't cause problems with the limitation. I'll leave it up to those who know more about coding!

OK that's one vote for the simple version and one vote for the efficient version. I think it will come down to how many axes and buttons you guys think you will need. For the simple version 1 button/switch is 1 byte and one analogue axis is 2 bytes. If you add it up and it's less than 255 then we can do the simple version. I think I will do a hybrid, i.e. map the common stuff (RCS, SAS, Gear, etc.) to 1 byte each and add a couple bytes at the end for other stuff. Like this:


struct ControlPacket {
byte SAS;
byte RCS;
...
uint ControlGroup; //control groups 1-10 in 2 bytes
byte AdditionalControlByte1; //other stuff
byte AdditionalControlByte2;
}

This way for simple stuff it's really easy, but if you want to control more things then some code is required.

It would be great if your plugin constantly checks the switch state and matches the game to it! For example If I load a game up and the RCS switch on my board is already set to "ON" I'd like the plugin to instantly read this state and turn the RCS on... without me having to touch the switch or reset its position.

That's what it should do.

Share this post


Link to post
Share on other sites

I can't imagine needing more than 255 inputs... I'm struggling to fill 25 with my current switch board. Is there anyway to increase the inputs with 2 arduinos on two com ports?... or would that need a reworking of the plugin...

I think usability could be imporatant for those with less knowledge (like me) and would encourage more users to give hardware building a try!

I like the idea of a hybrid! Allows for everyone :)

Share this post


Link to post
Share on other sites

I was wondering - what happens to the control packet when a control panel doesn't actually have buttons for every function (and let's say for example you want SAS to be controlled normally). It seems like you'd have to send a value for everything, or else have a different command packet structure for each control board. Or is there going to be some sort of config so define what the command struct will be? I guess that would be the easiest way?

Share this post


Link to post
Share on other sites

hmm... I didn't think about that. I was going to have a custom struct for each board but obviously that will require everyone to change the plugin code. I think the easiest way is to have a config file that allows you to to choose which commands and axes are enabled.

Share this post


Link to post
Share on other sites

Ok some more things I thought of for the outputs (I forgot about the science values within KSP)

Temp

Atmosphere

Seismic

Gravity

also will it be possible to set up custom inputs and outputs for custom resources? For example I use the TAC life support mod so would be great to have a gauge for O2. Or will these need to be defined within the plugin?

Share this post


Link to post
Share on other sites

Temperature atmosphere and gravity I can do, atmosphere density is already included. These will output regardless whether you have instruments or not. I donno where seismic comes from.

Working with other plugins is possible but pretty low on the priorities right now, but it shouldn't be to difficult to define custom resources for output. I will just leave some generic variables free to be used for whatever.

Share this post


Link to post
Share on other sites

Finally got it working! Please help test it before I put an update on the first post. As it turned out it was not an easy job!

Plugin: https://sites.google.com/site/zitronfiles/KSPSerialIO_013.zip

Arduino Code: https://sites.google.com/site/zitronfiles/KSPIODemo2.zip

Add switches between pins 8 (SAS) and 9 (RCS) and ground to test.

Important changes:

1. The plugin now detects the ports before flight instead of at main menu, so the first time you launch there will be a delay, but only the first launch. (This is because reasons)

2. I decided to go with efficient packets, but also included an easy way to code it in arduino, you simply do "MainControls(SAS, HIGH);" to turn on SAS, see the controls tab in the arduino code

3. Currently only implemented RCS and SAS

4. Arduino sends control packets at 40Hz, the plugin only does something when inputs change, so you can override switches with keyboard.

I need to find out how to get the status of RCS, SAS, Lights, etc. from KSP.

Share this post


Link to post
Share on other sites

Zitronen, I just wanted to say Thank you for making this. I love KSP and enjoy working with Arduinos and I am so glad there is now an easy way to interface between them that is only going to become better.

Share this post


Link to post
Share on other sites
Finally got it working! Please help test it before I put an update on the first post. As it turned out it was not an easy job!

Plugin: https://sites.google.com/site/zitronfiles/KSPSerialIO_013.zip

Arduino Code: https://sites.google.com/site/zitronfiles/KSPIODemo2.zip

Add switches between pins 8 (SAS) and 9 (RCS) and ground to test.

Important changes:

1. The plugin now detects the ports before flight instead of at main menu, so the first time you launch there will be a delay, but only the first launch. (This is because reasons)

2. I decided to go with efficient packets, but also included an easy way to code it in arduino, you simply do "MainControls(SAS, HIGH);" to turn on SAS, see the controls tab in the arduino code

3. Currently only implemented RCS and SAS

4. Arduino sends control packets at 40Hz, the plugin only does something when inputs change, so you can override switches with keyboard.

I need to find out how to get the status of RCS, SAS, Lights, etc. from KSP.

Great! I'll wire my rcs and sas switch on my control panel tonight and test it out! Hopefully the port detection before the flight might fix the bug on some megas :)

Share this post


Link to post
Share on other sites

Ok first test run... and it didn't seem to do anything. Oddly though when the flight loaded in the SAS and RCS were both already on. Using the switches had no effect but I could turn sas and rcs on/off with the usual keyboard commands.

Making a clean install to test again.

EDIT - forgot to mention I'm testing on an official Arduino Uno, not a copy.

Edited by Mulbin

Share this post


Link to post
Share on other sites
the plugin only does something when inputs change, so you can override switches with keyboard.

Doesn't this mean it will go out of sync with your switches every time you quickload / dock / change ships etc? Or will you change it later... I thought the point was it constantly checked the state of the switches so you could trust the game to accurately reflect the control panel.

Share this post


Link to post
Share on other sites

Every time you load a scene it will sync with the arduino at the start, that's why your SAS was on. Every time you flip a switch the states are synced.

Are you sure your switches are wired to ground? It needs to be PIN --> Switch --> Ground, not PIN --> Switch --> + 5V.

Share this post


Link to post
Share on other sites

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.