12V to 3.3V Signal to Arduino

I am currently using a limit switch powered by a 12V battery to determine when a motor has pushed an arm to its limit. I would the Arduino to receive the signal from the switch.

I was reading that using an optocoupler would be a good choice; however, I am having some issues getting it to work. Right now I am using the PC817 and on the LED side I have a 3.9K resistor connected to pin 1, pin 2 connected to ground, pin 3 connected to INPUT_PULLUP and pin 4 connected to Arduino ground.

When I read input pin on the arduino, I am not seeing a change in voltage when the switch is activated. I think it has something to do with the forward current required to drive the LED; however, I thought 3.9K would do the trick. Any help is greatly appreciated.

You should stare at the graphs in the datasheet for some time. They tell a lot.

The forward voltage over the led is about 1 V.
( 12V - 1V ) / 3k9 = 2.8 mA
Then you can look at the transfer ratio or saturation voltage vs forward current.
The CTR tells that at 2.8 mA, the ratio is about 6.5 times.
That means the collector can sink 17 mA, but I prefer to drive the transistor into saturation, I think 3mA collector current (or less) is okay for that.

Which Arduino board do you use ?
If the internal pullup resistor is 60k, then the current is only 55 µA.
That is still way above the dark current, but 55 µA is such a tiny current !
Can you add a extra external pullup resistor of 4k7 (2k2 to 10k or so) ?

Change your pin 3 and 4. Pin 3 is Arduino GND and pin 4 is the open collector output to a digital input (preferably with a external pullup resistors to 3.3V).

Thank you Koepel!

So I went about it a different way. I calculated R based on the 1.2V @ 20mA and came up with 540ohm (12V - 1.2V/20ma).

I then used a 4.7K external pull-up and swapped pins. I included my schematic. Hopefully this does the trick. Eventually, I would like to add an LED on the 12V side just to show when the limit switch is hit, but I want to get this working first.

Screen Shot 2021-07-01 at 8.46.22 AM

You likely don't need U14 to be 4.7k. You can probably get by with a 10K or by enabling the internal pullup.

And you can probably increase U13 to 2k.

"U" ?
For 50 years I always thought the schematic designation for a resistor was "R".

1 Like

That is the convention, however in reality it is arbitrary.

And I know R is the first letter in resistor.

So I used the resistors mentioned (10K on collector and 2K on pin 1). I am still not seeing a HIGH/LOW toggle from the optopcoupler in code. I've added my new schematic and code. I do see the toggle happen on the 12V side with my switch (LED blinks on the button), but not seeing the HIGH LOW on the Arduino side. I'm using an ESP32 HUZZAH from Adafruit.

#define LED_PIN 13
#define SIGNAL_PIN  12

void setup() {
  // put your setup code here, to run once:
  pinMode(SIGNAL_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);

  digitalWrite(LED_PIN, HIGH);
  delay(1000);
  digitalWrite(LED_PIN, LOW);
  delay(1000);
}

void loop() {
  uint8_t state = digitalRead(SIGNAL_PIN);
  switch (state) {
    case HIGH:
      digitalWrite(LED_PIN, HIGH);
      break;
    case LOW:
      digitalWrite(LED_PIN, LOW);
      break;
  }
}

Screen Shot 2021-07-01 at 11.22.10 AM

1 Like

What is the input pin (12) in? i.e. High or low?

I would add a delay in your loop. Should work as is but slowing it down might be wise.

I would then disconnect pin 4 of the opto (or actually you could disconnect all the pins). Input should be high.

If the above shows the correct output, I would short pin 12 to ground to verify the state changes.

Do you have a multimeter. If not you should get one. You don't need a super precision one, just enough to measure voltages and likely ohms.

It's always HIGH. It never goes LOW.

I can, but I am using one of these buttons on the 12V side.

I do. I'll try out some of these suggestions. I also found online that some people are using a transistor on the Arduino GND side. I'm not sure why though. I assume this should work and is common in these kind of scenarios right?

That is not a button, that is a ... well, I don't know, it is something.

afbeelding

How did you wire it ?

The RED wire goes to the 12V supply, Black 12V ground, Pin 2 on the Opto to 12V ground, Green to Pin 1 on the opto. Picture attached.

Perhaps, that is part of the problem. I have some basic leaf switches I can use instead.....

You are correct, it should work. Both the schematic in post 3 and 8 should be a slam dunk.

So:

  1. Previous wiring caused the opto to go bad.... not likely
  2. wiring is not what you think.

Suggestions: (two different tests)

  • Wire R13 directly to 12V (i.e. remove the button)
  • Connect Pins 3 and 4 at the opto verify the processor sees a change.

The delay is because the loop is going a full speed. It should not make a difference but a delay is easy to do.

When all the things that could possibly cause a problem are exhausted then you start checking those things that cannot possibly cause the problem.

Well, that depends on whether your motor circuit is actually isolated from the Arduino ESP32.

The original circuit using a 3.9K resistor to the optocoupler LED and INPUT_PULLUP on the Arduino ESP32 was perfectly correct. The optocoupler should be close to the Arduino ESP32. If it does not work, there is obviously a mistake in the wiring or a damaged component.

Yeah! :grin:

Hi guys! Thanks for the help. I switched out the PC817 for another one... and everything worked. I guess I fried it :smiley:

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.