Components and supplies
Arduino Mega 2560
Project description
Code
LEDDimmer.ino
c_cpp
1/* 2 documentation at http://arduino.cc 3 */ 4#include "myLEDS.h" 5 6#define ISR_FREQUENCY 31000L 7const long callFrequency = numberOfLEDS * FADING_RESOLUTION * 55L; // 55 instead of 50 for rounding up the frequency needed 8const long callFraction = ((callFrequency % ISR_FREQUENCY) *10L) / ISR_FREQUENCY; 9ISR(TIMER2_COMPA_vect) { // 30khz 10 static byte counter=0; 11 // ideal callFrequency for LED_ISR() = numberOfLEDS * FADING_RESOLUTION * 50; 12 // this routine maps the 30khz interupts on the required number of calls within a 10% accuracy 13 // For know configurations, this can be made simpler 14 long fraction = callFrequency; 15 while (fraction >= ISR_FREQUENCY) { 16 fraction -= ISR_FREQUENCY; 17 LED_ISR(); // multi calls inside one interrupt is allowed as long is doesn't exceed the number of LEDS 18 } 19 if (counter < callFraction ) // only callFraction times out of 10 true 20 LED_ISR(); 21 if (++counter == 10) 22 counter = 0; 23} 24 25// the setup function runs once when you press reset or power the board 26void setup() { 27 Serial.begin(9600); 28 Serial.println("LED dimmer v1.0"); 29 Serial.print("callFrequency: "); Serial.println(callFrequency); 30 Serial.print("callFraction : "); Serial.println(callFraction); 31 InitializeAllLEDS(); 32 // Timer 2 is used to dimm or fade LEDS independent of what the main loop is doing 33 34 TCCR2B = (TCCR2B & 0xF8) | 0x01; // 31khz, must match with ISR_FREQUENCY 35 TIMSK2 |= _BV(OCIE2A); // Activate the timer interrupt. 36 Serial.println("Serial input commands: +/- for adapting dimmer"); 37} 38 39// the loop function runs over and over again forever 40void loop() { 41 static unsigned long mask=0x66666666; 42 static unsigned long lastMillis = 0; 43 44 processSerialInput(); // handle serial input commands 45 // you can do whatever else you like while the leds are controlled 46 47 // invert all leds once per 2 second 48 if (millis()-lastMillis > 2000) { 49#ifdef DEBUG_LEDS 50 long count = debugCounter; 51 debugCounter=0; 52 Serial.print("Calling Freq: "); // this should be around 50(Hz) 53 count /= 2L*numberOfLEDS * FADING_RESOLUTION; 54 Serial.println(count); 55#endif 56 lastMillis = millis(); 57 ChangeAllLEDS(mask); 58 if (mask & 1) 59 mask = 0x8000000 | (mask>>1); 60 else 61 mask = (mask>>1); 62 } 63} 64 65void processSerialInput() 66{ 67 char c=Serial.read(); 68 switch(c) { 69 case '+': 70 SetDimmer(GetDimmer()+1); 71 Serial.print("Dimmer: "); Serial.println(GetDimmer()); 72 break; 73 case '-': 74 SetDimmer(GetDimmer()-1); 75 Serial.print("Dimmer: "); Serial.println(GetDimmer()); 76 break; 77 case -1: 78 break; 79 default: 80 Serial.println("Not supported; press +/- for adapting dimmer"); 81 break; 82 } 83} 84 85
myLEDS.h
c_cpp
1#ifndef myLEDS_h 2#define myLEDS_h 3 4#include "arduino.h" 5 6// +++++++++++++ SECTION to configure as you prefer +++++++++++++++++++ 7// I/O mapping. Program assumes that pinning of ALL leds are expected to be consecutive in order to be loop over them. 8#define pinLEDSBaseAddr 22 9#define numberOfLEDS 20L // max 32 leds!!! 10 11// Select the prefered resolution of for fading/dimming. Note: Together with the number of LEDs 12// this determines the timer frequency needed); Higher resolutions require more CPU!! 13//#define FADING_RESOLUTION 20L // Requires calling frequency F=1kHZ per LED 14//#define FADING_RESOLUTION 30L // Requires calling frequency F=1,5kHZ per LED 15#define FADING_RESOLUTION 40L // Requires calling frequency F=2kHZ per LED 16 17#define SLOW_FADING //pure what you want, has no influence on CPU load, but determines the number of dimming levels as well 18 19// note: my Arduino mega R3 can handle up to ca 25 leds at 40 dimm stepts and up to 32 leds at 30 dimm steps 20// +++++++++++++ SECTION END +++++++++++++++++++ 21 22// #define DEBUG_LEDS 23#ifdef DEBUG_LEDS 24extern unsigned long debugCounter; 25#endif 26 27// NOTE: max fading period (if dimming is set to 0) = MAX_DIMM_VALUE * 20msec 28#if (FADING_RESOLUTION==40) 29 #ifndef SLOW_FADING 30 #define MAX_DIM_VALUE 9 // 0=NO DIMMING; (you need to change briLUT if you adapt this value) 31 #else 32 #define MAX_DIM_VALUE 14 // select this one for slower dimming (need to change the briLUT as well) 33 #endif 34#elif (FADING_RESOLUTION==30) 35 #ifndef SLOW_FADING 36 #define MAX_DIM_VALUE 8 // 0=NO DIMMING; (you need to change briLUT if you adapt this value) 37 #else 38 #define MAX_DIM_VALUE 13 // select this one for slower dimming (need to change the briLUT as well) 39 #endif 40#else 41 #ifndef SLOW_FADING 42 #define MAX_DIM_VALUE 7 // 0=NO DIMMING; (you need to change briLUT if you adapt this value) 43 #else 44 #define MAX_DIM_VALUE 11 // select this one for slower dimming (need to change the briLUT as well) 45 #endif 46#endif 47 48// LEDS are controlled via an ISR. Just call LED_ISR() in a dedicated or exiting timer routine (e.g the IR remote ISR is running at 20kHZ) 49// The calling frequency F to this routine must be: F = #LEDS * FADING_RESOLUTION * 50 (HZ) 50// You can call LED_ISR() multile times in the ISR as long the number of calls inside the ISR are less then the number of LEDS!!! 51void LED_ISR(); //ISR routine; calling frequency F = #LEDS * FADING_RESOLUTION * 50 (HZ) 52 53void InitializeAllLEDS(); // call once in setup() 54 55int getLED(int number); // get a prepared (uncommited) led value 56 57extern unsigned long _prepLEDS; 58inline void setLED(int number, int value) { // prepare new value for a particular led 59 if (value ) { 60 _prepLEDS |= (1L<<number); 61 } 62 else { 63 _prepLEDS &= ~(1L<<number); 64 } 65} 66 67boolean getNewLED(int number); 68boolean getCurLED(int number); 69boolean getOutput(int number); 70 71void CommitLEDS(); // commit all preprared led changes defined in _prepLEDS 72void ChangeAllLEDS(unsigned long mask); // change and commit all leds in one call 73 74 75void SetDimmer(unsigned int Dimm); // 0..MAX_DIM_VALUE = 0%-95% 76int GetDimmer(); 77 78#endif 79 80 81
myLEDS.cpp
c_cpp
1#include "Arduino.h" 2#include "myLEDS.h" 3 4// NOTE: max fading period (if dimming is set to 0) = MAX_DIMM_VALUE * 20msec 5#if (FADING_RESOLUTION==40) 6 #ifndef SLOW_FADING 7 static byte briLUT[MAX_DIM_VALUE+1] = {0,10,17,23,28,31,33,35,37,38}; // support the logaritmic sensitivity for brightness 8 #else 9 static byte briLUT[MAX_DIM_VALUE+1] = {0,5,10,14,17,20,23,25,27,29,31,33,35,37,38}; // slower fading version 10 #endif 11#elif (FADING_RESOLUTION==30) 12 #ifndef SLOW_FADING 13 static byte briLUT[MAX_DIM_VALUE+1] = {0,8,14,19,23,25,26,27,28}; // support the logaritmic sensitivity for brightness 14 #else 15 static byte briLUT[MAX_DIM_VALUE+1] = {0,4,8,11,14,17,19,21,23,24,25,26,27,28}; // support the logaritmic sensitivity for brightness 16 #endif 17#elif (FADING_RESOLUTION==20) 18 #ifndef SLOW_FADING 19 static byte briLUT[MAX_DIM_VALUE+1] = {0,5,9,12,14,16,17,18}; // support the logaritmic sensitivity for brightness 20 #else 21 static byte briLUT[MAX_DIM_VALUE+1] = {0,3,5,7,9,11,13,14,15,16,17,18}; /// slower fading version 22 #endif 23#else 24 #error select a valid FADING_RESOLUTION 25#endif 26 27#ifdef DEBUG_LEDS 28unsigned long debugCounter=0; 29#endif 30 31static unsigned long _curLEDS=0, //current value for fading 32 _newLEDS=0, //target value for fading 33 _outputLEDS=0; // actual digital output 34unsigned long _prepLEDS=0;//uncommitted new led settings 35 36static byte _LEDFade[numberOfLEDS];// intensity per individual LED 37static byte _dimmLevel=0; // 0 = no dimming 38 39int getLED(int number) {return (_prepLEDS & (1L<<number)) > 0;} 40 41//boolean getNewLED(int number) {return (_newLEDS & (1L<<number)) > 0;} 42//boolean getCurLED(int number) {return (_curLEDS & (1L<<number)) > 0;} 43//boolean getOutput(int number) {return (_outputLEDS & (1L<<number)) > 0;} 44 45 46void InitializeAllLEDS() { 47 _newLEDS = 0; 48 _curLEDS= 0; 49 _prepLEDS = 0; 50 _outputLEDS=0; 51 _dimmLevel = 0; 52 for (int i=0; i<numberOfLEDS; i++) { 53 pinMode(i+pinLEDSBaseAddr, OUTPUT); 54 _LEDFade[i] = MAX_DIM_VALUE+1; // LEDS fully dimmed (off) 55 } 56} 57 58 59 60 61void SetDimmer(unsigned int Dimm) { // input range 0..MAX_DIM_VALUE,; for dimming. 0=full light 62 noInterrupts(); 63 _dimmLevel = constrain(Dimm, 0, MAX_DIM_VALUE); 64 interrupts(); 65 //Serial.print("Dimmer:"); Serial.println(_dimmLevel); 66} 67 68int GetDimmer() { 69 return _dimmLevel; 70} 71 72void LED_ISR() { // hook this routine into a 20kHZ timer (e.g. the IR remote) 73 static byte offset=0; 74 static byte ledNumber=0; 75 boolean newIsOn = ((long)(_newLEDS & (1L<<ledNumber))>0); 76 boolean curIsOn = ((long)(_curLEDS & (1L<<ledNumber))>0); 77 boolean outputHigh = ((long)(_outputLEDS & (1L<<ledNumber))>0); 78 79#ifdef DEBUG_LEDS 80 debugCounter++; // only neded for debugging 81#endif 82 // once per LED loop update fading values ( if new != cur ) 83 if (offset == 0) { 84 if (!newIsOn && curIsOn) { // LED is fading from on to off 85 _LEDFade[ledNumber]++; 86 if (_LEDFade[ledNumber] > MAX_DIM_VALUE ) { // value reached 87 _curLEDS &= ~(1L<<ledNumber); // set current LED is off 88 _LEDFade[ledNumber] = MAX_DIM_VALUE; 89 } 90 } 91 else if (newIsOn && !curIsOn) { // LED is fading from off to on 92 _LEDFade[ledNumber]--; 93 if (_LEDFade[ledNumber]<=_dimmLevel) { // value reached 94 _curLEDS |= (1L<<ledNumber); // set current LED is on 95 _LEDFade[ledNumber] = _dimmLevel; 96 } 97 } 98 else if (newIsOn && curIsOn) { // LED is not fading, just track changes in dimm level 99 if (_LEDFade[ledNumber] > _dimmLevel) 100 _LEDFade[ledNumber]--; 101 else if (_LEDFade[ledNumber] < _dimmLevel) 102 _LEDFade[ledNumber]++; 103 } 104 } 105 106 // some logic to only write differences to the digital outputs (time consuming calls)!! 107 if ( newIsOn || curIsOn ) { // handle normal dimming 108 if (briLUT[_LEDFade[ledNumber]] == offset) { 109 if (!outputHigh) { 110 digitalWrite(ledNumber+pinLEDSBaseAddr, HIGH); 111 _outputLEDS |= (1L<<ledNumber); 112 } 113 } 114 else if (offset == 0 && outputHigh) 115 { 116 digitalWrite(ledNumber+pinLEDSBaseAddr,LOW); 117 _outputLEDS &= ~(1L<<ledNumber); 118 } 119 } 120 else if (outputHigh) { // should be off 121 digitalWrite(ledNumber+pinLEDSBaseAddr,LOW); 122 } 123 124 // simulate a loop for all offsets over all leds 125 ledNumber++; 126 if (ledNumber==numberOfLEDS) { // full cycle over all leds, so next offset 127 ledNumber=0; 128 offset++; 129 if (offset > FADING_RESOLUTION) 130 offset=0; 131 } 132} 133 134void CommitLEDS() { //commit new led settings 135 noInterrupts(); 136 _newLEDS = _prepLEDS; 137 interrupts(); 138} 139 140void ChangeAllLEDS(unsigned long mask) { 141 _prepLEDS = mask; 142 noInterrupts(); 143 _newLEDS = _prepLEDS; 144 interrupts(); 145} 146 147boolean getNewLED(int number) {return (_newLEDS & (1L<<number)) > 0;} 148boolean getCurLED(int number) {return (_curLEDS & (1L<<number)) > 0;} 149boolean getOutput(int number) {return (_outputLEDS & (1L<<number)) > 0;} 150 151 152 153
myLEDS.h
c_cpp
1#ifndef myLEDS_h 2#define myLEDS_h 3 4#include "arduino.h" 5 6// +++++++++++++ SECTION to configure as you prefer +++++++++++++++++++ 7// I/O mapping. Program assumes that pinning of ALL leds are expected to be consecutive in order to be loop over them. 8#define pinLEDSBaseAddr 22 9#define numberOfLEDS 20L // max 32 leds!!! 10 11// Select the prefered resolution of for fading/dimming. Note: Together with the number of LEDs 12// this determines the timer frequency needed); Higher resolutions require more CPU!! 13//#define FADING_RESOLUTION 20L // Requires calling frequency F=1kHZ per LED 14//#define FADING_RESOLUTION 30L // Requires calling frequency F=1,5kHZ per LED 15#define FADING_RESOLUTION 40L // Requires calling frequency F=2kHZ per LED 16 17#define SLOW_FADING //pure what you want, has no influence on CPU load, but determines the number of dimming levels as well 18 19// note: my Arduino mega R3 can handle up to ca 25 leds at 40 dimm stepts and up to 32 leds at 30 dimm steps 20// +++++++++++++ SECTION END +++++++++++++++++++ 21 22// #define DEBUG_LEDS 23#ifdef DEBUG_LEDS 24extern unsigned long debugCounter; 25#endif 26 27// NOTE: max fading period (if dimming is set to 0) = MAX_DIMM_VALUE * 20msec 28#if (FADING_RESOLUTION==40) 29 #ifndef SLOW_FADING 30 #define MAX_DIM_VALUE 9 // 0=NO DIMMING; (you need to change briLUT if you adapt this value) 31 #else 32 #define MAX_DIM_VALUE 14 // select this one for slower dimming (need to change the briLUT as well) 33 #endif 34#elif (FADING_RESOLUTION==30) 35 #ifndef SLOW_FADING 36 #define MAX_DIM_VALUE 8 // 0=NO DIMMING; (you need to change briLUT if you adapt this value) 37 #else 38 #define MAX_DIM_VALUE 13 // select this one for slower dimming (need to change the briLUT as well) 39 #endif 40#else 41 #ifndef SLOW_FADING 42 #define MAX_DIM_VALUE 7 // 0=NO DIMMING; (you need to change briLUT if you adapt this value) 43 #else 44 #define MAX_DIM_VALUE 11 // select this one for slower dimming (need to change the briLUT as well) 45 #endif 46#endif 47 48// LEDS are controlled via an ISR. Just call LED_ISR() in a dedicated or exiting timer routine (e.g the IR remote ISR is running at 20kHZ) 49// The calling frequency F to this routine must be: F = #LEDS * FADING_RESOLUTION * 50 (HZ) 50// You can call LED_ISR() multile times in the ISR as long the number of calls inside the ISR are less then the number of LEDS!!! 51void LED_ISR(); //ISR routine; calling frequency F = #LEDS * FADING_RESOLUTION * 50 (HZ) 52 53void InitializeAllLEDS(); // call once in setup() 54 55int getLED(int number); // get a prepared (uncommited) led value 56 57extern unsigned long _prepLEDS; 58inline void setLED(int number, int value) { // prepare new value for a particular led 59 if (value ) { 60 _prepLEDS |= (1L<<number); 61 } 62 else { 63 _prepLEDS &= ~(1L<<number); 64 } 65} 66 67boolean getNewLED(int number); 68boolean getCurLED(int number); 69boolean getOutput(int number); 70 71void CommitLEDS(); // commit all preprared led changes defined in _prepLEDS 72void ChangeAllLEDS(unsigned long mask); // change and commit all leds in one call 73 74 75void SetDimmer(unsigned int Dimm); // 0..MAX_DIM_VALUE = 0%-95% 76int GetDimmer(); 77 78#endif 79 80 81
myLEDS.cpp
c_cpp
1#include "Arduino.h" 2#include "myLEDS.h" 3 4// NOTE: max fading 5 period (if dimming is set to 0) = MAX_DIMM_VALUE * 20msec 6#if (FADING_RESOLUTION==40) 7 8 #ifndef SLOW_FADING 9 static byte briLUT[MAX_DIM_VALUE+1] = {0,10,17,23,28,31,33,35,37,38}; 10 // support the logaritmic sensitivity for brightness 11 #else 12 static byte 13 briLUT[MAX_DIM_VALUE+1] = {0,5,10,14,17,20,23,25,27,29,31,33,35,37,38}; // slower 14 fading version 15 #endif 16#elif (FADING_RESOLUTION==30) 17 #ifndef SLOW_FADING 18 19 static byte briLUT[MAX_DIM_VALUE+1] = {0,8,14,19,23,25,26,27,28}; // support 20 the logaritmic sensitivity for brightness 21 #else 22 static byte briLUT[MAX_DIM_VALUE+1] 23 = {0,4,8,11,14,17,19,21,23,24,25,26,27,28}; // support the logaritmic sensitivity 24 for brightness 25 #endif 26#elif (FADING_RESOLUTION==20) 27 #ifndef SLOW_FADING 28 29 static byte briLUT[MAX_DIM_VALUE+1] = {0,5,9,12,14,16,17,18}; // support the 30 logaritmic sensitivity for brightness 31 #else 32 static byte briLUT[MAX_DIM_VALUE+1] 33 = {0,3,5,7,9,11,13,14,15,16,17,18}; /// slower fading version 34 #endif 35#else 36 37 #error select a valid FADING_RESOLUTION 38#endif 39 40#ifdef DEBUG_LEDS 41unsigned 42 long debugCounter=0; 43#endif 44 45static unsigned long _curLEDS=0, //current 46 value for fading 47 _newLEDS=0, //target value for fading 48 49 _outputLEDS=0; // actual digital output 50unsigned long _prepLEDS=0;//uncommitted 51 new led settings 52 53static byte _LEDFade[numberOfLEDS];// intensity per individual 54 LED 55static byte _dimmLevel=0; // 0 = no dimming 56 57int getLED(int number) 58 {return (_prepLEDS & (1L<<number)) > 0;} 59 60//boolean getNewLED(int number) 61 {return (_newLEDS & (1L<<number)) > 0;} 62//boolean getCurLED(int number) {return 63 (_curLEDS & (1L<<number)) > 0;} 64//boolean getOutput(int number) {return (_outputLEDS 65 & (1L<<number)) > 0;} 66 67 68void InitializeAllLEDS() { 69 _newLEDS = 0; 70 71 _curLEDS= 0; 72 _prepLEDS = 0; 73 _outputLEDS=0; 74 _dimmLevel = 0; 75 76 for (int i=0; i<numberOfLEDS; i++) { 77 pinMode(i+pinLEDSBaseAddr, OUTPUT); 78 79 _LEDFade[i] = MAX_DIM_VALUE+1; // LEDS fully dimmed (off) 80 } 81} 82 83 84 85 86void 87 SetDimmer(unsigned int Dimm) { // input range 0..MAX_DIM_VALUE,; for dimming. 0=full 88 light 89 noInterrupts(); 90 _dimmLevel = constrain(Dimm, 0, MAX_DIM_VALUE); 91 92 interrupts(); 93 //Serial.print("Dimmer:"); Serial.println(_dimmLevel); 94} 95 96int 97 GetDimmer() { 98 return _dimmLevel; 99} 100 101void LED_ISR() { // hook this 102 routine into a 20kHZ timer (e.g. the IR remote) 103 static byte offset=0; 104 105 static byte ledNumber=0; 106 boolean newIsOn = ((long)(_newLEDS & (1L<<ledNumber))>0); 107 108 boolean curIsOn = ((long)(_curLEDS & (1L<<ledNumber))>0); 109 boolean outputHigh 110 = ((long)(_outputLEDS & (1L<<ledNumber))>0); 111 112#ifdef DEBUG_LEDS 113 debugCounter++; 114 // only neded for debugging 115#endif 116 // once per LED loop update fading 117 values ( if new != cur ) 118 if (offset == 0) { 119 if (!newIsOn && 120 curIsOn) { // LED is fading from on to off 121 _LEDFade[ledNumber]++; 122 123 if (_LEDFade[ledNumber] > MAX_DIM_VALUE ) { // value reached 124 _curLEDS 125 &= ~(1L<<ledNumber); // set current LED is off 126 _LEDFade[ledNumber] 127 = MAX_DIM_VALUE; 128 } 129 } 130 else if (newIsOn && !curIsOn) { 131 // LED is fading from off to on 132 _LEDFade[ledNumber]--; 133 if 134 (_LEDFade[ledNumber]<=_dimmLevel) { // value reached 135 _curLEDS |= (1L<<ledNumber); 136 // set current LED is on 137 _LEDFade[ledNumber] = _dimmLevel; 138 } 139 140 } 141 else if (newIsOn && curIsOn) { // LED is not fading, just track 142 changes in dimm level 143 if (_LEDFade[ledNumber] > _dimmLevel) 144 _LEDFade[ledNumber]--; 145 146 else if (_LEDFade[ledNumber] < _dimmLevel) 147 _LEDFade[ledNumber]++; 148 149 } 150 } 151 152 // some logic to only write differences to the digital 153 outputs (time consuming calls)!! 154 if ( newIsOn || curIsOn ) { // handle 155 normal dimming 156 if (briLUT[_LEDFade[ledNumber]] == offset) { 157 if 158 (!outputHigh) { 159 digitalWrite(ledNumber+pinLEDSBaseAddr, HIGH); 160 161 _outputLEDS |= (1L<<ledNumber); 162 } 163 } 164 else 165 if (offset == 0 && outputHigh) 166 { 167 digitalWrite(ledNumber+pinLEDSBaseAddr,LOW); 168 169 _outputLEDS &= ~(1L<<ledNumber); 170 } 171 } 172 else if (outputHigh) 173 { // should be off 174 digitalWrite(ledNumber+pinLEDSBaseAddr,LOW); 175 } 176 177 178 // simulate a loop for all offsets over all leds 179 ledNumber++; 180 if 181 (ledNumber==numberOfLEDS) { // full cycle over all leds, so next offset 182 ledNumber=0; 183 184 offset++; 185 if (offset > FADING_RESOLUTION) 186 offset=0; 187 188 } 189} 190 191void CommitLEDS() { //commit new led settings 192 noInterrupts(); 193 194 _newLEDS = _prepLEDS; 195 interrupts(); 196} 197 198void ChangeAllLEDS(unsigned 199 long mask) { 200 _prepLEDS = mask; 201 noInterrupts(); 202 _newLEDS = _prepLEDS; 203 204 interrupts(); 205} 206 207boolean getNewLED(int number) {return (_newLEDS & (1L<<number)) 208 > 0;} 209boolean getCurLED(int number) {return (_curLEDS & (1L<<number)) > 0;} 210boolean 211 getOutput(int number) {return (_outputLEDS & (1L<<number)) > 0;} 212 213 214 215
Comments
Only logged in users can leave comments
erkr
0 Followers
•0 Projects
Table of contents
Intro
2
0