Jump to content

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


zitronen

Recommended Posts

First, I want to thanks zitronen as well as everyone that is working on this project. I think it's a great way to combine programming, electronics with KSP (all things that I have interest in!) and as such, I'm currently trying to build my own KSP controller with some basic buttons, switches and an Arduino Uno.

I'm still quite new, and was looking over the KSPIODemo10 example code and was not sure about one thing.

So far, I understand that

Are the defined pins for SAS (pin 8), RCS (pin 9) and so forth. Additional pins can be assigned to (say) control groups, lights, gears, brakes, etc relatively easily.

However, I then see another part of the code

I'm not quite sure what these assignments do. Are these pin assignments (i.e. if I wanted to assign (say) lights to pin 7, would this be possible? Though, looking at the top part of the code, it looks like pin 7 is assigned to a red LED for low fuel warning too...)

Look at controls() and MainControls() in output.ino. These values are not pin assignments but indicate which bit of the control byte represents the status of which system.

Link to comment
Share on other sites

Look at controls() and MainControls() in output.ino. These values are not pin assignments but indicate which bit of the control byte represents the status of which system.

So if I understand this correctly,

if (digitalRead(RCSPIN))

MainControls(RCS, HIGH);

else

MainControls(RCS, LOW);

RCS is on the RCSPIN (9 in the demo code). When the pin value is read as high/low, the RCS enum value is set to either high/low, respectively. I'm assuming this is somehow then passed to the plugin to enable/disable RCS in game.

Currently, in the demo code,

//pins for LEDs

#define GLED 5

#define YLED 6

#define RLED 7

Pins 5-7 are assigned for indicator LEDs, but if I were to (say) add in lights and brakes, I could simply just replace those lines with

#define LIGHTSPIN 5

#define GEARPIN 6

#define BRAKESPIN 7

and then add the following to output.ino

if (digitalRead(LIGHTSPIN)) //

MainControls(LIGHTS, HIGH);

else

MainControls(LIGHTS, LOW);

I made sure that the digitalRead matches the defined pin names (LIGHTSPIN) and then that the MainControls() part matches the defined enums in KSPIODemo.ino

Finally, in the output.ino, I am also noticing

void controlsInit() {

pinMode(SASPIN, INPUT_PULLUP);

pinMode(RCSPIN, INPUT_PULLUP);

pinMode(CG1PIN, INPUT_PULLUP);

}

I am assuming that I will also need to enable the internal pullup resistor for say LIGHTSPIN (pinMode(LIGHTSPIN, INPUT_PULLUP;) to ensure that I don't get floating values?

Link to comment
Share on other sites

Yeah the variable names are a bit confusing, you are not the first person to have this issue. The Arduino code could use some more documentation. I suck at documentation.

Not to worry! You have already contributed so much by writing the plugin and the Arduino code. Besides, trying to figure out which parts of code do what is kind of like a puzzle.

On another note, like Mulbin, when launching rockets from the VAB, the plugin seems to work fine, but if I load a rocket via the Launchpad, exit back to the space centre (leaving the rocket on the launch pad) and then try to reload the rocket via the Launchpad, I start to get weird results (auto staging; i.e. once the rocket loads, the first stage automatically stages!) This is despite not even having pressed my stage button.

I need to do more testing tonight; I'm not sure if it's software related, or just due to me having a short somewhere (I've checked to ensure I have the internal pullup enabled so that I don't have floating values, so it shouldn't be that; hardware wise, I have a key-lock switch wired in series to a momentary push button, so both need to be closed before the Arduino reads a logic LOW)...

Link to comment
Share on other sites

So I am encountering a weird bug.

http://imgur.com/Va5IkGK

The picture doesn't say much, but when I have my controller plugged in, my throttle controls go wonky (even though I do not have anything hooked up physically to throttle controls).

Pressing shift will increase throttle, as expected.

Pressing 'Z' will increase my throttle to 100% instantly, as expected.

Pressing control will decrease throttle, but only to the 1/3 mark (it will not decrease any further).

Pressing 'X' at this time will kill my throttle instantly, but only to the 1/3 mark. If I press shift at this time, the throttle will suddenly jump to zero before starting to increase again.

Anyone else have this problem? I don't think it is an Arduino coding problem, but am not sure.

I'm wondering if this has anything to do with it...

CPacket.Throttle = constrain(map(analogRead(THROTTLEPIN),THROTTLEDB,1024-THROTTLEDB,0,1000),0, 1000);

Link to comment
Share on other sites

If you are not using a physical throttle you can delete that line or try CPacket.Throttle = 0. Probably something to do with the analog pin floating causing weird problems. You can also try connect the pin to ground.

Link to comment
Share on other sites

If you are not using a physical throttle you can delete that line or try CPacket.Throttle = 0. Probably something to do with the analog pin floating causing weird problems. You can also try connect the pin to ground.

Excellent; commenting out that line seems to have sorted out that problem.

However, I am still getting an unusual problem with the first stage auto-staging. I've noticed it happens most frequently when I am launching my first ship after starting up the game. If I try to launch subsequent ships, there is no problem. This auto-staging happens even though my stage button is not being pressed.

Link to comment
Share on other sites

Excellent; commenting out that line seems to have sorted out that problem.

However, I am still getting an unusual problem with the first stage auto-staging. I've noticed it happens most frequently when I am launching my first ship after starting up the game. If I try to launch subsequent ships, there is no problem. This auto-staging happens even though my stage button is not being pressed.

What kind of switch are you using for staging?

I'm using a momentary normally closed and am not experiencing random auto stages.

I did experience unwanted staging when I was just testing with a toggle switch and wasn't fast enough to switch it off again.

Link to comment
Share on other sites

What kind of switch are you using for staging?

I'm using a momentary normally closed and am not experiencing random auto stages.

I did experience unwanted staging when I was just testing with a toggle switch and wasn't fast enough to switch it off again.

I have a key lock switch (http://p.globalsources.com/IMAGES/PDT/B1008164425/Keylock-Switch.jpg) that is wired in series to a momentary push button. One side of the key lock switch goes to the assigned pin, while ground is connected to one side of the momentary switch.

I also have the assigned stage pin internal pullup enabled with the following code, so I shouldn't be getting floating values.

pinMode(STAGEPIN, INPUT_PULLUP);

I notice that this problem happens when the Arduino is connecting to the interface for the first time after I launch the game. If I revert to VAB and try to launch again, everything is fine.

I'll try to recreate this more accurately for troubleshooting.

Link to comment
Share on other sites

The source is up at github. But basically there are handshake bytes sent to the chip, then the chip responds with ack bytes, and KspSerialIO then sets the display found Boolean to true . It's all in the source under a function called port_receivedEvent and processCom.

More:

The AVR and KSpSerialIO need to know the baud rate, And if you don't know the com port, the AVR will be searched for. A search is done by sending the HPacket to every com port and waiting for a response, if the response is a valid HPacket. bingo!

The board is scanned for at every vessel change, when you actually fly the ship.

See source here: https://github.com/zitron-git/KSPSerialIO/blob/master/KSPSerialIO/KSPIO.cs

You need to refer to these sources anyway to learn the VesselData structures that are supported in Zitronen's protocol. See the VesselData struct for what is exchanged with the avr.

As for analog input, that is totally possible.

zitronen, I would like to use your plug-in to interface my own (non-arduino) hardware controller with KSP, but I am having trouble understanding the handshake protocol.

Do you have any documentation to describe the absolute bare minimum that my hardware would need to do to even be recognised by KSP? All I'm getting at the moment is ""No display found" in the lower right corner of KSP at launch. I've never seen that before so I presume it's your plugin complaining that it can't read anything on any serial port.

Specifically I need to know how your code looks for a display and *when* it looks for it. Eg. does it do it once and then give up forever or does it do it repeatedly etc... Can I use 115200 baud or will that fail? I have not yet managed to get my microcontroller (a P8X32A if you are interested) to be recognised by KSP, even though I'm sending the 0x00030104 byte sequence on COM3 at 38400 baud at what I think is the right time.

I've combed through your arduino demo but I'm not really too familiar with that platform.

Could you describe the process of handshaking in hardware-independent (layman's) terms please, that would be unbelievably awesome. Especially if you could detail when and how KSP calls your plugin's functions and when it reads the config file (every launch or only at startup?).

When I get this working I'll release my P8X32A project as CC-BY-SA and share it with the KSP community.

I'm hoping to build a full analog control panel for KSP with toggle switches and 2-axis sticks (I'm thinking ripping some sticks and triggers out of an old xbox controller, that will give me full RCS control and pitch/yaw for rotation, plus another 1 axis stick for roll.

Another potentiometer for engine throttle, and a heap of toggles/momentaries for control groups and lights and gear etc...

LEDs for indication of stuff as you'd expect and a big abort button!

I'll also release the bill of materials and the schematics too.

Edited by marzubus
Link to comment
Share on other sites

Sorry, I deleted my post already. Thanks for the information. I'm sure others will find it useful if they want to use zitronen's system.

I decided to do it another way just now, hence deleting my post (didn't want to clutter the place up). Sorry once again.

Link to comment
Share on other sites

So I have been investigating my issue and I believe I have been able to reproduce it successfully now.

Hardware wise, I have two toggle switches connected to RCS and SAS (as per first post, pin 9 and 8, respectively). Pin 8 or 9 --> switch --> ground, as per instructions. No other wires.

When I load KSPIODemo10, I get the expected behaviour, SAS and RCS turn on/off as expected.

Now, I made the following changes to the Arduino code:

In KSPIODemo10.ino:

//pins for input

#define SASPIN 8

#define RCSPIN 9

#define STAGEPIN 2

#define CG1PIN 10

#define THROTTLEPIN 0

In output.ino

- added staging in void controls (), commented out CPacket.Throttle, added pullup resistor for stage pin in void controlsInit ()

void controls() {

if (Connected) {

if (digitalRead(SASPIN)) //--------- This is how you do main controls

MainControls(SAS, HIGH);

else

MainControls(SAS, LOW);

if (digitalRead(RCSPIN))

MainControls(RCS, HIGH);

else

MainControls(RCS, LOW);

if (digitalRead(STAGEPIN))

MainControls(STAGE, HIGH);

else

MainControls(STAGE, LOW);

if (digitalRead(CG1PIN)) //--------- This is how you do control groups

ControlGroups(1, HIGH);

else

ControlGroups(1, LOW);

//This is an example of reading analog inputs to an axis, with deadband and limits

// CPacket.Throttle = constrain(map(analogRead(THROTTLEPIN),THROTTLEDB,1024-THROTTLEDB,0,1000),0, 1000);

KSPBoardSendData(details(CPacket));

}

}

void controlsInit() {

pinMode(SASPIN, INPUT_PULLUP);

pinMode(RCSPIN, INPUT_PULLUP);

pinMode(STAGEPIN, INPUT_PULLUP);

pinMode(CG1PIN, INPUT_PULLUP);

}

Now, I launch KSP (clean install except for KSPSerialIO)

Go to VAB -> 1 man command pod, add a SRB to it and launch. A successful connection to the COM port is established, but the rocket will immediately take off. This is despite having nothing connected to pin 2. (Note: If I go ahead and connect pin 2 --> momentary button --> ground and make a multi-staged rocket, only the first SRB stage will auto-launch. The other stages will stage as expected when the momentary push button is pressed).

Can anyone test to see if this is reproducible?

Edit (more tests):

Once the rocket is airborne, I press escape, click Space Centre (ignore the warning and proceed to Space Centre). The rocket will be on the launch pad. Click it, press Fly. The rocket will immediately take off again.

Go back to the Space Centre (ignore the warning and proceed as before). Click the rocket on the launch pad and recover it. Go back to VAB, build the exact same rocket as before (it should still be loaded), and launch again. This time, the rocket will not auto launch.

Go to Space Centre again, click the rocket on the launch pad, and click Fly. The rocket will not launch automatically.

Edited by Darkblade48
Additional information, formatting
Link to comment
Share on other sites

I know sometimes you need to flip HIGH / LOW values, depending on if you pull-up or pull-down. Did you try that?

If you set the pin to pull-up, the default ( off ) would be HIGH right? But main controls would be inverted, as when the pin is HIGH, you send LOW to MainControls ( not triggered ).

Or am i mixing things up?

EDIT: My buttons pull to ground permanently when not pressed/toggled, when i press/toggle them they break the pull-to-ground, allowing the pull-up to set the pin to HIGH, this then works as expected. If you have a 2-pole, you might need to do something like: http://arduino.cc/en/uploads/Tutorial/button_schem.png

So I have been investigating my issue and I believe I have been able to reproduce it successfully now.

Hardware wise, I have two toggle switches connected to RCS and SAS (as per first post, pin 9 and 8, respectively). Pin 8 or 9 --> switch --> ground, as per instructions. No other wires.

When I load KSPIODemo10, I get the expected behaviour, SAS and RCS turn on/off as expected.

Now, I made the following changes to the Arduino code:

In KSPIODemo10.ino:

In output.ino

- added staging in void controls (), commented out CPacket.Throttle, added pullup resistor for stage pin in void controlsInit ()

Now, I launch KSP (clean install except for KSPSerialIO)

Go to VAB -> 1 man command pod, add a SRB to it and launch. A successful connection to the COM port is established, but the rocket will immediately take off. This is despite having nothing connected to pin 2. (Note: If I go ahead and connect pin 2 --> momentary button --> ground and make a multi-staged rocket, only the first SRB stage will auto-launch. The other stages will stage as expected when the momentary push button is pressed).

Can anyone test to see if this is reproducible?

Edit (more tests):

Once the rocket is airborne, I press escape, click Space Centre (ignore the warning and proceed to Space Centre). The rocket will be on the launch pad. Click it, press Fly. The rocket will immediately take off again.

Go back to the Space Centre (ignore the warning and proceed as before). Click the rocket on the launch pad and recover it. Go back to VAB, build the exact same rocket as before (it should still be loaded), and launch again. This time, the rocket will not auto launch.

Go to Space Centre again, click the rocket on the launch pad, and click Fly. The rocket will not launch automatically.

Edited by marzubus
Link to comment
Share on other sites

I know sometimes you need to flip HIGH / LOW values, depending on if you pull-up or pull-down. Did you try that?

If you set the pin to pull-up, the default ( off ) would be HIGH right? But main controls would be inverted, as when the pin is HIGH, you send LOW to MainControls ( not triggered ).

Or am i mixing things up?

EDIT: My buttons pull to ground permanently when not pressed/toggled, when i press/toggle them they break the pull-to-ground, allowing the pull-up to set the pin to HIGH, this then works as expected. If you have a 2-pole, you might need to do something like: http://arduino.cc/en/uploads/Tutorial/button_schem.png

Genius! Switching the logic around worked, though I'm trying to figure out why.

I am using the Arduino's internal pull-up, which means the default (button not pressed) would indeed be HIGH. Looking at main controls ()

if (digitalRead(STAGEPIN))

MainControls(STAGE, HIGH);

else

MainControls(STAGE, LOW);

How does the value of STAGEPIN (either 0 or 1) get passed to MainControls() to either make STAGE have a HIGH or LOW value? Looking at MainControls () doesn't provide me with many clues (mainly because I don't know what it's actually doing).

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.

}

Edited by Darkblade48
Link to comment
Share on other sites

The "why" is because the default state is pulled-UP to HIGH, so when nothing is connected, the pin reads HIGH. I use different switches that disconnect when I activate them, so I stop pulling-gnd when I engage them.

Im not sure on what you mean in the STAGEPIN passing question.

There is a method in the arduino sketch, that does some bitshifting.

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.

}

So when you say MainControls(0, HIGH), this would set STAGE to 1. The sketch has name to bit position mappings for this which I guess you have seen.

//Input enums

#define SAS 7

#define RCS 6

#define LIGHTS 5

#define GEAR 4

#define BRAKES 3

#define PRECISION 2

#define ABORT 1

#define STAGE 0

And there is a mapping for what bit values represent what Control value in KSP in KSPSerialIO code.

VControls.SAS = BitMathByte(CPacket.MainControls, 7);

VControls.RCS = BitMathByte(CPacket.MainControls, 6);

VControls.Lights = BitMathByte(CPacket.MainControls, 5);

VControls.Gear = BitMathByte(CPacket.MainControls, 4);

VControls.Brakes = BitMathByte(CPacket.MainControls, 3);

VControls.Precision = BitMathByte(CPacket.MainControls, 2);

VControls.Abort = BitMathByte(CPacket.MainControls, 1);

VControls.Stage = BitMathByte(CPacket.MainControls, 0);

So you can only set 8 states in this. And as you can see, the 1st bit ( position 0 ) is STAGE.

Genius! Switching the logic around worked, though I'm trying to figure out why.

I am using the Arduino's internal pull-up, which means the default (button not pressed) would indeed be HIGH. Looking at main controls ()

How does the value of STAGEPIN (either 0 or 1) get passed to MainControls() to either make STAGE have a HIGH or LOW value?

Does that answer the question?

Edited by marzubus
Link to comment
Share on other sites

Reading your reply, some light is being shed, but I have a few more questions (sorry for all the questions)

You mentioned there can only be 8 states; is it possible to have more, or is it limited to the number of possible bits in a byte (8 bits)?

Now back to the code:

A pull-up resistor for STAGEPIN would always return HIGH.

if (digitalRead(STAGEPIN))

MainControls(STAGE, HIGH);

else

MainControls(STAGE, LOW);

With the wrong logic, when STAGEPIN is HIGH, then the STAGE bit is also set to HIGH, meaning it auto launches. This makes sense to me. I assume the STAGE bit is then set to LOW (after it is triggered once), so that the following stages also do not activate by themselves.

Once I invert the logic,

if (digitalRead(STAGEPIN))

MainControls(STAGE, LOW);

else

MainControls(STAGE, HIGH);

Since STAGEPIN has a pull-up and is reading HIGH, then the STAGE bit will read LOW (i.e. do not stage). When I press the button, STAGEPIN will read LOW, which causes the STAGE bit to read HIGH -> my rocket will stage. This makes sense.

However, let's say I was using a pull-down resistor. Now the value of STAGEPIN will default to LOW.

Which way would be the correct logic?

if (digitalRead(STAGEPIN))

MainControls(STAGE, LOW);

else

MainControls(STAGE, HIGH);

To me, this seems correct. Read STAGEPIN. It is LOW (due to pull-down resistor). Thus, STAGE bit is also LOW (will not stage). Once I press the button, STAGEPIN is HIGH, so STAGE bit is also set to HIGH and my rocket will stage.

Is this correct?

Originally, I had my ABORTPIN and its logic set up the same (incorrect) way, i.e.

MainControls(ABORT, HIGH);

else

MainControls(ABORT, LOW);

If my thought process above was correct, why doesn't my rocket automatically ABORT everytime I launch?

And finally, with the wrong logic, how come the rocket will only stage incorrectly upon the first load? If I go and launch a second rocket, it doesn't auto-stage.

Edited by Darkblade48
Link to comment
Share on other sites

If you use pull-down on the pin, you could change the if (digitalRead(STAGEPIN)) to if (!digitalRead(STAGEPIN)) Remember that is only True if the pin is HIGH.

To add more controls, KSPSerialIO would need to be changed. And that would require a feature request. Though I think enough of the controls are already exposed. ActionGroups take care of most of the work.

Im not too sure on the reason for the second launch working. It sounds very strange.

Link to comment
Share on other sites

Using a pull down resistor means the input will be a logic LOW when the switch is open, and a logic HIGH when the switch is closed. The state of the input is exactly what you want to put in the control packet and send upstream; for the simplest case you can literally do this

  MainControls(STAGE, digitalRead(StagePin));

No need to constantly be confused inverting all the booleans. (and please, please don't invert them twice!)

The game carries out a stage operation when the value of the stage input transitions from 0 to 1. Under normal circumstances the control packet has the stage bit set to 0 when the stage button is open, and 1 when the button is closed - the transition from low to high happens when you press the button.

But with your bug, when the vessel is loaded and the connector handshake happens, the very first control packet the game receives already has the stage bit set to 1, causing the immediate stage. After that, pressing the button results in a transition from 1 to 0 (with no effect apart from preparing for the next rising transition). And releasing the button results in a transition from 0 to 1. So the staging happens approximately normally, but when the button is released, not pressed.

EDIT: Back to how things work with pulldowns, my code is complicated slightly by using a multiplexer and doing input debouncing in software. But the way the staging bit of the control packet is constructed is hopefully pretty straightforward:

boolean stageStatus() {
if (readMuxPin(stagePin) && readMuxPin(stageLockPin)) {
return true;
} else {
return false;
}
}

void controls() {
if (connected) {
if (stageStatus()) {
MainControls(STAGE, HIGH);
} else {
MainControls(STAGE, LOW);
}
...

Edited by stibbons
Link to comment
Share on other sites

Thanks for the reply, I think I'm finally starting to understand this now.

Using a pull down resistor means the input will be a logic LOW when the switch is open, and a logic HIGH when the switch is closed. The state of the input is exactly what you want to put in the control packet and send upstream; for the simplest case you can literally do this

  MainControls(STAGE, digitalRead(StagePin));

No need to constantly be confused inverting all the booleans. (and please, please don't invert them twice!)

As I suspected, this would be the easiest case.

Since the Arduino only has internal pull-up resistors, choosing to use pull-down resistors would mean additional hardware, hence, I went with the internal pull-up resistors. However, because of this, from what I understand, the state of the input is inverted to what I want to put in the control packet, hence, the boolean logic must also be inverted (i.e. the state of the input is HIGH, but I want the control packet to read LOW, and vice versa when the button is pressed).

This is made more confusing because some of the switches I have (toggle switches) are SPDT, meaning depending on how I connect them, and depending on how I set my logic will ultimately affect how the game interprets it. I just realized that I have my toggle switches set one way, and the push buttons set another way (oops!)

The game carries out a stage operation when the value of the stage input transitions from 0 to 1. Under normal circumstances the control packet has the stage bit set to 0 when the stage button is open, and 1 when the button is closed - the transition from low to high happens when you press the button.

But with your bug, when the vessel is loaded and the connector handshake happens, the very first control packet the game receives already has the stage bit set to 1, causing the immediate stage. After that, pressing the button results in a transition from 1 to 0 (with no effect apart from preparing for the next rising transition). And releasing the button results in a transition from 0 to 1. So the staging happens approximately normally, but when the button is released, not pressed.

Aha! I thought this was the case. I noticed that sometimes if I held down the button slightly, my rocket wouldn't stage (because it was suck at 0 and preparing for the next rising transition). I'm smacking my forehead and should have realized it at the time!

On another note, either a pull-up or a pull-down resistor will be required to prevent floating (erroneous) value reads, right?

EDIT: Back to how things work with pulldowns, my code is complicated slightly by using a multiplexer and doing input debouncing in software. But the way the staging bit of the control packet is constructed is hopefully pretty straightforward:

boolean stageStatus() {
if (readMuxPin(stagePin) && readMuxPin(stageLockPin)) {
return true;
} else {
return false;
}
}

void controls() {
if (connected) {
if (stageStatus()) {
MainControls(STAGE, HIGH);
} else {
MainControls(STAGE, LOW);
}
...

This code makes sense. I think mainly because when using pull-down resistors, the logic "makes sense" to humans, i.e. using a pull-down resistor, the bit value is LOW and so, the value passed to KSP is also LOW. Once you press the button, then the logic goes to HIGH, which also triggers the action.

With a pull-up, everything is inverted! I read through all 80+ pages of this and even bookmarked where Mulbin had a similar problem (page 20 something), but didn't realize that this was the case here as well!

Is there any reason you have the Stage pin and the Stage Lock pin separately and not simply wired in series? Also, is (software) debouncing absolutely required (I would assume for toggle SPDT switches, no, but for push buttons, perhaps?)

Link to comment
Share on other sites

I was thinking about what the problem was, since you had the pull up set properly I don't know what else it could be. I mean it's just a switch hooked up to a pin what can possibly go wrong XD

Wiring stage lock in series works fine, stibbons probably has some fancy code to light up warnings and what not with his stage lock :). Hardware and/or software debounce are recommended, imagine all the bad things that can happen if your stage button bounced... There are debounce libraries you can use.

Link to comment
Share on other sites

I was thinking about what the problem was, since you had the pull up set properly I don't know what else it could be. I mean it's just a switch hooked up to a pin what can possibly go wrong XD

Wiring stage lock in series works fine, stibbons probably has some fancy code to light up warnings and what not with his stage lock :). Hardware and/or software debounce are recommended, imagine all the bad things that can happen if your stage button bounced... There are debounce libraries you can use.

I thought a switch was simple too! I think the main reason I got confused was because my momentary switches are SPST, while my toggle switches are all SPDT. I wired the SPDT first, so my mind was "set" in that logic, so I kept it the same for the SPST switches, which was wrong :D

I'm probably going to add some fancy LEDs and such myself too, but have to figure out how to multiplex/use shift registers so that I can expand the number of pins I have first. My abort lock toggle is one of those fancy ones with a built in LED, so it'd be nice to get it working!

As for the debounce, I'll take a look at the software libraries, I believe there is an example that is included in the Arduino IDE, so I'm thinking I can just adapt that for use.

Link to comment
Share on other sites

On another note, either a pull-up or a pull-down resistor will be required to prevent floating (erroneous) value reads, right?

Yes, definitely. A floating pin sometimes works the way you'd expect, but I've also had them changing state based on the state of nearby switches on the panel, or the state of nearby pins on the arduino board, or even acting like a capacitive sensor and changing state when I waved my hand near the switch body.

Also, is (software) debouncing absolutely required (I would assume for toggle SPDT switches, no, but for push buttons, perhaps?)

Toggle switches are also susceptible to contact bounce. Possibly only when the contacts open, but it's there. I always wind up using software debouncing, and if you're looking I just used the Bounce2 library in a different project and it's quite easy to work with. But hardware debouncing looks like fun, and I'm a little envious of Mr0nak's setup.

Wiring stage lock in series works fine, stibbons probably has some fancy code to light up warnings and what not with his stage lock :)

Yep! :D I started out with the lock in series with the stage button, but I've got a few RGB status LEDs scattered around. Putting the lock on a separate input lets me make smart decisions about how to update them

void stageLedSet() {
// If abort button has been hit, blink fast.
// Otherwise, set the colour depending on whether stage lock is on.
if (abortState) {
if (fastBlinkState) {
leds[stageStateLed] = CRGB::Red;
} else {
leds[stageStateLed] = CRGB::Black;
}
} else {
if (readMuxPin(stageLockPin)) {
leds[stageStateLed] = CRGB::Green;
} else {
leds[stageStateLed] = CRGB::Red;
}
}
}

Link to comment
Share on other sites

Yes, definitely. A floating pin sometimes works the way you'd expect, but I've also had them changing state based on the state of nearby switches on the panel, or the state of nearby pins on the arduino board, or even acting like a capacitive sensor and changing state when I waved my hand near the switch body.

Toggle switches are also susceptible to contact bounce. Possibly only when the contacts open, but it's there. I always wind up using software debouncing, and if you're looking I just used the Bounce2 library in a different project and it's quite easy to work with. But hardware debouncing looks like fun, and I'm a little envious of Mr0nak's setup.

Thanks for the information; the Bounce2 library was helpful. I managed to integrate it with the KSPIO code, but I am not sure if I have done it correctly (there's no error, and the controller still seems to work).

Briefly, in KSPIO.ino, I have


Bounce debouncer = Bounce();

prior to the void Setup()

and then have


debouncer.update();
int value = debouncer.read();

in void loop ().

In output.ino, I have


debouncer.attach(SASPIN);
debouncer.interval(5);

along with the other pins.

Seems to work fine for me, but even without the software debounce, I wasn't getting bouncing...

Another question; if I wanted to use a pot/slide pot for throttle control, would any resistance value be fine? 50k linear pot, for example?

Edited by Darkblade48
Additional information
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...