AskSin++
PWM.h
1 //- -----------------------------------------------------------------------------------------------------------------------
2 // AskSin++
3 // 2018-08-10 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
4 //- -----------------------------------------------------------------------------------------------------------------------
5 
6 #ifndef __PWM_H__
7 #define __PWM_H__
8 
9 
10 #include <Arduino.h>
11 #include "PhaseCut.h"
12 
13 
14 
15 
16 namespace as {
17 
18 #if ARDUINO_ARCH_AVR
19 // we use this table for the dimmer levels
20 static const uint8_t pwmtable[32] PROGMEM = {
21  1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 10, 11, 13, 16, 19, 23,
22  27, 32, 38, 45, 54, 64, 76, 91, 108, 128, 152, 181, 215, 255
23 };
24 static const uint8_t zctable[45] PROGMEM = {
25  11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26  26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
27  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 58, 75
28 };
29 template<uint8_t STEPS=200, bool LINEAR=false, bool INVERSE=false,class PINTYPE=ArduinoPins>
30 class PWM8 {
31  uint8_t pin;
32 public:
33  PWM8 () : pin(0) {}
34  ~PWM8 () {}
35 
36  void init(uint8_t p) {
37  pin = p;
38  PINTYPE::setPWM(pin);
39  }
40  void set(uint8_t value) {
41  uint8_t pwm = 0;
42  if(LINEAR) {
43  if(INVERSE) {
44  pwm = map(value, 0, STEPS, 255, 0); // https://www.arduino.cc/reference/en/language/functions/math/map/
45  } else {
46  pwm = map(value, 0, STEPS, 0, 255);
47  }
48  } else {
49  if( value > 0 ) {
50  uint8_t offset = value*31/STEPS;
51  pwm = pgm_read_word (& pwmtable[offset]);
52  }
53  }
54  PINTYPE::setPWM(pin,pwm);
55  }
56 };
57 template<uint8_t STEPS=200>
58 class ZC_Control {
59  uint8_t outpin;
60  public:
61  ZC_Control () : outpin(0) {}
62  ~ZC_Control () {}
63 
64  void init(uint8_t p) {
65  outpin = p;
66  phaseCut.init(outpin);
67  phaseCut.Start();
68  }
69  void set(double value){
70  uint8_t pwm = 0;
71  if ( value > 0 ) {
72  if (!phaseCut.isrunning()){
73  phaseCut.Start();
74  }
75  #if PHASECUTMODE == 1
76  uint8_t offset = (STEPS - value)*44/STEPS;
77  #else
78  uint8_t offset = value*44/STEPS;
79  #endif
80  pwm = pgm_read_word (& zctable[offset]);
81  phaseCut.SetDimValue(pwm);
82  }
83  else{
84  phaseCut.Stop();
85  }
86  }
87 };
88 #endif
89 
90 #ifdef ARDUINO_ARCH_STM32F1
91 
92 template<uint8_t STEPS=200,uint16_t FREQU=65535,class PINTYPE=ArduinoPins>
93 class PWM16 {
94  float R;
95  uint8_t pin;
96 public:
97  PWM16 () : pin(0) {
98  R = (STEPS * log10(2))/(log10(FREQU));
99  }
100  ~PWM16 () {}
101 
102  void init(uint8_t p) {
103  pin = p;
104  PINTYPE::setPWM(pin);
105  set(0);
106  }
107 
108  void set(uint8_t value) {
109  uint16_t duty = 0;
110  if ( value == STEPS) {
111  duty = FREQU;
112  }
113  else if (value > 0) {
114  // https://diarmuid.ie/blog/pwm-exponential-led-fading-on-arduino-or-other-platforms/
115  // duty = pow(2,(value/R)) + 4;
116  // duty = pow(2,(value/20.9)+6.5);
117  // duty = pow(1.37,(value/15.0)+22.0)-500;
118  duty = pow(1.28,(value/13.0)+29.65)-1300;
119  // http://harald.studiokubota.com/wordpress/index.php/2010/09/05/linear-led-fading/index.html
120  //duty = exp(value/18.0) + 4;
121  }
122  // DDEC(pin);DPRINT(" - ");DDECLN(duty);
123  PINTYPE::setPWM(pin,duty);
124  }
125 };
126 
127 #endif
128 
129 };
130 
131 #endif
as::PWM8
Definition: PWM.h:30
as::PWM16
Definition: PWM.h:93
as::ZC_Control
Definition: PWM.h:58