zitronen

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

Recommended Posts

Qst 1 - What are the errors?

Qst 2 - Have you gone through the Arduino Tutorials?

They're a great place to start to get your head around the hardware, coding, and functionality of the devices.

Also, you should add things little by little (usually one at a time) to make sure everything is working, and to make troubleshooting / debugging a whole lot easier! :)

Sorry, rough day at work and I just sat down and re-tried. Took a different approach after doing some reading (a nice app for iPhone called Arduino Companion), everything seems to compile correctly. All of my LEDs have been coded out for my little project, just gotta try it on the breadboard tomorrow and see if it works. Expecting no problems.

Thank you very much though!

Share this post


Link to post
Share on other sites
Sorry, rough day at work and I just sat down and re-tried. Took a different approach after doing some reading (a nice app for iPhone called Arduino Companion), everything seems to compile correctly. All of my LEDs have been coded out for my little project, just gotta try it on the breadboard tomorrow and see if it works. Expecting no problems.

Thank you very much though!

Feel free to PM with any issues if you're still having troubles :)

Share this post


Link to post
Share on other sites
Yeah int on arduino is 16 bit, long is 32bit. Bit of a trap if you are using other platforms.

The ControlPacket now works fine :)

But there are 3 integers in the VesselData-Packet. Treating them as 32Bit works fine but switching them also to 16Bit don't work at all.

Your pugin is sending a payloadsize of 189 Bytes. The VesselData-Packet has 3x byte + 41x float, 3x int+ 2x UInt32+ 1x UInt16 = 183 Bytes (using 16-Bit int) or 189 Bytes (using 32-Bit int).

Edited by Sengir Vampire

Share this post


Link to post
Share on other sites

The VesselData packet as described on the first page is from the C# plugin code - those integers are indeed 32 bits. The arduino side uses longs to store those.

(if c# supported fixed-width data types I'd say just switch to those on both sides and be done, but it doesn't look like it does. :( )

Share this post


Link to post
Share on other sites
Now I changed to Int16 in ControlPacket and Int32 in VesselData and everything works fine.

Great job!

Thanks for sharing too (for other peoples sake :) )

Share this post


Link to post
Share on other sites

Hi guys, I'm trying to follow the first tutorial (3 leds warning) but it doesn't work... Can someone post the code? Thanks

Share this post


Link to post
Share on other sites
Hi guys, I'm trying to follow the first tutorial (3 leds warning) but it doesn't work... Can someone post the code? Thanks

If you download the example sketch, and wire up the components as per the instructions / designation in the sketch and have the plugin installed - it should all work.

Can you step us through what you have done? :)

Share this post


Link to post
Share on other sites
Ok so we are using 189 out of 255 bytes in the packet, so 66 bytes left. It's not a disaster if we run out of bytes, since we can just add another packet. However, since RAM is very limited on the AVR chips (255 bytes is a large chunk of RAM!), I would still avoid using too much.

So currently we have requests for:

Current stage: will add as byte, so 255 stages max (surely enough for everybody?)

Total stages: will add as byte, so 255 stages max, I didn't know it's as simple as Staging.StageCount! Thanks Cbrollin

Nice for my staging button. I can have a simple stage counter above it, and control the LED in the button!

Prograde + retrograde pitch and heading: will add as 4 floats (16 bytes), if I can figure out where to find the data.

PE, AP, and SOI name for next orbit patch: 2 floats, 1 byte (9 bytes total) can be added if people want it, could be useful for crazy people like stibbons :D

(I'm also crazy enough to be completely happy maintaining my own fork with bits nobody else wants :) )

You're already using Orbit.GetVel for orbital velocity. Pitch and heading are just the x and y components of that vector, aren't they?

I suspect only sending prograde would cut down on packet size, retrograde can be calculated by flipping the heading. The extra space would be better used sending orbit normal and radial vectors. :)

With my recent FDAI/ADI (Flight Director Attitude Indicator) "navball" acquisition (My navball came from an Israeli F-4 Phantom simulator), this stuff is critical to me! In order for the Flight Director crosshairs to guide me on my physical navball, I need to have the pitch and heading of not just Prograde, but all the heading vectors. I think stibbons is correct. If you send prograde, you just flip it 180° in the arduino to get retrograde. True of all the vectors. Sending Prograde, Radial, Normal, Target, and Maneuver Node is critical to be able to fly with a real navball. You can also flip every one of those 180° to get it's inverse. I want to have a pair of rotary switches (5 position and 2 position) to select my desired vector. That would then display on the navball's Flight Director crosshairs.

Without those 5 sets of data, the navball can't display markers.

In the mean time, I'm teaching myself coding for Arduino with this project. The big thing for me is creating an arduino program that reads the data over serial, converts it into the polarized attenuation multipliers for each of the three windings of a synchro (emulated), and then applies those multipliers to the reference 400 Hz sine wave. In the end, there are 10 signals that go to the FDAI to spin the Attitude Indicator ball. 1 reference, and three triplets of signals per axis. The angle is determined by the polarity and attenuation (in relation to the reference) of the three inputs (per axis). You do that for each of the three axes, and then for the Flight Director crosshairs, you run them exactly like regular analog meters... Cause they are analog meters.

My goal is to as much of the work in software, and limit hardware to low cost DACs and op-amps and such... I want to make it CHEAP to interface an FDAI to Kerbal... The FDAI will still be expensive as hell... but hey, Anything I can do to keep the costs as low as possible.

For reference, my unit is an ARU-11/A, I think made by Lear-Siegler, but the label came off at some point, and only the model/serial number label and the Israeli company that did the sim still has their label on it.

So if it's 8 bytes per vector, that's 40 bytes to get that data out, plus 9 for the next orbit patch info, plus 2 to cover staging... That's 51 bytes of 66 remaining... That leaves room for 15 bytes.

I personally wouldn't mind rate of roll, pitch, and yaw... That'd be 12 bytes, to add three floats, right? Pretty expensive for what little is left, and not NEARLY as important as the heading nodes though. I can look at the navball to see if I'm spinning... But rate of change would be nice... Those values would leave only 3 bytes left. Thing is... That can be calculated entirely inside the arduino though, right? If you sample the yaw, pitch, and roll periodically, and sample the MET, and then sample it all again, periodically, it should be possible to calculate the rate of change from those values, correct? Going based on MET also keeps it game time accurate, adjusting for physics lag, right?

SAS modes: not stalled, just completely forgot about them :sticktongue: will have a look at it again.

For the guys looking for a safe to deploy parachute thingie, I suspect it's base on indicated air speed, which is already included. I think you only need to check for IAS < 250 or something.

Parachutes Safe to deploy status... A MEEEELION times yessss! :sticktongue:

Any way to have a means to select MechJeb Smart A.S.S. vs stock in the config files, if this gets implemented? Can an extra 2 bits be packed in there somewhere to select Stock nodes, MJ Orbital, MJ Target, MJ Surface modes? Stock has SAS Stability, Prograde, Retrograde, Normal, Anti-Normal, Radial, Anti-Radial, Target, and Maneuver Node. MechJeb has the three tabs with the normal orbitals on one tab, but things like Target + and Target - and relative + and - and such... It'd be super cool if we could select those modes and be able to reassign those inputs to the different tabs/stock. I'm probably just being confusing at this point... I better go to bed. :(

I'm just REALLY excited to have a real navball, plus other gauges and readouts and such! I just REALLY want to be able play KSP with an all new level of immersion!

I'm so exited! And I just can't hide it! :0.0::cool:

Edited by richfiles

Share this post


Link to post
Share on other sites
If you download the example sketch, and wire up the components as per the instructions / designation in the sketch and have the plugin installed - it should all work.

Can you step us through what you have done? :)

My wiring is correct, but I'm having some trouble with the arduino code... maybe because i'm noob with it but when I download the .rar with demos, what i should upload to arduino? Also when I start ksp it says: no display found..

Share this post


Link to post
Share on other sites
My wiring is correct, but I'm having some trouble with the arduino code... maybe because i'm noob with it but when I download the .rar with demos, what i should upload to arduino? Also when I start ksp it says: no display found..

KSP is saying there's no display found because you haven't yet programmed your arduino to talk to it. :) And you end up compiling all of the files in the demo folder to a single binary that gets uploaded. Here's how I do it:

  • Download the KSPIODemo12.zip file.
  • Extract it, which will create a folder named KSPIODemo12.
  • Move the KSPIODemo12 folder to your Arduino sketchbook folder. Check the preferences in the Arduino IDE to find out where this is.
  • If the Arduino IDE is currently running, restart it so it will reread the sketchbook folder.
  • Go to File -> Sketchbook and select KSPIODemo12. This should open a new window, with all of the files contained in the folder open in different tabs.

If you hit the upload button in this window (it won't matter which tab is showing when you do so), the sketch will compile and upload. You should be good to go after that.

Share this post


Link to post
Share on other sites

Over on Curse, this was released...

http://www.curse.com/ksp-mods/kerbal/232908-chute-safety-indicator

Maybe you can contact the developer and see how they are doing this?

They are using the parachute staging icons to visually indicate unsafe, risky, and safe to deploy (using colors on the staging icons themselves).

Share this post


Link to post
Share on other sites
KSP is saying there's no display found because you haven't yet programmed your arduino to talk to it. :) And you end up compiling all of the files in the demo folder to a single binary that gets uploaded. Here's how I do it:

  • Download the KSPIODemo12.zip file.
  • Extract it, which will create a folder named KSPIODemo12.
  • Move the KSPIODemo12 folder to your Arduino sketchbook folder. Check the preferences in the Arduino IDE to find out where this is.
  • If the Arduino IDE is currently running, restart it so it will reread the sketchbook folder.
  • Go to File -> Sketchbook and select KSPIODemo12. This should open a new window, with all of the files contained in the folder open in different tabs.

If you hit the upload button in this window (it won't matter which tab is showing when you do so), the sketch will compile and upload. You should be good to go after that.

Thanks dude :):D:kiss:

Share this post


Link to post
Share on other sites
Over on Curse, this was released...

http://www.curse.com/ksp-mods/kerbal/232908-chute-safety-indicator

Maybe you can contact the developer and see how they are doing this?

They are using the parachute staging icons to visually indicate unsafe, risky, and safe to deploy (using colors on the staging icons themselves).

We already know how to do this, just check for Mach < 0.8

Share this post


Link to post
Share on other sites

I am really enjoying working through this and getting things working the way I would like them (huge thanks to Sputnix for a lot of help).

Has anyone had any luck with using shift registers to control LEDs (I only have 74HC595 shift registers). All of the tutorials are about continuously shifting out bytes in a pattern, but I was thinking this could be modified so that the LEDs light up depending on set warnings and cautions. The only way I could think of doing this is to shift out a specific byte for a given warning, but that will end up being a lot of code to cover all the conditions.

Share this post


Link to post
Share on other sites

So basically you want each output of the register to represent a different warning? No problem.

You assign each bit of your display byte to a different warning. You might say bit 0 is out of fuel, bit 1 is out of electric charge, bit 2 is whether the landing gear is deployed, and so on. Now, when you want to activate a warning LED, you just have to set the appropriate bit to 1.

Use a function like this (I'm totally copying and pasting a slightly-modified function from zitronen's code here :) )


byte warningSet(byte warnings, byte n, boolean s) {
if (s) {
warnings |= (1 << n); // forces nth bit to 1
} else {
warnings &= ~(1 << n); // forces nth bit to 0
}
return warnings
}

Using the above example, if you deploy the landing gear, you call the warningSet function like this to turn on bit 2


warnings = warningSet(warnings, 2, true);

And then, every time you update the display, just shift out the entire warnings byte.

Make sense?

Edited by stibbons

Share this post


Link to post
Share on other sites

Let me see if I can wrap my head around this. I'm just having some trouble connecting what you are explaining to what I want to do. It feels like that aha moment is right there but I am not quite seeing it.

Each output pin from a shift register corresponds to a bit in the total byte being shifted out. I have each LED physically connected to an output pin of the shift register and that will correspond to the bit in the byte.

So, would I set up something like warnings = for each LED combination I would want to display? Kind of like if the landing gear is down, but I would also have to set up another for if the landing gear is down and electrical charge is also low (and so on)?

Share this post


Link to post
Share on other sites

You just need to call the function once for each bit in the byte. The function changes one bit, and leaves all others unchanged.

So first you'd check the fuel state, and then call `warnings = warningSet(warnings, 0, true);` or false or whatever.

Then you'd check the power state, and call `warnings = warningSet(warnings, 1, true);` or false.

Then you'd check the landing gear, and call `warnings = warningSet(warnings, 2, true);` or false.

Then check whatever you've got bit 3 representing, and so on.

Share this post


Link to post
Share on other sites

Alright, so to set it all up to call a function for each indication I would need to just set it up how you explained for each indication that is needed.

Would I handle when they are called like how it is done with the caution and warning that comes in the code by default using the if( caution != 0) statements but replacing caution with one of my choosing?

Share this post


Link to post
Share on other sites
Update 0.17.4

Changed:

Fixed overheating bug caused by 1.0.4 update (Found by Sputnix, thanks!)

Added current stage number- byte

Added total stages - byte (Thanks Cbrollin)

Plugin:

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

Arduino Code:

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

Thanks for that! :D

RE: The Arduino code -

This is the first update that's been rolled since I started using the arduino + plugin --

is it quicker/easier to copy/paste the relevant updated parts of the various tabs to what we have implemented?

Or is it better to just transfer our custom code into the updated arduino sketch / tab?

Share this post


Link to post
Share on other sites
Would I handle when they are called like how it is done with the caution and warning that comes in the code by default using the if( caution != 0) statements but replacing caution with one of my choosing?

That's probably the easiest way to do it, yeah. :)

is it quicker/easier to copy/paste the relevant updated parts of the various tabs to what we have implemented?

Or is it better to just transfer our custom code into the updated arduino sketch / tab?

The only real changes in the demo sketch will be in the VesselData and ControlPacket definitions. You should be able to just make sure that you update those definitions in your code to match, to make your sketch run with the new plugin.

Hey zitronen, could I bug you to update your git repository again? I'd like to keep marzubus' cross-platform fork up to date while they're MIA.

Share this post


Link to post
Share on other sites

Alright, I added the code to the right tabs and have everything set up how I figure it should be set up. I decided to copy the code you showed in the example to get it working before I have a go at changing it. After some several compile/builds I managed to get the errors down to a couple, but I am unsure how to correct them.

Here is what I have added:

Utilities.ino


if (fuelcaution != 0)
warnings = warningSet(warnings, 0, true);



void warningSet(byte warnings, byte n, boolean s) {
if (s) {
warnings |= (1 << n); // forces nth bit to 1
} else {
warnings &= ~(1 << n); // forces nth bit to 0
}
return warnings;
}

The errors I am getting are:

/utilities.ino: In function 'void Indicators()':

/utilities.ino: error: void value not ignored as it ought to be

warnings = warningSet(warnings, 0, true);

/utilites.ino: In function 'void warningSet(byte, byte, boolean)'

/utilities.ino: error: return-statement with a value, in function returning 'void' [-fpermissive]

return warnings;

[stino - Edit with error code 1.]

Edited by kungfufishstick
corrections

Share this post


Link to post
Share on other sites

Oh, I messed it up yesterday sorry.

In the function definition for warningSet, the first word defines what that function returns. I accidentally set it to void when it later returns a byte. :(

Try this instead:

byte warningSet(byte warnings, byte n, boolean s) {
if (s) {
warnings |= (1 << n); // forces nth bit to 1
} else {
warnings &= ~(1 << n); // forces nth bit to 0
}
return warnings;
}

(future readers, I totally went back and fixed yesterday's post too)

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.