Do I need an opto-coupler?

Hi all,

I'm trying to build a test circuit to simulate a vehicle speed sensor, and then a system to read the pulses. I have successfully created the pulse generator, and have verified that the pulses are being translated from a Teensy 3.2 (3.3v digital output).

The speed sensor I'm simulating would normally be 5v square wave, so my plan was to use a PC817 optocoupler to ensure the security of the arduino. Does this sound like a worthwhile idea or is it overkill? I'm also not sure that the Teensy rig would generate enough current to drive the opto coupler so maybe I just take it out?

[EDIT] The other circuit I need to count is a 12v Tacho signal which comes from the ECU as such: Making the tach work with LS-series engines — SL-C Wiki

I was going to use a PC817 with a 470 ohm resistor for this, is this a reasonable idea?

Sounds good, why not simply use a 5V buffer or MOSFET with pull up to isolate the Arduino. You can drive the buffer with maybe a 27K resistor that way if the buffer fries it will not take the arduino port. Isolate the buffer from the supply with a MOSFET if you know how (see below), other wise use a SBR SUPER BARRIER RECTIFIERS or schottky diode. To minimize this forward drop you can configure a MOSFET as an ideal diode, which has a very low drop in the forward direction (equal to the current times the MOSFET's ON resistance) while blocking the current in he reverse direction.To minimize forward drop you can configure a MOSFET as an ideal diode, which has a very low drop in the forward direction (equal to the current times the MOSFET's ON resistance) while blocking the current in he reverse direction. This response is to help you get started in solving your problem, not solve it for you.
Good Luck & Have Fun!
Gil

Hi,
The opto would do the trick, good isolation for noise and simple low component count interface.

Tom... :slight_smile:

Thanks both for your input! So on my prototype PCB I have the attached setup (look for OK8, kind of top left, on the line labeled "Speedo Input". It's a fairly simple input, it just had a 470ohm resistor inline with the PC817 input, then the output pulls the Arduino pin to ground.

I've got the following code generating a pulse from another Arduino:

/* 2126mm per tyre revolution = 470 revs per km
diff ratio 3.42 so 1607 revs per km on gearbox = 1.6074 revs per m 

So 10mph = 4.4704 m/s = 7.19 revs/s = 122 pulses /s
70mph = 31.2928 m/s = 50 revs/s = 855 pulses /s

*/

int sensorPin = A0;              // select the input pin for the potentiometer
int sensorValue = 0;            // variable to store the value coming from the sensor

unsigned long val = 0;                    //value to be used with map
const int speedled =  13;      // the number of the LED pin //speed pulse
const int speedpin =  12;      // the number of the pulse pin //speed pulse


int ledState = LOW;            // ledState used to set the LED
int ledState2 = LOW;           // ledState used to set the LED

unsigned long previousMicros = 0;      // will store last time LED was updated
unsigned long interval = 500;          // interval at which to blink (milliseconds
unsigned long time = 0;
unsigned long previousTime = 0;      // will store last time Time was updated
float Hz = 0;
int i = 1;


void setup()
{
  Serial.begin(115200);
  // Serial.println("Start...");
  // set the digital pin as output:
  pinMode(speedpin, OUTPUT);
  pinMode(speedled, OUTPUT);   
}

void loop()
{
  sensorValue = analogRead(sensorPin);
  //Serial.println(analogRead(sensorPin));
  interval = map(sensorValue, 0, 1023, 11690, 81960);        // interval adjuster 8196   1169
  
  unsigned long currentMicros = micros();

  time = currentMicros - previousMicros;
  if (time > interval)                             // 17 cycles of HIGH to LOW on pin 14 speedpin (17 teeth on T56 speed sensor)
  {
    previousMicros = currentMicros;
    i++;

    if (i == 2)
    {
      time = currentMicros - previousTime;
      previousTime = currentMicros;
      Hz = 1000000.0 / time;
      Serial.println(Hz, 2);                     // 2 digits
      
    }

      ledState = !ledState;                      //  1 -> 0 -> 1 -> 0 etc 
      digitalWrite(speedpin, ledState);
      digitalWrite(speedled, ledState);
  //Serial.println(digitalRead(speedpin));

  }
}

If have the reader Ardunio set up like this to test the idea:

#include <AccelStepper.h>

//Speed
volatile unsigned long VSS_count=0;
unsigned long VSS_prior_count=0;
int pin_VSS = 15;

void pulse() {
  VSS_count = VSS_count + 1;
}

int SPEED_MPH;
int SPEED_STEPS;
int SPEED_SEND;


void setup()
{
  Serial.begin(9600);


   //---Speed Input Count-----------------------------------
  pinMode(pin_VSS, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pin_VSS), pulse, RISING);
  NVIC_SET_PRIORITY(IRQ_PORTA, 0);

}

void loop() {
  //currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)


  unsigned long VSS_new_count = VSS_count;
  if (VSS_new_count != VSS_prior_count) {
    Serial.println(VSS_new_count);
    VSS_prior_count = VSS_new_count;
    delay(10); // print at reasonable speed
  }
Serial.println(digitalRead(15));

}

If I connect the output pulse wire to the input pin on the schematic, I get nothing on the reader.
If I connect the output pulse wire to the input pin of the PC817 (bypassing the 470ohm resistor), I still get nothing
If I connect it direct to the receiving arduino's input pin (bypassing the PC817 opto-coupler) then I see the pulses on the serial monitor.

So the opto coupler isn't working - what am I doing wrong? Is the arduino's digital write signal simply to weak to trigger the opto-coupler to close?

Is anyone able to help with that last post? I'm stumped!

I cannot get the png file to download

Sure it can be found here: Link

When I clink on the link in message #3
https://forum.arduino.cc/index.php?action=dlattach;topic=662436.0;attach=344777
I get 'File not found.' on Win10 and Mac

in message #6 the link
https://onedrive.live.com/?authkey=!ABwWNJ_w7Melp8g&cid=1F69C00CA330AF09&id=1F69C00CA330AF09!3792&parId=1F69C00CA330AF09!3705&o=OneUp
is to 'Front PCB Schematic.png' not the "Rear PCB Schematic.png" mentioned in #3

Schematics are needed. I can't find any optocoupler in the schematic you linked to. A lot depends on how you actually wire the things.

Does this work?

I found the tach input.

It appears to be an open collector output as there's a 5k pull-up resistor. That may be why it doesn't work: 5k + 470Ω + diode means about 1.8 mA drive for the opto LED. Not much, though it should be enough to pull down a signal.

Not knowing much about your tach sensor makes it hard to suggest changes; one thing that may work is to reverse the connection of the optocoupler: with resistor connect to 12V and the negative side of the opto to the tach output. A 2k2 resistor would give a 5 mA drive current, that's enough.

The resistors you picked give almost 23 mA through the optocouplers, that's too much, it'll severely reduce lifespan. Use 1k-2k2 instead.

wvmarle:
I found the tach input.

It appears to be an open collector output as there's a 5k pull-up resistor. That may be why it doesn't work: 5k + 470Ω + diode means about 1.8 mA drive for the opto LED. Not much, though it should be enough to pull down a signal.

Not knowing much about your tach sensor makes it hard to suggest changes; one thing that may work is to reverse the connection of the optocoupler: with resistor connect to 12V and the negative side of the opto to the tach output. A 2k2 resistor would give a 5 mA drive current, that's enough.

The resistors you picked give almost 23 mA through the optocouplers, that's too much, it'll severely reduce lifespan. Use 1k-2k2 instead.

Thank you very much for your response this is really helpful! Ok I'm going to break my response into two parts:

Speed Sensor:

This is 0-5v square wave so in this case the optocoupler OK8 on the schematic would want the signal coming in on pin 1 via a ~100ohm resistor to give around 5mA?

RPM:

This one has a pullup resistor as recommended by the GM manual. It says the input must have a 5k resistor between the pin and ground as shown on the input to the OK7 optocouplerl, and this one is a 12v square wave. For this one I added the diode and stuff to control any spikes in case the RPM signal is in any way linked to the coils. This may not be necessary though? So for this I should use a 2k resistor to get around 5mA?

The one I have tried and doesn't work is the speed sensor, so just the 3.3v Teensy output through a 470ohm resistor and nothing happens. I guess current is too small. I tried bypassing the resistor by touching the wire the other side of the resistor so no resistance and that didn't work either...

450nick:
Speed Sensor:

This is 0-5v square wave so in this case the optocoupler OK8 on the schematic would want the signal coming in on pin 1 via a ~100ohm resistor to give around 5mA?

Check your math! That'd give 38 mA. 470Ω sounds more like it (8 mA).

RPM:

This one has a pullup resistor as recommended by the GM manual. It says the input must have a 5k resistor between the pin and ground as shown on the input to the OK7 optocouplerl, and this one is a 12v square wave. For this one I added the diode and stuff to control any spikes in case the RPM signal is in any way linked to the coils. This may not be necessary though? So for this I should use a 2k resistor to get around 5mA?

Most likely that will work - to be sure, do post a link to the data sheet of the sensor.

The one I have tried and doesn't work is the speed sensor, so just the 3.3v Teensy output through a 470ohm resistor and nothing happens. I guess current is too small. I tried bypassing the resistor by touching the wire the other side of the resistor so no resistance and that didn't work either...

Current? For what? What are you even trying to do here? Mixing up output/input??

So I have my prototype board built with he optocouplers in and the circuit as shown in the diagram. In the absence of having the car where I am, I am trying to test that the circuit works so I built a little Teensy breadboard signal generator which is pinging 3.3v output at the same rate the car VSS sensor will do. When I hook it up to the speedo input (the one with just the 470ohm resistor, the Teensy on the prototype board wired to the optocoupler sees nothing so the opto coupler doesn't seem to be working. Trying to work out if the circuit is wrong or my test signal isn't powerful enough.

If you connected the 3.3V to the optocoupler without resistor, you'd best first replace that optocoupler as it's LED is likely burnt out.

Doh. Ok I will replace, but once I do, do the proposed values make sense? I still tried connecting the 3.3v via 470 ohm resistor before then and it didn't work then either...

So 470ohm for speedo
2k for the RPM one?

Resistor values make sense.

470Ω is fine for a 3.3V input, it'd give about 4.5 mA. Use a 10k pull-up on the output and you should see a clear signal. Use your multimeter to confirm.

Make sure you connect the optocoupler the correct way around. That's a common error.

Ok I will give this a go now... So this is what I now have (inputs on the left, RPM 12v input on top, Speedo, 5v input on the bottom):

So you think I may also need a pullup on the output of each opto-coupler? Or would running the pin mode as input_pullup be enough?

IT WORKS! Don't know how I made that so difficult. Sorry for so many dumb questions... So pleased!

Using the input_pullup mode is fine. That's what it is for :slight_smile:

What's the purpose of that inductor FB1?

And congratulations getting it to work :slight_smile: