weak pull down resistor?

Hi!
I know this may seems a common question, but I googled a lot and didn't find a real solution.
I'm trying to read a button switch in a heavily rf/electrical polluted environment.
The electrical noise comes from the ignition system of a 2stroke kart engine where the circuit is mounted on.
The Arduino and the switch are about half meter far away from the engine (on the steering wheel).
The problem is represented by fake switch flips: it happens even if the switch is unconnected and also with a very very short cable <5cm
The internal pull-up resistor didn't work, so I turned to use a "strong" 100 Ohm pull-down with the attached scheme and this code:

/* pins for nano */

#define IN 2 
#define LED 12
int clck=0;
void setup() 
{
pinMode(LED, OUTPUT);     
pinMode(IN,INPUT);
digitalWrite(IN,LOW);
attachInterrupt(0, clicked, FALLING);
}

void clicked()
{
clck=1;
} 

void loop() 
{
if (clck==1)
{
  digitalWrite(LED, HIGH);
  delay(200);               
  digitalWrite(LED, LOW);   
  delay(200);           
  clck=0;  
}  
 
}

What else could I do?
A smaller resistor? But what about current?
Use analog pin? But what about timing without interrupt?

Grazie
Fabrizio

pulldown.png

Try the following scheme:

  • Connect the switch in series with a 100 ohm resistor, and connect the combination between the input pin and ground
  • Also connect a capacitor between the input pin and ground. Try 0.1uF or 1uF. The ground side of the capacitor should go to an Arduino ground pin via the shortest route possible - in particular, it should not share a ground pin that is being used to supply power to the Arduino
  • Enable the internal pullup resistor

It is normally better to read switches by polling them. Only use an interrupt if you need the switch to wake the mcu from a sleep mode. Polling them gives you the opportunity to use software to eliminate the effects of contact bounce and short-term interference.

int clck=0;
...
void clicked()
{
clck=1;
}

Variables used in an ISR should be declared volatile.

Quite so. However, in this case it won't actually matter, given the structure of the code, and the fact that the compiler used by the Arduino IDE doesn't support link-time code generation, and therefore can't optimize across modules. So the compiler has to generate code that re-reads 'clck' each time that loop() is entered.

Hi.
Have you tried installing a ceramic or monolithic capacitor to ground
something around 0.01 uf marking 104
you could also go down to 18-22pf

You could also help clean up the area by installing spark plug boots with some suppression built in.. Honda and Yamaha used them a lot over the years, they just screw directly into the spark plug wire.
Ford also used them on the Crown Victoria's...
Crown Vic's were the flag ship of most police services..with a lot of electrical gear.. hence the extra supression

@dc42:
Thank you I'll try as soon as possible!
I already tried a similar solution but without the resistor and without the internal pull-up.
I need interrupt because the switch is briefly closed by a magnet to measure lap time, polling misses events.

@Nick Gammon:
Thank you, I just forget it in the posted source code, in the real application it's correctly declared.

@Chris1448:
Hi! Yes already tried with 104 ceramic and many big electrolytic but always getting fake clicks,
but I will try with a RFI resistor spark plug , thank you!

I would not use interrupt. Seems a bit too complicated for just detecting a push button.

Try a lower value external pullup on the digital pin and then make the push button ground it. Also implement debouncing code that's available around this forum.

d2fryer:
Hi! Yes already tried with 104 ceramic and many big electrolytic but always getting fake clicks

You need to keep the wires between the capacitor and the ground & input pins really short, so that the area enclosed by the input_pin-capacitor-ground_pin circuit is as small as possible. Magnetic flux from interfering circuits (e.g. ignition) that pass through this area will induce voltages in the circuit.

Also, use twisted pair or shielded cable between the switch and the Arduino.

dc42:
Also, use twisted pair or shielded cable between the switch and the Arduino.

Good suggestion here! ^^

If you got some cat-6 cable, use both blue or green wires (any pair actually) for each wire run to the button
The pairs are twisted together, to help cut out interference.

Hi all!
Still getting random signals :frowning:

  • I turned on the internal pull up resistor
  • I lowered the pull down resistor to 50 Ohm
  • I put a parallel capacitor with 4-5mm length legs (many tries from small 202 ceramic to 100uF electrolytic)
    but I'm still getting random fake signals a little fewer than before (when I just used a simple pulldown) but still quite often (about one every second) even when the sensor cable is unplugged and the arduino only has 5cm coaxial cable ending with an rca jack and all is about 50cm far away from the engine...
    I didn't try to use resistor spark plug because all other karts don't have it... (so I'd get their pollution as I drive nearby)
    Maybe I should try to replace the SPST switch with a SPDT?
    Or maybe add an external 1K Ohm pullup resistor?

pullcond.png

  1. How are you powering the Arduino?

  2. Is the coax cable and RCA jack isolated from the vehicle chassis, apart from where the coax outer is connected to an Arduino ground pin?

  1. power comes from 9V battery

  2. Arduino, coax cable and plug are completely isolated from chassis, hosted in an electrical plastic enclosure held by cable ties (no screw), coax outer is connected to Arduino ground

I still think that's a poor circuit. The diode makes things worse, it allows that side of the switch to pick up noise, which is the carried into the Arduino enclosure. Also, switches etc. are better connected between the data pin and ground, not between the data pin and +5V. I suggest you use this (see schematic).

I turned the circuit as suggested to a pull-up resistor and capacitor... it works fine even at 1cm close to ignition cables of my car but at half meter from the kart engine it's still getting fake clicks and I also noticed that if I put the circuit closer (< 10 cm) even the 8x2 lcd display gets confused :frowning:

Does it get fake clicks even with the sensor cable disconnected at the Arduino end? If so, and bearing in mind the LCD corruption, then I suspect that the circuit is picking up interference inductively. The fix would be to put the whole thing except the sensor in a metal enclosure. You'll have to cut a hole for the display, but you could perhaps put a fine metal mesh over the top of that. Connect the metal enclosure to Ardino ground, but keep it isolated from kart chassis. For the sensor, use a BNC or F-type socket mounted on the metal box, and a matching plug and coax cable from there to the sensor.

Alternatively, add suppression to the ignition system of the kart. For example, use carbon string HT leads and run them close to the metal chassis. Putting ferrite beads over the existing HT leads may even help.

Quite so. However, in this case it won't actually matter, given the structure of the code, and the fact that the compiler used by the Arduino IDE doesn't support link-time code generation, and therefore can't optimize across modules.

What is a "module" in this case? Everything seems to be in one source file? And the fact that the IDE mashes up all the .ino's would affect that too, right? I assume that "module" is a "compilation unit" or source file.

If you define all your pins as OUTPUT you don't need to create physical pulldowns, and it works the same way :slight_smile: (because your IC start to use the internal pulldowns)

But if you want to do the things right just define them as INPUT_PULLUP, (and connect your push button to GND) but remember that when they are LOW it's when you are pressing it :slight_smile:

This way you avoid to use resistors :slight_smile:

KeithRB:

Quite so. However, in this case it won't actually matter, given the structure of the code, and the fact that the compiler used by the Arduino IDE doesn't support link-time code generation, and therefore can't optimize across modules.

What is a "module" in this case? Everything seems to be in one source file? And the fact that the IDE mashes up all the .ino's would affect that too, right? I assume that "module" is a "compilation unit" or source file.

Yes, by "module" I mean "translation unit" in C/C++ terminology - that is, a source file and all the header files it includes. My understanding is that the Arduino IDE, each .ino file gives rise to one source file.

Right, so volatile would work in this case, since it is all in one module, right?

'volatile' will "work" regardless of whether everything is in one module or not. You can sometimes get away with leaving out 'volatile' where it ought to be used, but that doesn't mean that you should.