Jump to content

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


zitronen

Recommended Posts

Ok some other general questions about your plugin!

I'm still in the very early stages of learning Arduino... but am I right in thinking the only bit I'd really need to edit to add more lights / dials etc to run off the existing fields would be Utilities? - adding similar parameter to caution +, warning + etc. The rest (kspiodemo, handshake, serialcoms) looks like stuff I probably shouldn't touch or I'll break the plugin...

Also... I picked this up with the hope that I can eventually get it to run as a dial using the plugin, any advice on how to safely wire it up? Do I need to run this in series with a resistor on the gnd like with an LED?.. don't want to put it near the arduino until I'm sure it won't fry my board!

http://i.imgur.com/ZhAbkQS.jpg

Sorry for the noobish questions, you are the best source of info on ksp simulator panels I've found!

Well I would make a new tab to put your own functions in. let's say you made a function that drives a gauge based on fuel level called "drivefuelgauge()" and another one called "LEDindicators()", you would put it in the main loop like this


void loop()
{
now = millis();

if (KSPBoardReceiveData()){ //we got some data
deadtimeOld = now;
switch(id) { //we check the packet id
case 0: //data is handshake packet
Handshake();
break;
case 1: //data is vessel data
drivefuelgauge(); //Add it here <<=========
LEDindicators();
break;
}

//We got some data, turn the green led on
digitalWrite(GLED,HIGH);
}
else
{ //if no message received for a while, go idle
deadtime = now - deadtimeOld;
if (deadtime > IDLETIMER)
{
deadtimeOld = now;
LEDSAllOff();
}
}

}

Unfortunately you got a 15V gauge, which is slightly more difficult to drive, since the arduino can only output 5V max. To drive a 15V gauge you will need to get a 15V power supply and some transistors/MOSFETs i.e. you will need some basic electronics skill. To drive a 5V gauge is easy just do "analogWrite(pin, value)" where pin is a PWM pin and value = 0-255. You can connect your 15V gauge to the arduino but you will only be able to use the 0-5V part of it unless you do what I said earlier.

This looks GREAT! but could someone add Mac OSX support to the plug in? it's the Serial port look up that needs an addition...

Mine is currently on /dev/cu.usbmodem14421.. should be able to search /dev/cu* for a list of ports.

Unfortunately that is unlikely to happen any time soon. I don't have a Mac so there would be no way for me to test it. But you are more than welcome to fork the plugin code and make it work. I don't think it will be very hard.

Link to comment
Share on other sites

Unfortunately you got a 15V gauge, which is slightly more difficult to drive, since the arduino can only output 5V max. To drive a 15V gauge you will need to get a 15V power supply and some transistors/MOSFETs i.e. you will need some basic electronics skill. To drive a 5V gauge is easy just do "analogWrite(pin, value)" where pin is a PWM pin and value = 0-255. You can connect your 15V gauge to the arduino but you will only be able to use the 0-5V part of it unless you do what I said earlier.

maybe with an operational amplifier in linear amplification non inverting mode ? although he will still need more than a 15v alimentation to power the amplifier. the formula (based on this drawing) would end up be : Vout = Vin*(1+R2/R1) - this should give a x3 linear amplification with R2 = 2*R1, which gives Vout = Vin*(1+2).

although for sure, 5V gauges would greatly simplify the system :)

Link to comment
Share on other sites

Well I would make a new tab to put your own functions in....

Thanks, thats a great help :)

To drive a 15V gauge you will need to get a 15V power supply and some transistors/MOSFETs i.e.....
maybe with an operational amplifier in linear amplification non inverting mode ?...

One step ahead of you both :) I pulled the gauge apart this morning, removed the 15k 1% resistor from inside and soldered in a 5k 1%... now it is a 0-5v gauge :) Just need to make a new face for it.

Link to comment
Share on other sites

Well I would make a new tab to put your own functions in. let's say you made a function that drives a gauge based on fuel level called "drivefuelgauge()" and another one called "LEDindicators()", you would put it in the main loop like this

Zitronen, it looks your using max7219's for the digit displays. Do mind sharing the functions you use to send the data to those displays? I've ended up with massive long convoluted loop just to send 8 digit numbers to the display. I'm sure there's a stupid simple way to do this, but I'm not a programmer so it eludes me.

Link to comment
Share on other sites

Unfortunately that is unlikely to happen any time soon. I don't have a Mac so there would be no way for me to test it. But you are more than welcome to fork the plugin code and make it work. I don't think it will be very hard.

Well I don't know anything about writing / compiling Mods for KSP..

I would be more than happy to be your beta tester! if you could compile the change I'd be happy to run it, and add suggestions to code.

Link to comment
Share on other sites

Can I make a request for the following to be added?

battery level (or is this already public float e; ? )

electric drain/charge

monopropellant

oxidizer

pitch angle

roll angle

yaw angle

Or... you could point me at the right software to open the DLLs myself and I can see if I can understand anything :)

Link to comment
Share on other sites

Zitronen, it looks your using max7219's for the digit displays. Do mind sharing the functions you use to send the data to those displays? I've ended up with massive long convoluted loop just to send 8 digit numbers to the display. I'm sure there's a stupid simple way to do this, but I'm not a programmer so it eludes me.

I've been using MAX7219s to drive my displays, so my code might help. I have four digit displays, though (I figured that you're only really interested in four digits worth of information anyways), so my function outputs either the number, the number in thousands, millions or billions, and then lights up a separate LED to indicate the range that it's in. It relies pretty heavily on LedControl (found here), but hopefully it's of some help.

The selector part is probably not of any use to you, but it lights up another led to indicate which of three options is chosen for the display (as here)

/* We start by including the library */
#include "LedControl.h"

/*
* Now we create a new LedControl.
* We use pins 12,11 and 10 on the Arduino for the SPI interface
* Pin 12 is connected to the DATA IN-pin of the first MAX7221
* Pin 11 is connected to the CLK-pin of the first MAX7221
* Pin 10 is connected to the LOAD(/CS)-pin of the first MAX7221
* There will only be a single MAX7221 attached to the arduino
*/
LedControl lc = LedControl(12,11,10,2);

void setup() {
//start up the various led readouts
lc.setIntensity(0,8);
lc.clearDisplay(0);
lc.shutdown(0,false);

lc.setIntensity(1,8);
lc.clearDisplay(1);
lc.shutdown(1,false);
}

void show4digit (float value, int displaynum, int selector) { //show the info on a 4 digit 7 segment display, with leds for kilo and mega prefixes, selector is 0,1,2 for switch position
int prefix = 0;
float tempnum = value;
while (tempnum >= 1000) {
tempnum = tempnum /1000;
prefix ++; //make it so we have a value less than 1000 and the prefix shows if we're in the range of ones, thousands, millions, billions, etc
}


//if we're above a trillion max everything out
int dec2spot = 9;
int decspot = 9;
int ones = 9;
int tens = 9;
int hundreds = 9;

if (prefix < 4 ) {

long tempint = (long)(tempnum*100); //if we're in a good range, get some ints that we can work with... actually need to use long, because int it only good up to 30k, and wee need up to 100k ... maybe get rid of the second decimal place and use int later to get better performance

dec2spot =(tempint%10); //use two decimal places, because if the value is less than 100, we have hte room to show it
decspot = ((tempint/10)%10);
ones = (tempint/100%10);
tens = ((tempint/1000)%10);
hundreds = ((tempint/10000)%10);
}
if (hundreds == 0) {
if (tens == 0) { //if our value is less than ten, leave one digit dark, and show it to two decimal places
lc.setChar(displaynum,0,' ',false);
lc.setDigit(displaynum,1,(byte)ones,true);
lc.setDigit(displaynum,2,(byte)decspot,false);
lc.setDigit(displaynum,3,(byte)dec2spot,false);
}
else { //if our value is greater than ten but less than a hundred, show it to two decimal places
lc.setDigit(displaynum,0,(byte)tens,false);
lc.setDigit(displaynum,1,(byte)ones,true);
lc.setDigit(displaynum,2,(byte)decspot,false);
lc.setDigit(displaynum,3,(byte)dec2spot,false);
}
}
else { //if our value is greater than a hundred, show it to one decimal place
lc.setDigit(displaynum,0,(byte)hundreds,false);
lc.setDigit(displaynum,1,(byte)tens,false);
lc.setDigit(displaynum,2,(byte)ones,true);
lc.setDigit(displaynum,3,(byte)decspot,false);
}

switch (prefix) { //set the leds to show the multiplier applied to the value - leds are wired up as digit 4 leds 1 and 2 (led 0 is colon)
case 0: // less than 1000, no multipliers lit up
lc.setLed(displaynum,4,1,false);
lc.setLed(displaynum,4,2,false);
break;

case 1: // between a thousand and a million, light up K multiplier
lc.setLed(displaynum,4,1,true);
lc.setLed(displaynum,4,2,false);
break;

case 2: // between a million and a billion, light up M multiplier
lc.setLed(displaynum,4,1,false);
lc.setLed(displaynum,4,2,true);
break;

default: // above a billion, light up both multipliers (oh god what's going on!)
lc.setLed(displaynum,4,1,true);
lc.setLed(displaynum,4,2,true);
}

//light up selector
lc.setLed(displaynum,4,3+selector,true);


}
void loop(){

show4digit(2.965874E6,0,1);


}

Link to comment
Share on other sites

Thread closed until we sort this out.

Alright, opening this once more. I'd like to ask you guys to be careful from now on. Any mud slinging like what was here before will be removed and awarded an infraction.

Thanks and carry on.

Edited by stupid_chris
Link to comment
Share on other sites

Hi Zitronen and Mulbin,

I just tried the sample sketch on an (off-brand) Mega 2560, and it worked fine. So, I don't think it's the Mega2560 that's the problem.

On the other hand, I'm trying to shoehorn my own display stuff in there too, and that's not going nearly as well :)

Link to comment
Share on other sites

Hi Zitronen and Mulbin,

I just tried the sample sketch on an (off-brand) Mega 2560, and it worked fine. So, I don't think it's the Mega2560 that's the problem.

On the other hand, I'm trying to shoehorn my own display stuff in there too, and that's not going nearly as well :)

My Uno should be here in the next 24 hours so I can see if it works on that... otherwise I don't know whats going on. Still wondering if there is something else I need installed on my computer like some missing .net stuff or something...

Link to comment
Share on other sites

I just tried the sample sketch on an (off-brand) Mega 2560

Can I just check which revision you are using? I'm seeing a lot of posts via google with similar problems of the mega 2560 not coping well with software serial. Some people saying stuff works on their uno or older mega but not on the new one.

Mine is an R3

Link to comment
Share on other sites

Mine is an R3

The sample code works for me on my R3 mega, although I did notice that I have to launch my rockets from the VAB and not straight from the launch pad or my communication light wouldn't turn on... Might be something I/you/Zitronen/we should look into

If you are wondering about the communication light, I just added a new variable definition to the code and changed the handshake LED to my new one.

Link to comment
Share on other sites

I did notice that I have to launch my rockets from the VAB and not straight from the launch pad or my communication light wouldn't turn on...

oh...my...god...

I've been launching from the launchpad to save time testing! IT WORKS!!! I know have three lights working perfectly when I launch from the VAB, but none if I launch from the pad.

Ok, so we've got to the bottom of the mystery....

Is this bug only on megas then? If so we can bug report that the mod only works if you launch from the VAB with a mega.

Of course me and Xitronen may have just bought another Arduino each for no reason :)

Link to comment
Share on other sites

ok, now that I have the plugin working I can begine to try and work out how to make an analog guage work!

Is it possible to adapt this bit of code by KK4TEE to work with the plugin? I'm not sure what format the plugin sends the data in... as a percentage? OR a total figure fo fuel? (in which case arduino will need to convert it to a usable percentage figure!)...

Here is the code, would be great if anyone can point out how to make this work...

//This program sets an analog meter to various levels.
// wire 11 goes to right dual gauge
// wire 12 goes to left dual gauge
// wire 10 goes to vertical gauge

int gaugeDualLeft = 12;
int gaugeDualRight = 11;
int gaugeVertical = 10;


int met = 0; //Mission Elapsed Time
int valueDualLeft = 0;
int valueDualRight = 0;
int valueVertical = 0;

void setup (){
pinMode(gaugeDualLeft, OUTPUT);
pinMode(gaugeDualRight, OUTPUT);
pinMode(gaugeVertical, OUTPUT);

Serial.begin(9600);

}

void loop (){
if (Serial.available()) {
//met = Serial.parseInt();
valueDualLeft = Serial.parseInt(); //Looks for the next valid integer in the serial stream
valueDualRight = Serial.parseInt();
valueVertical = Serial.parseInt();
}
// look for the newline
if (Serial.read() == '\n') {
// constrain the values to 0 - 255
valueDualLeft = constrain(valueDualLeft, 0, 255);
valueDualRight = constrain(valueDualRight, 0, 255);
valueVertical = constrain(valueVertical, 0, 255);


//Configure LiquidFuel for the Weird Gauge I have
valueDualLeft = valueDualLeft*8/255;
//Configure Oxidizer for the Weird Gauge I have
valueDualRight = valueDualRight*8/255;

//Configure Rate of Climb for the Vertical Gauge I have
valueVertical = valueVertical * 48/255 + 12;


// Write the values to the display
analogWrite(gaugeDualLeft, valueDualLeft);
analogWrite(gaugeDualRight, valueDualRight);
analogWrite(gaugeVertical, valueVertical);

// print the three numbers in one string as hexadecimal:
Serial.print("Gauges updated");


}
delay(20);
}

Here is the awesome thread it came from! KK4TEE hasnt managed to make a plugin to send the data directly so I pointed him here.

http://forum.kerbalspaceprogram.com/threads/60616-WIP-Custom-Hardware-Control-Panel?highlight=custom+gauges

Link to comment
Share on other sites

The sample code works for me on my R3 mega, although I did notice that I have to launch my rockets from the VAB and not straight from the launch pad or my communication light wouldn't turn on... Might be something I/you/Zitronen/we should look into

If you are wondering about the communication light, I just added a new variable definition to the code and changed the handshake LED to my new one.

Oh... This probably has something to do with how the plugin handles scene switching... I will add it to the bug list. An arduino mega is nice to have anyway I guess...

Link to comment
Share on other sites

Zitronen, it looks your using max7219's for the digit displays. Do mind sharing the functions you use to send the data to those displays? I've ended up with massive long convoluted loop just to send 8 digit numbers to the display. I'm sure there's a stupid simple way to do this, but I'm not a programmer so it eludes me.

I am actually using AS1117s, which are equivalent to a MAX7219 but half the price. I also use the LEDControl library katton used. My code for displaying is really simple:


void write7Segment(byte display, char value[7], byte decimal)
{
for (byte j = 0; j<6; j++) {
lc.setChar(display,j,value[j],decimal==j);
}
}

Display is the display number if you have daisy chained more

value is what you want to display, it's char so you can write "-BOOB-"

decimal is which digit you want the decimal to show, set it to 10 or some hight number if you don't want it.

This is obviously only for 6 digits, just modify it for more or less digits.

And if you want to display 3.14159 just do: write7Segment(0, "314159", 1)

Can I make a request for the following to be added?

battery level (or is this already public float e; ? )

electric drain/charge

monopropellant

oxidizer

pitch angle

roll angle

yaw angle

Or... you could point me at the right software to open the DLLs myself and I can see if I can understand anything :)

Yeah I can add whatever you want, but first I would like to figure out of config file saving so you guys can adjust things without me having to recompile the code every time.

Edit: I have updated the first post to add some descriptions to the data packet!

Edited by zitronen
Link to comment
Share on other sites

ok, now that I have the plugin working I can begine to try and work out how to make an analog guage work!

Since you have already changed it to work on 5V, all you need to do is analogWrite(PWMPin, map(VData.Fuelp, 0, 100, 0, 255)), and connect the gauge to whatever pin you choose (make sure the pin is able to output PWM, and set pinMode to output)

Edit: before you try it with KSP, follow this example: http://arduino.cc/en/Tutorial/Fading to make sure your gauge is working. Just replace the LED and resistor with your gauge.

Edited by zitronen
Link to comment
Share on other sites

Since you have already changed it to work on 5V, all you need to do is analogWrite(PWMPin, map(VData.Fuelp, 0, 100, 0, 255)), and connect the gauge to whatever pin you choose (make sure the pin is able to output PWM, and set pinMode to output)

Edit: before you try it with KSP, follow this example: http://arduino.cc/en/Tutorial/Fading to make sure your gauge is working. Just replace the LED and resistor with your gauge.

Great thanks! I'll give this a go.

is public float e; the electric charge?

Link to comment
Share on other sites

It works! I have an analogue fuel gauge :D

Edit - just noticed that the plugin also doesn't work if you revert to launch at the end of a flight, only if you go back through the VAB again.... I haven't tried buy I'm guessing quick load

Edited by Mulbin
Link to comment
Share on other sites

I've noticed that the gauge moves in steps, a bit like the second hand on a clock ticking. At first I thought it might be something in the loop causing it to pause every half second... but then I thought maybe it is because the plugin sends updated values in whole percents. Which would mean any gauge will be made up of 100 clicks rather than a smooth motion. If this is the cause is it possible to update the plugin with a decimal point or 2 added to the percentage? ie.. 99.9%, 99.8%, 99.7% etc effectively breaking the dial movement up into a thousand tiny movements rather than a hundred more obvious twitches.

I know you didn't initially design the plugin for dials.. but It has huge potential for a wide range of displays including gauges!

Link to comment
Share on other sites

Unfortunately arduino only supports 8bit PWM, so you only get 255 steps. You can try smooth it out a bit by experimenting with adding a 0.01-1uF capacitor in parallel with the meter. It doesn't give you more steps, just fake smooth.

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