Advertisement
Guest User

RGB Cross Fade (non-blocking)

a guest
Jan 2nd, 2023
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.16 KB | None | 0 0
  1. /*
  2. Gamma correction curtesy of https://learn.adafruit.com/led-tricks-gamma-correction?view=all
  3.  
  4. */
  5.  
  6. extern const uint8_t gamma8[];
  7.  
  8. // Comment out the line below for production
  9. // (serial monitoring affects timings)
  10. //#define DEBUG_MODE
  11.  
  12. bool isCommonAnode = true; // Set to false for common cathode
  13.  
  14. int pinsRGB[3] = { 9, 10, 11 };
  15.  
  16. int delayBeforeStartupMS = 3000;
  17. int powerUpFadeTimeMS = 5000;
  18. int delayBeforeWarpMS = 6000;
  19. int goToWarpFadeTimeMS = 3000;
  20.  
  21. bool waitForStartup = true;
  22. bool startupSeq = false;
  23. bool waitForWarp = false;
  24. bool gotoWarp = false;
  25. bool startLoop = false;
  26.  
  27. // Colour arrays
  28. int black[3] = { 0, 0, 0 };
  29. int white[3] = { 255, 255, 255 };
  30. int dimWhite[3] = { 76, 76, 76 };
  31. int red[3] = { 255, 0, 0 };
  32. int green[3] = { 0, 255, 0 };
  33. int blue[3] = { 0, 0, 255 };
  34.  
  35. // Amber/copper colour choices
  36. int orange[3] = { 255, 69, 0 };
  37. int orange2[3] = { 255, 102, 0 }; //#FF6600 rgb(255, 102, 0) rgb(100%, 40%, 0%)
  38. int orange3[3] = { 255, 128, 0 }; //#FF8000 rgb(255, 128, 0) rgb(100%, 50%, 0%)
  39. int orange4[3] = { 255, 153, 0 }; // 255, 153, 0;
  40. int orangeCrush[3] = { 248, 117, 49}; //#F87531 rgb(248, 117, 49) rgb(97%, 46%, 19%)
  41. int cadmiumOrange[3]= { 255, 97, 3 }; //#FF6103 rgb(255, 97, 3) rgb(100%, 38%, 1%)
  42. int darkOrange[3] = { 255, 140, 0 }; //#FF8C00 (255, 140, 0)
  43. int darkOrange5[3] = { 255, 134, 0 }; //#FF8600 rgb(255, 134, 0) rgb(100%, 53%, 0%)
  44. int cadmiumYellow[3]= { 255, 153, 18 }; //#FF9912 rgb(255, 153, 18) rgb(100%, 60%, 7%)
  45. int copper[3] = {84, 36, 10};
  46. int goldish[3] = {247, 216, 131};
  47. int cyan[3] = {44, 126, 166};
  48.  
  49. // Blue colour choices
  50. int royalBlue[3] = { 65, 105, 225 }; //#4169E1 (65, 105, 225)
  51. int dodgerBlue[3] = { 30, 144, 255 }; //#1E90FF (30, 144, 255)
  52. int mediumBlue[3] = { 0, 0, 205 }; //#0000CD (0, 0, 205)
  53. int mediumBlue2[3] = { 0, 0, 195};
  54. int mediumBlue3[3] = { 0, 0, 165};
  55.  
  56. // Set initial colour values
  57. int valsRGB[3] = { black[0], black[1], black[2] };
  58.  
  59. // Initialize colour variables
  60. int prevVals[3] = { valsRGB[0], valsRGB[1], valsRGB[2] };
  61.  
  62. int delayRGB[3] = { 0, 0, 0 };
  63.  
  64. // R/G/B PWM step values
  65. int stepsRGB[3] = { 0, 0, 0 };
  66.  
  67. bool fadingRGB[3] = { false, false, false }; // fade state
  68.  
  69. int fadeDirRGB[3] = { 1, 1, 1 }; // "1" for fade up; "-1" for fade down
  70.  
  71.  
  72. void setup() {
  73.  
  74. #ifdef DEBUG_MODE
  75. Serial.begin(115200);
  76.  
  77. Serial.println("DEBUG_MODE ON");
  78. Serial.println("=============");
  79. #endif
  80.  
  81. for (int i = 0; i<3; i++) {
  82. pinMode(pinsRGB[i], OUTPUT); // sets the pins as output
  83. writeLED(pinsRGB[i], valsRGB[i]); // sets initial PWM value
  84. }
  85.  
  86. }
  87.  
  88. void loop() {
  89.  
  90. static unsigned long startTimeRGBms[3]= { millis(), millis(), millis() };
  91.  
  92. unsigned long currentTimeMS = millis();
  93. static unsigned long timeStampMS = millis();
  94.  
  95.  
  96.  
  97. #ifdef DEBUG_MODE
  98. Serial.print("currentTimeMS = ");
  99. Serial.print(currentTimeMS);
  100.  
  101. for (int i=0; i<3; i++) {
  102. Serial.print(", startTimeRGBms[");
  103. Serial.print(i);
  104. Serial.print("] = ");
  105. Serial.print(startTimeRGBms[i]);
  106. }
  107. Serial.println("");
  108. #endif
  109.  
  110. // 1. Initial power-up -> dish and impulse crystal fade up to an orange/copper colour
  111. // ==================================================================================
  112. if ( (currentTimeMS >= delayBeforeStartupMS) && (waitForStartup == true) ) {
  113. waitForStartup = false;
  114. startupSeq = true;
  115. startLoop = true; // set boolean for first time thru loop
  116. }
  117.  
  118. if ( startupSeq == true ) {
  119.  
  120. if ( startLoop == true ) {
  121.  
  122. #ifdef DEBUG_MODE
  123. Serial.println("IN STARTUP SEQUENCE");
  124. Serial.println("===================");
  125. #endif
  126.  
  127. startFadeToColourSequence(orange, powerUpFadeTimeMS); // call function to calculate fading variables
  128.  
  129. debugPrintValues();
  130.  
  131. startLoop = false;
  132. }
  133.  
  134. doPWMStep(currentTimeMS, startTimeRGBms); // call function to do PWM stepping (if individual R/G/B delay has passed)
  135.  
  136. if ( fadingRGB[0] == false && fadingRGB[1] == false && fadingRGB[2] == false ) {
  137.  
  138. // Cross fade complete; update current values for next cross fade
  139. for (int i=0; i<3; i++) {
  140. prevVals[i] = valsRGB[i];
  141. }
  142.  
  143. startupSeq = false;
  144. waitForWarp = true; // set state variable to begin check for next cross fade
  145. timeStampMS = currentTimeMS; // start timer for pause before going to warp
  146.  
  147. #ifdef DEBUG_MODE
  148. for (int i=0; i<3; i++) {
  149. Serial.print("prevVals[");
  150. Serial.print(i);
  151. Serial.print("] = ");
  152. Serial.println(prevVals[i]);
  153. }
  154. Serial.println("");
  155. Serial.print("startupSeq = ");
  156. Serial.print(startupSeq);
  157. Serial.print("waitForWarp = ");
  158. Serial.print(waitForWarp);
  159. Serial.print(", timeStampMS = ");
  160. Serial.println(timeStampMS);
  161. #endif
  162.  
  163. }
  164.  
  165. }
  166.  
  167.  
  168.  
  169. // 2. Go to warp
  170. // =============
  171. if ( ((currentTimeMS - timeStampMS) >= delayBeforeWarpMS) && (waitForWarp == true) ) {
  172. waitForWarp = false;
  173. gotoWarp = true;
  174. startLoop = true; // set boolean for first time thru loop
  175. }
  176.  
  177. if ( gotoWarp == true ) {
  178.  
  179. if ( startLoop == true ) {
  180.  
  181. #ifdef DEBUG_MODE
  182. Serial.println("IN GO TO WARP SEQUENCE");
  183. Serial.println("======================");
  184. #endif
  185.  
  186. startFadeToColourSequence(mediumBlue3, goToWarpFadeTimeMS); // call function to calculate fading variables
  187.  
  188. debugPrintValues();
  189.  
  190. startLoop = false;
  191. }
  192.  
  193. doPWMStep(currentTimeMS, startTimeRGBms); // call function to do PWM stepping (if individual R/G/B delay has passed)
  194.  
  195. if ( fadingRGB[0] == false && fadingRGB[1] == false && fadingRGB[2] == false ) {
  196. gotoWarp = false;
  197. }
  198.  
  199. }
  200.  
  201. }
  202.  
  203.  
  204. // ------------------------------------------------------------------------------------------------------
  205.  
  206. /*
  207. Purpose: function to calculate delay between PWM steps (specific to each colour)
  208. Parameters: prevValue [current value]; endValue [fade to value]; overallFadeTimeMS [desired fade time]
  209. Returns: delay in microseconds
  210. */
  211. int calculateDelay(int prevValue, int endValue, int overallFadeTimeMS) {
  212. // For delay between PWM steps, value needs to be positive so take absolute value of difference
  213. int delayMS = abs((endValue - prevValue)); // What's the overall gap?
  214.  
  215. if (delayMS) { // If its non-zero,
  216. delayMS = overallFadeTimeMS/delayMS; // divide by overallFadeTimeMS
  217. }
  218.  
  219. return delayMS;
  220. }
  221.  
  222. /*
  223. Purpose: prepares variables for colour fading
  224. Parameters: fadeToColour [desired R/G/B colour]; fade time in microseconds
  225. Returns: nothing
  226. */
  227. void startFadeToColourSequence( int fadeToColour[], unsigned long fadeTimeMS ) {
  228.  
  229. for (int i=0; i<3; i++) {
  230. valsRGB[i] = fadeToColour[i]; // set new values for R/G/B
  231.  
  232. delayRGB[i] = calculateDelay( prevVals[i], valsRGB[i], fadeTimeMS ); // calculate time delay between PWM step changes for each colour
  233. stepsRGB[i] = prevVals[i]; // set starting value for PWM steps
  234. if ( valsRGB[i] > prevVals[i] ) { // calculate fade direction
  235. fadeDirRGB[i] = 1;
  236. } else {
  237. fadeDirRGB[i] = -1;
  238. }
  239. fadingRGB[i] = true;
  240. }
  241.  
  242. }
  243.  
  244. /*
  245. Purpose: performs PWM change
  246. Parameters: timestamp variale, array of delay timers
  247. Returns: nothing
  248. */
  249. void doPWMStep(unsigned long timeNowMS, unsigned long timerRGB[]) {
  250.  
  251. for (int i=0; i<3; i++) {
  252. // Check to see if colour should be changed
  253. if ( ( (timeNowMS - timerRGB[i]) >= delayRGB[i] ) && ( fadingRGB[i] == true ) ) {
  254.  
  255. #ifdef DEBUG_MODE
  256. Serial.print("timeNowMS = ");
  257. Serial.print(timeNowMS);
  258.  
  259. for (int i=0; i<3; i++) {
  260. Serial.print(", timerRGB[");
  261. Serial.print(i);
  262. Serial.print("] = ");
  263. Serial.print(timerRGB[i]);
  264.  
  265. Serial.print(", stepsRGB[");
  266. Serial.print(i);
  267. Serial.print("] = ");
  268. Serial.print(stepsRGB[i]);
  269. }
  270. Serial.println("");
  271. #endif
  272.  
  273. if ( stepsRGB[i] != valsRGB[i] ) {
  274. writeLED( pinsRGB[i], stepsRGB[i] );
  275. stepsRGB[i] += fadeDirRGB[i];
  276.  
  277. timerRGB[i] = timeNowMS; // set wait timer for this colour
  278. } else {
  279. // Done fading this colour
  280. fadingRGB[i] = false;
  281.  
  282. }
  283.  
  284. }
  285. }
  286.  
  287. }
  288.  
  289. /*
  290. Purpose: performs update on PWM pin
  291. Parameters: pin [one of R/G/B]; val [incremented or decremented PWM value]
  292. Returns: nothing
  293. */
  294. void writeLED(int pin, int val) {
  295. uint8_t gammaCorr; // Use Gamma correction table
  296.  
  297. if ( isCommonAnode == true ) {
  298. gammaCorr = pgm_read_byte(&gamma8[255-val]);
  299. } else {
  300. gammaCorr = pgm_read_byte(&gamma8[val]);
  301. }
  302.  
  303. #ifdef DEBUG_MODE
  304. Serial.print("pin = ");
  305. Serial.print(pin);
  306. Serial.print(", val = ");
  307. Serial.print(val);
  308. Serial.print(", gammaCorr = ");
  309. Serial.println(gammaCorr);
  310. #endif
  311.  
  312. analogWrite(pin, gammaCorr);
  313.  
  314. }
  315.  
  316. void debugPrintValues() {
  317.  
  318. #ifdef DEBUG_MODE
  319. for (int i=0; i<3; i++) {
  320. Serial.print("valsRGB[");
  321. Serial.print(i);
  322. Serial.print("] = ");
  323. Serial.print(valsRGB[i]);
  324.  
  325. Serial.print(", delayRGB[");
  326. Serial.print(i);
  327. Serial.print("] = ");
  328. Serial.print(delayRGB[i]);
  329.  
  330. Serial.print(", stepsRGB[");
  331. Serial.print(i);
  332. Serial.print("] = ");
  333. Serial.print(stepsRGB[i]);
  334.  
  335. Serial.print(", fadeDirRGB[");
  336. Serial.print(i);
  337. Serial.print("] = ");
  338. Serial.print(fadeDirRGB[i]);
  339.  
  340. Serial.print(", fadingRGB[");
  341. Serial.print(i);
  342. Serial.print("] = ");
  343. Serial.println(fadingRGB[i]);
  344. }
  345. #endif
  346.  
  347. }
  348.  
  349. /*
  350. 8-bit Gamma correction lookup table (uses gamma correction factor of 2.8)
  351.  
  352. Table generated using Processing app (Processing_Gamma_Correction_Table_Generator.pde)
  353.  
  354. */
  355. const uint8_t PROGMEM gamma8[] = {
  356. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  357. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
  358. 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
  359. 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
  360. 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
  361. 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
  362. 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
  363. 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
  364. 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
  365. 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
  366. 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
  367. 90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
  368. 115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
  369. 144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
  370. 177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
  371. 215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };
  372.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement