Jump to content

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


zitronen

Recommended Posts

Just tested with my Leonardo using the default script. Only tested very limited; no docking, SOI changes, or anything like that.

I could not really see a delay with either 38400 baud or at 115200 baud, so if Mulbin was having delays, I do not know what could be the cause. The in-game indicators in the top right worked correctly (I assume the specific method is a temporary measure). Also the toggling worked as well as it ever could. As you said, the game only registers a change if the Arduino sends a different value than before (one of the reads is different) and it will set it to the proper value sent from the Arduino. As such, you can have the Arduino be an optional input but won't cause any problems if you switch to purely keyboard mid-game. As I said, this is the best system I can think of and it works perfectly in my limited testing.

Indicators also all work properly as expected (as they did in the purely Arduino-receive version), and I had no other noticeable problems (random crashes or slowdowns) with vanilla KSP in my limited testing.

At Mulbin: very nice looking frontplate. Is that a printed metal board? I only fool around with things and most of my Arduino projects don't have a case or are enclosed in LEGOs due to my limited resource for making nice things, but I am hoping to learn/get my hands on the means to do nicer things. Also, any suggestions on good sites for cool-looking switches and such? The only hobby electronic sites I know of are Adafruit and Sparkfun which have a nice but limited selection.

Link to comment
Share on other sites

so, do you think your plugin could handle something like this?

https://www.sparkfun.com/products/9032

I think it would be good for docking.

Would also like an analogue throttle, do you think that is possible?

I am thinking I might need a new Arduino with more inputs, or something like this

http://numato.com/digital-and-analog-io-expander-shield

Link to comment
Share on other sites

so, do you think your plugin could handle something like this?

https://www.sparkfun.com/products/9032

I think it would be good for docking.

Would also like an analogue throttle, do you think that is possible?

I am thinking I might need a new Arduino with more inputs, or something like this

http://numato.com/digital-and-analog-io-expander-shield

Just get an Arduino Mega 2560.... Has plenty of ports (54 Input/Output).

Link to comment
Share on other sites

I am still amazed at how this plugin is turning out to make me do a hardware project similar to what Mulbin is doing.

As for what Pantner said:

Would also like an analogue throttle, do you think that is possible?

I did find a way for an analog value to be sent to control the throttle with an older version of this plugin. I am posting the code. Just be aware that it is for the .11 version since I forgot to update until yesterday. I did notice the since it is analog there is no way to make a value be constantly the same, other than 0 or 1, due to the nature of analog components being electrically noisy.

Arduino code


//Code here is in the KSPIODemo file
case 1:
FuelLights();
SendThrottle();//NEW LINE
break;
}

// I put this function in the Utilities file
void SendThrottle(){
CurThrottle = analogRead(ThrPIN);
CurThrottle = 1023.0 - CurThrottle;
CurThrottle = map(CurThrottle,657.0,1023.0,0.0,100.0)/100.0;
if(PrevThrottle != CurThrottle){
char ThrottleChar[4];
dtostrf(CurThrottle,4,2,ThrottleChar);
String ThrottleStr = String(ThrottleChar);
Serial.println("KSP;1;"+ThrottleStr);
}
PrevThrottle = CurThrottle;
}

Plugin Code


if (parsed[0] == "KSP")
{
short messageID = (short)double.Parse(parsed[1]);
if (messageID == 0)
{
DisplayFound = true;
}
//NEW CODE BELOW
if (messageID == 1)
{
float ThrVal = float.Parse(parsed[2]);
FlightInputHandler.state.mainThrottle = ThrVal;
}
}

Link to comment
Share on other sites

I did find a way for an analog value to be sent to control the throttle with an older version of this plugin. I am posting the code. Just be aware that it is for the .11 version since I forgot to update until yesterday. I did notice the since it is analog there is no way to make a value be constantly the same, other than 0 or 1, due to the nature of analog components being electrically noisy.

i'm sorry, I don't actually understand what you mean.

Firstly, you saying to get that working (at-least, at the moment) I need to compile from source with that code?

And not sure what you mean by the analogue 0/1 thing...

Link to comment
Share on other sites

Just tested with my Leonardo using the default script. Only tested very limited; no docking, SOI changes, or anything like that.

I could not really see a delay with either 38400 baud or at 115200 baud, so if Mulbin was having delays, I do not know what could be the cause. The in-game indicators in the top right worked correctly (I assume the specific method is a temporary measure). Also the toggling worked as well as it ever could. As you said, the game only registers a change if the Arduino sends a different value than before (one of the reads is different) and it will set it to the proper value sent from the Arduino. As such, you can have the Arduino be an optional input but won't cause any problems if you switch to purely keyboard mid-game. As I said, this is the best system I can think of and it works perfectly in my limited testing.

Great thanks! I will take out the debug messages and update the info on the first page.

so, do you think your plugin could handle something like this?

https://www.sparkfun.com/products/9032

I think it would be good for docking.

Would also like an analogue throttle, do you think that is possible?

I am thinking I might need a new Arduino with more inputs, or something like this

http://numato.com/digital-and-analog-io-expander-shield

Yes axes are in the plans (roll pitch yaw throttle etc.). I have been using old RC transmitter joystick for docking, works very nicely.

I did find a way for an analog value to be sent to control the throttle with an older version of this plugin. I am posting the code. Just be aware that it is for the .11 version since I forgot to update until yesterday. I did notice the since it is analog there is no way to make a value be constantly the same, other than 0 or 1, due to the nature of analog components being electrically noisy.

The axes will be implemented using the same data packet structure, I'm thinking 2 bytes per axis. There will need to be config settings to allow you to turn off certain axes that your are not using.

My current plans are:

1. Finish adding the rest of the major controls: lights, gear, etc.

2. Experiment with axes

3. Control groups? Go back and add more outputs?

Link to comment
Share on other sites

Yes axes are in the plans (roll pitch yaw throttle etc.). I have been using old RC transmitter joystick for docking, works very nicely.

is that going through the Arduino or separate? I know some of the good ones have computer controls so you can do flight sims with them.

Seems I have a fair bit to learn about the Arduinos, will need to get playing :P

Link to comment
Share on other sites

i'm sorry, I don't actually understand what you mean.

Firstly, you saying to get that working (at-least, at the moment) I need to compile from source with that code?

And not sure what you mean by the analogue 0/1 thing...

Yes you do need to compile from source with the given code. As for the analogue 0/1, I was trying to say the voltage usually not going to stay the same going across the analogue component. So the values may change by + or - one every time the arduino reads, even if the component does not change positions. Say your initial read is 10, the next read could be 11, 9, or 10. The reads should balance on one value.

I hope I am not adding more confusion... If I am, then ignore me trying to explain it because I am not an expert

Edited by AMirrodin
Clarification/ adding example
Link to comment
Share on other sites

thats good news that axes will be input as well as just an output. That means when I get to building the nav computer panel I can not only have readouts of current flight stats but also effectively program maneuvers manually :)

Link to comment
Share on other sites

Yes you do need to compile from source with the given code. As for the analogue 0/1, I was trying to say the voltage usually not going to stay the same going across the analogue component. So the values may change by + or - one every time the arduino reads, even if the component does not change positions. Say your initial read is 10, the next read could be 11, 9, or 10. The reads should balance on one value.

I hope I am not adding more confusion... If I am, then ignore me trying to explain it because I am not an expert

Yup, think I got ya :)

Update 5: added support for input, added input example, added description for the input packet format, see first post.

awesome, one question...

reading through the code, and I think I understand most of it, but what does the 'details' on this line mean

KSPBoardSendData(details(CPacket));

(from the 'output' page)

*EDIT - just letting you know, whacked my arduino on a breadboard and connected up a swtich and I was able to turn SAS on and off with it :)

Awesome work!

Edited by pantner
Link to comment
Share on other sites

reading through the code, and I think I understand most of it, but what does the 'details' on this line mean

KSPBoardSendData(details(CPacket));

(from the 'output' page)

*EDIT - just letting you know, whacked my arduino on a breadboard and connected up a swtich and I was able to turn SAS on and off with it :)

Awesome work!

Nice!

"details" is just a simple macro defined in the first tab line 20:


//macro
#define details(name) (uint8_t*)&name,sizeof(name)

So

KSPBoardSendData(details(CPacket));

is the same as

KSPBoardSendData((uint8_t*)&CPacket, sizeof(CPacket));

Link to comment
Share on other sites

Nice!

"details" is just a simple macro defined in the first tab line 20:


//macro
#define details(name) (uint8_t*)&name,sizeof(name)

So

KSPBoardSendData(details(CPacket));

is the same as

KSPBoardSendData((uint8_t*)&CPacket, sizeof(CPacket));

ahh, didn't see that!

Will need to do some more reading as to what things like uint8_t actually do :P

btw, forgot to mention, the timing for the control is instant, no delay.

also, if I want to add an LED light for something (ie, SAS) should I add an extra function into the loop to control that or should I add it into the 'output' function?

And should I be checking the state of the switch or getting feedback from the plugin as to whether it is 'on' or 'off'?

Link to comment
Share on other sites

also, if I want to add an LED light for something (ie, SAS) should I add an extra function into the loop to control that or should I add it into the 'output' function?

There really is no wrong way to do it per se, but since Zitronen's input and output macros are done so well, I would recommend just making it a separate function so that if he updates the library (the functions probably should just be turned into a library at this point), then you would not have to rewrite it.

And should I be checking the state of the switch or getting feedback from the plugin as to whether it is 'on' or 'off'?

I would recommend checking the feedback from the plugin. The game readings can be different from the Arduino if you use the keyboard to change any values (try toggling the SAS using the keyboard and with the Arduino plugged in and you will see what I mean).

Haven't tried it, so read Zitronen's post below.

Edited by Katamari
I was wrong...
Link to comment
Share on other sites

Yeah unfortunately I still have not found reliable ways of getting the status of SAS, Lights, etc from KSP. So for now if you want an indicator you can just simply hard wire a LED to the switch, if you use the keyboard then the LED will be wrong until you flip the switch again.

Edited by zitronen
Link to comment
Share on other sites

Yeah unfortunately I still have not found reliable ways of getting the status of SAS, Lights, etc from KSP. So for now if you want an indicator you can just simply hard wire a LED to the switch, if you use the keyboard then the LED will be wrong until you flip the switch again.

ok then, having a squiz through the source code now, is there anything there at the moment regarding checking the SAS status so I know what to look at?

btw, love

Debug.Log("KSPSerialIO: Dude do you even win32 serial port??");

Link to comment
Share on other sites

Just tried it using simple tactile buttons. The lights, gear, brakes, and abort all work. I could not get staging to work, though. Neither for initial takeoff/first stage nor any other stage after the first.

Link to comment
Share on other sites

Pretty epic plugin you got going here, I'm pretty adept at arduino having made self navigating robots and remote controlled robots using wireless serial etc, not sure how I could implement this in a way I'd like to use, I'd need a better screen than my 16x2 LCDs that's for sure, pretty tempting to assemble a custom controller/display combo, mount one or more joysticks into a base and add switches and readouts to make a steelbattalion-ish controller but that needs some pretty nice looking hardware to make it look good.

Frankly one plug-in I'm surprised hasn't happened yet is one of the RPM MFD:s on your iPad/iPhone/Android device.

Link to comment
Share on other sites

So... if my limited understanding and guesswork is right, my arduino code should now look like this...?

Definitions in "KSPdemo2"


#define SASPIN 8
#define RCSPIN 9
#define LIGHTPIN 7
#define GEARPIN 6
#define BRAKEPIN 5
#define ABORTPIN 4
#define STAGEPIN 3

Code in the "output" tab

void output() {
now = millis();
controlTime = now - controlTimeOld;
if (controlTime > CONTROLREFRESH){
controlTimeOld = now;
controls();
}
}

void controls() {
if (Connected) {

if (digitalRead(SASPIN))
MainControls(SAS, LOW);
else
MainControls(SAS, HIGH);

if (digitalRead(RCSPIN))
MainControls(RCS, LOW);
else
MainControls(RCS, HIGH);

if (digitalRead(LIGHTPIN))
MainControls(LIGHTS, LOW);
else
MainControls(LIGHTS, HIGH);

if (digitalRead(GEARPIN))
MainControls(GEAR, LOW);
else
MainControls(GEAR, HIGH);

if (digitalRead(BRAKEPIN))
MainControls(BRAKE, LOW);
else
MainControls(BRAKE, HIGH);

if (digitalRead(ABORTPIN))
MainControls(ABORT, LOW);
else
MainControls(ABORT, HIGH);

if (digitalRead(STAGEPIN))
MainControls(STAGE, LOW);
else
MainControls(STAGE, HIGH);

KSPBoardSendData(details(CPacket));
}
}

void controlsInit() {
pinMode(SASPIN, INPUT_PULLUP);
pinMode(RCSPIN, INPUT_PULLUP);
pinMode(LIGHTPIN, INPUT_PULLUP);
pinMode(GEARPIN, INPUT_PULLUP);
pinMode(BRAKEPIN, INPUT_PULLUP);
pinMode(ABORTPIN, INPUT_PULLUP);
pinMode(STAGEPIN, INPUT_PULLUP);
}

void MainControls(byte n, boolean s) {
if (s)
CPacket.MainControls |= (1 << n); // forces nth bit of x to be 1. all other bits left alone.
else
CPacket.MainControls &= ~(1 << n); // forces nth bit of x to be 0. all other bits left alone.
}

EDIT - bear in mind that the HIGH /LOWs are all reversed in my code to make the switches function the correct way round.

Edited by Mulbin
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...