Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 12 of 12

Thread: Teensy 3: Avoiding 'USB lockout' / need for Reset?

  1. #1
    Junior Member
    Join Date
    Nov 2012
    Location
    Boston
    Posts
    7

    Teensy 3: Avoiding 'USB lockout' / need for Reset?

    I'm continuing to find that running some of my programs seem to cause 'USB lockout', where no new code can be uploaded to the Teensy 3 without resorting to a hardware Reset first. Given that I'm going to be armoring the Teensy inside a weather-proof (playa-proof!) enclosure, I want to be able to make sure that new software can be loaded over USB without requiring any access to the hardware Reset function.

    My code is all SPI-heavy LED-driving (LPD8809) code; I'm using FastSPI_LED2 -- the new, Teensy-savvy version, but I was seeing the same periodic 'USB lockout' with older versions of the FastSPI library, too. My code runs inside the loop() call -- and does not ever return from the first call to 'loop()', so if there's some service routine happening outside of 'loop()', it's not getting automatically called. I have a few dozen different programs, and which ones cause 'USB lockout' and which ones don't seems mysteriously unpredictable to me. It seems, casually, to me that if I insert a call to delay() here and there, I get fewer lockouts, but this might just be anecdotal accidents. How likely is it that noise/ringing on the SPI pins is borking USB communication? Is it worth trying the 220-ohm-resistor trick, or is that merely voodoo here?

    Ultimately, my question is this: What actually causes the Teensy 3 'USB lockout' condition? What can I do (or avoid) in my code to ensure that it never happens? Is there a service routine that I should periodically call?

    Seeking enLEDenment-
    -Mark

  2. #2
    Junior Member
    Join Date
    Jan 2015
    Posts
    5
    ...it's over two years later, but did you ever figure this one out? I'm having the exact same problem, only with a teensy 3.1.

  3. #3
    Senior Member
    Join Date
    Nov 2013
    Posts
    720
    The basic answer is do not loop inside of the loop() routine in a 'normal' arduino style sketch, write your loop routine as if
    Code:
    void loop() {
      // do your thing
    }
    actually meant
    Code:
    while(1) {
      // do your thing
    }
    and it will have a much better chance of being robust over time.

  4. #4
    Junior Member
    Join Date
    Nov 2012
    Location
    Boston
    Posts
    7
    Quote Originally Posted by robsoles View Post
    The basic answer is do not loop inside of the loop() routine in a 'normal' arduino style sketch, write your loop routine as if (...) ant it will have a much better chance of being robust over time.
    Thanks for the advise and comments!

    Also, my basic old question still remains: Why is it like that? I'm looking for a complete "cause-and-effect" level of understanding here, not just "this works better / that works worse" -- although that is definitely useful, too!

    I still don't understand why or how the T3 or T3.1 can lock itself out of USB communication like this, and that's what I'm really striving to understand deeply.


    For the record, in the two years since I posted the original question, "FastSPI_LED2" has evolved into "FastLED v3" (which totally supports the T3 and T3.1), and I've become one of the two co-authors of that library. And even with all that additional time and coding... I still don't understand why the Teensy3/3.1 sometimes locks out USB communication and needs a hard reset... and I still wish I knew the cause.

    Truthfully, it happens less to me these days, but it still happens, and I still can't say for sure why.

  5. #5
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,900
    Quote Originally Posted by kriegsman View Post
    Also, my basic old question still remains: Why is it like that? I'm looking for a complete "cause-and-effect" level of understanding here, not just "this works better / that works worse" -- although that is definitely useful, too!

    I still don't understand why or how the T3 or T3.1 can lock itself out of USB communication like this, and that's what I'm really striving to understand deeply.
    As I do not know, what you are exactly doing inside the loop, or know your host OS, I can offer only my observation when T3.1 becomes non-responsive. Every time when the T3.1 cycles around a Serial.print, either intentionally, as in loop{Serial.print(...);}, or by chance, e.g. where an error handler cycles around a Serial.printf, and the Terminal on my windows system cannot keep up, the T3.1 will become non-responsive. On windows, there is potentially a very large Queue building up that could (IMO) lock the interaction with T3.1.

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,044
    I wish I knew why too. It's very possible there's some subtle bug lurking deep within the USB code.

    As always, to even start investigating, I need a program that reproduces the problem.

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,044
    Quote Originally Posted by WMXZ View Post
    .... the Terminal on my windows system cannot keep up, the T3.1 will become non-responsive.
    Teensyduino 1.21-test2 tries to address this, with several improvements to improve the Arduino Serial Monitor's ability to handle fast data. If you haven't given 1.21-test2 a try, I'd really like to know if it's effective at keeping up with maximum rate data on your machine?

    However, 1.21-test2 is far from perfect. It's called "test2" and not even beta for a reason (the other half of that reason is testing the transition from gcc 4.7.2 to 4.8.4). It breaks the serial monitor in non-serial modes, and it also crashes the entire Arduino IDE if you try to initiate an upload at just the wrong moment during high speed incoming data.

    Handling fast incoming data is difficult. I'm trying to get this working reliably, and 1.21-test2 is at least a step in that direction, but clearly I still have more work to do. Even with the known bugs, it's really help me if you could test on a machine that's seen bad problems with keeping up with maximum speed printing, and let me know what it's CPU usage is. Also, keep an eye on the java process's memory usage. It will grow initially, but over a long time, it should stablize and not infinitely leak memory (like 1.20 and all other Arduino without Teensyduino does).

  8. #8
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,900
    Quote Originally Posted by PaulStoffregen View Post
    Handling fast incoming data is difficult. I'm trying to get this working reliably, and 1.21-test2 is at least a step in that direction, but clearly I still have more work to do. Even with the known bugs, it's really help me if you could test on a machine that's seen bad problems with keeping up with maximum speed printing, and let me know what it's CPU usage is. Also, keep an eye on the java process's memory usage. It will grow initially, but over a long time, it should stablize and not infinitely leak memory (like 1.20 and all other Arduino without Teensyduino does).
    As I experienced this in the last hour more or less every 5 minutes (trying to understand the behavior of spi-dma while doing scatter-gather)
    and I only could go around this by killing JAVA Platform SE binary, I will try to collect some statistics.

  9. #9
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,900
    Quote Originally Posted by WMXZ View Post
    As I experienced this in the last hour more or less every 5 minutes (trying to understand the behavior of spi-dma while doing scatter-gather)
    and I only could go around this by killing JAVA Platform SE binary, I will try to collect some statistics.
    I just generated on Windows 8.1 quad core I7 laptop, a non-responsive IDE and a locked Terminal (commented out clearInterrupt() (sic!) in an isr with an Serial.printf statement inside) but could not see any changes in the Task manager JAVA is stable on 0-1% CPU; 142.9 MB Memory; 0 MB/s disk activity. Any special place I could look to?
    Last edited by WMXZ; 01-10-2015 at 04:21 PM.

  10. #10
    Junior Member
    Join Date
    Jan 2015
    Posts
    5
    So, I will admit I really only understand about 25% of what is being said in the above replies! But, in my own testing, I've narrowed down to this phenomenon, and I'm wondering if someone could help me figure it out (and if it has anything to do with the above comments).

    I've got the following piece of code that will only work if I comment out the
    else if(pushNumber>0){
    greenDots(pushNumber);
    }
    else (pushNumber==0){
    setBlank();
    }
    bit in the loop.

    //~~~~~~~~~~~~~~~~~~~~~~~ALL the libraries!~~~~~~~~~~~~~~~~~
    //TIME
    #include <Time.h>

    //SD CARD
    #include <SD.h>
    #include <SPI.h>

    //BTLE
    //char INBYTE;
    #define BTLE Serial1

    //SPEAKER
    #include "pitches.h"

    //LEDS
    #include <Adafruit_NeoPixel.h>

    //VIBE MOTOR

    //BUTTON




    //~~~~~~~~~~~~~~~~~~~~~~~~PRE-SETUP~~~~~~~~~~~~~~~~~~~~~~~~~~~

    //TIME

    //SD CARD
    File logFile;
    const int chipSelect = 10;

    //BTLE



    //SPEAKER
    const int speakerPin = 20;
    int celebration1notes[8]={NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5};

    //LEDS
    #define PIN 16
    #define NUMPIXELS 12
    // Parameter 1 = number of pixels in strip
    // Parameter 2 = Arduino pin number (most are valid)
    // Parameter 3 = pixel type flags, add together as needed:
    // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
    // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
    // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
    // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
    Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

    // IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
    // pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
    // and minimize distance between Arduino and first pixel. Avoid connecting
    // on a live circuit...if you must, connect GND first.

    //VIBE MOTOR
    const int motorPin = 9;

    //BUTTON
    const int buttonPin = 8;
    int buttonState = 0;
    int pushNumber = 0;

    //~~~~~~~~~~~~~~~~~~~~~~~~~SETUP~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
    void setup() {

    //TIME
    // set the Time library to use Teensy 3.0's RTC to keep time

    setSyncProvider(getTeensy3Time);

    Serial1.begin(9600);
    if (timeStatus()!= timeSet) {
    Serial1.println("Unable to sync with the RTC");
    } else {
    Serial1.println("RTC has set the system time");
    Serial1.println("Time is:");
    digitalClockDisplay();
    }


    //SD CARD
    pinMode(10, OUTPUT);
    if (!SD.begin(chipSelect)) {
    Serial1.println("SD initialization failed!");
    return;
    }

    //BTLE

    //SPEAKER

    //LEDS
    strip.begin();
    strip.show(); // Initialize all pixels to 'off'

    //VIBE MOTOR
    pinMode(motorPin, OUTPUT);

    //BUTTON
    pinMode(buttonPin, INPUT_PULLUP);
    }

    //~~~~~~~~~~~~~~~~~~~~~~~~~LOOP~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~

    void loop() {

    buttonState = digitalRead(buttonPin);
    if (buttonState == LOW) {
    time_t t = now();
    Serial1.print("Log time: ");
    digitalClockDisplay();

    //~~~~~~~~~~~~~~~~~~~ CELEBRATION~~~~~~~~~~~~~~~~~~~~~~~~

    celebration1();

    //~~~~~~~~~~~~~~~~~~~~LOG TO SD~~~~~~~~~~~~~~~~~~~~~~~~
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    logFile = SD.open("logFile.txt", FILE_WRITE);

    // if the file opened okay, write to it:
    if (logFile) {
    Serial1.print("Writing to logFile.txt...");
    logFile.print(hour());
    logFile.print(":");
    logFile.print((minute()));
    logFile.print(":");
    logFile.print((second()));
    logFile.print(" ");
    logFile.print(day());
    logFile.print(" ");
    logFile.print(month());
    logFile.print(" ");
    logFile.print(year());
    logFile.println();
    // close the file:
    logFile.close();
    Serial1.println("done.");
    }
    else {
    // if the file didn't open, print an error:
    Serial1.println("error opening logFile.txt");
    }
    pushNumber++;
    delay(10);

    }
    else if(pushNumber>0){
    greenDots(pushNumber);
    }
    else (pushNumber==0){
    setBlank();
    }
    }

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~FUNCTIONS~~~~~~~~~~~~~~ ~~~~~~~~~

    //CELEBRATION 1

    void celebration1() {
    strip.setBrightness(255);
    for(int i=0; i<8; i++){
    digitalWrite(motorPin, HIGH);
    if(i<7){
    //Serial1.println(i);
    tone(speakerPin, celebration1notes[i]);
    strip.setPixelColor(i, strip.Color(50,10,250));
    strip.show();
    delay(100);
    }
    else{
    tone(speakerPin, celebration1notes[i]);
    theaterChase(strip.Color(127, 127, 127), 20);
    delay(200);
    }
    }
    digitalWrite(motorPin, LOW);
    noTone(speakerPin);
    fadeOut(1000);
    }


    //TIME

    void digitalClockDisplay() {
    // digital clock display of the time
    Serial1.print(hour());
    printDigits(minute());
    printDigits(second());
    Serial1.print(" ");
    Serial1.print(day());
    Serial1.print(" ");
    Serial1.print(month());
    Serial1.print(" ");
    Serial1.print(year());
    Serial1.println();
    }

    time_t getTeensy3Time()
    {
    return Teensy3Clock.get();
    }

    /* code to process time sync messages from the serial port */
    #define TIME_HEADER "T" // Header tag for serial time sync message

    unsigned long processSyncMessage() {
    unsigned long pctime = 0L;
    const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013

    if(Serial1.find(TIME_HEADER)) {
    pctime = Serial1.parseInt();
    return pctime;
    if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
    pctime = 0L; // return 0 to indicate that the time is not valid
    }
    }
    return pctime;
    }

    void printDigits(int digits){
    // utility function for digital clock display: prints preceding colon and leading 0
    Serial1.print(":");
    if(digits < 10)
    Serial1.print('0');
    Serial1.print(digits);
    }



    //SD CARD

    //BTLE

    //SPEAKER

    //LEDS
    // Fill the dots one after the other with a color
    void colorWipe(uint32_t c, uint8_t wait) {
    for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
    }
    }

    //Theatre-style crawling lights.
    void theaterChase(uint32_t c, uint8_t wait) {
    for (int j=0; j<10; j++) { //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
    for (int i=0; i < strip.numPixels(); i=i+3) {
    strip.setPixelColor(i+q, c); //turn every third pixel on
    }
    strip.show();

    delay(wait);

    for (int i=0; i < strip.numPixels(); i=i+3) {
    strip.setPixelColor(i+q, 0); //turn every third pixel off
    }
    }
    }
    }


    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos) {
    WheelPos = 255 - WheelPos;
    if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
    } else if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
    } else {
    WheelPos -= 170;
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
    }
    }

    void blackout()
    {
    for (int i = 0 ; i < NUMPIXELS; i++)
    {
    strip.setPixelColor(i, 0, 0, 0);
    }
    strip.show();
    }

    void fadeOut(int time) {
    for (int i = 0; i < 255; i++) {
    strip.setBrightness(255-i);
    strip.show();
    delay (time/255);
    }
    blackout();
    }

    void setGreen() {
    strip.setBrightness(20);
    for (int j = 0 ; j < NUMPIXELS; j++)
    {
    strip.setPixelColor(j, 0, 250, 20);
    }
    strip.show();
    }

    void setRed()
    {
    strip.setBrightness(20);
    for (int j = 0 ; j < NUMPIXELS; j++)
    {
    strip.setPixelColor(j, 250, 0, 20);
    }
    strip.show();
    }

    void greenDots(int number)
    {
    for (int i = 0 ; i < NUMPIXELS; i++)
    {
    strip.setPixelColor(i, 0, 0, 0);
    }
    strip.setBrightness(50);
    int s=0;
    int z=0;
    for (int j = 0 ; j < number; j++)
    {
    if (((j+1) % 2) == 0) { //even
    strip.setPixelColor(j+1+z, 0, 250, 20);
    z++;
    }
    else { //odd
    strip.setPixelColor(s, 0, 250, 20);
    strip.setPixelColor(s+1, 0, 250, 20);
    s= s+3;
    }

    }
    strip.show();
    }

    void setBlank()
    {
    strip.setBrightness(10);
    for (int j = 0 ; j < NUMPIXELS; j++)
    {
    strip.setPixelColor(j, 0, 0, 0);
    }
    strip.show();
    }

    //VIBE MOTOR

    //BUTTON
    If I don't comment out the else if/else parts of the loop, the program will run just fine if it's still plugged into the computer. But, as soon as I transfer it to an external power source, it acts as though there is no sketch there at all. When I plug it back into the computer, the arduino IDE doesn't list my usb port as a serial port option, and then re-upload the sketch, it will tell me to press the reset button (which all makes me think that somehow my sketch is getting deleted when unplugged).

    If I do comment out. it will run fine no matter how many times I unplug/replug into whatever power sources. Thoughts?

  11. #11
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    7,078
    WMXZ,
    i'm away from the serial monitor a long time ago.
    HID is great, with putty. No reconnection needed, all can stay open.
    The only issue i have is, that i can't send anything to the teensy with HID (i don't know why, and i did'nt investigate this ..)

  12. #12
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,900
    Quote Originally Posted by Frank B View Post
    WMXZ,
    i'm away from the serial monitor a long time ago.
    HID is great, with putty. No reconnection needed, all can stay open.
    The only issue i have is, that i can't send anything to the teensy with HID (i don't know why, and i did'nt investigate this ..)
    The above note is only for my testing the DMA Scatter/Gather issue.
    In my real application I used first HID and switched then to usb_serial trying to maximize transfer rate.
    I now realize the for usb_serial the CPU load is still significant.

    I may try HID again and compare performance (speed and CPU load)

    Frank, do you have any performance numbers?

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •