Teensy Quick Reference: Code Examples, Tips and Tricks

Calling this "CPUspecs();" from setup will show you compile time details on your Teensy:
Code:
void CPUspecs() {
  Serial.println();
#if defined(__MKL26Z64__)
  Serial.println( "CPU is T_LC");
#elif defined(__MK20DX256__)
  Serial.println( "CPU is T_3.1/3.2");
#elif defined(__MK20DX128__)
  Serial.println( "CPU is T_3.0");
#elif defined(__MK64FX512__)
  Serial.println( "CPU is T_3.5");
#elif defined(__MK66FX1M0__)
  Serial.println( "CPU is T_3.6");
#endif
  Serial.print( "F_CPU =");   Serial.println( F_CPU );
  Serial.print( "ARDUINO =");   Serial.println( ARDUINO );
  Serial.print( "F_PLL =");   Serial.println( F_PLL );
  Serial.print( "F_BUS =");   Serial.println( F_BUS );
  Serial.print( "F_MEM =");   Serial.println( F_MEM );
  Serial.print( "NVIC_NUM_INTERRUPTS =");   Serial.println( NVIC_NUM_INTERRUPTS );
  Serial.print( "DMA_NUM_CHANNELS =");   Serial.println( DMA_NUM_CHANNELS );
  Serial.print( "CORE_NUM_TOTAL_PINS =");   Serial.println( CORE_NUM_TOTAL_PINS );
  Serial.print( "CORE_NUM_DIGITAL =");   Serial.println( CORE_NUM_DIGITAL );
  Serial.print( "CORE_NUM_INTERRUPT =");   Serial.println( CORE_NUM_INTERRUPT );
  Serial.print( "CORE_NUM_ANALOG =");   Serial.println( CORE_NUM_ANALOG );
  Serial.print( "CORE_NUM_PWM =");   Serial.println( CORE_NUM_PWM );
}

Above should be correct - I never had a T_3.0 and apparently never ran it on the T_LC - I made this to watch the T_3.5 and T_3.6.

This line is also useful to record compile TIME and DATE:
Code:
  Serial.print(__DATE__);   Serial.print(" -- ");  Serial.println(__TIME__);
 
Last edited:
This line is also useful to record compile TIME and DATE:
Code:
  Serial.print(__DATE__);   Serial.print(" -- ");  Serial.println(__TIME__);
You can simplify this via string pasting at compilation time to:

Code:
  Serial.print (__DATE__ " --- " __TIME__);

Basically, adjacent strings are combined together by the compiler to from one single string.
 
We also have a special linker symbol for the build time. Unlike these macros (which don't force a rebuild of the file they're in), it's always updated on every build because Arduino passes it as a parameter to the linker command line. But it's UNIX time, so you need mktime() or TimeLib.h to convert to human readable.
 
You can simplify this via string pasting at compilation time to:

Code:
  Serial.print (__DATE__ " --- " __TIME__);

Basically, adjacent strings are combined together by the compiler to from one single string.

Thanks MichaelMeissner - I finally got around to using this as follows - in setup() after SerialStart( #milis ); is called a programmed wait for Serial to appear is done and a compile signature for the file is the first output.

#define SerialStart(a) ({Serial.begin(19200); while (!Serial && (millis()< (a))); Serial.print("\n" __DATE__ " --- " __TIME__ " --- " __FILE__ "\n");} )

used like :: SerialStart( 4000 );

So setup() just gets one line { if you copy the macro ) that waits a #millis for Serial to come online, and starting a Teensy shows if it was programmed after the last change 3 minutes ago - and a random Teensy on the desk will show with what file and when it was last programmed.
 
Thanks everyone, this is all helpful! I have so many versions of test code running at the moment it is nice to see the exact build time, file, and also the CPU details verify settings like clock were correct.
 
Teensy 4 is listed at 100 mA, but is sometimes less. My sample running the stock "blink" application draws about 54 mA or 51 mA depending if the LED is on or off.
 
Here are a couple of details that help keep TeensyLC hibernate current
as low as possible. a) before hibernate delare pin 17 as output and
write a high or low to it to prevent the input of the buffer chip from
floating at an intermediate level due to leakages (this can cause up to
240 ua of extra Iq during hibernate). b) if you are using the atod
converter and any of the analog input(s) could be somewhere far from
the rails (not close to 0 or 3.3) during hibernate this can cause an
extra 70-100 ua of Iq. For a telemetry transmitter that hibernates most
of the time and sends two analog values over the radio once each minute,
low Iq was more important than conversion bandwidth. In my case a10 and
a11 were connected to very high dc impedance resistive dividers (2.2 meg
and 470k to minimize drain from the batteries being measured) fed from
batteries to monitor two voltages in the 0-18 volt range. A relatively
large capacitance (100n) was used at pins a10 and a11 to keep the
dynamic impedance low during conversions. Because a10 and a11 could
be below 3.3 or above 0 during hibernate the extra Iq mentioned above
was occurring. Fix is to tie pin 2 to a10 and pin 3 to a11 and use
those two pins as outputs to drag a10 and a11 very near ground during
hibernation. Upon wakeup pins 2 and 3 are declared as inputs followed
by a delay allowing the dividers and capacitors 5 time constants, the
conversions are done, and the pins re-stated as outputs that are low
again. Using these two pre cautions the Iq during hibernate (including
the drain of an LM2936-5 regulator) is typically 11-12 ua.

The hardware datasheet for the mcu used in the TeensyLC shows that the
input current into analog inputs is typically only 0.025 ua but I think
they forgot to look at Iq vs analog input voltage, and it is hard to
imagine why they did not do that and/or put the results in the data-
sheet when the extra current can be 10x sleeping current if the analog
input(s) are near mid-supply sleeping current. This extra Iq tapers
down to nil as you move away from mid-supply towards either supply rail.


Code:
//
// note input divider r's are 2.2 meg and 470 k


  unsigned short int value1,value2,wrd1,wrd2;
  unsigned int ch1,ch2;


//  atod function
void atod() {
// release a10 and a11
    pinMode(2,INPUT);
    pinMode(3,INPUT);
//  wait for 5 time const
    delay(250);
//  actual conversions
    value1 = adc->analogRead(A10,ADC_0);
    value2 = adc->analogRead(A11,ADC_0);
//  limit results
    if (value1<0) value1=0;
    if (value2<0) value2=0;
    if (value1>4095) value1=4095;
    if (value2>4095) value2=4095;
//  offset error comp both chan
    ch1=(value1-1);
    ch2=(value2-1);
    if(ch1<0)ch1=0;
    if(ch2<0)ch2=0;
//  error scaling both chan
    ch1=ch1*34330;
    ch1=ch1>>15;
    ch2=ch2*34315;
    ch2=ch2>>15;
    value1=ch1;
    value2=ch2;
//  re-clamp a10 and a11
    pinMode(2,OUTPUT);
    pinMode(3,OUTPUT);
    digitalWrite(2,LOW);
    digitalWrite(3,LOW);
    wrd1=value1;
    wrd2=value2;
}


int main() {
// declare pin 17 as output
   pinMode(17, OUTPUT);
// put pin 17 buffer input at one rail
   digitalWrite(17, LOW);
//
    pinMode(A10, INPUT);
    pinMode(A11, INPUT);
//
//
    adc->setAveraging(32); // set number of averages
    adc->setResolution(12); // set bits of resolution
    adc->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_LOW_SPEED, ADC_0);
    adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_LOW_SPEED, ADC_0);
//
 
Last edited by a moderator:
Don't know if this is on here yet but to use the Dual Serial and Triple Serial USB option in the newer TeensyDuino (1.52+). Use SerialUSB vs Serial. This is not in any documentation on the Web site yet.

void setup() {
SerialUSB.begin(250000);
SerialUSB1.begin(250000);
SerialUSB2.begin(250000);
}

void loop() {
SerialUSBx.println("Howdy from USB Serial");
//etc.
}

Obviously there is only one Serial Monitor allowed at a time but you can use an external terminal program such as RealTerm (my fav) to interact with the other virtual ports.

Enjoy!
 
Last edited:
Indeed not a lot published ... There is a single sample showing usage: ...\examples\Teensy\USB_Serial\Triple_Serial_Test\Triple_Serial_Test.ino

TyCommander has been updated and will support Multiple Serial Teensy. In a single window or one for each desired with Ctrl+N.
 
Indeed not a lot published ... There is a single sample showing usage: ...\examples\Teensy\USB_Serial\Triple_Serial_Test\Triple_Serial_Test.ino

TyCommander has been updated and will support Multiple Serial Teensy. In a single window or one for each desired with Ctrl+N.

Never is a lot of info about these devices (it's my one major malfunction about these powerful little things). It's a shame that there isn't a source list of pdf files detailing the current understanding of them and containing the current programming syntax. I think they would develop far further and faster if we could get the obvious details out of the way and move to new ground quicker. Then again I am biased with about 20 years of reverse engineering of various things well in my past now. These days I just want to get things built and admit to impatience with the work wasted re-inventing the wheel.
 
Great stuff here, I looked over this and can't find Lib for the Joystick example "Complete" I would like to modify the Lib code to rename the type of sliders from this:
Joystick.sliderLeft(analogRead(A4));
Joystick.sliderRight(analogRead(A5));
to this:
Joystick,InputA(analogRead(A0));
Joystick,InputB(analogRead(A0));
Joystick,InputC(analogRead(A0));
Joystick,InputD(analogRead(A0));
Joystick,InputE(analogRead(A0));
Joystick,InputF(analogRead(A0));
Joystick,InputG(analogRead(A0));
Joystick,InputH(analogRead(A0));
Joystick,InputJ(analogRead(A0));
Joystick,InputK(analogRead(A0));
Joystick,InputL(analogRead(A0));
Joystick,InputM(analogRead(A0));
Joystick,InputN(analogRead(A0));
Joystick,InputP(analogRead(A0));
Where is the lib located?
 
Which Teensy? 3.x or 4.x?

{local install}\hardware\teensy\avr\cores\teensy4\usb_joystick.h

{local install}\hardware\teensy\avr\cores\teensy3\usb_joystick.h:
 
Back
Top