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

Commit

Permalink
v1.2.0 to fix multiple-definitions linker error
Browse files Browse the repository at this point in the history
### Releases v1.2.0

1. Fix `multiple-definitions` linker error. Drop `src_cpp` and `src_h` directories
2. Add example [multiFileProject](examples/multiFileProject) to demo for multiple-file project
3. Improve accuracy by using `double`, instead of `uint32_t` for `dutycycle`, `period`
4. Optimize library code by using `reference-passing` instead of `value-passing`
5. Update examples accordingly
  • Loading branch information
khoih-prog authored Jan 30, 2022
1 parent ccb1ac7 commit b7dcbd4
Show file tree
Hide file tree
Showing 20 changed files with 2,147 additions and 1,927 deletions.
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ If you don't find anything, please [open a new issue](https://github.com/khoih-p

Please ensure to specify the following:

* Arduino IDE version (e.g. 1.8.16) or Platform.io version
* Arduino IDE version (e.g. 1.8.19) or Platform.io version
* Arduino / Adafruit / Sparkfun `AVR` Core Version (e.g. Arduino AVR core v1.8.3)
* Contextual information (e.g. what you were trying to achieve)
* Simplest possible steps to reproduce
Expand All @@ -26,10 +26,10 @@ Please ensure to specify the following:
### Example

```
Arduino IDE version: 1.8.16
Arduino IDE version: 1.8.19
Arduino AVR core v1.8.3
OS: Ubuntu 20.04 LTS
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
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
Context:
I encountered a crash while trying to use the Timer Interrupt.
Expand Down
203 changes: 111 additions & 92 deletions README.md

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
## Table of Contents

* [Changelog](#changelog)
* [Releases v1.2.0](#releases-v120)
* [Releases v1.1.0](#releases-v110)
* [Initial Releases v1.0.0](#Initial-Releases-v100)

Expand All @@ -20,6 +21,14 @@

## Changelog

### Releases v1.2.0

1. Fix `multiple-definitions` linker error. Drop `src_cpp` and `src_h` directories
2. Add example [multiFileProject](examples/multiFileProject) to demo for multiple-file project
3. Improve accuracy by using `double`, instead of `uint32_t` for `dutycycle`, `period`
4. Optimize library code by using `reference-passing` instead of `value-passing`
5. Update examples accordingly

### Releases v1.1.0

1. Add functions to modify PWM settings on-the-fly
Expand Down
9 changes: 5 additions & 4 deletions examples/ISR_8_PWMs_Array/ISR_8_PWMs_Array.ino
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#define USING_MICROS_RESOLUTION true //false

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "AVR_Slow_PWM.h"

#include <SimpleTimer.h> // https://github.com/jfturcot/SimpleTimer
Expand Down Expand Up @@ -97,15 +98,15 @@ uint32_t PWM_Pin[] =
#define NUMBER_ISR_PWMS ( sizeof(PWM_Pin) / sizeof(uint32_t) )

// You can assign any interval for any timer here, in Hz
double PWM_Freq[NUMBER_ISR_PWMS] =
double PWM_Freq[] =
{
1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f,
};

// You can assign any interval for any timer here, in Microseconds
uint32_t PWM_DutyCycle[NUMBER_ISR_PWMS] =
double PWM_DutyCycle[] =
{
5, 10, 20, 25, 30, 35, 40, 45
5.0, 10.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0
};

typedef void (*irqCallback) ();
Expand Down Expand Up @@ -147,7 +148,7 @@ void doingSomething7()
}


irqCallback irqCallbackStartFunc[NUMBER_ISR_PWMS] =
irqCallback irqCallbackStartFunc[] =
{
doingSomething0, doingSomething1, doingSomething2, doingSomething3,
doingSomething4, doingSomething5, doingSomething6, doingSomething7
Expand Down
51 changes: 26 additions & 25 deletions examples/ISR_8_PWMs_Array_Complex/ISR_8_PWMs_Array_Complex.ino
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#define USING_MICROS_RESOLUTION true //false

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "AVR_Slow_PWM.h"

#include <SimpleTimer.h> // https://github.com/jfturcot/SimpleTimer
Expand Down Expand Up @@ -110,9 +111,9 @@ typedef struct
irqCallback irqCallbackStartFunc;
irqCallback irqCallbackStopFunc;

uint32_t PWM_Freq;
double PWM_Freq;

uint32_t PWM_DutyCycle;
double PWM_DutyCycle;

uint32_t deltaMicrosStart;
uint32_t previousMicrosStart;
Expand All @@ -132,29 +133,29 @@ void doingSomethingStop(int index);

#else // #if USE_COMPLEX_STRUCT

volatile unsigned long deltaMicrosStart [NUMBER_ISR_PWMS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
volatile unsigned long previousMicrosStart [NUMBER_ISR_PWMS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
volatile unsigned long deltaMicrosStart [] = { 0, 0, 0, 0, 0, 0, 0, 0 };
volatile unsigned long previousMicrosStart [] = { 0, 0, 0, 0, 0, 0, 0, 0 };

volatile unsigned long deltaMicrosStop [NUMBER_ISR_PWMS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
volatile unsigned long previousMicrosStop [NUMBER_ISR_PWMS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
volatile unsigned long deltaMicrosStop [] = { 0, 0, 0, 0, 0, 0, 0, 0 };
volatile unsigned long previousMicrosStop [] = { 0, 0, 0, 0, 0, 0, 0, 0 };


// You can assign any interval for any timer here, in Microseconds
uint32_t PWM_Period[NUMBER_ISR_PWMS] =
double PWM_Period[] =
{
1000L, 500L, 333L, 250L, 200L, 166L, 142L, 125L
1000.0, 500.0, 333.333, 250.0, 200.0, 166.667, 142.857, 125.0
};

// You can assign any interval for any timer here, in Hz
double PWM_Freq[NUMBER_ISR_PWMS] =
double PWM_Freq[] =
{
1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f,
};

// You can assign any interval for any timer here, in Microseconds
uint32_t PWM_DutyCycle[NUMBER_ISR_PWMS] =
double PWM_DutyCycle[] =
{
5, 10, 20, 25, 30, 35, 40, 45
5.0, 10.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0
};

void doingSomethingStart(int index)
Expand Down Expand Up @@ -268,17 +269,17 @@ void doingSomethingStop7()

#if USE_COMPLEX_STRUCT

ISR_PWM_Data curISR_PWM_Data[NUMBER_ISR_PWMS] =
ISR_PWM_Data curISR_PWM_Data[] =
{
// pin, irqCallbackStartFunc, irqCallbackStopFunc, PWM_Freq, PWM_DutyCycle, deltaMicrosStart, previousMicrosStart, deltaMicrosStop, previousMicrosStop
{ LED_BUILTIN, doingSomethingStart0, doingSomethingStop0, 1, 5, 0, 0, 0, 0 },
{ PIN_D0, doingSomethingStart1, doingSomethingStop1, 2, 10, 0, 0, 0, 0 },
{ PIN_D1, doingSomethingStart2, doingSomethingStop2, 3, 20, 0, 0, 0, 0 },
{ PIN_D2, doingSomethingStart3, doingSomethingStop3, 4, 25, 0, 0, 0, 0 },
{ PIN_D3, doingSomethingStart4, doingSomethingStop4, 5, 30, 0, 0, 0, 0 },
{ PIN_D4, doingSomethingStart5, doingSomethingStop5, 6, 35, 0, 0, 0, 0 },
{ PIN_D5, doingSomethingStart6, doingSomethingStop6, 7, 40, 0, 0, 0, 0 },
{ PIN_D6, doingSomethingStart7, doingSomethingStop7, 8, 45, 0, 0, 0, 0 },
{ LED_BUILTIN, doingSomethingStart0, doingSomethingStop0, 1.0, 5.0, 0, 0, 0, 0 },
{ PIN_D0, doingSomethingStart1, doingSomethingStop1, 2.0, 10.0, 0, 0, 0, 0 },
{ PIN_D1, doingSomethingStart2, doingSomethingStop2, 3.0, 20.0, 0, 0, 0, 0 },
{ PIN_D2, doingSomethingStart3, doingSomethingStop3, 4.0, 25.0, 0, 0, 0, 0 },
{ PIN_D3, doingSomethingStart4, doingSomethingStop4, 5.0, 30.0, 0, 0, 0, 0 },
{ PIN_D4, doingSomethingStart5, doingSomethingStop5, 6.0, 35.0, 0, 0, 0, 0 },
{ PIN_D5, doingSomethingStart6, doingSomethingStop6, 7.0, 40.0, 0, 0, 0, 0 },
{ PIN_D6, doingSomethingStart7, doingSomethingStop7, 8.0, 45.0, 0, 0, 0, 0 },
};


Expand All @@ -302,13 +303,13 @@ void doingSomethingStop(int index)

#else // #if USE_COMPLEX_STRUCT

irqCallback irqCallbackStartFunc[NUMBER_ISR_PWMS] =
irqCallback irqCallbackStartFunc[] =
{
doingSomethingStart0, doingSomethingStart1, doingSomethingStart2, doingSomethingStart3,
doingSomethingStart4, doingSomethingStart5, doingSomethingStart6, doingSomethingStart7
};

irqCallback irqCallbackStopFunc[NUMBER_ISR_PWMS] =
irqCallback irqCallbackStopFunc[] =
{
doingSomethingStop0, doingSomethingStop1, doingSomethingStop2, doingSomethingStop3,
doingSomethingStop4, doingSomethingStop5, doingSomethingStop6, doingSomethingStop7
Expand Down Expand Up @@ -343,9 +344,9 @@ void simpleTimerDoingSomething2s()
Serial.print(F("PWM Channel : ")); Serial.print(i);
Serial.print(F(", prog Period (ms): "));

Serial.print(1000.f / curISR_PWM_Data[i].PWM_Freq);
Serial.print(1000.0f / curISR_PWM_Data[i].PWM_Freq);

Serial.print(F(", actual : ")); Serial.print((uint32_t) curISR_PWM_Data[i].deltaMicrosStart);
Serial.print(F(", actual (uS) : ")); Serial.print(curISR_PWM_Data[i].deltaMicrosStart);

Serial.print(F(", prog DutyCycle : "));

Expand All @@ -359,7 +360,7 @@ void simpleTimerDoingSomething2s()

Serial.print(F("PWM Channel : ")); Serial.print(i);

Serial.print(1000 / PWM_Freq[i]);
Serial.print(1000.0f / PWM_Freq[i]);

Serial.print(F(", prog. Period (us): ")); Serial.print(PWM_Period[i]);
Serial.print(F(", actual : ")); Serial.print(deltaMicrosStart[i]);
Expand Down
7 changes: 4 additions & 3 deletions examples/ISR_8_PWMs_Array_Simple/ISR_8_PWMs_Array_Simple.ino
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#define USING_MICROS_RESOLUTION true //false

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "AVR_Slow_PWM.h"

#include <SimpleTimer.h> // https://github.com/jfturcot/SimpleTimer
Expand Down Expand Up @@ -97,15 +98,15 @@ uint32_t PWM_Pin[] =
#define NUMBER_ISR_PWMS ( sizeof(PWM_Pin) / sizeof(uint32_t) )

// You can assign any interval for any timer here, in Hz
double PWM_Freq[NUMBER_ISR_PWMS] =
double PWM_Freq[] =
{
1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f,
};

// You can assign any interval for any timer here, in Microseconds
uint32_t PWM_DutyCycle[NUMBER_ISR_PWMS] =
double PWM_DutyCycle[] =
{
5, 10, 20, 25, 30, 35, 40, 45
5.0, 10.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0
};

////////////////////////////////////////////////
Expand Down
13 changes: 7 additions & 6 deletions examples/ISR_Changing_PWM/ISR_Changing_PWM.ino
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#define USING_MICROS_RESOLUTION true //false

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "AVR_Slow_PWM.h"

#define LED_OFF HIGH
Expand Down Expand Up @@ -87,14 +88,14 @@ double PWM_Freq1 = 1.0f;
double PWM_Freq2 = 2.0f;

// You can assign any interval for any timer here, in microseconds
uint32_t PWM_Period1 = 1000000 / PWM_Freq1;
double PWM_Period1 = 1000000.0 / PWM_Freq1;
// You can assign any interval for any timer here, in microseconds
uint32_t PWM_Period2 = 1000000 / PWM_Freq2;
double PWM_Period2 = 1000000.0 / PWM_Freq2;

// You can assign any duty_cycle for any PWM here, from 0-100
uint32_t PWM_DutyCycle1 = 50;
double PWM_DutyCycle1 = 50.0;
// You can assign any duty_cycle for any PWM here, from 0-100
uint32_t PWM_DutyCycle2 = 90;
double PWM_DutyCycle2 = 90.0;

// Channel number used to identify associated channel
int channelNum;
Expand Down Expand Up @@ -191,7 +192,7 @@ void loop()
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period1, PWM_DutyCycle1);
#else
// Or using period in millisecs resolution
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period1 / 1000, PWM_DutyCycle1);
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period1 / 1000.0, PWM_DutyCycle1);
#endif
#endif

Expand All @@ -212,7 +213,7 @@ void loop()
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period2, PWM_DutyCycle2);
#else
// Or using period in millisecs resolution
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period2 / 1000, PWM_DutyCycle2);
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period2 / 1000.0, PWM_DutyCycle2);
#endif
#endif

Expand Down
11 changes: 6 additions & 5 deletions examples/ISR_Modify_PWM/ISR_Modify_PWM.ino
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#define USING_MICROS_RESOLUTION true //false

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "AVR_Slow_PWM.h"

#define LED_OFF HIGH
Expand Down Expand Up @@ -87,14 +88,14 @@ double PWM_Freq1 = 1.0f;
double PWM_Freq2 = 2.0f;

// You can assign any interval for any timer here, in microseconds
uint32_t PWM_Period1 = 1000000 / PWM_Freq1;
double PWM_Period1 = 1000000.0 / PWM_Freq1;
// You can assign any interval for any timer here, in microseconds
uint32_t PWM_Period2 = 1000000 / PWM_Freq2;
double PWM_Period2 = 1000000.0 / PWM_Freq2;

// You can assign any duty_cycle for any PWM here, from 0-100
uint32_t PWM_DutyCycle1 = 10;
double PWM_DutyCycle1 = 10.0;
// You can assign any duty_cycle for any PWM here, from 0-100
uint32_t PWM_DutyCycle2 = 90;
double PWM_DutyCycle2 = 90.0;

// Channel number used to identify associated channel
int channelNum;
Expand Down Expand Up @@ -192,7 +193,7 @@ void setup()
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period1, PWM_DutyCycle1);
#else
// Or using period in millisecs resolution
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period1 / 1000, PWM_DutyCycle1);
channelNum = ISR_PWM.setPWM_Period(PWM_Pin, PWM_Period1 / 1000.0, PWM_DutyCycle1);
#endif
#endif
}
Expand Down
13 changes: 13 additions & 0 deletions examples/multiFileProject/multiFileProject.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/****************************************************************************************************************************
multiFileProject.cpp
For AVR-based boards (UNO, Nano, Mega, 32U4, 16U4, etc. )
Written by Khoi Hoang
Built by Khoi Hoang https://github.com/khoih-prog/AVR_Slow_PWM
Licensed under MIT license
*****************************************************************************************************************************/

// To demo how to include files in multi-file Projects

#include "multiFileProject.h"
18 changes: 18 additions & 0 deletions examples/multiFileProject/multiFileProject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/****************************************************************************************************************************
multiFileProject.h
For AVR-based boards (UNO, Nano, Mega, 32U4, 16U4, etc. )
Written by Khoi Hoang
Built by Khoi Hoang https://github.com/khoih-prog/AVR_Slow_PWM
Licensed under MIT license
*****************************************************************************************************************************/

// To demo how to include files in multi-file Projects

#pragma once

#define USING_MICROS_RESOLUTION true //false

// Can be included as many times as necessary, without `Multiple Definitions` Linker Error
#include "AVR_Slow_PWM.hpp"
54 changes: 54 additions & 0 deletions examples/multiFileProject/multiFileProject.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/****************************************************************************************************************************
multiFileProject.ino
For AVR-based boards (UNO, Nano, Mega, 32U4, 16U4, etc. )
Written by Khoi Hoang
Built by Khoi Hoang https://github.com/khoih-prog/AVR_Slow_PWM
Licensed under MIT license
*****************************************************************************************************************************/

// To demo how to include files in multi-file Projects

#if ( defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || \
defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) || defined(ARDUINO_AVR_MINI) || defined(ARDUINO_AVR_ETHERNET) || \
defined(ARDUINO_AVR_FIO) || defined(ARDUINO_AVR_BT) || defined(ARDUINO_AVR_LILYPAD) || defined(ARDUINO_AVR_PRO) || \
defined(ARDUINO_AVR_NG) || defined(ARDUINO_AVR_UNO_WIFI_DEV_ED) || defined(ARDUINO_AVR_DUEMILANOVE) || defined(ARDUINO_AVR_FEATHER328P) || \
defined(ARDUINO_AVR_METRO) || defined(ARDUINO_AVR_PROTRINKET5) || defined(ARDUINO_AVR_PROTRINKET3) || defined(ARDUINO_AVR_PROTRINKET5FTDI) || \
defined(ARDUINO_AVR_PROTRINKET3FTDI) )
#define USE_TIMER_1 true
#warning Using Timer1
#else
#define USE_TIMER_3 true
#warning Using Timer3
#endif

#define AVR_SLOW_PWM_VERSION_MIN_TARGET F("AVR_Slow_PWM v1.2.0")
#define AVR_SLOW_PWM_VERSION_MIN 1002000

#include "multiFileProject.h"

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "AVR_Slow_PWM.h"

void setup()
{
Serial.begin(115200);
while (!Serial);

Serial.println("\nStart multiFileProject");
Serial.println(AVR_SLOW_PWM_VERSION);

#if defined(AVR_SLOW_PWM_VERSION_MIN)
if (AVR_SLOW_PWM_VERSION_INT < AVR_SLOW_PWM_VERSION_MIN)
{
Serial.print("Warning. Must use this example on Version equal or later than : ");
Serial.println(AVR_SLOW_PWM_VERSION_MIN_TARGET);
}
#endif
}

void loop()
{
// put your main code here, to run repeatedly:
}
Loading

0 comments on commit b7dcbd4

Please sign in to comment.