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

Commit 486a8cd

Browse files
authored
v1.2.0 to fix multiple-definitions linker error
### Releases v1.2.0 1. Fix `multiple-definitions` linker error. Drop `src_cpp` and `src_h` directories 2. DutyCycle to be optionally updated at the end current PWM period instead of immediately. Check [DutyCycle to be updated at the end current PWM period #2](khoih-prog/ESP8266_PWM#2) 3. Add examples [multiFileProject](examples/multiFileProject) to demo for multiple-file project 4. Improve accuracy by using `double`, instead of `uint32_t` for `dutycycle`, `period`. Check [Change Duty Cycle #1](khoih-prog/ESP8266_PWM#1 (comment)) 5. Optimize library code by using `reference-passing` instead of `value-passing` 6. Update examples accordingly
1 parent 3ec17d1 commit 486a8cd

21 files changed

+1578
-1266
lines changed

CONTRIBUTING.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ If you don't find anything, please [open a new issue](https://github.com/khoih-p
1414

1515
Please ensure to specify the following:
1616

17-
* Arduino IDE version (e.g. 1.8.16) or Platform.io version
17+
* Arduino IDE version (e.g. 1.8.19) or Platform.io version
1818
* `SAMDUE` Core Version (e.g. Arduino SAMDUE_ core v1.6.12)
1919
* Contextual information (e.g. what you were trying to achieve)
2020
* Simplest possible steps to reproduce
@@ -26,10 +26,10 @@ Please ensure to specify the following:
2626
### Example
2727

2828
```
29-
Arduino IDE version: 1.8.16
29+
Arduino IDE version: 1.8.19
3030
Arduino SAMDUE Core Version 1.6.12
3131
OS: Ubuntu 20.04 LTS
32-
Linux xy-Inspiron-3593 5.4.0-90-generic #101-Ubuntu SMP Fri Oct 15 20:00:55 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
32+
Linux xy-Inspiron-3593 5.4.0-96-generic #109-Ubuntu SMP Wed Jan 12 16:49:16 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
3333
Context:
3434
I encountered a crash while trying to use the Timer Interrupt.
3535

README.md

+118-108
Large diffs are not rendered by default.

changelog.md

+11-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
## Table of Contents
1313

1414
* [Changelog](#changelog)
15+
* [Releases v1.2.0](#releases-v120)
1516
* [Releases v1.1.0](#releases-v110)
1617
* [Initial Releases v1.0.0](#Initial-Releases-v100)
1718

@@ -20,6 +21,16 @@
2021

2122
## Changelog
2223

24+
### Releases v1.2.0
25+
26+
1. Fix `multiple-definitions` linker error. Drop `src_cpp` and `src_h` directories
27+
2. DutyCycle to be optionally updated at the end current PWM period instead of immediately. Check [DutyCycle to be updated at the end current PWM period #2](https://github.com/khoih-prog/ESP8266_PWM/issues/2)
28+
3. Add examples [multiFileProject](examples/multiFileProject) to demo for multiple-file project
29+
4. Improve accuracy by using `double`, instead of `uint32_t` for `dutycycle`, `period`. Check [Change Duty Cycle #1](https://github.com/khoih-prog/ESP8266_PWM/issues/1#issuecomment-1024969658)
30+
5. Optimize library code by using `reference-passing` instead of `value-passing`
31+
6. Update examples accordingly
32+
33+
2334
### Releases v1.1.0
2435

2536
1. Add functions to modify PWM settings on-the-fly
@@ -31,11 +42,5 @@
3142

3243
2. The hybrid ISR-based PWM channels can generate from very low (much less than 1Hz) to highest PWM frequencies up to 1000Hz with acceptable accuracy.
3344

34-
---
35-
---
36-
37-
## Copyright
38-
39-
Copyright 2021- Khoi Hoang
4045

4146

examples/ISR_8_PWMs_Array/ISR_8_PWMs_Array.ino

+12-8
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,20 @@
2222
// Don't define _PWM_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
2323
#define _PWM_LOGLEVEL_ 4
2424

25+
// Default is true, uncomment to false
26+
#define CHANGING_PWM_END_OF_CYCLE false
27+
28+
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
2529
#include "SAMDUE_Slow_PWM.h"
2630

2731
#include <SimpleTimer.h> // https://github.com/jfturcot/SimpleTimer
2832

2933
#define LED_OFF HIGH
3034
#define LED_ON LOW
3135

32-
#ifndef LED_BUILTIN
33-
#define LED_BUILTIN 13
34-
#endif
36+
//#ifndef LED_BUILTIN
37+
// #define LED_BUILTIN 13
38+
//#endif
3539

3640
#ifndef LED_BLUE
3741
#define LED_BLUE 2
@@ -44,8 +48,8 @@
4448
#define USING_HW_TIMER_INTERVAL_MS false //true
4549

4650
// Don't change these numbers to make higher Timer freq. System can hang
47-
#define HW_TIMER_INTERVAL_US 10L
48-
#define HW_TIMER_INTERVAL_FREQ 100000L
51+
#define HW_TIMER_INTERVAL_US 30L
52+
#define HW_TIMER_INTERVAL_FREQ 33333L
4953

5054
volatile uint32_t startMicros = 0;
5155

@@ -80,15 +84,15 @@ uint32_t PWM_Pin[] =
8084
#define NUMBER_ISR_PWMS ( sizeof(PWM_Pin) / sizeof(uint32_t) )
8185

8286
// You can assign any interval for any timer here, in Hz
83-
double PWM_Freq[NUMBER_ISR_PWMS] =
87+
double PWM_Freq[] =
8488
{
8589
1.0f, 2.0f, 3.0f, 5.0f, 10.0f, 20.0f, 30.0f, 50.0f
8690
};
8791

8892
// You can assign any duty-cycle for any PWM channel here, in %
89-
uint32_t PWM_DutyCycle[NUMBER_ISR_PWMS] =
93+
double PWM_DutyCycle[] =
9094
{
91-
5, 10, 20, 25, 30, 35, 40, 45
95+
5.0, 10.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0
9296
};
9397

9498

examples/ISR_8_PWMs_Array_Complex/ISR_8_PWMs_Array_Complex.ino

+29-25
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,20 @@
2222
// Don't define _PWM_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
2323
#define _PWM_LOGLEVEL_ 3
2424

25+
// Default is true, uncomment to false
26+
//#define CHANGING_PWM_END_OF_CYCLE false
27+
28+
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
2529
#include "SAMDUE_Slow_PWM.h"
2630

2731
#include <SimpleTimer.h> // https://github.com/jfturcot/SimpleTimer
2832

2933
#define LED_OFF HIGH
3034
#define LED_ON LOW
3135

32-
#ifndef LED_BUILTIN
33-
#define LED_BUILTIN 13
34-
#endif
36+
//#ifndef LED_BUILTIN
37+
// #define LED_BUILTIN 13
38+
//#endif
3539

3640
#ifndef LED_BLUE
3741
#define LED_BLUE 2
@@ -44,8 +48,8 @@
4448
#define USING_HW_TIMER_INTERVAL_MS false //true
4549

4650
// Don't change these numbers to make higher Timer freq. System can hang
47-
#define HW_TIMER_INTERVAL_US 10L
48-
#define HW_TIMER_INTERVAL_FREQ 100000L
51+
#define HW_TIMER_INTERVAL_US 30L
52+
#define HW_TIMER_INTERVAL_FREQ 33333L
4953

5054
volatile uint32_t startMicros = 0;
5155

@@ -93,9 +97,9 @@ typedef struct
9397
irqCallback irqCallbackStartFunc;
9498
irqCallback irqCallbackStopFunc;
9599

96-
uint32_t PWM_Freq;
100+
double PWM_Freq;
97101

98-
uint32_t PWM_DutyCycle;
102+
double PWM_DutyCycle;
99103

100104
uint32_t deltaMicrosStart;
101105
uint32_t previousMicrosStart;
@@ -115,22 +119,22 @@ void doingSomethingStop(int index);
115119

116120
#else // #if USE_COMPLEX_STRUCT
117121

118-
volatile unsigned long deltaMicrosStart [NUMBER_ISR_PWMS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
119-
volatile unsigned long previousMicrosStart [NUMBER_ISR_PWMS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
122+
volatile unsigned long deltaMicrosStart [] = { 0, 0, 0, 0, 0, 0, 0, 0 };
123+
volatile unsigned long previousMicrosStart [] = { 0, 0, 0, 0, 0, 0, 0, 0 };
120124

121-
volatile unsigned long deltaMicrosStop [NUMBER_ISR_PWMS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
122-
volatile unsigned long previousMicrosStop [NUMBER_ISR_PWMS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
125+
volatile unsigned long deltaMicrosStop [] = { 0, 0, 0, 0, 0, 0, 0, 0 };
126+
volatile unsigned long previousMicrosStop [] = { 0, 0, 0, 0, 0, 0, 0, 0 };
123127

124128
// You can assign any interval for any timer here, in Hz
125-
double PWM_Freq[NUMBER_ISR_PWMS] =
129+
double PWM_Freq[] =
126130
{
127131
1.0f, 2.0f, 3.0f, 5.0f, 10.0f, 20.0f, 30.0f, 50.0f
128132
};
129133

130134
// You can assign any duty-cycle for any PWM channel here, in %
131-
uint32_t PWM_DutyCycle[NUMBER_ISR_PWMS] =
135+
double PWM_DutyCycle[] =
132136
{
133-
5, 10, 20, 25, 30, 35, 40, 45
137+
5.0, 10.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0
134138
};
135139

136140
void doingSomethingStart(int index)
@@ -244,17 +248,17 @@ void doingSomethingStop7()
244248

245249
#if USE_COMPLEX_STRUCT
246250

247-
ISR_PWM_Data curISR_PWM_Data[NUMBER_ISR_PWMS] =
251+
ISR_PWM_Data curISR_PWM_Data[] =
248252
{
249253
// pin, irqCallbackStartFunc, irqCallbackStopFunc, PWM_Freq, PWM_DutyCycle, deltaMicrosStart, previousMicrosStart, deltaMicrosStop, previousMicrosStop
250-
{ LED_BUILTIN, doingSomethingStart0, doingSomethingStop0, 1, 5, 0, 0, 0, 0 },
251-
{ PIN_22, doingSomethingStart1, doingSomethingStop1, 2, 10, 0, 0, 0, 0 },
252-
{ PIN_23, doingSomethingStart2, doingSomethingStop2, 3, 20, 0, 0, 0, 0 },
253-
{ PIN_24, doingSomethingStart3, doingSomethingStop3, 5, 25, 0, 0, 0, 0 },
254-
{ PIN_25, doingSomethingStart4, doingSomethingStop4, 10, 30, 0, 0, 0, 0 },
255-
{ PIN_26, doingSomethingStart5, doingSomethingStop5, 20, 35, 0, 0, 0, 0 },
256-
{ PIN_27, doingSomethingStart6, doingSomethingStop6, 30, 40, 0, 0, 0, 0 },
257-
{ PIN_28, doingSomethingStart7, doingSomethingStop7, 50, 45, 0, 0, 0, 0 },
254+
{ LED_BUILTIN, doingSomethingStart0, doingSomethingStop0, 1.0, 5.0, 0, 0, 0, 0 },
255+
{ PIN_22, doingSomethingStart1, doingSomethingStop1, 2.0, 10.0, 0, 0, 0, 0 },
256+
{ PIN_23, doingSomethingStart2, doingSomethingStop2, 3.0, 20.0, 0, 0, 0, 0 },
257+
{ PIN_24, doingSomethingStart3, doingSomethingStop3, 5.0, 25.0, 0, 0, 0, 0 },
258+
{ PIN_25, doingSomethingStart4, doingSomethingStop4, 10.0, 30.0, 0, 0, 0, 0 },
259+
{ PIN_26, doingSomethingStart5, doingSomethingStop5, 20.0, 35.0, 0, 0, 0, 0 },
260+
{ PIN_27, doingSomethingStart6, doingSomethingStop6, 30.0, 40.0, 0, 0, 0, 0 },
261+
{ PIN_28, doingSomethingStart7, doingSomethingStop7, 50.0, 45.0, 0, 0, 0, 0 },
258262
};
259263

260264

@@ -278,13 +282,13 @@ void doingSomethingStop(int index)
278282

279283
#else // #if USE_COMPLEX_STRUCT
280284

281-
irqCallback irqCallbackStartFunc[NUMBER_ISR_PWMS] =
285+
irqCallback irqCallbackStartFunc[] =
282286
{
283287
doingSomethingStart0, doingSomethingStart1, doingSomethingStart2, doingSomethingStart3,
284288
doingSomethingStart4, doingSomethingStart5, doingSomethingStart6, doingSomethingStart7
285289
};
286290

287-
irqCallback irqCallbackStopFunc[NUMBER_ISR_PWMS] =
291+
irqCallback irqCallbackStopFunc[] =
288292
{
289293
doingSomethingStop0, doingSomethingStop1, doingSomethingStop2, doingSomethingStop3,
290294
doingSomethingStop4, doingSomethingStop5, doingSomethingStop6, doingSomethingStop7

examples/ISR_8_PWMs_Array_Simple/ISR_8_PWMs_Array_Simple.ino

+12-8
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,20 @@
2222
// Don't define _PWM_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
2323
#define _PWM_LOGLEVEL_ 3
2424

25+
// Default is true, uncomment to false
26+
#define CHANGING_PWM_END_OF_CYCLE false
27+
28+
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
2529
#include "SAMDUE_Slow_PWM.h"
2630

2731
#include <SimpleTimer.h> // https://github.com/jfturcot/SimpleTimer
2832

2933
#define LED_OFF HIGH
3034
#define LED_ON LOW
3135

32-
#ifndef LED_BUILTIN
33-
#define LED_BUILTIN 13
34-
#endif
36+
//#ifndef LED_BUILTIN
37+
// #define LED_BUILTIN 13
38+
//#endif
3539

3640
#ifndef LED_BLUE
3741
#define LED_BLUE 2
@@ -44,8 +48,8 @@
4448
#define USING_HW_TIMER_INTERVAL_MS false //true
4549

4650
// Don't change these numbers to make higher Timer freq. System can hang
47-
#define HW_TIMER_INTERVAL_US 10L
48-
#define HW_TIMER_INTERVAL_FREQ 100000L
51+
#define HW_TIMER_INTERVAL_US 30L
52+
#define HW_TIMER_INTERVAL_FREQ 33333L
4953

5054
volatile uint32_t startMicros = 0;
5155

@@ -80,15 +84,15 @@ uint32_t PWM_Pin[] =
8084
#define NUMBER_ISR_PWMS ( sizeof(PWM_Pin) / sizeof(uint32_t) )
8185

8286
// You can assign any interval for any timer here, in Hz
83-
double PWM_Freq[NUMBER_ISR_PWMS] =
87+
double PWM_Freq[] =
8488
{
8589
1.0f, 2.0f, 3.0f, 5.0f, 10.0f, 20.0f, 30.0f, 50.0f
8690
};
8791

8892
// You can assign any duty-cycle for any PWM channel here, in %
89-
uint32_t PWM_DutyCycle[NUMBER_ISR_PWMS] =
93+
double PWM_DutyCycle[] =
9094
{
91-
5, 10, 20, 25, 30, 35, 40, 45
95+
5.0, 10.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0
9296
};
9397

9498

examples/ISR_Changing_PWM/ISR_Changing_PWM.ino

+13-9
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,18 @@
2222
// Don't define _PWM_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
2323
#define _PWM_LOGLEVEL_ 3
2424

25+
// Default is true, uncomment to false
26+
//#define CHANGING_PWM_END_OF_CYCLE false
27+
28+
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
2529
#include "SAMDUE_Slow_PWM.h"
2630

2731
#define LED_OFF HIGH
2832
#define LED_ON LOW
2933

30-
#ifndef LED_BUILTIN
31-
#define LED_BUILTIN 13
32-
#endif
34+
//#ifndef LED_BUILTIN
35+
// #define LED_BUILTIN 13
36+
//#endif
3337

3438
#ifndef LED_BLUE
3539
#define LED_BLUE 2
@@ -42,8 +46,8 @@
4246
#define USING_HW_TIMER_INTERVAL_MS false //true
4347

4448
// Don't change these numbers to make higher Timer freq. System can hang
45-
#define HW_TIMER_INTERVAL_US 10L
46-
#define HW_TIMER_INTERVAL_FREQ 100000L
49+
#define HW_TIMER_INTERVAL_US 20L
50+
#define HW_TIMER_INTERVAL_FREQ 50000L
4751

4852
volatile uint32_t startMicros = 0;
4953

@@ -72,14 +76,14 @@ double PWM_Freq1 = 1.0f;
7276
double PWM_Freq2 = 2.0f;
7377

7478
// You can assign any interval for any timer here, in microseconds
75-
uint32_t PWM_Period1 = 1000000 / PWM_Freq1;
79+
double PWM_Period1 = 1000000 / PWM_Freq1;
7680
// You can assign any interval for any timer here, in microseconds
77-
uint32_t PWM_Period2 = 1000000 / PWM_Freq2;
81+
double PWM_Period2 = 1000000 / PWM_Freq2;
7882

7983
// You can assign any duty_cycle for any PWM here, from 0-100
80-
uint32_t PWM_DutyCycle1 = 50;
84+
double PWM_DutyCycle1 = 50;
8185
// You can assign any duty_cycle for any PWM here, from 0-100
82-
uint32_t PWM_DutyCycle2 = 90;
86+
double PWM_DutyCycle2 = 90;
8387

8488
// Channel number used to identify associated channel
8589
int channelNum;

examples/ISR_Modify_PWM/ISR_Modify_PWM.ino

+14-10
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,18 @@
2222
// Don't define _PWM_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
2323
#define _PWM_LOGLEVEL_ 3
2424

25+
// Default is true, uncomment to false
26+
//#define CHANGING_PWM_END_OF_CYCLE false
27+
28+
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
2529
#include "SAMDUE_Slow_PWM.h"
2630

2731
#define LED_OFF HIGH
2832
#define LED_ON LOW
2933

30-
#ifndef LED_BUILTIN
31-
#define LED_BUILTIN 13
32-
#endif
34+
//#ifndef LED_BUILTIN
35+
// #define LED_BUILTIN 13
36+
//#endif
3337

3438
#ifndef LED_BLUE
3539
#define LED_BLUE 2
@@ -42,8 +46,8 @@
4246
#define USING_HW_TIMER_INTERVAL_MS false //true
4347

4448
// Don't change these numbers to make higher Timer freq. System can hang
45-
#define HW_TIMER_INTERVAL_US 10L
46-
#define HW_TIMER_INTERVAL_FREQ 100000L
49+
#define HW_TIMER_INTERVAL_US 20L
50+
#define HW_TIMER_INTERVAL_FREQ 50000L
4751

4852
volatile uint32_t startMicros = 0;
4953

@@ -72,14 +76,14 @@ double PWM_Freq1 = 1.0f;
7276
double PWM_Freq2 = 2.0f;
7377

7478
// You can assign any interval for any timer here, in microseconds
75-
uint32_t PWM_Period1 = 1000000 / PWM_Freq1;
79+
double PWM_Period1 = 1000000.0 / PWM_Freq1;
7680
// You can assign any interval for any timer here, in microseconds
77-
uint32_t PWM_Period2 = 1000000 / PWM_Freq2;
81+
double PWM_Period2 = 1000000.0 / PWM_Freq2;
7882

7983
// You can assign any duty_cycle for any PWM here, from 0-100
80-
uint32_t PWM_DutyCycle1 = 10;
84+
double PWM_DutyCycle1 = 10.0;
8185
// You can assign any duty_cycle for any PWM here, from 0-100
82-
uint32_t PWM_DutyCycle2 = 90;
86+
double PWM_DutyCycle2 = 90.0;
8387

8488
// Channel number used to identify associated channel
8589
int channelNum;
@@ -134,7 +138,7 @@ void changePWM()
134138
static uint8_t count = 1;
135139

136140
double PWM_Freq;
137-
uint32_t PWM_DutyCycle;
141+
double PWM_DutyCycle;
138142

139143
if (count++ % 2)
140144
{

0 commit comments

Comments
 (0)