|
1 | 1 | /****************************************************************************************************************************
|
2 | 2 | Argument_None.ino
|
3 |
| - For ESP32, ESP32_S2, ESP32_S3, ESP32_C3 boards with ESP32 core v2.0.2+ |
| 3 | + For ESP8266 boards |
4 | 4 | Written by Khoi Hoang
|
5 | 5 |
|
6 |
| - Built by Khoi Hoang https://github.com/khoih-prog/ESP32TimerInterrupt |
| 6 | + Built by Khoi Hoang https://github.com/khoih-prog/ESP8266TimerInterrupt |
7 | 7 | Licensed under MIT license
|
8 | 8 |
|
9 |
| - The ESP32, ESP32_S2, ESP32_S3, ESP32_C3 have two timer groups, TIMER_GROUP_0 and TIMER_GROUP_1 |
10 |
| - 1) each group of ESP32, ESP32_S2, ESP32_S3 has two general purpose hardware timers, TIMER_0 and TIMER_1 |
11 |
| - 2) each group of ESP32_C3 has ony one general purpose hardware timer, TIMER_0 |
| 9 | + The ESP8266 timers are badly designed, using only 23-bit counter along with maximum 256 prescaler. They're only better than UNO / Mega. |
| 10 | + The ESP8266 has two hardware timers, but timer0 has been used for WiFi and it's not advisable to use. Only timer1 is available. |
| 11 | + The timer1's 23-bit counter terribly can count only up to 8,388,607. So the timer1 maximum interval is very short. |
| 12 | + Using 256 prescaler, maximum timer1 interval is only 26.843542 seconds !!! |
12 | 13 |
|
13 |
| - All the timers are based on 64-bit counters (except 54-bit counter for ESP32_S3 counter) and 16 bit prescalers. |
14 |
| - The timer counters can be configured to count up or down and support automatic reload and software reload. |
15 |
| - They can also generate alarms when they reach a specific value, defined by the software. |
16 |
| - The value of the counter can be read by the software program. |
17 |
| -
|
18 |
| - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by |
19 |
| - unsigned long miliseconds), you just consume only one ESP32-S2 timer and avoid conflicting with other cores' tasks. |
| 14 | + Now with these new 16 ISR-based timers, the maximum interval is practically unlimited (limited only by unsigned long milliseconds) |
20 | 15 | The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers
|
21 | 16 | Therefore, their executions are not blocked by bad-behaving functions / tasks.
|
22 | 17 | This important feature is absolutely necessary for mission-critical tasks.
|
23 | 18 | *****************************************************************************************************************************/
|
24 | 19 |
|
25 |
| -/* |
26 |
| - Notes: |
| 20 | +/* Notes: |
27 | 21 | Special design is necessary to share data between interrupt code and the rest of your program.
|
28 | 22 | Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume
|
29 | 23 | variable can not spontaneously change. Because your function may change variables while your program is using them,
|
|
34 | 28 | or the entire sequence of your code which accesses the data.
|
35 | 29 | */
|
36 | 30 |
|
37 |
| -#if !defined( ESP32 ) |
38 |
| - #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting. |
| 31 | +#if !defined(ESP8266) |
| 32 | + #error This code is designed to run on ESP8266 and ESP8266-based boards! Please check your Tools->Board setting. |
39 | 33 | #endif
|
40 | 34 |
|
41 |
| -// These define's must be placed at the beginning before #include "_TIMERINTERRUPT_LOGLEVEL_.h" |
| 35 | +// These define's must be placed at the beginning before #include "ESP8266TimerInterrupt.h" |
42 | 36 | // _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
|
43 |
| -#define _TIMERINTERRUPT_LOGLEVEL_ 3 |
44 |
| - |
45 |
| -// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error |
46 |
| -#include "ESP32TimerInterrupt.h" |
47 |
| - |
48 |
| -// Don't use PIN_D1 in core v2.0.0 and v2.0.1. Check https://github.com/espressif/arduino-esp32/issues/5868 |
49 |
| -// Don't use PIN_D2 with ESP32_C3 (crash) |
50 |
| -#define PIN_D19 19 // Pin D19 mapped to pin GPIO9 of ESP32 |
51 |
| -#define PIN_D3 3 // Pin D3 mapped to pin GPIO3/RX0 of ESP32 |
| 37 | +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. |
| 38 | +#define TIMER_INTERRUPT_DEBUG 0 |
| 39 | +#define _TIMERINTERRUPT_LOGLEVEL_ 0 |
52 | 40 |
|
| 41 | +// Select a Timer Clock |
| 42 | +#define USING_TIM_DIV1 false // for shortest and most accurate timer |
| 43 | +#define USING_TIM_DIV16 false // for medium time and medium accurate timer |
| 44 | +#define USING_TIM_DIV256 true // for longest timer but least accurate. Default |
53 | 45 |
|
54 |
| -// With core v2.0.0+, you can't use Serial.print/println in ISR or crash. |
55 |
| -// and you can't use float calculation inside ISR |
56 |
| -// Only OK in core v1.0.6- |
57 |
| -bool IRAM_ATTR TimerHandler0(void * timerNo) |
58 |
| -{ |
59 |
| - static bool toggle0 = false; |
| 46 | +#include "ESP8266TimerInterrupt.h" |
60 | 47 |
|
61 |
| - //timer interrupt toggles pin PIN_D19 |
62 |
| - digitalWrite(PIN_D19, toggle0); |
63 |
| - toggle0 = !toggle0; |
| 48 | +#ifndef LED_BUILTIN |
| 49 | + #define LED_BUILTIN 2 // Pin D4 mapped to pin GPIO2/TXD1 of ESP8266, NodeMCU and WeMoS, control on-board LED |
| 50 | +#endif |
64 | 51 |
|
65 |
| - return true; |
66 |
| -} |
| 52 | +volatile uint32_t lastMillis = 0; |
67 | 53 |
|
68 |
| -// With core v2.0.0+, you can't use Serial.print/println in ISR or crash. |
69 |
| -// and you can't use float calculation inside ISR |
70 |
| -// Only OK in core v1.0.6- |
71 |
| -bool IRAM_ATTR TimerHandler1(void * timerNo) |
| 54 | +void IRAM_ATTR TimerHandler() |
72 | 55 | {
|
73 |
| - ///////////////////////////////////////////////////////// |
74 |
| - |
75 |
| - static bool toggle1 = false; |
76 |
| - |
77 |
| - //timer interrupt toggles outputPin |
78 |
| - digitalWrite(PIN_D3, toggle1); |
79 |
| - toggle1 = !toggle1; |
| 56 | + static bool toggle = false; |
| 57 | + static bool started = false; |
| 58 | + |
| 59 | + if (!started) |
| 60 | + { |
| 61 | + started = true; |
| 62 | + pinMode(LED_BUILTIN, OUTPUT); |
| 63 | + } |
| 64 | + |
| 65 | +#if (TIMER_INTERRUPT_DEBUG > 0) |
| 66 | + Serial.print("Delta ms = "); |
| 67 | + Serial.println(millis() - lastMillis); |
| 68 | + lastMillis = millis(); |
| 69 | +#endif |
80 | 70 |
|
81 |
| - return true; |
| 71 | + //timer interrupt toggles pin LED_BUILTIN |
| 72 | + digitalWrite(LED_BUILTIN, toggle); |
| 73 | + toggle = !toggle; |
82 | 74 | }
|
83 | 75 |
|
84 |
| -#define TIMER0_INTERVAL_MS 100 |
| 76 | +#define TIMER_INTERVAL_MS 1000 |
85 | 77 |
|
86 |
| -#define TIMER1_INTERVAL_MS 5000 |
87 |
| - |
88 |
| -// Init ESP32 timer 0 and 1 |
89 |
| -ESP32Timer ITimer0(0); |
90 |
| -ESP32Timer ITimer1(1); |
| 78 | +// Init ESP8266 timer 1 |
| 79 | +ESP8266Timer ITimer; |
91 | 80 |
|
92 | 81 | void setup()
|
93 | 82 | {
|
94 |
| - pinMode(PIN_D19, OUTPUT); |
95 |
| - pinMode(PIN_D3, OUTPUT); |
96 |
| - |
97 |
| - Serial.begin(115200); |
| 83 | + Serial.begin(115200); |
98 | 84 |
|
99 |
| - while (!Serial && millis() < 5000); |
| 85 | + while (!Serial && millis() < 5000); |
100 | 86 |
|
101 | 87 | delay(500);
|
102 | 88 |
|
103 |
| - Serial.print(F("\nStarting Argument_None on ")); |
104 |
| - Serial.println(ARDUINO_BOARD); |
105 |
| - Serial.println(ESP32_TIMER_INTERRUPT_VERSION); |
106 |
| - Serial.print(F("CPU Frequency = ")); |
107 |
| - Serial.print(F_CPU / 1000000); |
108 |
| - Serial.println(F(" MHz")); |
109 |
| - |
110 |
| - // Using ESP32 => 80 / 160 / 240MHz CPU clock , |
111 |
| - // For 64-bit timer counter |
112 |
| - // For 16-bit timer prescaler up to 1024 |
113 |
| - |
114 |
| - // Interval in microsecs |
115 |
| - if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)) |
116 |
| - //if (ITimer0.attachInterrupt(1, TimerHandler0)) |
117 |
| - { |
118 |
| - Serial.print(F("Starting ITimer0 OK, millis() = ")); |
119 |
| - Serial.println(millis()); |
120 |
| - } |
121 |
| - else |
122 |
| - Serial.println(F("Can't set ITimer0. Select another Timer, freq. or timer")); |
123 |
| - |
124 |
| - |
125 |
| - // Interval in microsecs |
126 |
| - if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1)) |
127 |
| - //if (ITimer1.attachInterrupt(2, TimerHandler1)) |
128 |
| - { |
129 |
| - Serial.print(F("Starting ITimer1 OK, millis() = ")); |
130 |
| - Serial.println(millis()); |
131 |
| - } |
132 |
| - else |
133 |
| - Serial.println(F("Can't set ITimer1. Select another Timer, freq. or timer")); |
| 89 | + Serial.print(F("\nStarting Argument_None on ")); |
| 90 | + Serial.println(ARDUINO_BOARD); |
| 91 | + Serial.println(ESP8266_TIMER_INTERRUPT_VERSION); |
| 92 | + Serial.print(F("CPU Frequency = ")); |
| 93 | + Serial.print(F_CPU / 1000000); |
| 94 | + Serial.println(F(" MHz")); |
| 95 | + |
| 96 | + // Interval in microsecs |
| 97 | + if (ITimer.attachInterruptInterval(TIMER_INTERVAL_MS * 1000, TimerHandler)) |
| 98 | + { |
| 99 | + lastMillis = millis(); |
| 100 | + Serial.print(F("Starting ITimer OK, millis() = ")); |
| 101 | + Serial.println(lastMillis); |
| 102 | + } |
| 103 | + else |
| 104 | + Serial.println(F("Can't set ITimer correctly. Select another freq. or interval")); |
134 | 105 | }
|
135 | 106 |
|
136 | 107 | void loop()
|
137 | 108 | {
|
138 |
| - delay(1); |
| 109 | + |
139 | 110 | }
|
0 commit comments