High Speed Timer - DigitalRead problems

Status
Not open for further replies.

rjb

Member
I have two related problems with my optically isolated inputs and the associated digital reads on the TEENSY 3.1.

The primary problem is that the DigitalRead is not consistent in reading the status of the optically isolated input (pins 14 through to 21). As it goes through the FOR loop monitoring status, sometimes the status is read and sometimes not. For example pins 16 and 17 are pretty consistent, but 14 and especially 15 are not. Note that this was tested with the TEENSY plugged into a VMWare Windows 8.1 computer running on Mac Yosemite via a USB cable.

The secondary problem is that when the TEENSY is plugged directly into a USB power supply, all of the inputs status are not read. They remain high even through there is an optically isolated input (and the LED comes on). Note as well that I have tried both INPUT and INPUT_PULLUP with no impact.

Thanks, Rudy



// set this to the hardware serial port you wish to use
#define LCD Serial1

// Teensy 2.0 has the LED on pin 11
// Teensy++ 2.0 has the LED on pin 6
// Teensy 3.x has the LED on pin 13
const int LEDPOWER = 13;

// Definte Input Pins
const int INPUTRESET = 3;
const int INPUTSTART = 4;
const int INPUT0 = 14;
const int INPUT1 = 15;
const int INPUT2 = 16;
const int INPUT3 = 17;
const int INPUT4 = 18;
const int INPUT5 = 19;
const int INPUT6 = 20;
const int INPUT7 = 21;
const int VERSIONMAJOR = 1;
const int VERSIONMINOR = 1;

// Clear the LCD Display
void clearLCD(){
LCD.write(254);
LCD.write(88);
}

// Set Cursor Position on LCD Display
void setCursorLCD(){
LCD.write(254);
LCD.write(121);
LCD.write(0);
LCD.write(40);
}

void setup() {
// Set up inputs and outputs
pinMode(LEDPOWER, OUTPUT);
pinMode(INPUTSTART, INPUT_PULLUP);
pinMode(INPUTRESET, INPUT_PULLUP);
pinMode(INPUT0, INPUT);
pinMode(INPUT1, INPUT);
pinMode(INPUT2, INPUT);
pinMode(INPUT3, INPUT);
pinMode(INPUT4, INPUT);
pinMode(INPUT5, INPUT);
pinMode(INPUT6, INPUT);
pinMode(INPUT7, INPUT);
}

void loop() {
int inputInitial[8];
int inputFinal[8];
unsigned long inputTime[8];
unsigned long timeTemp;
unsigned long timeInitial;
int i = 0;
int j;
delay(100);

// Turn on LED on CPU
digitalWrite(LEDPOWER, HIGH);

// Display Startup Message
LCD.begin(19200);
delay(100);
clearLCD();

LCD.print("R Engineering Inc.\n");
LCD.print("High Speed 8 Channel Timer\n");
LCD.print("Version ");
LCD.print(VERSIONMAJOR, DEC );
LCD.print(".");
LCD.println(VERSIONMINOR, DEC );

while(digitalRead(INPUTSTART) == HIGH) delay(50);
LCD.print("Waiting to arm for testing...");

while(digitalRead(INPUTSTART) == LOW) {
setCursorLCD();
switch(i) {
case 0:
LCD.print("- ");
break;
case 1:
LCD.print("\\ ");
break;
case 2:
LCD.print("| ");
break;
case 3:
LCD.print("/ ");
break;
default:
LCD.print(" ");
break;
}
// Read input status
inputInitial[0] = digitalReadFast(INPUT0);
inputInitial[1] = digitalReadFast(INPUT1);
inputInitial[2] = digitalReadFast(INPUT2);
inputInitial[3] = digitalReadFast(INPUT3);
inputInitial[4] = digitalReadFast(INPUT4);
inputInitial[5] = digitalReadFast(INPUT5);
inputInitial[6] = digitalReadFast(INPUT6);
inputInitial[7] = digitalReadFast(INPUT7);
i+=1;
if(i>3) i = 0;
// for(j=0;j<8;j++) LCD.print(!inputInitial[j]);
// Delay for serial to catch up
delay(100);
}

// Display current value and set counters / flags to zero
setCursorLCD();
LCD.print("INIT ");
for(i=0;i<8;i++) {
LCD.print(!inputInitial);
inputTime = 0;
}
while(digitalRead(INPUTSTART) == HIGH) delay(50);
// Display current time
LCD.print("\nTIME ");
timeInitial = micros();
LCD.print(timeInitial);
LCD.print("uSec\nTiming Circuit Active...\n");

// Make timing measurements
while(digitalRead(INPUTSTART) == LOW) {
if(!inputTime[0] && digitalRead(INPUT0) == LOW) inputTime[0] = micros();
if(!inputTime[1] && digitalRead(INPUT1) == LOW) inputTime[1] = micros();
if(!inputTime[2] && digitalRead(INPUT2) == LOW) inputTime[2] = micros();
if(!inputTime[3] && digitalRead(INPUT3) == LOW) inputTime[3] = micros();
if(!inputTime[4] && digitalRead(INPUT4) == LOW) inputTime[4] = micros();
if(!inputTime[5] && digitalRead(INPUT5) == LOW) inputTime[5] = micros();
if(!inputTime[6] && digitalRead(INPUT6) == LOW) inputTime[6] = micros();
if(!inputTime[7] && digitalRead(INPUT7) == LOW) inputTime[7] = micros();
}
inputFinal[0] = digitalReadFast(INPUT0);
inputFinal[1] = digitalReadFast(INPUT1);
inputFinal[2] = digitalReadFast(INPUT2);
inputFinal[3] = digitalReadFast(INPUT3);
inputFinal[4] = digitalReadFast(INPUT4);
inputFinal[5] = digitalReadFast(INPUT5);
inputFinal[6] = digitalReadFast(INPUT6);
inputFinal[7] = digitalReadFast(INPUT7);

// Display data
for(i=0;i<8;i++) {
LCD.print("\n");
LCD.print(i);
LCD.print(": ");
LCD.print(!inputInitial);
LCD.print(" > ");
LCD.print(!inputFinal);
LCD.print(" ");
if(inputTime) {
timeTemp = inputTime - timeInitial;
LCD.printf("%10d",timeTemp);
LCD.print(" uSec");
if(inputTime[0]) {
timeTemp = inputTime - inputTime[0];
LCD.printf("%10d",timeTemp);
LCD.print(" uSec");
}
}
}

while(digitalRead(INPUTSTART) == HIGH) delay(50);
while(digitalRead(INPUTSTART) == LOW) delay(50);
}


OpticalTeensy.jpg
 
What sort of voltages are on the optocoupler inputs, and what is the value of the resistors in series with the LEDs?

You have a lot of resistance on the optocoupler inputs, so you may not be driving enough current to pull the optocoupler outputs low enough for the Teensy to recognize them as low. The optocoupler output current may be high enough to light the LEDs without pulling the voltage low enough to switch the Teensy inputs.
 
Whollender, that is a good point. The current limiting resistors in front of the optocoupler are 3W 10k. I wanted to make sure I could take in 125VDC (12.3mA and 1.5W), but was doing my testing at 12VDC (1.0mA and 0.01W). The OptoCoupler is a Vishay K847PH. The LEDs have a 1k resistor.

I have a 24VDC power supply and will try that, which should give 2.2mA (0.05W) on the optical side.

Any advice on whether I need to use INPUT or INPUT_PULLUP for the optocoupler inputs. As you mention above, given the at there is built in resistance, the INPUT should be appropriate for the pinmode setup.

Thanks,
Rudy
 
Last edited:
Rudy,

I don't think that you need to use the INPUT_PULLUP mode because you already have a "pullup" in the diode and resistor.

If the possible input voltage has a pretty wide range, I'd size the current limiting resistor on the optical side to give around 40mA (the datasheet has an absolute max of 60mA) at the max allowable input voltage. At that range, if your input voltage is even 1/10th of the max, then you'll still have a pretty reasonable forward current (4mA).

If you don't want to use such high forward currents at max voltage, you'll need to increase the pullup resistor values to make sure that the collector current on the optocoupler output can pull the voltage all the way down to ground.
 
Whollender... You were right in that I did not need the INPUT_PULLUP mode. The circuit works flawlessly and measures micro-second times perfectly. Thanks. Rudy
 
Glad you got everything working.

Did you just have to adjust the resistors on the optocoupler input to get everything to work?
 
Whollender... I simply just used a 24VDC power supply instead of a ~12VDC power supply. After this, I tested it again with 125VDC and it worked properly. Therefore, as you suggested, at 12VDC, I was dropping the input voltage a little too much and therefore there was not enough current to the optocoupler input to properly drive the optocoupler outputs low enough to trigger the inputs on the Teensy from HIGH to LOW. Thanks again... Rudy

PS.
I will try to post the final design / code on my web site and will provide a link when I do that.
 
Status
Not open for further replies.
Back
Top