What we learend the hard way: Normally open or normally closed

At the start of this season, I had read all about how normally closed is better than normally open. The basic reason why is that if the limit switch is disconnected, it is treated like the limit switch is being pressed down, switch stops movement in the direction towards the limit switch. This is a great use case for normally closed. We used normally closed on most of the limit switches on our robot with a few exceptions.

Downsides to normally closed

  • If the limit switch fails, that mechanism isn’t moving at all, unless you program a manual override (sometimes this is a good thing, as it’s almost guaranteed to not try and go past a hard stop)
  • If you use the limit switch being pressed down to reset encoder counts, having the limit switch unplugged will reset the position to 0 (or your maximum encoder counts).

We ran into the second downside yesterday at GRC. For our hatch stow, we have a reverse limit switch and an encoder on the hatch stow mechanism. Whenever the limit switch is pressed, we reset the encoder counts to 0. We don’t have a forward limit switch. We decided that an encoder would work just fine. And while we tested the robot, it worked perfectly. That motor always seemed to smoke when we used our hatch mechanism during the match and we never figured out why until yesterday.

During the operation of the robot the reverse limit switch would sometimes be open for a single instant even when the limit switch was not being pressed (this limit switch uses normally closed). When the limit switch was open, the program registered this as the limit switch being pressed down. It reset the encoder counts to 0 and our code to drive the motor out to 9000 encoder counts decided that it needed to go 9000 more encoder counts to reach its desired position. This means that the motor was trying to drive past a hard stop (in the forward direction), the very thing we wanted to avoid!

TDLR; Don’t use normally closed limit switches to reset your encoder counts

1 Like

You can also use debounce code and look for a certain number of consecutive sensor readings before resetting. This is always a good Idea .


We always require an absolute sensor for all mechanisms to avoid this issue. We don’t always use the absolute sensor for control directly though, we will sometimes initialize an offset for an incremental encoder to the absolute encoder and use the incremental encoder for control. But we can continuously check our estimated position (from the incremental encoder + offset) to the absolute sensor, and see if we are having any sensor issues.


When you’re designing the circuit for your application you need to be the engineer. You get to think about how the circuit performs in normal conditions, and also how it will perform in a failure condition. Then you can take it one step further and determine if you need to detect the failure condition, or if it matters at all.

Real world example - machine guarding and safety. You might have a door switch that leads into an area of the machine where the machine is in motion or has potential energy that could lead to injury. You have two options for the door switch: power to lock or power to unlock. Power to unlock is great - when the machine loses power it defaults into a safe state, and keeps everyone out. Until you realize that in some situations power to unlock could trap someone in the machine!


We use current sensing as a backup. We currently use Talon SRX on all motors and lets assume the stall current on a motor is 10A and it drawas a max of lets say 4A under normal operation (we get that value to log current during design and or practice.) So if we exceed lets say 8A for a certain period of time lets say 200ms then we assume we either have a bad limit switch or something broke. At that point we either shut down or keep it at 8A or maybe scale back to 6 or whatever is safe for the motor. We burned up some motors in 2014 or 2013 I think and we had that in one way or another since then. We also have used it in autonomous on occasion we call it “bouncing of walls” like when we had to put something on the scale we drove forward until the current rose over 8A (the drive CIMs drew 2-3 under normal unempeded going forward. So when we hit 8 we knew we hit the wall in front of the scale so we stopped the drive and opened the mechanism holding the box. Or you could also back off for a 1/4 sec and then strafe (mechanum) until you hit the next wall etc. Bottom line we have not burned a motor in at least 5 years that way. All you do is poll the current


Exactly. OP, think about the reason that NC is considered “good”. Usually it’s because the pull-up/down resistor configuration on the roboRIO cause the unplugged switch to read like a pressed switch.

The real criteria - this common “unplugged” failure mode must put the robot in the safe state.

Usually, this means “no motion”. If the function of a pressed switch causes no motion, you’re good for NC as you described. However, in the two exception cases you described, the safe state wasn’t exactly achieved.

It’s also worthwhile noting that this unplugged switch is called an in-range failure - ie, inside your software, the failed condition looks like a valid reading. In general, this is a no-no for robust operation.

Assuming there is a mitigating action you can take without having the sensor available:

The way around it is to add some form of redundancy. Current sensors or encoders measuring a related quantity is definitely a good way to go. If you carefully craft the constraints between the two readings, you can detect physically implausible conditions, and make corrective actions to achieve safe state. Probably just “turn off motors”, but maybe not - depends on the mechanism.

One additional suggestion use two digital inputs, and wire up both the NC and NO contacts on the switch (one to each input). This is called a parity setup - you know at all times one of the two switches should be pressed at any time. If you see two or zero, you know you have an issue.


I’m not a programmer but could you put in some code that tracked the relative count (0-9000) and ignored a reset signal if the motor was increasing the count and the count was over a certain count?

We have moved to this over the years as well. When combined with a beam break sensor, reliability goes through the roof. Our approach is very similar to yours, including the time above the limit. We add a divisor of output voltage though, in order to account for a stalled motor under multiple conditions. We also have to account for edge cases of ramp up, where current is expected to be higher than the target limit for a few milliseconds. We have even been able to simulate this without an SRX using the PDP current with a projected voltage based upon % output - useful for sensorless intakes. Here is how ours works:

if LIMIT_RATIO = 3.0
then 40A / 12V = current limited (full power)
and 18A / 6V = current limited (half power)
and 17A / 6V = not current limited
For an intake @ 75% output = 9V - therefore the PDP would have to read 27A 
    before tripping the limit

We were inspired by 1538’s 2015 robot, which had 4 encoders and no limit switches. Every elevator we’ve built since then has had 0 physical limit switches. In 2019 with Smart Motion on the NEOs, our properly-tuned elevator never hit their current limits after the initialization routine, unless something mechanically seized (like our ropes at our first event).


I really like this idea. I think I will definitely use this next time along with consecutive sensor readings.

Yes, we could have done that but if we, for some reason, start the robot with the hatch mechanism out, it the encoder counts would be 0 when it’s really at 9000. So this would work, but it might affect quick tests we do when changing things. It’s probably better than nothing, though.

1 Like

“Threshold and debounce” doesn’t get enough love if you ask me. Just debouncing switch or sensor readings for a few loops does wonders to cure small gremlins that often get blamed on electrical team. It’s not a panacea, but it’s a quick and dirty way to get from feeble to fairly robust.


Use of techniques such as switch debouncing are standard practice in industrial electronics.


And in large yellow dirt-moving machines.