Microcontroller projects

Teensy tips and tricks

last updated: 12/06/17

Fast PWM with Teensy 2.0 (mega32u4) in Arduino

Fast PWM on Teensy 2.0 is cool because it is very simple to initialise and needs no interrupts. Because Timer0 is used by Arduino we will use the 16 Bit Timer1 or Timer3 or the 10 Bit Timer4. We have to set the right bits in TCCRnA and TCCRnB register. That's all. The byte in OCR register (8 bit PWM) defines the pulsewidth from 0 (0%) to 255 (100%).

Timer1 has 3 PWM outputs (14,15 and 4), Timer3 only one output (9) and Timer4 two outputs (10 and 15 (same as Timer1!). Here are the sample codes:

// Fast PWM for Teensy Timer1 (3 outputs)
    const byte fan1Pin = 14;      // PB5 on Teensy (OC1A of Timer1)
    const byte fan2Pin = 15;      // PB6 on Teensy (OC1B of Timer1)
    const byte fan3Pin = 4;       // PB7 on Teensy (OC1C of Timer1)
    void setup() {
      pinMode(fan1Pin, OUTPUT);
      pinMode(fan2Pin, OUTPUT);
      pinMode(fan3Pin, OUTPUT);      
      TCCR1A = 0xA9;              // COM1A1, COM1B1, COM1C1, WGM10
      TCCR1B = 0x0A;              // WGM12 (Fast PWM 8 Bit) CK/8  -> 7,8kHz 
      OCR1A = 51;                 // 20%
      OCR1B = 127;                // 50%
      OCR1C = 179;}               // 70%
    void loop() {}
    // Fast PWM for Teensy Timer3 (only one pin available!)
    const byte fan1Pin = 9;       // PC6 on Teensy (OC3A of Timer3)
    void setup() {
      pinMode(fan1Pin, OUTPUT);
      TCCR3A = 0xA1;              // COM3A1,WGM30;
      TCCR3B = 0x0A;              // WGM32 (Fast PWM 8 Bit) CK/8  -> 7,8kHz 
      OCR3A = 51;}                // 20%
    void loop() {}
    // Fast PWM for Teensy Timer4 (2 outputs)
    const byte fan1Pin = 10;    // PC7 on Teensy (OC4A of Timer4)
    const byte fan2Pin = 15;    // PB6 on Teensy (OC4B of Timer4)
    void setup() {
      TCCR4A = 0xA3;            // COM4A1, COM4B1, PWM4A, PWM4B
      TCCR4B = 0x04;            // CK/8  -> 3,92kHz (8MHz 10Bit??))
      OCR4A = 51;               // 20%
      OCR4B = 127;}             // 50%
    void loop() {}

To change the PWM frequency, adjust the bits in TCCRnB (see data sheet of mega32u4).

Using Timers in CTC mode on Teensy 2.0 (mega32u4) in Arduino

We will use the Timer1 and Timer3 (both 16 bit) with compare match (CTC mode).

Timer1 will print seconds and minutes once a second in the serial terminal (115200 bits/s) without using an interrupt. For this we watch the interrupt flag. By clearing the flag with "1" (i know it's not logical but hardware dictates the laws) we simulate an interrupt and initiate the timer to run again.

Timer3 fires an interrupt in half a second time to blink the Teensy LED and an LED on PB0 (0) once a second. Setting the PIN register to "1" is an efficient way (2 cycles) to toggle a pin but works only on AVR controller.

    // CTC Mode (with and without interrupt)
    // on Teensy2 (mega32u4)
    // Timer1 prints seconds and minutes in serial terminal without interrupt
    // Timer3 toggles PB0 once a second
    // weigu.lu 
    // This example code is in the public domain.

    const byte teensyLED = 11; // PD6 Teensy LED
    const byte toggleLED = 0;  // PB0 on Teensy
    int seccounter = 0, mincounter = 0;

    void setup() {
    pinMode(teensyLED, OUTPUT);
    pinMode(toggleLED, OUTPUT);
    Serial.begin(115200);   
    noInterrupts();
    TCCR1A = 0;
    TCCR1B = 0x0C;         // WGM32 (CTC) , Prescaler = 256
    OCR1A = 62500;         // 16M/256/62500 = 1 second
    TCCR3A = 0;
    TCCR3B = 0x0C;         // WGM32 (CTC) , Prescaler = 256
    OCR3A = 31250;         // 16M/256/31250 = 0,5 seconds
    TIMSK3 = 0x02;         // enable compare interrupt
    interrupts();}

    void loop() {
    if (TIFR1 & 0x02) {    // Flag set?
        seccounter++;
        TIFR1 |= 0x02;       // clear Flag with 1! (data sheet)
        if (seccounter == 60) {
        seccounter = 0;
        mincounter++;}
        Serial.print(mincounter);   
        Serial.print(":");   
        Serial.println(seccounter);}}

    ISR (TIMER3_COMPA_vect) {
    PINB = PINB | 0x01;    // toggle pin PB0
    PIND = PIND | 0x40; }  // toggle pin PD6 Teensy LED

Using Ethernet shield (WZ5500) with SD-card shield at the same time

Both shields are using SPI. Because the SD-card shield is on top of the Teensy2 it uses pin 0 (PB0) as chip select. The Ethernet shield has to use a different chip select. In the Teensy library (hardware/teensy/avr/libraries/Ethernet) the chip select is on pin 10 (PC7) but only if you use the init() function.
Without using this function chip select stays on pin 0 and conflicts with the SD-card. You can pass a parameter to the init() function an so specify another pin for chip select.

So here is the code for pin 10:

    Ethernet.init();
    Ethernet.begin(mac, eth_ip);  

And here the code for example pin 13 (PB4):

    Ethernet.init(13);
    Ethernet.begin(mac, eth_ip);