Skip to content
This repository was archived by the owner on Jan 29, 2023. It is now read-only.

Commit 8317624

Browse files
authored
Add ISR_Changing_PWM example
1 parent 00052a2 commit 8317624

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/****************************************************************************************************************************
2+
ISR_16_PWMs_Array_Simple.ino
3+
For ESP8266 boards
4+
Written by Khoi Hoang
5+
6+
Built by Khoi Hoang https://github.com/khoih-prog/ESP8266_PWM
7+
Licensed under MIT license
8+
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 !!!
13+
14+
Now with these new 16 ISR-based timers, the maximum interval is practically unlimited (limited only by unsigned long miliseconds)
15+
The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers
16+
Therefore, their executions are not blocked by bad-behaving functions / tasks.
17+
This important feature is absolutely necessary for mission-critical tasks.
18+
19+
Version: 1.0.0
20+
21+
Version Modified By Date Comments
22+
------- ----------- ---------- -----------
23+
1.0.0 K Hoang 21/09/2021 Initial coding for ESP8266 boards with ESP8266 core v3.0.2+
24+
*****************************************************************************************************************************/
25+
26+
#if !defined(ESP8266)
27+
#error This code is designed to run on ESP8266 and ESP8266-based boards! Please check your Tools->Board setting.
28+
#endif
29+
30+
// These define's must be placed at the beginning before #include "ESP8266_PWM.h"
31+
// _PWM_LOGLEVEL_ from 0 to 4
32+
// Don't define _PWM_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
33+
#define _PWM_LOGLEVEL_ 4
34+
35+
#define USING_MICROS_RESOLUTION true //false
36+
37+
#include "ESP8266_PWM.h"
38+
39+
#ifndef LED_BUILTIN
40+
#define LED_BUILTIN 2
41+
#endif
42+
43+
#define HW_TIMER_INTERVAL_US 20L
44+
45+
volatile uint32_t startMicros = 0;
46+
47+
// Init ESP8266Timer
48+
ESP8266Timer ITimer;
49+
50+
// Init ESP8266_ISR_PWM
51+
ESP8266_PWM ISR_PWM;
52+
53+
void IRAM_ATTR TimerHandler()
54+
{
55+
ISR_PWM.run();
56+
}
57+
58+
//////////////////////////////////////////////////////
59+
60+
//PIN_D0 can't be used for PWM/I2C
61+
#define PIN_D0 16 // Pin D0 mapped to pin GPIO16/USER/WAKE of ESP8266. This pin is also used for Onboard-Blue LED. PIN_D0 = 0 => LED ON
62+
#define PIN_D1 5 // Pin D1 mapped to pin GPIO5 of ESP8266
63+
#define PIN_D2 4 // Pin D2 mapped to pin GPIO4 of ESP8266
64+
#define PIN_D3 0 // Pin D3 mapped to pin GPIO0/FLASH of ESP8266
65+
#define PIN_D4 2 // Pin D4 mapped to pin GPIO2/TXD1 of ESP8266
66+
//#define PIN_LED 2 // Pin D4 mapped to pin GPIO2/TXD1 of ESP8266, NodeMCU and WeMoS, control on-board LED
67+
#define PIN_D5 14 // Pin D5 mapped to pin GPIO14/HSCLK of ESP8266
68+
#define PIN_D6 12 // Pin D6 mapped to pin GPIO12/HMISO of ESP8266
69+
#define PIN_D7 13 // Pin D7 mapped to pin GPIO13/RXD2/HMOSI of ESP8266
70+
#define PIN_D8 15 // Pin D8 mapped to pin GPIO15/TXD2/HCS of ESP8266
71+
#define PIN_D9 3 // Pin D9 /RX mapped to pin GPIO3/RXD0 of ESP8266
72+
#define PIN_D10 1 // Pin D10/TX mapped to pin GPIO1/TXD0 of ESP8266
73+
74+
//Don't use pins GPIO6 to GPIO11 as already connected to flash, etc. Use them can crash the program
75+
//GPIO9(D11/SD2) and GPIO11 can be used only if flash in DIO mode ( not the default QIO mode)
76+
#define PIN_D11 9 // Pin D11/SD2 mapped to pin GPIO9/SDD2 of ESP8266
77+
#define PIN_D12 10 // Pin D12/SD3 mapped to pin GPIO10/SDD3 of ESP8266
78+
79+
//////////////////////////////////////////////////////
80+
81+
#define USING_PWM_FREQUENCY true
82+
83+
//////////////////////////////////////////////////////
84+
85+
// You can assign pins here. Be carefull to select good pin to use or crash
86+
uint32_t PWM_Pin = LED_BUILTIN;
87+
88+
// You can assign any interval for any timer here, in microseconds
89+
uint32_t PWM_Period1 = 1000000L;
90+
// You can assign any interval for any timer here, in microseconds
91+
uint32_t PWM_Period2 = 500000L;
92+
93+
// You can assign any interval for any timer here, in Hz
94+
uint32_t PWM_Freq1 = 1;
95+
// You can assign any interval for any timer here, in Hz
96+
uint32_t PWM_Freq2 = 2;
97+
98+
// You can assign any duty_cycle for any PWM here, from 0-100
99+
uint32_t PWM_DutyCycle1 = 50;
100+
// You can assign any duty_cycle for any PWM here, from 0-100
101+
uint32_t PWM_DutyCycle2 = 90;
102+
103+
// Channel number used to identify associated channel
104+
int channelNum;
105+
106+
////////////////////////////////////////////////
107+
108+
void setup()
109+
{
110+
Serial.begin(115200);
111+
while (!Serial);
112+
113+
delay(2000);
114+
115+
Serial.print(F("\nStarting ISR_Changing_PWM on ")); Serial.println(ARDUINO_BOARD);
116+
Serial.println(ESP8266_PWM_VERSION);
117+
Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));
118+
119+
// Interval in microsecs
120+
if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_US, TimerHandler))
121+
{
122+
startMicros = micros();
123+
Serial.print(F("Starting ITimer OK, micros() = ")); Serial.println(startMicros);
124+
}
125+
else
126+
Serial.println(F("Can't set ITimer. Select another freq. or timer"));
127+
128+
// Just to demonstrate, don't use too many ISR Timers if not absolutely necessary
129+
// You can use up to 16 timer for each ISR_PWM
130+
//void setPWM(uint32_t pin, uint32_t frequency, uint32_t dutycycle
131+
// , timer_callback_p StartCallback = nullptr, timer_callback_p StopCallback = nullptr)
132+
}
133+
134+
void loop()
135+
{
136+
Serial.print(F("Using PWM Freq = ")); Serial.print(PWM_Freq1); Serial.print(F(", PWM DutyCycle = ")); Serial.println(PWM_DutyCycle1);
137+
138+
#if USING_PWM_FREQUENCY
139+
140+
// You can use this with PWM_Freq in Hz
141+
ISR_PWM.setPWM(PWM_Pin, PWM_Freq1, PWM_DutyCycle1);
142+
143+
#else
144+
#if USING_MICROS_RESOLUTION
145+
// Or using period in microsecs resolution
146+
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Freq1, PWM_DutyCycle1);
147+
#else
148+
// Or using period in millisecs resolution
149+
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period1 / 1000, PWM_DutyCycle1);
150+
#endif
151+
#endif
152+
153+
delay(10000);
154+
155+
ISR_PWM.deleteChannel((unsigned) channelNum);
156+
157+
Serial.print(F("Using PWM Freq = ")); Serial.print(PWM_Freq2); Serial.print(F(", PWM DutyCycle = ")); Serial.println(PWM_DutyCycle2);
158+
159+
#if USING_PWM_FREQUENCY
160+
161+
// You can use this with PWM_Freq in Hz
162+
ISR_PWM.setPWM(PWM_Pin, PWM_Freq2, PWM_DutyCycle2);
163+
164+
#else
165+
#if USING_MICROS_RESOLUTION
166+
// Or using period in microsecs resolution
167+
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Freq2, PWM_DutyCycle2);
168+
#else
169+
// Or using period in millisecs resolution
170+
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period2 / 1000, PWM_DutyCycle2);
171+
#endif
172+
#endif
173+
174+
delay(10000);
175+
}

0 commit comments

Comments
 (0)