The Industruino's D21G MCU belongs to the SAMD21G family of 32 bit ARM Cortex M0 microcontrollers. The Arduino Zero board has the same ATSAMD21G18 chip, but the pin mapping is slightly different. For most applications and libraries this is not relevant, but for some features, such as timers, there are minor differences that should be taken into account. This blog post explains how to use timers on the Industruino D21G, based on an earlier version (1.0.0) of the Adafruit_ZeroTimer library (written for Arduino Zero) available here, and the extra layer of the avdweb_SAMDtimer library that makes it very easy to use these timer functions:
- attach an ISR (interrupt service routine) to a timer
- generate PWM on specific timer output pins (PROTO only)
First install the above libraries. (If you'd rather use the latest version of the Adafruit_ZeroTimer library, you will have to find out what needs to be changed based on the below info).
As mentioned, the pin mapping is slightly different for the Industruino D21G, so we have to edit the Adafruit_ZeroTimer.cpp library file (in sketchbook/libraries).
- in line 31, change pin 12 to pin 0 (the Industruino D21G has timer 3 on D0 instead of D12)
- comment out 4 lines 45-49 (the Industruino D21G does not use pin A1) - you can add // in front of the line to achieve this
- in line 56, change pin A2 to pin 6 (the Industruino D21G does not use A2 and has timer 4 on D6)
Now you can use 3 16-bit timers with the avdweb_SAMDtimer library, for this functionality:
- timer3 with interrupt (ISR) and with PWM output on D0 (if you do not use it for Serial)
- timer4 with interrupt (ISR) and with PWM output on D6
- timer5 with interrupt (ISR)
Example of constructors for that avdweb_SAMDtimer library:
- SAMDtimer timer3_10Hz = SAMDtimer(3, ISR_timer3_LED1 , 1e5); // timer 3 with 10Hz interrupt routine
- SAMDtimer timer3_1Hz = SAMDtimer(3, TC_COUNTER_SIZE_16BIT, 0, 1e6, 9e5); // timer 3 on D0 with 1Hz, pulse width 0.9s
- SAMDtimer timer4_2Hz = SAMDtimer(4, TC_COUNTER_SIZE_16BIT, 6, 5e5, 1e5); // timer 4 on D6 with 2Hz, pulse width 20%
- SAMDtimer timer5_1Hz = SAMDtimer(5, ISR_timer5_LED2 , 1e6); // timer 5 with 1Hz interrupt routine
Code example (tested on PROTO, generating signals on D4, D0, D6, and the LCD backlight)
/* TIMER library example for Industruino D21G Arduino Zero timer library https://github.com/adafruit/Adafruit_ZeroTimer/ simplified library http://www.avdweb.nl/arduino/libraries/samd21-timer.html simple example below Necessary modifications to Adafruit_ZeroTimer.cpp: >> in line 31, change pin 12 to pin 0 (the Industruino D21G has timer 3 on D0 instead of D12) >> comment out 4 lines 45-49 (the Industruino D21G does not use pin A1) >> in line 56, change pin A2 to pin 6 (the Industruino D21G does not use A2 and has timer 4 on D6) Industruino D21G timer functionality: >> timer3 with interrupt and with output on D0 (if you do not use it for Serial) >> timer4 with interrupt and with output on D6 >> timer5 with interrupt Note: D0 and D6 are available on the terminals of the PROTO platform (and on the IDC connector of both PROTO and INDIO) Tom Tobback Oct 2017 */ #include <Arduino.h> #include "avdweb_SAMDtimer.h" const byte LED1 = 26; // D21G LCD backlight or any other pin const byte LED2 = 4; // D21G D4 or any other pin void ISR_timer3_LED1(struct tc_module *const module_inst) { static bool b; pinMode(LED1, OUTPUT); digitalWrite(LED1, b = !b); } void ISR_timer5_LED2(struct tc_module *const module_inst) { static bool b; pinMode(LED2, OUTPUT); digitalWrite(LED2, b = !b); } // ------------- Timer3 with output on D0 and/or interrupt ------------- SAMDtimer timer3_1Hz = SAMDtimer(3, ISR_timer3_LED1 , 1e6); // timer 3 with 1Hz interrupt (PWM 50% default) // SAMDtimer timer3_1Hz = SAMDtimer(3, TC_COUNTER_SIZE_16BIT, 0, 1e6, 9e5); // timer 3 on D0 with 1Hz pulse -- also attach 1Hz interrupt, see below // ------------- Timer4 with output on D6 and/or interrupt ------------- // SAMDtimer timer4_2Hz = SAMDtimer(4, ISR_timer4_LED2, 5e5, 0); // timer 4 with 2Hz interrupt, disabled SAMDtimer timer4_2Hz = SAMDtimer(4, TC_COUNTER_SIZE_16BIT, 6, 5e5, 1e5); // timer 4 on D6 with 1Hz, pulse width 0.9s // ------------- Timer5 with interrupt ------------- SAMDtimer timer5_10Hz = SAMDtimer(5, ISR_timer5_LED2 , 1e5); // timer 5 with 10Hz interrupt void setup() // test out the several functions: { // ------------- timer3 ------------- // timer3_1Hz.enableTimer(1); // enable timer *1), LED4 blinks again // timer3_1Hz.setPulseWidth(1e5); // change pulse width to 0.1s // attach a new ISR to a timer with output, this can't be done in the constructor timer3_1Hz.attachInterrupt(ISR_timer3_LED1); // LCD backlight blinks // timer3_1Hz.attachInterrupt(ISR_timer3_LED1, 0); // the same but ISR is disabled, the timer-output is not disabled // ------------- timer4 ------------- // timer4_2Hz.enableInterrupt(0); // disable ISR_timer4_LED2, LED2 stops blinking // timer4_2Hz.enableInterrupt(1); // enable ISR_timer4_LED2, LED2 blinks again *2) } void loop() { timer3_1Hz.enableTimer(0); // all timers off timer4_2Hz.enableTimer(0); timer5_10Hz.enableTimer(0); delay(5000); timer3_1Hz.enableTimer(1); // start timer3 1Hz -- PWM on D0 (default 50%) timer3_1Hz.enableInterrupt(0); // ISR off delay(5000); timer3_1Hz.enableInterrupt(1); // ISR on delay(5000); timer4_2Hz.enableTimer(1); // start timer4 2Hz -- PWM on D6 timer4_2Hz.setPulseWidth(1e5); // 20% delay(5000); timer4_2Hz.setPulseWidth(4e5); // 80% delay(5000); timer5_10Hz.enableTimer(1); // start timer5 10Hz -- ISR on delay(5000); }
Code for Indio (Digital Output channel 1 and 2)
/* TIMER library example for Industruino D21G Arduino Zero timer library https://github.com/adafruit/Adafruit_ZeroTimer/ simplified library http://www.avdweb.nl/arduino/libraries/samd21-timer.html simple example below Necessary modifications to Adafruit_ZeroTimer.cpp: >> in line 31, change pin 12 to pin 0 (the Industruino D21G has timer 3 on D0 instead of D12) >> comment out 4 lines 45-49 (the Industruino D21G does not use pin A1) >> in line 56, change pin A2 to pin 6 (the Industruino D21G does not use A2 and has timer 4 on D6) Industruino D21G timer functionality: >> timer3 with interrupt and with output on D0 (if you do not use it for Serial) >> timer4 with interrupt and with output on D6 >> timer5 with interrupt Note: D0 and D6 are available on the terminals of the PROTO platform (and on the IDC connector of both PROTO and INDIO) Tom Tobback Oct 2017 */ #include <Indio.h> #include <Wire.h> #include <Arduino.h> #include "avdweb_SAMDtimer.h" void ISR_timer3_CH1(struct tc_module *const module_inst) { static bool b; Indio.digitalWrite(1, b = !b); } void ISR_timer5_CH2(struct tc_module *const module_inst) { static bool b; Indio.digitalWrite(2, b = !b); } // ------------- Timer3 with output on D0 and/or interrupt ------------- SAMDtimer timer3_1Hz = SAMDtimer(3, ISR_timer3_CH1 , 1e6); // timer 3 with 1Hz interrupt // ------------- Timer5 with interrupt ------------- SAMDtimer timer5_10Hz = SAMDtimer(5, ISR_timer5_CH2 , 1e5); // timer 5 with 10Hz interrupt void setup() // test out the several functions: { Indio.digitalMode(1, OUTPUT); Indio.digitalMode(2, OUTPUT); Indio.digitalWrite(1, LOW); Indio.digitalWrite(2, LOW); } void loop() { timer3_1Hz.enableTimer(0); // all timers off timer5_10Hz.enableTimer(0); delay(5000); timer3_1Hz.enableTimer(1); // start timer3 1Hz -- ISR CH1 delay(5000); timer5_10Hz.enableTimer(1); // start timer5 10Hz -- ISR CH2 delay(5000); }