(WIP) RGB controller on Arduino w/ sync to main PC system
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

WTFRGB.ino 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include "main.h"
  2. #include "effect.h"
  3. #include "aura.h"
  4. #include "breathing.h"
  5. #include "ripple.h"
  6. byte brightness = 100;
  7. // Delay between frames, a.k.a. fps,
  8. // in ms (normally don't use this for speed control, it may cause the animation to look sticky
  9. byte cycle = 40;
  10. // Main color palette
  11. // We support a maximum of 6 colors
  12. #define NUM_PALETTE_COLORS_MAX 6
  13. byte paletteColorNum = 3;
  14. CRGB palette[NUM_PALETTE_COLORS_MAX];
  15. CRGB leds[NUM_LEDS];
  16. CRGB realLeds[NUM_LEDS];
  17. #define EFFECTS_NUM 3
  18. Effect* effects[] = {new BreathingEffect(), new AuraEffect(),
  19. new RippleEffect()};
  20. byte curEffect = 2;
  21. void setup() {
  22. Serial.begin(115200);
  23. // Initialize the palette with simple RGB
  24. palette[0] = CRGB(255, 0, 0);
  25. palette[1] = CRGB(0, 255, 0);
  26. palette[2] = CRGB(0, 0, 255);
  27. for (int i = 0; i < NUM_LEDS; i++) {
  28. leds[i] = CRGB(0, 0, 0);
  29. realLeds[i] = CRGB(0, 0, 0);
  30. }
  31. pinMode(LED_PIN, OUTPUT);
  32. loadEEPROM(false);
  33. }
  34. void loadEEPROM(bool forceReset) {
  35. for (auto& effect : effects) {
  36. effect->reset();
  37. }
  38. if (forceReset || EEPROM.read(EEPROM_VERSION_COUNTER) != EEPROM_VERSION) {
  39. writeAllToEEPROM();
  40. return;
  41. }
  42. curEffect = EEPROM.read(EEPROM_MODE);
  43. brightness = EEPROM.read(EEPROM_BRIGHTNESS);
  44. cycle = EEPROM.read(EEPROM_CYCLE);
  45. // Load the palette length + palette
  46. paletteColorNum = EEPROM.read(EEPROM_PALETTE);
  47. for (int i = 0; i < paletteColorNum; i++) {
  48. palette[i] = CRGB(
  49. EEPROM.read(EEPROM_PALETTE + i * 3 + 1),
  50. EEPROM.read(EEPROM_PALETTE + i * 3 + 2),
  51. EEPROM.read(EEPROM_PALETTE + i * 3 + 3));
  52. }
  53. for (auto& effect : effects) {
  54. effect->loadFromEEPROM();
  55. }
  56. // Call post-init hooks when everything has been loaded.
  57. for (auto& effect : effects) {
  58. effect->postInit();
  59. }
  60. }
  61. void writeAllToEEPROM() {
  62. EEPROM.update(EEPROM_VERSION_COUNTER, EEPROM_VERSION);
  63. EEPROM.update(EEPROM_MODE, curEffect);
  64. EEPROM.update(EEPROM_BRIGHTNESS, brightness);
  65. EEPROM.update(EEPROM_CYCLE, cycle);
  66. // Write the palette length + palette
  67. EEPROM.update(EEPROM_PALETTE, paletteColorNum);
  68. for (unsigned int i = 0; i < paletteColorNum; i++) {
  69. EEPROM.update(EEPROM_PALETTE + i * 3 + 1, palette[i].r);
  70. EEPROM.update(EEPROM_PALETTE + i * 3 + 2, palette[i].g);
  71. EEPROM.update(EEPROM_PALETTE + i * 3 + 3, palette[i].b);
  72. }
  73. for (auto& effect : effects) {
  74. effect->writeToEEPROM();
  75. }
  76. }
  77. CRGB *getPaletteColor(unsigned char index) {
  78. return &palette[index % paletteColorNum];
  79. }
  80. CRGB *nextPaletteColor(unsigned char *counter) {
  81. (*counter)++;
  82. if (*counter >= paletteColorNum) {
  83. *counter = (*counter) % paletteColorNum;
  84. }
  85. return getPaletteColor(*counter);
  86. }
  87. void loop() {
  88. processCommand();
  89. if (curEffect < EFFECTS_NUM) effects[curEffect]->onUpdate();
  90. // Apply brightness transformation to the led array
  91. for (int i = 0; i < NUM_LEDS; i++) {
  92. realLeds[i] =
  93. CRGB(leds[i].r * brightness / 255, leds[i].g * brightness / 255,
  94. leds[i].b * brightness / 255);
  95. }
  96. postLedUpdate(realLeds, NUM_LEDS, LED_PIN);
  97. delay((int) cycle + 15);
  98. }
  99. void processCommand() {
  100. // Try reading from the serial
  101. char cmdBuf[50];
  102. if (Serial.available()) {
  103. int len = Serial.readBytesUntil('\n', cmdBuf, 50);
  104. if (len > 0) {
  105. // A command might be available to execute
  106. cmdBuf[len] = '\0';
  107. // Note: all numerical parameters of the following commands
  108. // should be sent in their BINARY form.
  109. if (strncmp("SAVE", cmdBuf, 4) == 0) {
  110. // SAVE - save everything to EEPROM
  111. writeAllToEEPROM();
  112. } else if (strncmp("MODE ", cmdBuf, 5) == 0) {
  113. // MODE <mode_id> - switch pattern to mode_id
  114. curEffect = cmdBuf[5] % EFFECTS_NUM;
  115. } else if (strncmp("BRIGHT ", cmdBuf, 7) == 0) {
  116. // BRIGHT <brightness> - change brightness value
  117. brightness = cmdBuf[7];
  118. } else if (strncmp("CYCLE ", cmdBuf, 6) == 0) {
  119. // CYCLE <cycle_period> - set cycle to cycle_period. This only affects FPS.
  120. cycle = cmdBuf[6];
  121. } else if (strncmp("PALETTE ", cmdBuf, 8) == 0) {
  122. // PALETTE <r1> <g1> <b1> <r2> <g2> <b2> .... - set the palette. Maximum of 6 colors.
  123. paletteColorNum = 255; // Mark that we haven't determined the number yet.
  124. for (unsigned int i = 0; i < NUM_PALETTE_COLORS_MAX; i++) {
  125. unsigned int startPos = 8 + i * 3;
  126. if (startPos >= len || startPos + 2 > len) {
  127. paletteColorNum = i;
  128. break;
  129. } else {
  130. palette[i] = CRGB(cmdBuf[startPos], cmdBuf[startPos + 1], cmdBuf[startPos + 2]);
  131. }
  132. }
  133. if (paletteColorNum == 255) {
  134. // The previous loop finished without overflowing the command sequence
  135. // So we have a maximum of 6 colors
  136. paletteColorNum = 6;
  137. }
  138. for (auto& effect : effects) {
  139. effect->onParamUpdate();
  140. }
  141. } else {
  142. // Delegate command to the current effect
  143. if (curEffect < EFFECTS_NUM) {
  144. effects[curEffect]->handleCommand(cmdBuf, len);
  145. }
  146. }
  147. }
  148. }
  149. }