Shop OBEX P1 Docs P2 Docs Learn Events
Custom Space Simulator System for KSP using the Prop — Parallax Forums

Custom Space Simulator System for KSP using the Prop

The more I look at this the more it looks like this is really going to happen.

I want to make a simulator sort of like how some people make 737 cockpits for FSX. In this case I want to make an Apollo themed system for Kerbal Space Program using the Prop. I may also be adding a Teensy in the mix.

There are many things to get working, such as multi monitor etc. But a lot of the work will be getting all my buttons, displays, and joysticks to communicate back and forth with the game.

forum.kerbalspaceprogram.com/threads/66393-Hardware-Plugin-Arduino-based-physical-display-serial-port-io-tutorial-%2806-Jun%29

Here is the mod that should make this possible.

So anyway this is where I plan to have the thread for this. Timelines always change but I hope to start construction in early January. So for the time being I'm going to be trying to see if I can actually get the Prop to take in the physical flipping of a switch and watch my RCS thrusters activate in game etc.

If any of you have some advice for this project I'm all ears. I got the main essentials working. There are a few other things such as finding a way to delay data transmission to command and control for example to simulate the time it would take to communicate light minutes away.

Some inspiration and examples:

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



The purpose will be to teach kids about Space, Orbital Mechanics, the whole 9 through my own teeny tiny space camp as part of my teeny tiny education company.

Being a business venture to the tune of 5-10 grand there are decent odds this idea will die if the numbers slowly narrow down to a loss. But for now it's looking feasible so I need to start checking in to the difficulty and cost of the hardware.

Any advice please fire away.
«134

Comments

  • Reserved for future updates
  • Well I have some first questions:

    Do you think the Prop is the right way to handle this? I will be needing a way to effectively get more IO. I think the Prop is right for this.
    What language should I use? I think I should use SPIN, assuming I do use the Prop.
  • Haha that figures. I didn't know there was a KSP serial plugin. I've been using a Propeller connected to a Pro Micro as an HID. Thanks for posting that link. I will try it and do some comparisons.

    I wanted a handheld controller for EVA, with adjustable RCS bursts. I'd just imagine myself in a spacesuit and bam, no cockpit needed. It's 25% done. I used SPIN, there is nothing complex about the programming so I think you could use anything you want.

    The backyard rocket ship tree house is one of the best home cockpits in my book.
  • Keith YoungKeith Young Posts: 569
    edited 2015-11-03 20:04
    My current difficulty is getting the Prop to communicate with KSP.

    There is a handshake that needs to happen. Their arduino code:

    if (KSPBoardReceiveData()){
    deadtimeOld = now;
    returnValue = id;
    switch(id) {
    case 0: //Handshake packet
    Handshake();
    break;
    case 1:
    Indicators();
    break;
    }


    void Handshake(){
    digitalWrite(GLED,HIGH);

    HPacket.id = 0;
    HPacket.M1 = 3;
    HPacket.M2 = 1;
    HPacket.M3 = 4;

    KSPBoardSendData(details(HPacket));
    //Serial.println(F("KSP;0"));
    //delay(1000);
    }


    void KSPBoardSendData(uint8_t * address, uint8_t len){
    uint8_t CS = len;
    Serial.write(0xBE);
    Serial.write(0xEF);
    Serial.write(len);

    for(int i = 0; i<len; i++){
    CS^=*(address+i);
    Serial.write(*(address+i));
    }

    Serial.write(CS);
    }

    HandShakePacket HPacket;




  • Wow.
    That's one simulation I've never really found the time to get into. But the one described in here:
    http://forum.kerbalspaceprogram.com/threads/66393-Hardware-Plugin-Arduino-based-physical-display-serial-port-io-tutorial-%2806-Jun%29

    That is the ship building aspect of it in there.
  • Yep that's the mod I linked which has Arduino code I'm trying to port to SPIN.

    Once I know how to handle the handshake and the data in and out it should be fairly easy. Granted expanding the IO might not be super easy either since I haven't done it.

    At the moment I'm still stuck on the handshake.
  • However.... I'd give anything to know where the guy tracked down a P-suit as described in the photo series you also linked to earlier.

    They closed a long time ago but there was a store on Canal Street that sold gigatons of surplus gear, including the helmet shown here: https://en.wikipedia.org/wiki/Francis_Gary_Powers oddly enough the suit he's wearing sometimes shows up in a variety of surplus stores in the city.

    However.... Be careful. Those kerbals do not have the training our guys have.....

    And I might even give that one for the other guy a trial later this month as soon as I figure out how to support the software here.
  • Which software are you trying to support? The KSP game?
  • However.... I'd give anything to know where the guy tracked down a P-suit as described in the photo series you also linked to earlier.

    They closed a long time ago but there was a store on Canal Street that sold gigatons of surplus gear, including the helmet shown here: https://en.wikipedia.org/wiki/Francis_Gary_Powers oddly enough the suit he's wearing sometimes shows up in a variety of surplus stores in the city.

    However.... Be careful. Those kerbals do not have the training our guys have.....

    And I might even give that one for the other guy a trial later this month as soon as I figure out how to support the software here.

    Answering myself here, I still wonder why they prefer a Debian based example of Linux where there are scads of them out there.

  • I don't remember if I ever tried it on Linux.

    However I don't think there is a KSPIO type mod for Linux. The main one is Windows only, and the only fork I currently know of is for Mac.

    Do you guys know anyone that knows how to port arduino to SPIN? Still having some trouble with this handshake.
  • This seems to be where it's looking for the handshake in the windows mod itself. Not sure why I'm not getting this to work.

    private void Port_ReceivedEvent(object sender, SerialReceivedEventArgs e)
    {
    while (Port.BytesToRead > 0)
    {
    if (processCOM())
    {
    switch (id)
    {
    case HSPid:
    HPacket = (HandShakePacket)ByteArrayToStructure(buffer, HPacket);
    Invoke("HandShake", 0);

    if ((HPacket.M1 == 3) && (HPacket.M2 == 1) && (HPacket.M3 == 4))
    {
    DisplayFound = true;

    }
    else
    {
    DisplayFound = false;
    }
    break;
    case Cid:
    VesselControls();
    //Invoke("VesselControls", 0);
    break;
    default:
    Invoke("Unimplemented", 0);
    break;
    }
    }
    }
    }
  • Good question.

    Oddly enough there is a Steam (also a Debian based) system who connects to an ordinary HDTV set, the big problem is that its more designed for playing regular games that exist on Steam. Chances are its not capable of, ah, playing KSP.

    Not surprisingly there's a LUG meeting here coming up on the 18th concerning SteamOS. Here:
    http://www.meetup.com/nylug-meetings/events/225196157/meetup.com/nylug-meetings/events/225196157/

    And of course the regular Hack Night meeting for Tuesday:
    http://www.meetup.com/nylug-meetings/events/226335423/ meetup.com/nylug-meetings/events/226335423/

    Not that it matters, but someone in the area might be interested in the second, and we're always interested in new members for the first.
  • Keith YoungKeith Young Posts: 569
    edited 2015-11-03 20:05
    OK I'm totally not an expert at this but it seems like there is a checksum going on.


    Here is part of the code in the game mod:

    private static bool processCOM()
    {
    byte calc_CS;

    if (rx_len == 0)
    {
    while (Port.ReadByte() != 0xBE)
    {
    if (Port.BytesToRead == 0)
    return false;
    }

    if (Port.ReadByte() == 0xEF)
    {
    rx_len = (byte)Port.ReadByte();
    id = (byte)Port.ReadByte();
    rx_array_inx = 1;

    switch (id)
    {
    case HSPid:
    structSize = Marshal.SizeOf(HPacket);
    break;
    case Cid:
    structSize = Marshal.SizeOf(CPacket);
    break;
    }

    //make sure the binary structs on both Arduino and plugin are the same size.
    if (rx_len != structSize || rx_len == 0)
    {
    rx_len = 0;
    return false;
    }
    }
    else
    {
    return false;
    }
    }
    else
    {
    while (Port.BytesToRead > 0 && rx_array_inx <= rx_len)
    {
    buffer[rx_array_inx++] = (byte)Port.ReadByte();
    }
    buffer[0] = id;

    if (rx_len == (rx_array_inx - 1))
    {
    //seem to have got whole message
    //last uint8_t is CS
    calc_CS = rx_len;
    for (int i = 0; i < rx_len; i++)
    {
    calc_CS ^= buffer;
    }

    if (calc_CS == buffer[rx_array_inx - 1])
    {//CS good
    rx_len = 0;
    rx_array_inx = 1;
    return true;
    }
    else
    {
    //failed checksum, need to clear this out anyway
    rx_len = 0;
    rx_array_inx = 1;
    return false;
    }
    }
    }

    return false;
    }
  • I'm not an expert in how the Prop does its job. But wouldn't that code be easier to read inside a code box? I'd also say you're getting it.
  • Keith YoungKeith Young Posts: 569
    edited 2015-11-03 20:05
    Still not working. Hopefully these code boxes help. Didn't know they worked yet on new forum.
    private static bool processCOM()
            {
                byte calc_CS;
    
                if (rx_len == 0)
                {
                    while (Port.ReadByte() != 0xBE)
                    {
                        if (Port.BytesToRead == 0)
                            return false;
                    }
    
                    if (Port.ReadByte() == 0xEF)
                    {
                        rx_len = (byte)Port.ReadByte();
                        id = (byte)Port.ReadByte();
                        rx_array_inx = 1;
    
                        switch (id)
                        {
                            case HSPid:
                                structSize = Marshal.SizeOf(HPacket);
                                break;
                            case Cid:
                                structSize = Marshal.SizeOf(CPacket);
                                break;
                        }
    
                        //make sure the binary structs on both Arduino and plugin are the same size.
                        if (rx_len != structSize || rx_len == 0)
                        {
                            rx_len = 0;
                            return false;
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    while (Port.BytesToRead > 0 && rx_array_inx <= rx_len)
                    {
                        buffer[rx_array_inx++] = (byte)Port.ReadByte();
                    }
                    buffer[0] = id;
    
                    if (rx_len == (rx_array_inx - 1))
                    {
                        //seem to have got whole message
                        //last uint8_t is CS
                        calc_CS = rx_len;
                        for (int i = 0; i < rx_len; i++)
                        {
                            calc_CS ^= buffer[i];
                        }
    
                        if (calc_CS == buffer[rx_array_inx - 1])
                        {//CS good
                            rx_len = 0;
                            rx_array_inx = 1;
                            return true;
                        }
                        else
                        {
                            //failed checksum, need to clear this out anyway
                            rx_len = 0;
                            rx_array_inx = 1;
                            return false;
                        }
                    }
                }
    
                return false;
            }
    
  • I can't offer any help as my knowledge isn't up to par for the task at hand, but ever since I heard of the Kerbal Space Program, I have felt that the Propeller was an excellent matchup. Hope the right people get involved to get this off the ground!
  • So they're saying hpacket contains id, M1, M2, M3.

    Does that give it a length of 4? I don't think you can have a zero length.

    Next, in the Arduino and in this code (C# I think) they say CS ^=

    Can someone confirm if SPIN does the same operation? It seems so.

    Anyway I still can't get this handshake working, and I'm at the point where I'm not quickly finding dumb mistakes in my attempt.

    I'd really rather use the Prop for this than an Arduino. Arduino should drop right in but I'd like to add features they might not have in.

    In addition I'd like the kids to be able to program the module in SPIN or C using the Prop so they can write things such as when fuel is low sound an alarm, etc.

    Hopefully someone knows what I'm doing wrong here. I don't see my mistake.
  • I successfully received a single packet from the game. Big step forward.

    The game still can't find the board, but getting the first packet is a good sign.
  • kwinnkwinn Posts: 8,697
    Well I have some first questions:

    Do you think the Prop is the right way to handle this? I will be needing a way to effectively get more IO. I think the Prop is right for this.
    What language should I use? I think I should use SPIN, assuming I do use the Prop.

    For multiplexing a large number of switches and leds the Prop is awesome. Definitely the way to go. How many switches and leds are do you plan on using? Will you use '595/'165's or similar chips, or do want to multiplex things more directly?
  • I've never multiplexed before so I don't know exactly what I'm going to use.

    I figure I'll be using around say 50 switches and 25 LEDs. I've yet to lay out all the functions since I still don't know if I can get the Prop to even interface.

    However getting that data packet is a good sign!!!
  • I'm just starting, what are you using for serial and float objects? Care to share what you have so far?

    I got "No display found" from the plugin while in game so hopefully that part is working.

  • Keith YoungKeith Young Posts: 569
    edited 2015-11-03 20:07
    My progress so far. This is set up for PPDB. Beware of hard numbers for pins etc.

    This tells me it's getting a packet from the computer. When I then try to send the hpacket the TV shows it right, I think, yet it says No Display Found.

    One more warning, this is the first time I've used checksums. I'm not a computer scientist, I just hack until things work.
  • Also note, I think it considers the board itself to be the display.

    So no display found seems to indicate no com ports I found confirmed they wanted to talk to me via saying 0 3 1 4 checksum at the right moment.
  • Keith YoungKeith Young Posts: 569
    edited 2015-11-03 20:08
    Here is the part of the Arduino code that I think is sending the hpacket:
    void KSPBoardSendData(uint8_t * address, uint8_t len){
      uint8_t CS = len;
      Serial.write(0xBE);
      Serial.write(0xEF);
      Serial.write(len);
      
      for(int i = 0; i<len; i++){
        CS^=*(address+i);
        Serial.write(*(address+i));
      }
      
      Serial.write(CS);
    }
    
  • Here is the part of the mod itself that I think is looking for the handshake:
    private void Port_ReceivedEvent(object sender, SerialReceivedEventArgs e)
            {
                while (Port.BytesToRead > 0)
                {
                    if (processCOM())
                    {
                        switch (id)
                        {
                            case HSPid:
                                HPacket = (HandShakePacket)ByteArrayToStructure(buffer, HPacket);
                                Invoke("HandShake", 0);
    
                                if ((HPacket.M1 == 3) && (HPacket.M2 == 1) && (HPacket.M3 == 4))
                                {
                                    DisplayFound = true;
    
                                }
                                else
                                {
                                    DisplayFound = false;
                                }
                                break;
                            case Cid:
                                VesselControls();
                                //Invoke("VesselControls", 0);
                                break;
                            default:
                                Invoke("Unimplemented", 0);
                                break;
                        }
                    }
                }
            }
    
  • Keith YoungKeith Young Posts: 569
    edited 2015-11-03 20:08
    I think it just worked!!!

    So I'm going to post here exactly what worked even though it's still a rat's nest.

    Will clean it up and start working on sending and receiving actual data. For now it's just finding the COM port.

    Which is awesome!
  • AddonLoader: Instantiating addon 'KSPSerialPort' from assembly 'KSPSerialIO'


    KSPSerialIO: Version 0.17.3


    KSPSerialIO: Getting serial ports...


    KSPSerialIO: Output packet size: 189/255


    KSPSerialIO: Found 2 serial ports


    KSPSerialIO: trying default port COM8


    Error opening serial port COM8: CreateFile Failed: 2


    KSPSerialIO: trying port \Device\VCP0 - COM5


    KSPSerialIO: found KSP Display at COM5


    AddonLoader: Instantiating addon 'KSPSerialIO' from assembly 'KSPSerialIO'
  • Nice work, I loaded your code and saw the plugin detect it too.
  • I don't know if the hard part is behind me or ahead of me.

    Here is what's ahead of me:
    struct VesselData
    {
        byte id;                //1
        float AP;               //2
        float PE;               //3
        float SemiMajorAxis;    //4
        float SemiMinorAxis;    //5
        float VVI;              //6
        float e;                //7
        float inc;              //8
        float G;                //9
        long TAp;               //10
        long TPe;               //11
        float TrueAnomaly;      //12
        float Density;          //13
        long period;            //14
        float RAlt;             //15
        float Alt;              //16
        float Vsurf;            //17
        float Lat;              //18
        float Lon;              //19
        float LiquidFuelTot;    //20
        float LiquidFuel;       //21
        float OxidizerTot;      //22
        float Oxidizer;         //23
        float EChargeTot;       //24
        float ECharge;          //25
        float MonoPropTot;      //26
        float MonoProp;         //27
        float IntakeAirTot;     //28
        float IntakeAir;        //29
        float SolidFuelTot;     //30
        float SolidFuel;        //31
        float XenonGasTot;      //32
        float XenonGas;         //33
        float LiquidFuelTotS;   //34
        float LiquidFuelS;      //35
        float OxidizerTotS;     //36
        float OxidizerS;        //37
        uint32_t MissionTime;   //38
        float deltaTime;        //39
        float VOrbit;           //40
        uint32_t MNTime;        //41
        float MNDeltaV;         //42
        float Pitch;            //43
        float Roll;             //44
        float Heading;          //45
        uint16_t ActionGroups;  //46 status bit order:SAS, RCS, Light, Gear, Brakes, Abort, Custom01 - 10
        byte SOINumber;         //47 SOI Number (decimal format: sun-planet-moon e.g. 130 = kerbin, 131 = mun)
        byte MaxOverHeat;       //48  Max part overheat (% percent)
        float MachNumber;       //49
        float IAS;              //50  Indicated Air Speed
    };
    
  • I really don't know how to change the mod itself.

    The mod uses Float values, as well as uint32.

    Are we SOL or are there ways to make this work?
Sign In or Register to comment.