Teensy Loader has stopped auto loading but reset works - Normal?

Status
Not open for further replies.

richteel

Member
I have made a custom USB Device with the Teesy 3.1 and have it working. Teensy Loader no longer loads a new program unless I press the reset button on the Teensy. I would like to know if this is normal or if there is something that I should change in the code to allow Teensy Loader to load programs from the IDE? I also do not see debug messages in the IDE's Serial Monitor. I would like to restore these two things if possible.

Another Question: I included the serial device as I thought it may have been necessary for Teensy Loader and/or serial debuging in the IDE. Is it needed for either function? If not, I can remove it. (Yes, I could give it a try but wanted to ask. I would also like to get the other things working before removing it.)

Project
----------------
Custom Game Pad for Raspberry Pi with
- Joystick
- 10 buttons
- 2 Keyboard buttons to act as hotkeys for OS
- Raw HID device to communicate battery level

Software
----------------
Teensy: Teensy 3.1
Teensy Loader: 1.20
OS: Windows 7 Ultimate SP 1 (64-bit)
IDE: Arduino 1.0.6 w/ Teensyduino 1.20

Hardware Setup
----------------
Teensy 3.1 (1)
Adafruit PSP 2-Axis Analog Thumb Joystick PRODUCT ID: 444 (1) connected to 3.3VDC, GND, and Analog Pins 0 & 1
Adafruit Tactile Switch Buttons (6mm slim) x 20 pack PRODUCT ID: 1489 (12) connected between GND and digital pins 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, & 11
LEDs (6) connected to GND & 150 ohm resistors with the resistors connected to digital pins 18, 19, 20, 21, 22, & 23

Code
----------------
Changes to the default configuration to create Pi Controller USB Device - View attachment Phase_03b-Final.zip
Test Code
Code:
/* Complete USB Joystick Example
 Teensy becomes a USB joystick with 16 or 32 buttons and 6 axis input
 
 You must select Joystick from the "Tools > USB Type" menu
 
 Pushbuttons should be connected between the digital pins and ground.
 Potentiometers should be connected to analog inputs 0 to 5.
 
 This example code is in the public domain.
 */

// Configure the number of buttons.  Be careful not
// to use a pin for both a digital button and analog
// axis.  The pullup resistor will interfere with
// the analog voltage.

// Incudes modifications from
// https://github.com/adafruit/USBgamepad/blob/master/teensySNES_test2/teensySNES_test2.ino

/*
  This test for the Pi Control is to check the hardware
 The USB Type must be set to "Pi Controller"
 */

// Joystick
const int pinAnalogXInput = 0;
const int pinAnalogYInput = 1;

// Buttons
const int pinBtnA = 0;
const int pinBtnB = 1;
const int pinBtnX = 2;
const int pinBtnY = 3;
const int pinBtnTrigLeft = 4;
const int pinBtnTrigRight = 5;
const int pinBtnBack = 6;
const int pinBtnStart = 7;
const int pinBtnMenu = 8;
const int pinBtnCoin = 9;

// Special buttons for scripts
const int pinBtnPwr = 10;
const int pinBtnBatteryLevel = 11;

// LEDs
const int pinLedPower = 23;
const int pinLed0 = 22;
const int pinLed1 = 21;
const int pinLed2 = 20;
const int pinLed3 = 19;
const int pinLed4 = 18;

//Variables for the states of the buttons
byte buttons[] = {  
  pinBtnA, pinBtnB, pinBtnX, pinBtnY, 
  pinBtnTrigLeft, pinBtnTrigRight,
  pinBtnBack, pinBtnMenu, pinBtnCoin, pinBtnStart};

//Variables for the states of the special buttons
byte specialButtons[] = {
  pinBtnPwr, pinBtnBatteryLevel};

//Variables for the LEDs
byte leds[] = {
  pinLedPower, pinLed0, pinLed1, pinLed2, pinLed3, pinLed4};

#define NUMBUTTONS sizeof(buttons)
#define NUMSPECIALBUTTONS sizeof(specialButtons)
#define NUMLEDS sizeof(leds)

typedef void KeyFunction_t(uint8_t c);

byte allButtons[NUMBUTTONS];
byte prevButtons[NUMBUTTONS];
byte specialButtonsPressed[NUMSPECIALBUTTONS];

// RawHID packets are always 64 bytes
byte buffer[64];
elapsedMillis msUntilNextSend;
unsigned int packetCount = 0;

void setup() {
  // you can print to the serial monitor while the joystick is active!
  Serial.begin(9600);
  // configure the joystick to manual send mode.  This gives precise
  // control over when the computer receives updates, but it does
  // require you to manually call Joystick.send_now().
  Gamepad.useManualSend(true);
  for (int i=0; i<NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT_PULLUP);
  }

  for (int i=0; i<NUMSPECIALBUTTONS; i++) {
    pinMode(specialButtons[i], INPUT_PULLUP);
  }

  for (int i=0; i<NUMLEDS; i++) {
    pinMode(leds[i], OUTPUT);
    digitalWrite(leds[i], LOW);
  }

  // initialize control over the keyboard:
  Keyboard.begin();

  Serial.println("Begin Complete Joystick Test");
}



void loop() {
  processGamepad();
  
  processKeyboard();
  
  processHID();

  // a brief delay, so this runs "only" 200 times per second
  delay(50);
  
  blinkLED();
}

unsigned long previousMillis = 0;        // will store last time LED was updated
// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)

void blinkLED() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the 
  // difference between the current time and last time you blinked 
  // the LED is bigger than the interval at which you want to 
  // blink the LED.
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // set the LED with the ledState of the variable:
    digitalWrite(pinLed4, !digitalRead(pinLed4));
  }
}

void processGamepad() {
  // read 2 analog inputs and use them for the joystick axis
  Gamepad.X(analogRead(pinAnalogXInput));
  Gamepad.Y(analogRead(pinAnalogYInput));

  // read digital pins and use them for the buttons
  for (int i=0; i<NUMBUTTONS; i++) {
    if (digitalRead(buttons[i])) {
      // when a pin reads high, the button is not pressed
      // the pullup resistor creates the "on" signal
      allButtons[i] = 0;
    } 
    else {
      // when a pin reads low, the button is connecting to ground.
      allButtons[i] = 1;
    }
    Gamepad.button(i + 1, allButtons[i]);
  }

  // Because setup configured the Joystick manual send,
  // the computer does not see any of the changes yet.
  // This send_now() transmits everything all at once.
  Gamepad.send_now();

  // check to see if any button changed since last time
  boolean anyChange = false;
  for (int i=0; i<NUMBUTTONS; i++) {
    if (allButtons[i] != prevButtons[i]) anyChange = true;
    prevButtons[i] = allButtons[i];
  }

  // if any button changed, print them to the serial monitor
  if (anyChange) {
    Serial.print("Buttons: ");
    for (int i=0; i<NUMBUTTONS; i++) {
      Serial.print(allButtons[i], DEC);
    }
    Serial.println();
  }
}

void processHID() {
  int n;
  n = RawHID.recv(buffer, 0); // 0 timeout = do not wait
  if (n > 0) {
    // the computer sent a message.  Display the bits
    // of the first byte on pin 0 to 7.  Ignore the
    // other 63 bytes!
    Serial.print(F("Received packet, first byte: "));
    Serial.println((int)buffer[0]);
    for (int i=0; i<NUMLEDS; i++) {
      int b = buffer[0] & (1 << i);
      digitalWrite(leds[i], b);
    }
  }
  // every 2 seconds, send a packet to the computer
  if (msUntilNextSend > 2000) {
    msUntilNextSend = msUntilNextSend - 2000;
    // first 2 bytes are a signature
    buffer[0] = 0xAB;
    buffer[1] = 0xCD;
    // next 24 bytes are analog measurements
    for (int i=0; i<12; i++) {
      int val = analogRead(i);
      buffer[i * 2 + 2] = highByte(val);
      buffer[i * 2 + 3] = lowByte(val);
    }
    // fill the rest with zeros
    for (int i=26; i<62; i++) {
      buffer[i] = 0;
    }
    // and put a count of packets sent at the end
    buffer[62] = highByte(packetCount);
    buffer[63] = lowByte(packetCount);
    // actually send the packet
    n = RawHID.send(buffer, 100);
    if (n > 0) {
      Serial.print(F("Transmit packet "));
      Serial.println(packetCount);
      packetCount = packetCount + 1;
    } else {
      Serial.println(F("Unable to transmit packet"));
    }
  }
}

void processKeyboard() {
  // run through all the special buttons
  for (byte i = 0; i < NUMSPECIALBUTTONS; i++) {
    // are any of them pressed?
    if (!digitalRead(specialButtons[i])) 
    {                              //this button is pressed
      if(specialButtonsPressed[i] != 1)
      {

        Serial.println(specialButtonsPressed[i], DEC);

        switch (specialButtons[i]) {
        case pinBtnPwr:
          Keyboard.press(KEY_LEFT_CTRL);
          Keyboard.press(KEY_LEFT_ALT);
          Keyboard.press(KEY_DELETE);
          delay(500);
          Keyboard.releaseAll();
          delay(500);
          digitalWrite(pinLedPower, HIGH);
          break;
        case pinBtnBatteryLevel:
          Keyboard.press(KEY_LEFT_CTRL);
          Keyboard.press(KEY_SCROLL_LOCK);
          Keyboard.press(KEY_PRINTSCREEN);
          delay(500);
          Keyboard.releaseAll();
          delay(500);
          break;
        default:
          break;
        }
        // Don't process the button again until released and pressed
        specialButtonsPressed[i]=1;
      }
    }
    else
    {
      // Button released - process on next press
      specialButtonsPressed[i]=0;
    }
  }

}
 
Last edited:
I have made a custom USB Device with the Teesy 3.1 and have it working. Teensy Loader no longer loads a new program unless I press the reset button on the Teensy. I would like to know if this is normal

Yes, that's perfectly normal. The teensy_reboot utility only "knows" about the standard device configurations. If you change things too much, it can't figure out which device to send the reboot request.
 
Status
Not open for further replies.
Back
Top