Help reliably reading switch on long wire

I have wired a push-to-make microswitch to an interrupt pin on my Arduino Mega using an external 1k pull down resistor as shown in the image "pull down connection" here: Inputs

The switch seems to reliably trigger the interrupt on close (actually multiple times due to bounce). However, very occasionally (say once every hour or so of operation) the interrupt will be triggered when the switch is NOT closed. This is a very big problem for me as the switch is an essential limit switch which is used to calibrate the position of the machine. Typically the switch will not be closed more than once a second and <10ms delay before interrupting would probably be ok. It is just important that I get reasonably immediate (<10ms) notification that the switch is closed which I can rely on!

I have seen a few posts regarding using capacitors in series across the switch, capacitors from the Arduino interrupt pin to ground and a resistor between the switch and the Arduino interrupt pin. I am not really too sure what to try and what value components to use (quite new to electronics as my other posts will indicate! :D).

The switch is ~2m from the Arduino and is connected using 7-core trailer cable (http://www.maplin.co.uk/7-core-trailer-cable-70). Some of the cores in that cable are used to power two DC motors which can typically pull a total of about 4A@12V, other cores are used to carry the signal from a hall sensor which operates at 12V. Essentially, the environment is unavoidably noisy. For example, using the internal pull up resistors of the Arduino results in the switch wildly being detected as opened and closed. Using a pull up resistor of 10k also results in very unstable operation.

Can anybody help? :slight_smile:

I'll throw in my 21 cent here... I think you either need to add proper filtering or switch to polling to ensure proper software debouncing is in place. If you have the possibility, put an oscilloscope in there to see what you are battling against. :slight_smile:

Thanks for getting back to me.

you either need to add proper filtering or switch to polling to ensure proper software debouncing is in place

I agree with adding proper filtering. The issue is I'm not sure how!

Debouncing in the strict sense isn't required, I am happy for the switch to trigger the interrupt multiple times when it is closed, I just don't want it triggering it at all when it isn't closed!

I agree that polling could potentially cure this but it may affect the operation of the machine as it will have to poll the switch multiple times before it is "sure" it is closed THEN stop the motors moving it towards the switch.

If you have the possibility, put an oscilloscope in there to see what you are battling against.

I wish I had an oscilloscope but do not :(.

I agree that polling could potentially cure this but it may affect the operation of the machine as it will have to poll the switch multiple times before it is "sure" it is closed THEN stop the motors moving it towards the switch.

Depending on hw timings you could just digitalRead() the switch state twice, 5 to 20 ms apart. That's what I did on a project of mine with a stepper motor. But it was moving "slowly".

Yeah. The motors aren't usually moving incredibly fast so this would probably sort of work unless, of course, in the unlikely event that both readings have interference.

I would really quite like to try some of the hardware filters that I have seen mentioned elsewhere on this forum. Do you have any idea how to implement them? This will allow me to keep my tested code the same, keep the fast response to the switch closing and reduce the chance of getting two bad readings.

I am also wondering if I could increase the resistance of the pull down resistor to deliberately make things unstable, check that the hardware filter works correctly then reduce the resistance back to 1k. Does that sound like a sensible way of solving (and knowing I've solved) this rare intermittent fault?

How much trouble is this worth to you...

Here's a very robust (I think... never tried it... but based on other stuff about long wire monitoring) "answer" for you:

With a different switch at the other end, at the "sense it" end, you could arrange for the voltages on the end of the wire NEAR... not directly connected to!!... the Arduino, call them "A" and "B", to be powered "one way" or "the other", depending on switch position.

Switch "on": A is positive with respect to B
Switch "off": B is positive with respect to A

Once that is in place, near the Arduino, you wire up a comparator circuit with a digital output to the Arduino.

====
Less involved thing to try:

At Arduino, a small circuit based around an opto-isolator...

... and drive the LED in that with a larger voltage than the voltage you are currently using. (Larger voltage= more room for "must be higher than".)

The same circuit could incorporate a capacitor/ resistor on the LED side to discard transients.

NOTE: tkbyd you posted as I was writing this, I will read your post now.

Some of the posts that mention hardware filters:

Terry King said...

  • You add, across the switch, a series Resistor-Capacitor combination of 470 ohms and 4.7 uF (Or other appropriate combination)

When you press the button, you will have a discharge time constant of 2.2 ms during which Arduino will 'see' the transition with it's input circuit, which has a small amount of hysteresis and it should get a clean single, 'debounced' value. When you release the button, you will have a charge time constant of 50 ms, which is fast enough that you can't push the button again 'too soon'. Unless you have a 20 Hz finger, in which case you could be a drummer with U2.

Will this work for me? It seems like it would have the effect I want.

http://arduino.cc/forum/index.php/topic,15737.0.html
Grumpy_Mike said...

Protection

Also adding capacitors at the arduino end can help. Also consider using the analogue input to detect the push switch. That way you can set your own thresholds instead of having them set for you by the digital input pins.

I can't really use the analogue pins as I am using interrupts but what is meant by "adding capacitors at the arduino end"? A capacitor between the interrupt pin and ground? What value is sensible? Should I put a resistor between the switch and the Arduino as shown in the protection circuits at the above link?

How much trouble is this worth to you...

This is worth quite a lot of trouble! If I don't get this right I may be looking at a very mangled and difficult to replace machine! :smiley:

I am not sure I understand how to implement your first answer. What kind of switch would that require and how would that be wired up?

Are you saying it should essentially work like:
SWITCH OPEN:
A = 5V
B = 0V

SWITCH CLOSED:
A = 0V
B = 5V

Then use a comparator on A and B with the output connected to the Arduino interrupt?

Your second idea is exactly what I am using with the hall sensor. I guess I could also do this with the switch... thinks

The switch is ~2m from the Arduino and is connected using 7-core trailer cable (http://www.maplin.co.uk/7-core-trailer-cable-70). Some of the cores in that cable are used to power two DC motors which can typically pull a total of about 4A@12V, other cores are used to carry the signal from a hall sensor which operates at 12V.

Of course its going to mis-trigger if you run it parallel to high-current cables. You will be getting a lot of electromagnetic and capacitive coupling if you do that.

You should run your inputs/sensor wiring completely separate from the high current wiring, and it should be shielded, twisted-pair or both.

Add 100pF between the input pin and ground too for RF suppression.

Hey MarkT.

This sounds pretty convincing to me. I will try to get hold of some shielded twisted-pair cable and add the 100pF capacitor.

Do you think my idea to reduce the resistor value in order to make the problem more reproducible is a good idea? Basically I will swap the 1k for 10k, check that the cap and cable fixes the issue still then switch back to 1k.

Now I just need to get hold of ~2m of this cable here in the UK! I'll get back to you guys once I manage to do so and install it.

Thanks again!

Bob101:
Hey MarkT.

This sounds pretty convincing to me. I will try to get hold of some shielded twisted-pair cable and add the 100pF capacitor.

You can make twisted pair easily with a hand-drill and a bench-vice. Shielding or twisting both reduce the pickup, you're unlikely to need both - just moving the wires away from the source of interference will be the biggest win.

Do you think my idea to reduce the resistor value in order to make the problem more reproducible is a good idea? Basically I will swap the 1k for 10k, check that the cap and cable fixes the issue still then switch back to 1k.

I'd be worried the existing pulses are risking the input pin - adding a 10k series resistor at the Arduino end would be a wise precaution if using the same cable.

Now I just need to get hold of ~2m of this cable here in the UK! I'll get back to you guys once I manage to do so and install it.

Any cable that's not run parallel to the motor wiring will likely solve the problem - worth testing before spending money on anything fancy.

Thanks again!

Having the wires close together is sort of unavoidable. The motors are mounted very close to the switches and the entire unit is to be mounted on a vehicle (an RV). Both sets of wires have to run from near the Arduino to the unit so they will always have to be fairly close together. I can at least run two sets of wires, one for the motors and one for the switches and there can be some separation between them.

I may just try purchasing shielded twisted pair cable. I can use the current cables for something else in the future. This will save me making a terrible job tearing up the 7-core then twisting it back up! :slight_smile: If this doesn't work then at least I know I can not improve the situation any more by changing the cable again so no worries about cost.

I see your point about the pulses. Ok I will add a 10k resistor in series just before the Arduino interrupt pin and test this out.

Thanks!

By the way... you can see the machine (it is a solar tracker :D) in action here:

The motors/switches/hall sensors are all run over those 2 coiled black 7-core wires. When it is fitted in the vehicle the wire will not be coiled :D.

Use the pull up method rather than the pull down. This is because the decoupling and spike suppression is more effective.
I would use a 0.1uF cap, I don't think a 100pF will do anything for you, it is way too small.
On my site look for the protection tutorial that shows techniques for suppressing interference like this.

Are you suggesting I build something like this: http://www.thebox.myzen.co.uk/Tutorial/Protection_files/shapeimage_10.png ?

With a 10k resistor in place of the 22R and a 0.1uF in place of the 100pF? Then use a 1k resistor as a pullup rather than a pulldown? Should this resistor be located to the left of "outside world" in the image from your site?

I know these are basics questions but this is really one of my first projects... I'm amazed I got this far... it's thanks to help on forums like this one!

For two metres of shielded twisted pair cable, just go down to your local Radio Shack/ hi-fi store and buy some audio cable.

With a 10k resistor in place of the 22R

No but you could push it up to 330R.

and a 0.1uF in place of the 100pF?

Yes.

Then use a 1k resistor as a pullup rather than a pulldown?

Yes.

should this resistor be located to the left of "outside world" in the image from your site?

No have the pull up directly onto the arduino pin.

I know these are basics questions

No problem with that. :slight_smile:

thanks to help on forums like this one!

It's a good place to be.