Jump to content

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


zitronen

Recommended Posts

Not with this plugin. I haven't seen anywhere that sort of control is exposed in the KSP API.

But it should be a fairly simple matter to have an Arduino implement USB HID functionality. Your head tracker would end up emulating a mouse, and you could control movement in the IVA that way.

Link to comment
Share on other sites

For an microcontroller-driven USB HID, go here: http://www.obdev.at/products/vusb/index.html . As far as the Arduino family of microcontroller boards is concerned I believe the Leonardo might be a better choice than the Uno since it seems to allow USB HID more or less natively. But please check your facts, my memory on that is sketchy at best of times and I didn't have my morning coffee yet ;).

I'm using it to emulate a joystick/keyboard combination, a mouse is much easier. But If I remember correctly there's a mod called KerbTrack or something similar that enables TrackIR and other headtrackers in KSP. Of course you want something slightly different but it might nonetheless be a good start.

Found it: http://forum.kerbalspaceprogram.com/threads/73184-0-90-KerbTrack-Head-tracking-using-your-webcam-TrackIR-Oculus-Rift-%282014-10-16%29

Link to comment
Share on other sites

You can check out how lazor systems implements camera control and easily set that up I think. You can turn and control the remote cameras and telescopes with that plugin. I think you could derive a new EVA/IVA plugin to control the Kerbal Cam from this code. You could also possibly use firmata to transmit Any DOF style data to your new Camera control plugin. Source is in the release zip. http://www.curse.com/ksp-mods/kerbal/220271-lazor-system#t1:other-downloads

Also see this class:

http://anatid.github.io/XML-Documentation-for-the-KSP-API/class_flight_camera.html

You can write a plugin that controls that camHdg and camPitch, I didn't see roll though.

As for mouse/joystick control, you don't need a Leonardo, you can checkout nichood 's hoodloader2 project for turning your UNO into a customizable HID in concert with his HID plugin. There are example code for turning it into a joystick+keyboard+gamepad all in one super HID system.

/Kegan

Edited by marzubus
more info
Link to comment
Share on other sites

Kegan is right, you definitely don't need a Leonardo for USB HID stuff (I had my coffee now :D) - I'm personally using the same chip that's on the Uno (different from the one on the Leonardo) for USB HID. See the V-USB link above.

Link to comment
Share on other sites

This branch has everything I've done on the plugin to date: the configuration changes to keep the plugin from stomping on keyboard input, using the new autopilot handlers, and extensions to the control packet for rover control: https://github.com/phardy/KSPSerialIO/tree/new-autopilot

Most of it is working fine, but I'm not able to get the wheels working yet. Hoping I've just done something dumb. :) Doing some more testing on it now, hoping to have it finished tonight. After that, I was going to take the liberty of updating the arduino demo code for the new control packet and adding it to the repository as well.

EDIT: Turns out the wheels weren't working because I hadn't turned them on in the config file. :blush:

Hey Stibbons, your fork still seems to be using

ActiveVessel.Autopilot.SAS.ManualOverride(true);

I'm trying to figure out what you did to change over to the new 0.90 autopilot stuff. I see you added some more options to the settings and rover stuff, so that's cool.

For an microcontroller-driven USB HID, go here: http://www.obdev.at/products/vusb/index.html . As far as the Arduino family of microcontroller boards is concerned I believe the Leonardo might be a better choice than the Uno since it seems to allow USB HID more or less natively. But please check your facts, my memory on that is sketchy at best of times and I didn't have my morning coffee yet ;).

I'm using it to emulate a joystick/keyboard combination, a mouse is much easier. But If I remember correctly there's a mod called KerbTrack or something similar that enables TrackIR and other headtrackers in KSP. Of course you want something slightly different but it might nonetheless be a good start.

Found it: http://forum.kerbalspaceprogram.com/threads/73184-0-90-KerbTrack-Head-tracking-using-your-webcam-TrackIR-Oculus-Rift-%282014-10-16%29

From KerbTrack it looks like to change the IVA camera angle you just need to change

InternalCamera.Instance.transform.localEulerAngles

I guess I can add it, but since facetracknoir already works it's kind of pointless.

Link to comment
Share on other sites

Ok, now that my board is built I'm on to wiring and coding, so it's time for my noob questions again!

Problem

I want a switch that turns on SAS, then I want a light to illuminate.

What's wrong with my code? I suspect it's just a grammar issue.

if (digitalRead(SASPIN))

MainControls(SAS, LOW); digitalWrite(SASLEDG,HIGH);

else

MainControls(SAS, HIGH); digitalWrite(SASLEDG,HIGH);

EDIT - before anyone says it, yes SAS,LOW is correct, arduino detects a completed circuit as off for some reason.

Short version, how do I make an arduino do two things at once? Separating with a semi colon doesnt seem to be the answer.

Link to comment
Share on other sites

if (digitalRead(SASPIN)) {

MainControls(SAS, LOW);

digitalWrite(SASLEDG,HIGH);

} else {

MainControls(SAS, HIGH);

digitalWrite(SASLEDG,HIGH);

}

Thanks :), when i doubt, it's usually missing wiggly brackets! (my technical term for them)

EDIT TO EDITS

Nevermind, just turned the switch upside down and will treat off as on / on as off... easier than fixing the code!

Edited by Mulbin
Link to comment
Share on other sites

Not so weekly "Weekly" update

Changed: Plugin version 0.17.1

A whole lot of changes if you are moving from 0.16.1! There are probably bugs that I have not found yet, but it should be safe to update now. I will wait till someone confirms it's working before I update the first post and kerbalstuff.

Recap from 0.17.0:

  1. Added sending back of control statuses in a single uint16: SAS, RCS, Light, Gear, Brakes, Abort, Custom01 - 10
  2. Added simple function in arduino for reading the statuses
  3. SAS and RCS controls are now synced when switching vessel (Freshmeat request)
  4. Added return value for input() function in arduino code (MrOnak post #705)

New in 0.17.1:

  1. I gave up on the new autopilot stuff (no one seem to have a working example yet), just merged the controls code from Stibbons which works really well
  2. Integrated new axes WheelSteer and WheelThrottle using code from Stibbons, now you can drive your rovers from your control panel!
  3. New config file settings for enabling/disabling axes from Stibbons

New config.xml file settings for axes:

0: The internal value (supplied by KSP) is always used.

1: The external value (read from serial packet) is always used.

2: If the internal value is not zero use it, otherwise use the external value. (Now default!!!)

3: If the external value is not zero use it, otherwise use the internal value.

Data structure has changed, you will need to change your code for compatibility. Specifically, you need to update your ControlPacket to

struct ControlPacket {
byte id;
byte MainControls; //SAS RCS Lights Gear Brakes Precision Abort Stage
byte Mode; //0 = stage, 1 = docking, 2 = map
unsigned int ControlGroup; //control groups 1-10 in 2 bytes
byte AdditionalControlByte1; //other stuff
byte AdditionalControlByte2;
int Pitch; //-1000 -> 1000
int Roll; //-1000 -> 1000
int Yaw; //-1000 -> 1000
int TX; //-1000 -> 1000
int TY; //-1000 -> 1000
int TZ; //-1000 -> 1000
int WheelSteer; //-1000 -> 1000
int Throttle; // 0 -> 1000
int WheelThrottle; // 0 -> 1000
};

and add:

uint16_t ActionGroups;  //46 status bit order:SAS, RCS, Light, Gear, Brakes, Abort, Custom01 - 10

to the end of your VesselData.

To make it easier to use the action group statuses, a new function is added to the arduino code called "ControlStatus()". You can use this to say turn on leds for SAS, control groups, etc.:

digitalWrite(SASLED,ControlStatus(AGSAS));

Where the available parameters (AGSAS, AGRCS etc.) are defined in the first tab line 27.

Plugin:

https://sites.google.com/site/zitronfiles/KSPSerialIO_017_1.zip

Arduino Code:

https://sites.google.com/site/zitronfiles/KSPIODemo10.zip

Link to comment
Share on other sites

Awesome.

Just a clarification: You integrated the controls code from Stibbons. Does that mean something from a user perspective? The way the post is written it sounds like something else then his rover control.

Rebuilding looks more rewarding than ever.

In other news, I managed to transfer my control buttons to two shift registers, freeing up three analog pins and a large current drain on my +5 V. Next up is adding a MAX display driver chip for my LEDs.

Link to comment
Share on other sites

Just a clarification: You integrated the controls code from Stibbons. Does that mean something from a user perspective? The way the post is written it sounds like something else then his rover control.

It should work just the same, but with Stibbons' code now you can override the controller by using the keyboard and vice versa by choosing what you want in the config file.

@Zitronen, RasterProp seems to have a proposal for the Autopilot stuff:

https://github.com/Mihara/RasterPropMonitor/pull/149/commits

Interesting. Not what I was looking for, I was trying to do what Stibbons but with the new onautopilotupdate added in 0.90, but this looks simple enough to steal. It does mean you will need yet more switches and LEDs! :D

Link to comment
Share on other sites

Interesting. Not what I was looking for, I was trying to do what Stibbons but with the new onautopilotupdate added in 0.90, but this looks simple enough to steal. It does mean you will need yet more switches and LEDs! :D

I raise you a vacant Max7219, several CD4021s and the ability to multiplex inputs. Bring it on :sticktongue:

Link to comment
Share on other sites

Interesting. Not what I was looking for, I was trying to do what Stibbons but with the new onautopilotupdate added in 0.90, but this looks simple enough to steal.

The term you were looking for is "borrow" I think ;)

Oh and...

It does mean you will need yet more switches and LEDs! :D

have a close look at the top right ;)

at2mY35.jpg

Link to comment
Share on other sites

Hmmm, time for me to ask a question :). This is more about C itself rather than the plugin since it is not my first language ;)

I'm looking for an efficient way to access individual values in the VesselData struct.

Let me explain:

KSPSerialIO's VesselData struct contains all flight information in a handy format, 45 of them at the moment. On a test-rig of mine I want to display any four of them on a 4-row LCD. The naive approach to this would be to use a gigantic switch-statement for each row (code is untested):


#define DISPLAY_LINES 4

byte lineIndex[DISPLAY_LINES];

// these would be derived through inputs and not fixed as in this example
lineIndex[0] = 2; // AP
lineIndex[1] = 10; // TAp
lineIndex[2] = 16; // alt
lineIndex[3] = 40; // VOrbit

for (byte i = 0; i < DISPLAY_LINES; i++) {
switch (lineIndex[i]) {
case 1:
lcd.print(VData.id);
break;
case 2:
lcd.print(VData.AP);
break;
// add another 43 case-statements here
}
}

...but this solution makes me sad :(

Instead, I would like to store the address in memory at which the data that I want is located and use that so print it out directly, something like this:


#define DISPLAY_LINES 4

byte lineAddress[DISPLAY_LINES];
byte lineSize[DISPLAY_LINES];

// again, these would be derived through inputs and not fixed
lineAddress[0] = (byte*)&VData.AP;
lineSize[0] = sizeof(VData.AP);
lineAddress[1] = (byte*)&VData.TAp;
lineSize[1] = sizeof(VData.TAp);
lineAddress[2] = (byte*)&VData.alt;
lineSize[2] = sizeof(VData.alt);
lineAddress[3] = (byte*)&VData.VOrbit;
lineSize[3] = sizeof(VData.VOrbit);

for (byte i = 0; i < DISPLAY_LINES; i++) {
for (byte j = 0; j < lineSize[i]; j++) {
lcd.write(*lineAddress[i]+j);
}
}

Now, couple of questions - partially because I can't test this code until the weekend:

- will the lineAddress[0] = (byte) &Vdata.AP; part work as intended and give me the value of the address in memory where the apoapsis value is stored?

- in the lcd.write(*lineAddress+j); line, will this really point to each byte in the value I want or does the pointer dereference before I add j to the address?

- and most importantly: is there a better way to do all this?

Thanks a TON

Link to comment
Share on other sites

I think you will need to use 16bit rather than byte to store the addresses. Almost all of the data are in 4 byte blocks, so you may get away with just incrementing the address by 4 for each line for a large part of the struct. Now the tricky part will be figuring out what TYPE the variable is, if you just blindly print out lcd.write(*lineAddress+j); you will just end up with nonsensical stuff. You would need to cast a float into a float before you print it out, unless you are like Neo in the Matrix or something :).

Link to comment
Share on other sites

Now that you point that out a 16-bit address seems logical. Although the serial comms KSPBoardReceiveData() uses uint8_t to store the address of VData as a whole. Interesting that that works.

Regarding the typecasting you definitely have a point, I didn't think that one through :D. I think I have a rough idea that involves storing the values behind the address in a buffer and then comparing the buffer with a typecast to long of that buffer - if that's the same it's long, otherwise it's float. That might not work though... hmmm

More thinking required I believe... if anyone has a better approach (see question 3 above ;)) let me know.

Link to comment
Share on other sites

Looks like the effort required to do what I had in mind is not worth the result. I welcome my new 46-case switch-statement overlord! :-(

In other news @Zitronen, the config.xml file has ThrottleEnable set to 2, which seems to require a "throttle-off" ("x" key) upon launch, in order to make the hardware throttle actually able to put the throttle in game to zero. Without the "x" the game throttle simply jumps back to the 50% that it was at launch when the hardware throttle goes to zero. I've changed the ThrottleEnable to 1, which seems to work better.

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...