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).
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.
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;
}
}
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?
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.