Interfacing a inductive proximity sensor to an Arduino Uno

I have been asked to come up with a project, for a course that I am studying, to help solve a problem in the place that I work. I work in a factory that produces metal pedestrian barriers and temporary fencing and on these machines are hoppers where the tube is placed into. At the minute there is no notification system of when these hoppers run empty so my project is to solve this.

My idea is basically using inductive proximity sensors, like the ones already used on the machine, to detect the presence of tube and send a signal to the Arduino. I then plan on sending this signal from a transmitter to a receiver which will then display the result on a screen to show if the hopper is low/empty. [Design of system - Imgur: The magic of the Internet]

I intend to use a IFM IM5128 to detect the tube using the 24v circuit from the machine to power them. The signal produced from the sensor when activated will be ~24v where this signal will be sent to the digital pins. However from what I've read the Arduino's digital I/O pins can only handle around 5v. I've also read to use a voltage divider to step down this voltage to a safer level in which the Arduino can use.

Another problem is from the datasheet of the sensor it says it's current output is 200mA which, from what I've also read, is also far too high for the digital I/O pins to handle - maximum 40mA.

So my question is would there be safe way to interface these sensors to the Arduino?

if the signal is 24V AC you will reed to rectify it to DC then use a voltage divider

or use a zeener diode to get it in 5 V range

it may also be a good idea to use an opto isolator

I don't know much about electronics, maybe somebody will put us right; Looking at the datasheet I don't think it means the output is 200mA since it says the current consumption of the device is <20mA. I think 'Permanent current rating of
switching output DC 200mA' means that when closed the sensor is able to pass a current of upto 200mA continuously.

However I would have thought that you supply both the current and the voltage. What makes you think the output will be 24V? I admit am really not clear what 'Max. voltage drop switching output DCV 2.5' means.

Thinking about it the device only seems to have one connector with 4 pins, three of which are used so I was probably writing rubbish. I don't understand how this works;
pins.jpg

OP: You're confusing need (input current required) with capability (output source capacity).

The prox can source (output) a maximum of 200ma when it detects metal. The Arduino input only needs microamps to detect the high (triggered) state.

The IFM is a quality part using a 24 vdc supply so a simple resistive divider is all that is required to drop the 24v signal to the <5 volt input level the Arduino requires. A divider of R1=2K2 and R2=470-560R will be fine.

The note in the datasheet about max voltage drop is just that, the output voltage can be as much as 2.5 volts lower at full load (200ma) than the applied supply voltage. As the voltage divider will only require about 1ma of current when on, the actual volt drop seen will be insignificant.

avr_fred:
OP: You're confusing need (input current required) with capability (output source capacity).

The prox can source (output) a maximum of 200ma when it detects metal. The Arduino input only needs microamps to detect the high (triggered) state.

The IFM is a quality part using a 24 vdc supply so a simple resistive divider is all that is required to drop the 24v signal to the <5 volt input level the Arduino requires. A divider of R1=2K2 and R2=470-560R will be fine.

The note in the datasheet about max voltage drop is just that, the output voltage can be as much as 2.5 volts lower at full load (200ma) than the applied supply voltage. As the voltage divider will only require about 1ma of current when on, the actual volt drop seen will be insignificant.

So the 24VDC supply is attached across pins 1 and 3. How does the voltage divider then attach to the the device and the Arduino? If the device can supply 200mA what limits the current to the amount required by the Arduino?
Sorry if this is basic electronics but I am interested in understanding this.

Ardly: You're attempting to hijack another members thread, it's rude. If you have basic electronics guestions, start your own thread in the appropriate forum subsection (general electronics).

Sorry, got carried away - I was on-topic though.

Thanks for the replies so far.

@horace - I should have specified it in my post but the signal is 24VDC. I know a lot of the equipment at my work is opto isolated so that was another thought. An electrical guy at my work said I could supply the coil of a relay with the signal from the inductive proximity sensor energising the coil of the relay every time the sensor is activated. A separate lower voltage circuit would be connected to the common terminal of the relay and then terminating at one of the digital pins so when the relay's activated the lower voltage circuit would be complete and one of the digital pins read "high".

@ardly - [Imgur: The magic of the Internet] This is my understanding of how the wiring of both Normally Open PNP and NPN sensors work. I believe you can think of them as simple switches where a switch closes between the +V (BR) and the signal wire (BK) and 24VDC is outputted from the signal wire (BK). We don't use the extra white wire (4th pin) at my work but I think it's used as another signal wire. I tested the output of the signal wire when supplied with 24VDC and it returned around 23.4VDC so a slight voltage drop. I then lowered the supply voltage to 20VDC, the sensor LED lit but no voltage was outputted from the signal wire. This is what I'm taking the max voltage drop to switch the output as.

@avr_fred - Ah okay, brilliant thankyou that clears it up. I thought when the sensor was activated the signal produced would be ~24VDC at 200mA but didn't know the current actually needed would be a lot lower. The 24VDC output wasn't as much as a problem because I knew I'd be able to reduce the voltage down, like you say, it was just the current I was worried about but knowing its interfaceable with the arduino is good to hear. I'll end up using three of these sensors so I assume the sum of these currents on the digital I/O pins is safe for the max current on all pins - 200mA?

You're confusing inputs with outputs again.

One IFM prox sensor, using the resistive voltage divider described above, will drop the voltage from 24v to about 4.5v and will cause less than 1ma of current to flow out of the sensors output pin. That current originates in the 24 vdc power supply that powers the IFM prox sensors, not the Arduino. The actual current that flows into the Arduinos input pin is nanoamps, insignificant in the grand scheme of things.

200ma is the total maximum current that can flow between the VCC and GND pins on the atMega328p. The maximum safe current for any one output pin is 20ma which can be sourced by the pin or sunk by the pin. Sourcing means the current is positive relative to ground, sinking means its negative relative to ground. It safe to assume that inputs require no significant current and can be ignored, you have to check every output to ensure it isn't going to source or sink more than 20ma each and them sum them up to ensure you're not too close to the total package limit of 200ma since the processor itself needs some current to operate as well.

The terms used in the prox sensor world for output types is NPN or PNP which actually refers to the type of transistor that was used back in the early days of the devices. PNP means that the output sources current, NPN means that it sinks current.

@avr_fred - Okay, I believe it's starting to make more sense. So the maximum current the sensor's output (signal wire) outputs when activated can be up to 200mA but only actually only requires a fraction of this amount to be able to operate (20mA<) and that this outputted current will still be enough for the arduino to pick up the triggered high state of the sensor?

Could be a stupid question but the resistive voltage divider would be placed between the sensor and arduino digital input and not before the sensor as it requires a minimum of 10... 30V to operate?

Thankyou for the info and for clearing up my other points as well.

The voltage divider is to be connected to the signal output of the sensor.

The mid point of that divider is connected to the Arduino input - which in itself will not take any current (maybe one micro-amp, probably much less than that). An input just measures what's out there, an ideal input takes no current at all.

So for arv_fred's question: the input of an Arduino has a very high input impedance, which is what limits the current when connecting something to that pin (and the voltage is within the -0.5 to Vcc + 0.5V range). Should be in the dozens of MOhm region, I don't know the actual number.

The important thing is to make sure that the voltage supplied to the Arduino input pin is within that range, and that's what the voltage divider does. You get some +4.5V, which is enough for a high signal (anything above about 3V will read as high) from the pin.

Of note: if what you have is indeed an NPN or PNP type output, you need an additional pull-up resp. pull-down resistor for reliable detection of the "off" signal.

You are correct, sir.

I'm on an iPad so it have to describe it rather than draw it... the output from the prox sensor is connected to one end of the 2K2 resistor, the other end is attached to the Arduino digital input. Also connected to that digital input is one end of the ~500 ohm resistor. The remaining 500 ohm end is connected to Arduino GND. Also connected to Arduino GND is the common (-) of the prox and the 24vdc supply.

The maximum voltage that appears on the Arduino digital input is 24 (input voltage) * 500/(2200+500) = 4.44 volts. The current that flows out of the prox output is given by I = E/R which is approximately 24/2700=0.0088A or 8.8ma.

The Arduino digital input impedance is significantly high enough to ignore its current requirements when calculating the current that will flow in the prox output. Essentially, all the current flows in the resistors alone with the 500 ohm resistor acting as a load across the otherwise very sensitive digital input. With that 500 ohm resistor in place, it takes at least 2-3 ma of current to develop the minimum input voltage required for the Arduino input to see the pin as a logic HIGH level rather than LOW.

As an exercise, you could raise the ratio of the resistive divider by say a ratio of 100, making R1=220K (2K2100) and R2=50K (500100). You still get the same 4.5 volts output but you've reduced the current flowing in the circuit by a factor of 100 resulting in about 80 microamps rather than 8 ma. What's the result? A higher susceptibility to noise since it would now take only 40ua to make the input a logic HIGH. It is common to see the effect described in inverse logic by saying that lowering the resistor values increases the noise immunity.

Of note: if what you have is indeed an NPN or PNP type output, you need an additional pull-up resp. pull-down resistor for reliable detection of the "off" signal.

The 500 ohm resistor of the divider performs that function.

Regardless of the prox output type, the divider required to drop the output from 24 volts to <5 provides the needed pull-up (NPN aka sinking) or pull-down (PNP aka sourcing)

Yes, I said that incorrectly. For NPN output you'd have to connect the divider between +24V and the output.

For the resistor divider: I'd go for about 10x the suggested values. Less current but normally still enough to prevent accidental triggers, though actual resistor values used are often also determined by the question "what's in my parts box?".

@wvmarle and @avr_fred - Here's what I've drawn out from the way you described it and I believe it is correct but just wanted to check.

PhilGuitar:

Other than a missing connection to Arduino GND (or was that implied by the GND symbol? Better draw such connections explicitly) that looks correct to me.

My bad should have been more concise in what I put but yeh that was implied in the drawing.

Managed to get it working and I hope it's clear how I wired it all up in the photos. Put an LED on pin 13 just to show when the sensor is activated and I will use this signal in the future to transmit it from a transmitter to a receiver and then display it on a screen.

Here's the code:
int sensorState = 0;

void setup() {
pinMode(3, INPUT);
pinMode(13, OUTPUT);
}

void loop() {
sensorState = digitalRead(2);

if (sensorState == LOW) {
digitalWrite(13, LOW);
}
else {
digitalWrite(13, HIGH);
}
}

Thanks again for the help it's much appreciated!

A couple of comments.

You schematic doesn't show the negative 24v power supply connection. It's best to draw a complete circuit and don't assume that connecting a wire to a "ground" point completes a circuit. The 24 volt common needs to be connected to both the prox common and the Arduino GND. Obviously they're connected or things wouldn't be working.

A lot of industrial control systems using 24 vdc control voltage ground the common of the supply as you've shown, actually connecting this point to metal back panels and ultimately to earth ground through the power system. It's a bad idea for a number of reasons but it seems to be gaining acceptance as 24 vdc control voltage systems replace older US standard 120 vac control systems. That's a topic for another day...

Your code, while working, could be refined a bit as a learning exercise.

You first declare your prox variable as "int sensorState = 0;" which is fine but the initial setting to zero is redundant, all Arduino read/write variables are initialized to zero upon a power up/reset.

Next, you setup the prox input with the pinMode statement as pin 2 and then read pin 3. It works because all pins are initialized in the Arduino as inputs so there's no actual need to set the pin mode to input, other than for clairity.

You then use an "if" statement to compare the prox status to LOW and then write a LOW to LED when true. That's absolutely fine but it's redundant, if the desired output value is the same as the input, there is no need to use the if test.

Here's a modified version that adds variables that represent the pin numbers, this avoids numbering mistakes and makes the program more readable. The "const" keyword added before the int size declaration tells the compiler the name is a constant and cannot be changed. If you try to assign a new value to the name, you'll get a compile time error.

// declare I/O
const int proxInput = 2;
const int LED = 13;

//declare variables
int sensorState;

void setup() {
  pinMode(proxInput, INPUT);
  pinMode(LED, OUTPUT);
}

void loop() {
  sensorState = digitalRead(proxInput);
  digitalWrite(LED, sensorState);
}

avr_fred:
You first declare your prox variable as "int sensorState = 0;" which is fine but the initial setting to zero is redundant, all Arduino read/write variables are initialized to zero upon a power up/reset.

That must be specific Arduino then (handled by the IDE?) as it's not the C++ standard which would initialise the value to whatever happens to be on that memory address.

This specific line can do with some optimisation. As it's a digital pin state the value can only be 0 or 1, and this would be better declared as bool or byte. That saves 1 byte of RAM and should make the code run a little faster (yes, purely academic and not of practical importance in this code).

In this example code the whole variable is actually unnecessary as it's not used for anything but setting that output pin. The loop() can be written as:

void loop() {
  digitalWrite(LED, digitalRead(proxInput));
}

For the declaration of pin numbers I prefer to use #define statements. I still don't know if there's any real difference between the two methods.