Trouble with an Opto-Coupler...

Status
Not open for further replies.

450nick

Active member
Hi all,

As part of my instrument cluster project, I need to be able to read 12v RPM square wave and vehicle speed 5v square wave input signals. I'm testing my prototype board and so far have no joy starting with the speedo input; partly as I sized the resistor for a 12v pulse and then realised it actually will be 5v. Doh!

So for testing, I started by creating a 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 Teensy. Does this sound like a worthwhile idea or is it overkill?


The other circuit I need to count is a 12v Tacho signal which comes from the ECU as such: http://slc-wiki.squarespace.com/making-the-tach-work-with-ls-series-engines

For this one I was going to use a PC817 with a 470 ohm resistor for this but with a suppression coil and cap to prevent any potential spike (not sure if the RPM signal is in any way attached to the coils in this ECU though so it may be way overkill...


So back to the speedo input I'm testing currently. On my prototype PCB I have this setup (look for OK8, kind of top left, on the line labeled "Speedo Input". It's a fairly simple input, it just has a 470ohm resistor inline with the PC817 input, then the output pulls the Teensy 3.2 pin to ground.

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

Code:
/* 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 Teensy 3.2 set up like this to test the idea:

Code:
#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 Teensy'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 Teensy 3.2's digital write signal simply to weak to trigger the opto-coupler to close?

Thank you in advance!!
 
A quick web search re: the T-56 speed sensor indicates that it is a variable reluctance sensor.

Typically a variable reluctance sensor produces positive and negative-going pulses of variable voltage usually increasing with speed and as such needs some signal conditioning before connecting it to a Teensy pin or you will fry it.

An alternative might be something like this speed sensor conversion kit:-
http://www.importmuscle.com/s2000-speed-sensor-kit

although in your case you don't necessarily need the box, just the adapter and the hall-effect sensor.

The Tach output from your ECU may be 5v and may or may not have the capability to drive the input of an optocoupler without some kind of buffer.

I hope you have an Oscilloscope.
 
Fiddled around with it and it works!

Good shout on the variable reluctance, though I think the -5 to +5 goes from gearbox to engine ECU then ECU outputs 0-5v only. I will check this though.
 
Status
Not open for further replies.
Back
Top