Jump to content

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


zitronen

Recommended Posts

i was just playing around with one of those esp8266 boards. its pretty nifty. i was able to get it on my network in a single evening and got it talking to a lua script on another rig. it also only takes 5 connections to my arduino due (if you run a 3.3v board, 5v needs level conversion). it also has a very simple at command set over serial, so you dont need any libraries to use it. supposedly you can run the thing stand alone though the mcu on the module doesnt have a whole lot of i/o. anyone using these things yet?

did we ever get an over ip version of this interface?

Edited by Nuke
Link to comment
Share on other sites

Update 0.17.3

Changed:

Added max overheat (Sputnix request) - byte, reports the overheat percentage of the part mostly likely to explode :D

Added Mach number - float

Added indicated air speed (IAS) - float m/s

Plugin:

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

Arduino Code:

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

Link to comment
Share on other sites

Update 0.17.3

Changed:

Added max overheat (Sputnix request) - byte, reports the overheat percentage of the part mostly likely to explode :D

Added Mach number - float

Added indicated air speed (IAS) - float m/s

Plugin:

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

Arduino Code:

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

What a coincidence, I finally assembled the joystick module of my new controller. Expect details soonish.

Link to comment
Share on other sites

How do I Change the LED Pin 5 6 7

I think it looks better when they are on and get off when fuel is empty.

This is based on Demo10, I do not think it has changed line numbers in later versions

In the utilities code, exchange HIGH for LOW and LOW for HIGH in lines 11, 13, 16, 19:

void Indicators() {
caution = 0;
warning = 0;

caution += VData.G > GCAUTION;
warning += VData.G > GWARN;
caution += VData.LiquidFuelS/VData.LiquidFuelTotS*100 < FUELCAUTION;
warning += VData.LiquidFuelS/VData.LiquidFuelTotS*100 < FUELWARN;

if (caution != 0)
digitalWrite(YLED,[B]LOW[/B]); //---used to be HIGH
else
digitalWrite(YLED,[B]HIGH[/B]); //---used to be LOW

if (warning != 0)
digitalWrite(RLED,[B]LOW[/B]); //---used to be HIGH
else
digitalWrite(RLED,[B]HIGH[/B]); //---used to be LOW

digitalWrite(SASLED,ControlStatus(AGSAS));
digitalWrite(RCSLED,ControlStatus(AGRCS));
digitalWrite(CG1LED,ControlStatus(AGCustom01));
}
......

Link to comment
Share on other sites

I am in the process of constructing my KSP controller. I've got everything planned out, I've assembled most of it as a prototype but I can't really comprehend how to use this plugin. I don't get all those handshakes and weird communication functions in the example. I wouldn't be able to write those things. I have some knowledge of Arduino and C/C++ programming but how to approach this project? Should I copy the example and just change the Input and Output files or what? In the beginning I just want to achieve any form of communication programmed by me but I really don't know how to get started. Could someone please explain to me the first step using this plugin?

Link to comment
Share on other sites

The only things you need to touch in the beginning are in the utilities (for indicators) and output (for controlling the vessel) files. I just comment out what I do not need and write new code as I go along, but the main structure is wholly taken from zitronens demos. Read through the KSPIODemo file to see what info you get and send each packet, and go from there.

And ask questions here. People are likely to fall over one another to help, esp. if the find your problem a challenge. Be as specific when you ask as possible, post the code you tried and explain what you wanted it to do, and what it did.

Link to comment
Share on other sites

I am in the process of constructing my KSP controller. I've got everything planned out, I've assembled most of it as a prototype but I can't really comprehend how to use this plugin. I don't get all those handshakes and weird communication functions in the example. I wouldn't be able to write those things. I have some knowledge of Arduino and C/C++ programming but how to approach this project? Should I copy the example and just change the Input and Output files or what? In the beginning I just want to achieve any form of communication programmed by me but I really don't know how to get started. Could someone please explain to me the first step using this plugin?

Yeah what freshmeat said. The documentation of the protocol is for people who want to roll their own thing. It's very easy to get the tutorial working and go from there.

Link to comment
Share on other sites

I have a Problem with my Uno. I upload the firmware but nothing will run. But I have several Nano´s and with them everything is ok.

I gave the Uno Port No 4 and the Nano´s Port No 2.

I checked the IO from the Uno with the Standard Firmata Firmware and their own Checkprogram. With this setup everything is ok.

I would like to the my LCDKeypadshield but nothing happens with the Uno.

Link to comment
Share on other sites

I have a Problem with my Uno. I upload the firmware but nothing will run. But I have several Nano´s and with them everything is ok.

I gave the Uno Port No 4 and the Nano´s Port No 2.

Have you set the correct port number in the KSPSerialIO config file? My Mega is acting up if it does not get the correct port from the config file, even if it should autodetect.

Link to comment
Share on other sites

I must add that the rx led is flashing.

Log with UNO it doesnt run

[LOG 01:29:36.239] KSPSerialIO: Default Port = COM1

[LOG 01:29:36.239] KSPSerialIO: Refreshrate = 0.08

[LOG 01:29:36.240] KSPSerialIO: BaudRate = 38400

[LOG 01:29:36.240] KSPSerialIO: Handshake Delay = 2500

[LOG 01:29:36.240] KSPSerialIO: Pitch Enable = 2

[LOG 01:29:36.241] KSPSerialIO: Roll Enable = 2

[LOG 01:29:36.241] KSPSerialIO: Yaw Enable = 2

[LOG 01:29:36.242] KSPSerialIO: Translate X Enable = 2

[LOG 01:29:36.242] KSPSerialIO: Translate Y Enable = 2

[LOG 01:29:36.242] KSPSerialIO: Translate Z Enable = 2

[LOG 01:29:36.243] KSPSerialIO: Wheel Steering Enable = 2

[LOG 01:29:36.243] KSPSerialIO: Throttle Enable = 2

[LOG 01:29:36.244] KSPSerialIO: Wheel Throttle Enable = 2

[LOG 01:29:36.244] KSPSerialIO: SAS Tol = 0.1

[LOG 01:34:36.614] KSPSerialIO: Version 0.17.1

[LOG 01:34:36.614] KSPSerialIO: Getting serial ports...

[LOG 01:34:36.614] KSPSerialIO: Output packet size: 179/255

[LOG 01:34:36.616] KSPSerialIO: Found 2 serial ports

[LOG 01:34:36.617] KSPSerialIO: trying default port COM1

[LOG 01:34:39.240] KSPSerialIO: found KSP Display at COM1

[LOG 01:34:46.094] KSPSerialIO: Handshake received - 314

With Nano everything is ok

[LOG 01:43:05.823] KSPSerialIO: Default Port = COM4

[LOG 01:43:05.824] KSPSerialIO: Refreshrate = 0.08

[LOG 01:43:05.824] KSPSerialIO: BaudRate = 38400

[LOG 01:43:05.825] KSPSerialIO: Handshake Delay = 2500

[LOG 01:43:05.825] KSPSerialIO: Pitch Enable = 2

[LOG 01:43:05.825] KSPSerialIO: Roll Enable = 2

[LOG 01:43:05.826] KSPSerialIO: Yaw Enable = 2

[LOG 01:43:05.826] KSPSerialIO: Translate X Enable = 2

[LOG 01:43:05.827] KSPSerialIO: Translate Y Enable = 2

[LOG 01:43:05.827] KSPSerialIO: Translate Z Enable = 2

[LOG 01:43:05.827] KSPSerialIO: Wheel Steering Enable = 2

[LOG 01:43:05.828] KSPSerialIO: Throttle Enable = 2

[LOG 01:43:05.828] KSPSerialIO: Wheel Throttle Enable = 2

[LOG 01:43:05.828] KSPSerialIO: SAS Tol = 0.1

[LOG 01:44:04.383] KSPSerialIO: Version 0.17.1

[LOG 01:44:04.383] KSPSerialIO: Getting serial ports...

[LOG 01:44:04.383] KSPSerialIO: Output packet size: 179/255

[LOG 01:44:04.385] KSPSerialIO: Found 2 serial ports

[LOG 01:44:04.386] KSPSerialIO: trying default port COM4

[LOG 01:44:07.008] KSPSerialIO: found KSP Display at COM4

[LOG 01:44:13.808] KSPSerialIO: Handshake received - 314

Edited by cino
Link to comment
Share on other sites

I have a question about action group behavior. For example, when using the standard action group code I set an action group to toggle a landing leg. But when I press the corresponding button on my controller, I need to hold the button down for the gear to stay extended. When I let go of the button, it retracts. I have coded a really messy solution to this problem in my code, but I want to know if any of you guys have an efficient way to solve this problem.

Link to comment
Share on other sites

For example, when using the standard action group code I set an action group to toggle a landing leg. But when I press the corresponding button on my controller, I need to hold the button down for the gear to stay extended. When I let go of the button, it retracts. I have coded a really messy solution to this problem in my code, but I want to know if any of you guys have an efficient way to solve this problem.

My button handling uses some advanced concepts, but is fairly simple and, IMO, very efficient. It relies on storing button states as individual bits in larger numbers; an unsigned integer stores 16 inputs. This means a lot of bitwise math, which is hard for me to comprehend properly without my morning coffee. But it means I can latch all ten control group buttons in a few operations.

First, reading in the inputs. Define a uint16_t buffer to hold the readings. Reading pins in to this buffer uses the same bit shifting code zitronen used in his example sketch. My live sketch is much more convoluted than this because I'm reading 32 pins through a multiplexed shield, so I haven't actually tested the below code. But it'll be close to working!

uint16_t read_controlgroups() {
uint16_t controlgroup_buf;
for (int i=0; i<10; i++) {
if (digitalRead(16+i)) { // first action group is on pin 16, so add that to i
controlgroup_buf |= 1 << i; // bit-shift a 1 in to the buffer
} else {
controlgroup_buf &= ~(1 << i); // bit-shift a 0 in to the buffer
}
i << 6; // shift six more bits across so the first bit matches the first control group
return controlgroup_buf;
}

To do software debouncing, I cribbed a technique from http://www.embedded.com/electronics-blogs/break-points/4024981/My-favorite-software-debouncers . Raw readings are placed in a circular buffer, and debouncing is done by a bitwise AND of all the buffer elements.

#define NUM_READINGS 3
uint16_t raw_controlgroup[NUM_READINGS];
int controlgroup_idx = 0; // current index in the raw controlgroup buffer

uint16_t debounce_controlgroups() {
// First, read current CG status in to the buffer
raw_controlgroup[controlgroup_idx] = read_controlgroups();
++controlgroup_idx;
if (controlgroup_idx == NUM_READINGS) controlgroup_idx = 0;

uint16_t debounced = 0xffff;
for (int i=0; i<NUM_READINGS; i++) {
debounced = debounced & raw_controlgroup[i];
}

return debounced;
}

Now for the button latching. We need to keep the last debounced state and the current debounced state. When a button's state changes from low to high, we need to flip the latched state. To figure that out I had to draw up a Karnaugh map for the first time since the late 90s, but ended up doing it like this:

uint16_t cur_controlgroup = 0; // The most recent debounced controlgroup reading
uint16_t last_controlgroup = 0; // The last debounced controlgroup reading
uint16_t latched_controlgroup = 0; // Controlgroup state after latching button presses

void latch_controlgroups() {
// rotate and get new controlgroup readings
last_controlgroup = cur_controlgroup;
cur_controlgroup = debounce_controlgroups();

uint16_t mask;
mask = ~last_controlgroup & cur_controlgroup; // Mask of all inputs that have changed between last and current
mask = mask & cur_controlgroup; // Mask now only contains changed inputs that are high in current reading (and low in last)
latched_controlgroup = latched_controlgroup ^ mask; // Apply mask to flip controlgroups that have changed
}

Set up your sketch to call latch_controlgroups() every 5ms, and the latched_controlgroup variable will contain control group states that flip on and off every time the buttons are pressed. You can just copy latched_controlgroup in to the ControlPacket.ControlGroup when you send a packet.

Edited by stibbons
Link to comment
Share on other sites

I must add that the rx led is flashing.

Log with UNO it doesnt run

[LOG 01:29:36.239] KSPSerialIO: Default Port = COM1

[LOG 01:29:36.239] KSPSerialIO: Refreshrate = 0.08

[LOG 01:29:36.240] KSPSerialIO: BaudRate = 38400

[LOG 01:29:36.240] KSPSerialIO: Handshake Delay = 2500

[LOG 01:29:36.240] KSPSerialIO: Pitch Enable = 2

[LOG 01:29:36.241] KSPSerialIO: Roll Enable = 2

[LOG 01:29:36.241] KSPSerialIO: Yaw Enable = 2

[LOG 01:29:36.242] KSPSerialIO: Translate X Enable = 2

[LOG 01:29:36.242] KSPSerialIO: Translate Y Enable = 2

[LOG 01:29:36.242] KSPSerialIO: Translate Z Enable = 2

[LOG 01:29:36.243] KSPSerialIO: Wheel Steering Enable = 2

[LOG 01:29:36.243] KSPSerialIO: Throttle Enable = 2

[LOG 01:29:36.244] KSPSerialIO: Wheel Throttle Enable = 2

[LOG 01:29:36.244] KSPSerialIO: SAS Tol = 0.1

[LOG 01:34:36.614] KSPSerialIO: Version 0.17.1

[LOG 01:34:36.614] KSPSerialIO: Getting serial ports...

[LOG 01:34:36.614] KSPSerialIO: Output packet size: 179/255

[LOG 01:34:36.616] KSPSerialIO: Found 2 serial ports

[LOG 01:34:36.617] KSPSerialIO: trying default port COM1

[LOG 01:34:39.240] KSPSerialIO: found KSP Display at COM1

[LOG 01:34:46.094] KSPSerialIO: Handshake received - 314

With Nano everything is ok

[LOG 01:43:05.823] KSPSerialIO: Default Port = COM4

[LOG 01:43:05.824] KSPSerialIO: Refreshrate = 0.08

[LOG 01:43:05.824] KSPSerialIO: BaudRate = 38400

[LOG 01:43:05.825] KSPSerialIO: Handshake Delay = 2500

[LOG 01:43:05.825] KSPSerialIO: Pitch Enable = 2

[LOG 01:43:05.825] KSPSerialIO: Roll Enable = 2

[LOG 01:43:05.826] KSPSerialIO: Yaw Enable = 2

[LOG 01:43:05.826] KSPSerialIO: Translate X Enable = 2

[LOG 01:43:05.827] KSPSerialIO: Translate Y Enable = 2

[LOG 01:43:05.827] KSPSerialIO: Translate Z Enable = 2

[LOG 01:43:05.827] KSPSerialIO: Wheel Steering Enable = 2

[LOG 01:43:05.828] KSPSerialIO: Throttle Enable = 2

[LOG 01:43:05.828] KSPSerialIO: Wheel Throttle Enable = 2

[LOG 01:43:05.828] KSPSerialIO: SAS Tol = 0.1

[LOG 01:44:04.383] KSPSerialIO: Version 0.17.1

[LOG 01:44:04.383] KSPSerialIO: Getting serial ports...

[LOG 01:44:04.383] KSPSerialIO: Output packet size: 179/255

[LOG 01:44:04.385] KSPSerialIO: Found 2 serial ports

[LOG 01:44:04.386] KSPSerialIO: trying default port COM4

[LOG 01:44:07.008] KSPSerialIO: found KSP Display at COM4

[LOG 01:44:13.808] KSPSerialIO: Handshake received - 314

You are using version 0.17.1, which version of the arduino code are you using? The current version of the plugin is 0.17.3 and arduino code version 12. They are not compatible between versions.

- - - Updated - - -

I have a question about action group behavior. For example, when using the standard action group code I set an action group to toggle a landing leg. But when I press the corresponding button on my controller, I need to hold the button down for the gear to stay extended. When I let go of the button, it retracts. I have coded a really messy solution to this problem in my code, but I want to know if any of you guys have an efficient way to solve this problem.

The action groups are designed to be operated with toggle switches. If you want to use buttons you can follow stibbon's method.

Link to comment
Share on other sites

My button handling uses some advanced concepts, but is fairly simple and, IMO, very efficient. It relies on storing button states as individual bits in larger numbers; an unsigned integer stores 16 inputs. This means a lot of bitwise math, which is hard for me to comprehend properly without my morning coffee. But it means I can latch all ten control group buttons in a few operations.

Thanks for all this help! Will this make it behave like keyboard buttons?, because that's what I'm going for.

--edit--

I have started to integrate this code, but I'm wondering about the line that says "#define NUM_READINGS 3". Do I keep the 3 there, or is it supposed to be something else?

Edited by jandcando
Link to comment
Share on other sites

You are using version 0.17.1, which version of the arduino code are you using? The current version of the plugin is 0.17.3 and arduino code version 12. They are not compatible between versions.

Thanks, this was the solution.

Link to comment
Share on other sites

Thanks for all this help! Will this make it behave like keyboard buttons?, because that's what I'm going for.

I'm not sure what you mean. It's code that lets a momentary push button act as a toggle - pretty much exactly how the caps lock key on your keyboard works yes.

I have started to integrate this code, but I'm wondering about the line that says "#define NUM_READINGS 3". Do I keep the 3 there, or is it supposed to be something else?

NUM_READINGS is used in the button debouncing routine. It defines how many consecutive readings need to be high before the debounced button state is considered to be high. For my hardware, 3 is a pretty good number for a 5ms polling interval.

Also, it's worth noting that this code is intended to be used for buttons that have pull-down resistors. If you're using the internal pull-up resistors on the arduino, it will only toggle state when the button is released not when it's pushed. Easiest thing to do for that sort of setup would be invert the result of the digitalRead.

Link to comment
Share on other sites

I'm not sure what you mean. It's code that lets a momentary push button act as a toggle - pretty much exactly how the caps lock key on your keyboard works yes.

Oh. I'm looking for something that makes the buttons on my controller behave as if I was using the keyboard buttons to trigger action groups. I'm not sure what the game does with keyboard input, but I want it to be the same behavior on my controller board.

Link to comment
Share on other sites

Essentially you get the same functionality as a key press. However, you need to send a command by KSPserialIO instead of a keyboard character. A single arduino cannot both be a keyboard emulator and communicate with KSP over serial.

Link to comment
Share on other sites

I have another Question. I have the AP on my LCD but it shows to many digits till down to meters. I want only km.

This is my Code

lcd.setCursor(0, 0);   lcd.print((long) VData.Alt);
lcd.print(" ");
lcd.setCursor(7, 0);
lcd.print((long) VData.AP);
lcd.setCursor(0, 1);
lcd.print((long) VData.LiquidFuel);
lcd.print(" ");
lcd.setCursor(4, 1);
lcd.print("/");
lcd.setCursor(6, 1);
lcd.print((long) VData.SolidFuel);
lcd.print(" ");
lcd.setCursor(10, 1);
lcd.print("/");
lcd.print((long) VData.Vsurf);

Edit:

I did it with

[FONT=Verdana]  lcd.print((long) VData.AP / 100);[/FONT]

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