Teensy cannot send (but can receive) USB serial commands

Status
Not open for further replies.

kb1

New member
Hi everyone,

I'm having a problem with a Teensy LC that's left me scratching my head. I am using the Teensy in a simple system to control a laser diode based on serial commands sent from a PC over USB. The Teensy receives one letter serial commands which tell it to: turn the laser on, turn the laser off, pulse the laser for a certain amount of time, or set the pulse time to XXXXX miliseconds ('n', 'f', 'p', and 'tXXXXX' respectively). To control the laser, a digital output of the Teensy is connected to the gate of a P-channel MOSFET which either connects or disconnects the laser diode input to a 5V supply based on the high/low of the digital output (I realize that the Teensy is 3.3V, but I think that is sufficient to trigger the MOSFET at 5V). Following a pulse command, the Teensy sends two signals back to the PC over serial: 'f' as soon as the laser is turned off and 'c' five seconds later.

When the laser diode is not connected (the transistor is still in place, but just doesn't have anything to control) everything works fine. For some reason, as soon as the laser diode is connected to the transistor, the Teensy seems to lose its ability to send serial data (i.e. the 'f' and 'c' following a laser pulse). Interestingly, the Teensy can still act in response to serial commands it receives to correctly turn the laser on/off/pulse. If I disconnect the laser diode, the problem still occurs until the Teensy is reset (either using the reset button or unplugging it from power). I have tried several different output pins and the problem seems to occur independent of the pin used. I have tried receiving serial commands both with the Arduino IDE serial monitor and a MATLAB script that communicates over serial (which I have used used successfully before so I believe it works fine).

Is there some condition that causes the Teensy to disable its ability to send serial commands over USB?

Thanks in advance.


Source code:

Code:
#include <TimerOne.h>   //TimerOne downloaded from Paul Stoffregen: [url]https://www.pjrc.com/teensy/td_libs_TimerOne.html[/url]
                        //Change described below is required for proper functionality
#define LASER_PIN 8
#define PRE_LASER_TIME 2000  //time to delay before activating laser in ms
#define POST_LASER_TIME 5000 //time to record after laser pulse in ms
      // Sum of PRE_LASER_TIME + pulse_length + POST_LASER_TIME must be less than 4,294,967,295 ms


void setup() {
  // put your setup code here, to run once:

  pinMode(LASER_PIN, OUTPUT);
  digitalWrite(LASER_PIN,HIGH);
  pinMode(LED_BUILTIN, OUTPUT);
  //Serial.println("Serial Ready");
  Timer1.initialize(1000);
  Timer1.stop();
  Timer1.attachInterrupt(blinkLED);
  Serial.begin(9600);
}

char input;
char delay_time[6];
unsigned long pulse_length = 1000;
volatile unsigned long n = 0;
unsigned int cycles = 0;
//unsigned int remainder1 = 1000;


void blinkLED(){
  n++;
  if (n == PRE_LASER_TIME) {
    digitalWrite(LED_BUILTIN, HIGH);
    digitalWrite(LASER_PIN,LOW);
  }
  else if (n == PRE_LASER_TIME + pulse_length) {
    digitalWrite(LASER_PIN, HIGH);
    digitalWrite(LED_BUILTIN, LOW);
    Serial.println("f");    
  }
  else if (n >= PRE_LASER_TIME + pulse_length + POST_LASER_TIME) {
    Serial.println("c");
    Timer1.stop();
    n = 0;
  }
}
  
void loop() {
  // put your main code here, to run repeatedly:

/*
  n: laser on
  f: laser off
  p: laser pulse
  tXXXXX: set pulse time, where XXXXX is time in ms
    NOTE: time must be a five digit number with leading zeros if necessary
    EX: t05200 sets pulse time to 5200 ms or 5.2 s
*/

  if (Serial.available() > 0) {
    input = Serial.read();
    if (input == 'n') {
      delay(PRE_LASER_TIME);
      digitalWrite(LASER_PIN,LOW);
      digitalWrite(LED_BUILTIN, HIGH);
    }
    else if(input == 'f') {
      digitalWrite(LASER_PIN,HIGH);
      digitalWrite(LED_BUILTIN, LOW);
    }
    else if(input == 'p') {
      Timer1.restart();
    }
    else if(input == 't'){
      int num_read = Serial.readBytes(delay_time,5);
      pulse_length = strtol(delay_time,NULL,10);
    }
    else if(input = 'z'){
      Serial.println("a");
    }
    else{
      Serial.println("invalid input");
    }
  }
}
 
Last edited by a moderator:
Try putting this in setup() before any printing and then look to see the printed line.
Code:
  while ( !Serial && millis()<3000);
  Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);

That will wait up to 3 seconds for Serial to connect to PC serial monitor before printing that line. The timed wait can be extended or removed to see the following line print.

What OS is in use? If the IDE SerMon being used to send the characters to the Teensy?

Generally the Serial USB device is quite robust - unless the code misbehaves and corrupts the processor.
 
Thanks for the quick reply - I will try that when I am next in the lab. Is the purpose of that to ensure the Teensy has connected via serial before trying to send a command? To elaborate also on when the problem appears, I can start up the Teensy and serial connection without the laser connected and successfully receive and send commands with the Teensy. Without closing the serial monitor, reseting the Teensy, powering anything off, etc. I then plug in the laser. After plugging in the laser, sending commands from the Teensy seems to no longer work.

I am using Windows 7 Enterprise and the serial monitor built into the Arduino IDE (Arduino 1.8.7) to send/receive characters from the Teensy.
 
Yes, the Teensy has USB support in code on the processor - it can get up and running and present that quickly - then the PC needs to recognize and attach to it - that wait can be 35ms to 200ms or more depending on the PC. And having prints go out before connection may never show.

Added detail about plugging in laser sounds like it is causing the trouble. It is causing an electrical or software disturbance. Device and connection details would be needed ...
 
Hi everyone,

a digital output of the Teensy is connected to the gate of a P-channel MOSFET which either connects or disconnects the laser diode input to a 5V supply based on the high/low of the digital output (I realize that the Teensy is 3.3V, but I think that is sufficient to trigger the MOSFET at 5V)

So you're using a P-MOSFET as an high side switch.
This can be tricky: transients may cause issues to the Teensy.
Do you have a current limiting resistor between the digital pin and the MOSFET?
Just as an extra safety measure, do you have a flywheel diode protecting from unwanted reversed polarity (should not happen when driving a laser, but still...)?
 
Thanks for clarifying - the help is appreciated. A schematic is attached:
schematic.png

I am powering the Teensy off of the same 5V input as the laser is driven by (I cut the 5V-USB connection as described here: https://www.pjrc.com/teensy/external_power.html

This is the laser diode (200mW version) - unfortunately there isn't a whole lot of detail: https://www.laserlands.net/diode-laser-module/405nm-laser-module/405nm-dot-laser-module/1668-405d.html

So you're using a P-MOSFET as an high side switch.
This can be tricky: transients may cause issues to the Teensy.
Do you have a current limiting resistor between the digital pin and the MOSFET?
Just as an extra safety measure, do you have a flywheel diode protecting from unwanted reversed polarity (should not happen when driving a laser, but still...)?

That's correct. I don't have a diode or resistor between the digital pin and MOSFET - that's a good idea. I have have checked both the digit output of the Teensy and the drain of the MOSFET with an oscope. The digital output signal looks very clean as far as I can tell (for both turning laser on and off). It also looks the same regardless of whether the laser is connected, which I would expect. The drain has some fairly significant noise when the laser is turned on, but it doesn't seem to cause problems with the laser output and I figured this was not getting to the Teensy as the digital pin does not show noise. Not much noise on the drain when the laser is switched off, just a longish fall time.
 
From your schematics, it seems you have no current limiting resistor towards the MOSFET.
When the gate of the P-MF charges, it can eat quite some current (albeit for a small time).
Teensy LC can only source 5mA from a digital pin (except digital pins 5, 16, 17, 21, which can source 20mA).
If you draw more current than it can source, it may show strange issues (and possibly get damaged).
So I would add a 1K resistor between the digital pin and the gate. You could lose a tiny bit of switching speed, but I doubt it would be noticeable.
And, I would still add that flywheel diode (on the drain, not at the gate). Better safe than sorry. :)
 
I added a 1k resistor at the gate of the MOSFET as you suggested and that seemed to fix the issue - thanks for your help! The flywheel diode will go on my to do list also...
 
Status
Not open for further replies.
Back
Top