Overactive interrupt triggering using internal pullups

RogerClark
Sat Dec 17, 2016 10:18 pm
I’ve just built a small project that uses a Maple mini with a Nokia 5110 monochrome LCD display , and a rotary encoder, and a external switch input (reed switch to detect a magnet), and also a high current put 1A using a FET driver.

I’m using the internal 22k pullup on the input from the rotary encoder and also from the reed switch input, but I’ve noticed I appear to get false triggers on the reed switch input and more recently on the rotary encoder input.

I was using the internal 22k pullup, e.g.

pinMode(PUSH_BUTTON, INPUT_PULLUP);

But it now looks like this is too weak for real world usage.

I suppose I could solder on external pullups e.g. 4.7k or perhaps even 1k, to prevent false triggers, but it seems odd that STM would have 22k as the internal pullup, if its value was too high to be usable.

It could also be that a lot of the miss-triggers are caused by supply noise.

Note. I’m debouncing the rotary switch extrnally using 100nF cap across the switch, so I would have thought this would also act to decouple the pin and stop miss triggering as well as debouncing, but at the moment it doesnt seem to be working as well as I’d like ?

BTW. I’m powering the Maple Mini on Vin, via a 9V external supply, because the switched high current output – which drives a solenoid, is designed to run from 12V, but 9V seems to be plenty (but 5V is not quite enough)

Any thoughts about what I am doing wrong.


ahull
Sat Dec 17, 2016 10:44 pm
What does the ‘scope show?

mrburnette
Sat Dec 17, 2016 10:57 pm
Sounds like you have a radio receiver on your hands. My guess is 50Hz noise.

Ray


ahull
Sat Dec 17, 2016 10:58 pm
mrburnette wrote:Sounds like you have a radio receiver on your hands. My guess is 50Hz noise.

Ray


RogerClark
Sun Dec 18, 2016 2:32 am
I’ve not looked on the scope, as I built 2 of these and the units and the one that is exhibiting the fault is the one I build for my dad.

I agree it sounds like the input wires are too long, but I modified the code to disable the external reed switch detector, (which is on a 10ft long pair of wires), and its still going wrong, so I think its miss triggering on the rotary encoder, and the rotary encoder connections are only about 2 inches long, inside a box.

To be honest, I cut some corners, to save having to solder loads external components, I use the internall 22k pullups on all inputs, which are the 2 rotary encoder signals, as well as the push button that is on my rotary encoder, and also use the 22k pullups on the reed switch sensor.

To debounce, I just have a 100nF capacitors to gnd on all these inputs.

But initially I had a problem, where if I pushed the Press button on the rotary encoder, I”d get a miss trigger on the rotary encoder its self.
And to stop that happening, I had to change my wiring, so that it didnt have a common ground wire from the system GND to the button gnd and the rotary encoder ground.

I presumed the problem was that when the button was pushed, it shorts the 100nF to GND, (across the push button).

Somehow this was causing current to flow up the common GND, and caused the GND on the rotary encoder to rise, hence somehow applying noise / spike to the rotary encoder trigger input.

Basically, I’m doing the same as Nick Gammon describes here

http://www.gammon.com.au/forum/?id=11130

Image

But the push button on the rotary encoder is debounced in the same way, and shares a common GND wire


RogerClark
Sun Dec 18, 2016 3:00 am
OK.

I learnt something new.

For some reason I thought the internal pullups were 22k. But they are not !

On page 62 of the datasheet

http://www.st.com/content/ccc/resource/ … 161566.pdf

It says

RPU

Weak pull-up equivalent resistor min 30k, typical 40k, max 50k

Mine are appear to be around 42k.

So really I need a much lower external resistor, as these “weak” pullups are far to high to be usable in my application, (at least for the interrupt lines)


Pito
Sun Dec 18, 2016 10:05 am
Also use an R=1k-2k2 in series with switches contacts, see the schematics in the previous rot enc topic.
You may try to pass 3 turns (all wires incl gnd) via a ferrite bead with longer cables too.. when living close to a radio station :)

RogerClark
Sun Dec 18, 2016 11:17 am
Pito wrote:Also use an R=1k-2k2 in series with switches contacts, see the schematics in the previous rot enc topic.
You may try to pass 3 turns (all wires incl gnd) via a ferrite bead with longer cables too.. when living close to a radio station :)

Pito
Sun Dec 18, 2016 11:34 am
Without a simulation a 100nF capacitor @3V shorted via 0.010Ohm switch resistance can cause Amps of currents :)

ahull
Sun Dec 18, 2016 2:21 pm
Pito wrote:Without a simulation a 100nF capacitor @3V shorted via 0.010Ohm switch resistance can cause Amps of currents :)

racemaniac
Sun Dec 18, 2016 3:15 pm
Btw, just wondering how necessary it is to use interrupt on an encoder.
I started the same way on a cheap chinese rotary encoder i had, but when i noticed 1 step would trigger the interrupt over 50 times, i looked at the signal of my encoder with a logic analyzer, and there was about a 2ms gap between one line changing state, and then the other. So now i ended up just making a program that samples the pins every millisecond (and it does some debouncing by requiring the pin to have the new state on 2 consecutive reads), and it works very reliably, and it hardly taxes the processor at all, so unless your encoder can make lots of steps per second or is of far better quality than what i have, is using interrupts and all that effort in hardware debouncing really necessary?
(and in the end it’s running on a timer that also generates interrupts, i confess :p)

Pito
Sun Dec 18, 2016 4:57 pm
Long time back I used to use the pic16 (DDS vfo) with the encoders in a similar way – ~4kHz interrupt, in the interrupt the encoder routine reading the enc values, inclusive acceleration, incrementing/decrementing a global var and an flag the enc was active).

Btw, 100nF @3.3V, shorted down via 0.1ohm (esr+cont res) creates a 20ns long pulse of 30A current.. (mcu clock is 14ns).

Switch current 100nF.JPG
Switch current 100nF.JPG (53.74 KiB) Viewed 553 times

Pito
Sun Dec 18, 2016 6:50 pm
Considering 2x 100mm long flying wires (2x 100nH) the situation would be (assuming 1ns edges of the driving pulse):

Switch current 100nF 200nH 0_1ohm.JPG
Switch current 100nF 200nH 0_1ohm.JPG (81.29 KiB) Viewed 549 times

RogerClark
Sun Dec 18, 2016 8:31 pm
The lines to the rotary encoder are actually quite short, and relatively thick wire.

Picture 21.jpg
Picture 21.jpg (110.52 KiB) Viewed 541 times

mrburnette
Mon Dec 19, 2016 1:26 am
I think the internal pullup’s are just too weak in this high noise environment.

The rule-of-thumb for pull-up/pull-down is 10K. I doubt this would eliminate your issue.
– Poor input DC source over long length,
– Plastic enclosure
– FET + solenoid inductive load

I would minimize the voltage stability by use of a 1A DC-DC
Caps should be low ESR caps, tantalum preferred
Use ferrite filters between Maple and FET

You can probably live with the plastic box but do use ground strapping between common ground and the DC-DC The reference.

Ray


ahull
Mon Dec 19, 2016 1:43 am
How much current does the solenoid draw? What FET are you using? High or low side switching? What diode did you use? Is the diode fried?

RogerClark
Mon Dec 19, 2016 2:34 am
Hi Andy,

Solenoid this this one

http://www.ebay.com.au/itm/WS-2X-5-6lbs … 2245433151

Its supposed to be 12V but normally run it from 6V as it produces enough magnetism at 6V, however sometimes I need to use 9V.

FET is 2N7000 which is rated at 200mA continuous and 500mA when pulsed. And I’m only turning the FET on for 5mS and then off for 350mS.

The solenoid has a DC resistance of 50 Ohms, so at 9V the max current drawn should be inside the spec for the FET

Flyback diode is a 1n4148 – I could be blown, but I don’t have the unit exhibiting the problem (long story)

I have a partially built backup unit (the one I took a photo of) so I will need to add the solenoid and FET etc and attach my scope and see what’s going on !

But as the problem of miss triggering seems to be caused purely by pressing the push button on the rotary encoder and not purely by the FET and the solenoid, I think the main cause is just that the internal pullup’s are “weak” as described in STM’s on docs.

I won’t use the internal pullups again for any real world products which involve interrupt inputs, as it looks like the changes of miss triggering due to supply noise is too high.


stevestrong
Mon Dec 19, 2016 9:37 am
RogerClark wrote:BUt I agree I should have a resistor in series with the encoder as well, rather than the 100nF being shorted by the encoder.

roffey
Fri Dec 23, 2016 11:07 am
I don’t know if this will be helpful or not, but I was having issues with using multiple ints when dealing with 6 button switches plus a couple of bcd switches. I have never really been a fan of edge triggered ints in possibly noisy environments. Can be a pain.
I ended up running all the ‘commons’ through the base of an npn, and using just one line as the int. The base and collector lines were decoupled and I only had to deal with that one edge input.
Ok, it meant a scan at the int time to see what was active, but it certainly allowed me to tailor the circuit to my needs.

RogerClark
Fri Dec 23, 2016 7:23 pm
I think the important lesson for me, is that the internal pullup is very weak.
Possibly as high as 50k, and is probably only useful on inputs between devices on the same PCB.

I should have not tried to use the internal pullup for any external connections, as the lightlyhood of false triggering is too hig.


fredbox
Sat Dec 24, 2016 4:23 am
RogerClark wrote:

Basically, I’m doing the same as Nick Gammon describes here

http://www.gammon.com.au/forum/?id=11130

Image


roffey
Sat Dec 24, 2016 8:40 am
That looks interesting, and a useful reference…. Single int using change …. should be far more robust…. thanks for putting that up.
I do note however, that you are using 0.1uF electrolytics in your circuit. I would want to swap those out for some decent ceramics, and ground any metal areas on the encoder if they are isolated. Just my preference though :)

mrburnette
Sat Dec 24, 2016 5:06 pm
roffey wrote:That looks interesting, and a useful reference…. Single int using change …. should be far more robust…. thanks for putting that up.
I do note however, that you are using 0.1uF electrolytics in your circuit. I would want to swap those out for some decent ceramics, and ground any metal areas on the encoder if they are isolated. Just my preference though :)

octavio
Sun Sep 17, 2017 8:25 pm
The code below counts when button is pressed,the button is connected to a pin with a 10uf capacitor in parallel to filter posible noise,only the internal pullup is used,and it works ok if i press the button betwen calls to ” Serial.println(f1);” but if i reduce the delay to 100ms then it counts about 20 times for every button press.As a work around i’m going to directly read the port status and add a digital filter,but this seems to be a important bug in the arduino libraries or the stm mcu.The test was done with a usb to serial adapter.

//stm32f103cb 20k ram 128k flash

#define B_nextfile PA4

void setup()
{
afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY); // release PB3 and PB5
afio_remap(AFIO_REMAP_SPI1); // remap SPI1
gpio_set_mode(GPIOB, 3, GPIO_AF_OUTPUT_PP);
gpio_set_mode(GPIOB, 4, GPIO_INPUT_FLOATING);
gpio_set_mode(GPIOB, 5, GPIO_AF_OUTPUT_PP);

Serial.begin(250000);delay(1000);
Serial.println("serial ok");
pinMode(B_nextfile,INPUT_PULLUP) ;
attachInterrupt(B_nextfile,isr_next,FALLING);

}
int f1;
void loop()
{
Serial.println(f1);
delay(10000);
}

void isr_next(void)
{
++f1;
}


RogerClark
Sun Sep 17, 2017 10:33 pm
Internal pullups are virtually useless for buttons etc.

The spec says their values can range from 30k to 50k

Use a suitable value external pullup


octavio
Sun Sep 17, 2017 11:33 pm
The pullups values are similar to those found in other microcontrollers (atmega,xmega) and they work without problem in those microcontrollers,with or without filters if the wires are not too large.And 50k seems a suitable value,sometimes i have used 1M external resistors to reduce current consumption and still works.

RogerClark
Mon Sep 18, 2017 12:10 am
[octavio – Sun Sep 17, 2017 11:33 pm] –
The pullups values are similar to those found in other microcontrollers (atmega,xmega) and they work without problem in those microcontrollers,with or without filters if the wires are not too large.And 50k seems a suitable value,sometimes i have used 1M external resistors to reduce current consumption and still works.

This is irrelevant. They are not a STM processor.


octavio
Mon Sep 18, 2017 6:22 pm
I have disabled the internall pullup and conected a 4k external pullup,problem continues.

stevestrong
Mon Sep 18, 2017 6:36 pm
First, you should define all variables used in ISRs as “volatile”.
Second, it does not seem to be a bug for me, it is rather the MCU which runs couple of times faster than the AVR processors.
Third, you should put a resistor (100 Ohm) in series with the capacitor to the button in order to reduce the currents produced by shorting the capacitor when you press the button. Otherwise it can generate noise spikes which can erroneously trigger interrupts.

Pito
Mon Sep 18, 2017 6:38 pm
Your f1 must be volatile..
volatile int f1;

victor_pv
Mon Sep 18, 2017 7:20 pm
[Pito – Mon Sep 18, 2017 6:38 pm] –
Btw, I am running here (BPill) 3 attached interrupts at 3 pins, the first fires 1300x per second, the second about 550x, the third about 4-10x per second (all at random times). I am not loosing a single one (so far). In parallel Serial.print(), math, HardWire I2C, bitbanged SPI into Xilinx.
Doing in ISR exactly what you do – incrementing a volatile uint32_t.

Can you post what circuit and settings you are using for debugging if any? (internal pullup, internall pulldown, floating with external resistor of XXohms to 3v3, etc)
That will help a lot as starting point to other people since you are getting good results.


Pito
Mon Sep 18, 2017 8:05 pm
Victor, the 3 outputs of CMOS logic (3.3V) are fed into interrupts inputs – ie PA2, PB3, PA0 (works with any pins with index <= 5, not the same index on several ports).. You know what I mean :)

There are 360ohm resistors in series in my case. I’ve put them there to minimize ringing (it may catch more interrupts when it rings). Why it may ring? Because the CMOS outputs are fast and the wires are long, the parasitic LC driven by fast edges rings. The same may happen with encoders, switches etc.

The resistor’s value could be higher, as the interrupt’s frequency is rather low (max few kilohertz) – thus the RC will not mess too much.

CMOS ---> 360ohm -----> BPill interrupt input


octavio
Mon Sep 18, 2017 8:48 pm
I get aditionals interrupts without pin changing value, when the button is released and the pin voltage goes slowly (about 200ms) from 0 to 3.3v.Since the interrupt happens without a pin status change,it should be a bug ,not electrical noise.
About volatile: the value is not written out of the ISR and is read on with a single instruction ,so it should not be a problem.

Pito
Mon Sep 18, 2017 8:51 pm
I get aditionals interrupts without pin changing value, when the button is released and the pin voltage goes slowly (about 200ms) from 0 to 3.3v.Since the interrupt happens without a pin status change,it should be a bug ,not electrical noise.
Could you explain me in more detail – what does it mean you get interrupts “without pin changing value” when you also add the input goes “slowly” from zero to 3.3V. Can you clarify it more precisely pls?

If your signal goes slow from 0 to 3.3V in 200ms, you may get 50 additional interrupts. That is because your signal is slow.
The decision level for 1 or 0 in 3.3V CMOS is at 1.65V approximately.
The decision level may change, as the environment is noisy. So you have to spend a minimal time in that region. The logic while at 1.65V will trigger each time the level changes by few millivolts (the changes comes from VCC and GND – it jumps +/- 30mV).
Therefore Schmitt triggers are used – the Schmitt trigger introduces hysteresis – thus a small change at the 1.65V decision level will not retrigger. The BluePill does not have Schmitt triggers at its inputs I think (or does it)? It does have the Schmitt trigger inputs.
https://en.wikipedia.org/wiki/Schmitt_trigger

When somebody wants to chase each and every edge:
1. you must use fast edges (to minimize time spent at 1.65V)
2. or you have to use Schmitt triggers to process slow signals (where the edges are slow)

PS: The Schmitt trigger’s hysteresis in BPill is 200mV (datasheet). Hopefully it works. So – when your slow growing signal does not change (while around 1.65V) by 200mV downhill, you have to get 1 interrupt. Anyway, I would recommend to have edges fast.


Pito
Mon Sep 18, 2017 9:55 pm
@octavio: try to use a different pin for the interrupt, not PA4. Try PA0.
PA4 is SPI1 NSS, you do a remapping of SPI1, maybe there is something weird.
BTW, SPI1 is not at PB3,4,5 by default, but on PA4,5,6,7.

octavio
Mon Sep 18, 2017 10:05 pm
I mean that the ISR code reads the pin value using “digitalread()” and compares with the value stored in the previous interrupt ,and sometimes is the same,so no interrupt should occur but it happens.And this problem happens while using “Serial.print()”, else it works fine.

Pito
Mon Sep 18, 2017 10:07 pm
So pls be so kind and do post your entire code, otherwise we cannot help you..

RogerClark
Mon Sep 18, 2017 10:09 pm
in response to a couple of posts…

Steve is correct.. If you dont put a resistor in series with the switch, the surge current to charge the capacitor will cause problems. I experienced this when using a rotary encoder.

@pito.. +1
Supply rail on the BluePill seems quite noisy when I look at it with a scope, and this will potentially cause multiple triggers,

E.g if the i put voltage is from a cap that is slowly charging up, its effectively a high pass filter, and will be a fairly smooth rise.
where as the GPIO input threshold changes all the time as its approx Vcc/2 and Vcc varies slightly all the time.


Pito
Mon Sep 18, 2017 10:12 pm
We will know more when Octavio will show us the code he actually uses when he experiences issues.
Most probably he has the switch from pin against GND, pullup, and the 10uF capacitor from pin to GND. So he discharges the capacitor to GND, and then he slowly charges it via pullup. So the voltage rises kRC. He is using falling edge, so he fires the interrupt when he presses the button against ground.

RogerClark
Mon Sep 18, 2017 10:19 pm
True…

BTW. good call about potential issues with NSS.

Code was added to make it usable as GPIO even when using SPI, and I dont recall anyone having problems with using it as an output.

But there may be problems as an input or with using it as an interrupt pin


octavio
Mon Sep 18, 2017 10:55 pm
Problem solved,it was electrical noise (problably caused by the serial line).There was a 4cm thin wire betwen the capacitor and the pin,this wire was a enought good antenna to make the chip (an me too) crazy. I solved the problem adding a 3k resistor in series with the pin and as close as possible to the mcu,the pin capacitance and the resitor makes a low band pass filter that cancels the high frecuency noise.

Pito
Mon Sep 18, 2017 11:01 pm
So it means your 10uF capacitor did not work as the capacitor at higher frequencies. Most probably you have not used a 10uF ceramic multilayer smd one :)

octavio
Tue Sep 19, 2017 12:08 am
It was a multilayer ceramic capacitor,but there was a 4cm wire betwen the capacitor and the port pin and another 4cm betwen the capacitor and the board gnd.It seems that this wire has a good radiofrecuency coupling with the serial line.

Leave a Reply

Your email address will not be published. Required fields are marked *