Advertisement
macca-nz

Blynk_RGB_Widget_example

Apr 21st, 2025 (edited)
793
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 14.97 KB | Source Code | 0 0
  1. /* Fill-in information from Blynk Device Info here */
  2. #define BLYNK_TEMPLATE_ID           "TMPxxxxxx"
  3. #define BLYNK_TEMPLATE_NAME         "Device"
  4. #define BLYNK_AUTH_TOKEN            "YourAuthToken"
  5.  
  6. /* Comment this out to disable prints and save space */
  7. #define BLYNK_PRINT Serial
  8.  
  9.  
  10. #include <WiFi.h>
  11. #include <WiFiClient.h>
  12. #include <BlynkSimpleEsp32_SSL.h>
  13.  
  14. // Your WiFi credentials.
  15. // Set password to "" for open networks.
  16. char ssid[] = "YourNetworkName";
  17. char pass[] = "YourPassword";
  18.  
  19.  
  20. const bool GAMMA_CORRECT = true;    // set to false to disable gamma correction
  21.  
  22. // This table remaps linear input RGB values to
  23. // nonlinear gamma-corrected output values for human eyes.
  24. // To use/read it:  result = pgm_read_byte(&gamma8[color]);
  25. // Source:  https://learn.adafruit.com/led-tricks-gamma-correction/the-quick-fix
  26. const uint8_t PROGMEM gamma8[] = {
  27.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  28.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
  29.     1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
  30.     2,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  5,  5,  5,
  31.     5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,  9,  9, 10,
  32.    10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
  33.    17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
  34.    25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
  35.    37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
  36.    51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
  37.    69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
  38.    90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
  39.   115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
  40.   144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
  41.   177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
  42.   215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255
  43. };
  44.  
  45.  
  46. // Makes sure you assign PWM capable pins
  47. const byte PIN_RED = 14;
  48. const byte PIN_GREEN = 12;
  49. const byte PIN_BLUE = 13;
  50.  
  51. int rgb_red = 0;
  52. int rgb_green = 0;
  53. int rgb_blue = 0;
  54. int rgb_brightness = 0;
  55.  
  56. //uncomment next line if using a Common Anode LED
  57. //#define COMMON_ANODE
  58. const uint8_t MAX_COLOR_VALUE = 255;
  59.  
  60. struct HSL_t {
  61.   double h; // angle in degrees
  62.   double s; // saturation % between 0 and 1
  63.   double l; // luminance % between 0 and 1
  64. };
  65.  
  66. struct RGB_t {
  67.   int r; // red, 0 to 255
  68.   int g; // green, 0 to 255
  69.   int b; // blue, 0 to 255
  70. };
  71.  
  72.  
  73. HSL_t rgb2hsl(uint8_t red, uint8_t green, uint8_t blue) {
  74.   // Returns HSL value calculated from red, green, blue values where:
  75.   //  h = hue in degrees, 0 to 360
  76.   //  s = saturation, 0.0 to 1.0
  77.   //  l = luminance, 0.0 to 1.0
  78.   HSL_t result;
  79.  
  80.   // Scale red, blue, green from integer range 0-255 to float 0-1
  81.   double r = static_cast<double>(red / 255.0);
  82.   double g = static_cast<double>(green / 255.0);
  83.   double b = static_cast<double>(blue / 255.0);
  84.  
  85.   float c_max = max(max(r,g),b);
  86.   float c_min = min(min(r,g),b);
  87.  
  88.   // Luminance
  89.   result.l = (c_max + c_min) / 2.0;
  90.  
  91.   // Saturation
  92.   if (c_max == c_min) {
  93.     // No saturation, achromatic
  94.     result.h = 0.0;
  95.     result.s = 0.0;
  96.     return result;
  97.   } else {
  98.     if (result.l > 0.5) {
  99.       // Saturation = ( max-min)/(2.0-max-min)
  100.       result.s = (c_max - c_min) / (2.0 - c_max - c_min);
  101.     } else {
  102.       // Saturation = (max-min)/(max+min)
  103.       result.s = (c_max - c_min) / (c_max + c_min);
  104.     }
  105.   }
  106.  
  107.   // Hue
  108.   if (r == max(max(r,g),b)) {
  109.     // red is the maximum value
  110.     result.h = (g - b) / (c_max - c_min);
  111.   } else if (g == max(max(r,g),b)) {
  112.     // green is the maximum value
  113.     result.h = 2.0 + (b - r) / (c_max - c_min);
  114.   } else if (b == max(max(r,g),b)) {
  115.     // blue is the maximum value
  116.     result.h = 4.0 + (r - g) / (c_max - c_min);
  117.   } else {
  118.     // ERROR
  119.     result.h = 0.0;
  120.   }
  121.  
  122.   result.h *= 60.0;
  123.   if (result.h < 0) {
  124.     result.h += 360.0;
  125.   }
  126.    
  127.   return result;
  128.      
  129. } //rgb2hsl()
  130.  
  131.  
  132. RGB_t hsl2rgb(double h, double s, double l) {
  133.   RGB_t result;
  134.   float t_1 = 0.0;
  135.   float t_2 = 0.0;
  136.   float t_r = 0.0;
  137.   float t_g = 0.0;
  138.   float t_b = 0.0;
  139.  
  140.   if (h == 0.0 && s == 0.0) {
  141.     // No saturation, so it is a shade of gray.
  142.     // Covert the luminance and set r, g, b to that level.
  143.     result.r = static_cast<int>(l * 255.0);
  144.     result.g = static_cast<int>(l * 255.0);
  145.     result.b = static_cast<int>(l * 255.0);
  146.   } else {
  147.     if (l < 0.5) {
  148.       t_1 = l * (1.0 + s);
  149.     } else {
  150.       t_1 = l + s - l * s;
  151.     }
  152.    
  153.     t_2 = 2.0 * l - t_1;
  154.    
  155.     // convert hue in degress to 1 by diving by 360 degrees
  156.     h /= 360.0;
  157.    
  158.     t_r = h + (1.0/3.0);
  159.     if (t_r < 0.0) {
  160.       t_r += 1.0;
  161.     }
  162.     if (t_r > 1.0) {
  163.       t_r -= 1.0;
  164.     }
  165.    
  166.     t_g = h;
  167.     if (t_g < 0.0) {
  168.       t_g += 1.0;
  169.     }
  170.     if (t_g > 1.0) {
  171.       t_g -= 1.0;
  172.     }
  173.    
  174.     t_b = h - (1.0/3.0);
  175.     if (t_b < 0.0) {
  176.       t_b += 1.0;
  177.     }
  178.     if (t_b > 1.0) {
  179.       t_b -= 1.0;
  180.     }
  181.    
  182.     // red
  183.     if (6.0*t_r < 1.0) {
  184.       result.r = static_cast<int>(round((t_2 + (t_1 - t_2) * 6.0 * t_r) * 255.0));
  185.     } else if (2.0*t_r < 1.0) {
  186.       result.r = static_cast<int>(round(t_1 * 255.0));
  187.     } else if (3.0*t_r < 2.0) {
  188.       result.r = static_cast<int>(round((t_2 + (t_1 - t_2) * (2.0/3.0 - t_r) * 6.0) * 255.0));
  189.     } else if (3.0*t_r > 2.0) {
  190.       result.r = static_cast<int>(round(t_2 * 255.0));
  191.     }
  192.  
  193.     // green
  194.     if (6.0*t_g < 1.0) {
  195.       result.g = static_cast<int>(round((t_2 + (t_1 - t_2) * 6.0 * t_g) * 255.0));
  196.     } else if (2.0*t_g < 1.0) {
  197.       result.g = static_cast<int>(round(t_1 * 255.0));
  198.     } else if (3.0*t_g < 2.0) {
  199.       result.g = static_cast<int>(round((t_2 + (t_1 - t_2) * (2.0/3.0 - t_g) * 6.0) * 255.0));
  200.     } else if (3.0*t_g > 2.0) {
  201.       result.g = static_cast<int>(round(t_2 * 255.0));
  202.     }
  203.  
  204.     // blue
  205.     if (6.0*t_b < 1.0) {
  206.       result.b = static_cast<int>(round((t_2 + (t_1 - t_2) * 6.0 * t_b) * 255.0));
  207.     } else if (2.0*t_b < 1.0) {
  208.       result.b = static_cast<int>(round(t_1 * 255.0));
  209.     } else if (3.0*t_b < 2.0) {
  210.       result.b = static_cast<int>(round((t_2 + (t_1 - t_2) * (2.0/3.0 - t_b) * 6.0) * 255.0));
  211.     } else if (3.0*t_b > 2.0) {
  212.       result.b = static_cast<int>(round(t_2 * 255.0));
  213.     }
  214.        
  215.   }
  216.  
  217.   return result;
  218.  
  219. } // hsl2rgb()
  220.  
  221.  
  222. void setRGB(uint8_t red, uint8_t green, uint8_t blue, uint8_t luminance, bool gamma_correct) {
  223.  
  224.   // Note: the Blynk RGB Light Control widget color values
  225.   // assume the use of a common cathode RGB.
  226.  
  227.   bool white_mode = false;
  228.  
  229.   if (red > 218 && green > 218 && blue > 168) {
  230.     // Possibly in White Mode
  231.     white_mode = true;
  232.   }
  233.  
  234.   if (MAX_COLOR_VALUE == 255 && gamma_correct == true && white_mode == false) {
  235.     // Gamma correction is applied to compensate for the non-linearity of
  236.     // the human eye perception of color using pgm_read_byte(&gamma8[color]);
  237.     red = pgm_read_byte(&gamma8[red]);
  238.     green = pgm_read_byte(&gamma8[green]);
  239.     blue = pgm_read_byte(&gamma8[blue]);
  240.   }
  241.  
  242.   // Scale RGB color values based on the luminance setting.
  243.   // Note that above 50% luminance, the color changes a lot.
  244.   // Therefore, scale everything down by 1/2, so 100% = 50%.
  245.   HSL_t hsl = rgb2hsl(red, green, blue);
  246.   // hsl.l range is 0.0 to 1.0
  247.   // luminance range is 0 to 100
  248.   // Scale luminance from 0 to 100 to 0.0 to 1.0
  249.   hsl.l = static_cast<double>(luminance)/100.0;
  250.   // Scale luminance further by 1/2 to keep color true
  251.   hsl.l /= 2.0;
  252.   RGB_t rgb = hsl2rgb(hsl.h, hsl.s, hsl.l);
  253.   red = rgb.r; green = rgb.g; blue=rgb.b;
  254.  
  255.   #ifdef COMMON_ANODE
  256.     red = MAX_COLOR_VALUE - red;
  257.     green = MAX_COLOR_VALUE - green;
  258.     blue = MAX_COLOR_VALUE - blue;
  259.   #else
  260.     // common cathode RGB
  261.   #endif
  262.  
  263.   // Write the RGB values to the RGB attached to the hardware
  264.   analogWrite(PIN_RED, red);
  265.   analogWrite(PIN_GREEN, green);
  266.   analogWrite(PIN_BLUE, blue);  
  267. } // setRGB()
  268.  
  269. uint8_t rgb_light_control_mode = 0; // 0 = mode unknown, 1 = Color, 2 = White, 3 = Animation
  270. uint8_t animation_fade_strobe = 0;  // 0 = mode unknown, 1 = strobe, 2 = fade
  271. RGB_t rgb_color_white_mode;
  272. uint8_t animation_pattern_count = 0;  // either 3 or 2 when known
  273. RGB_t rgb_animation_left;
  274. RGB_t rgb_animation_right;
  275. RGB_t rgb_animation_top;
  276.  
  277. /////////////////////////////////////////////////////////////////////////
  278.  
  279.  
  280. BLYNK_WRITE(V10) {  
  281.   // V10    integer, BUTTON, 0 or 1
  282.   // Turn RGB on/off based on the BUTTON value
  283.   int btn_state = param.asInt();  
  284.   if (btn_state == 1) {
  285.     // do nothing with rgb_brightness
  286.   } else {
  287.     rgb_brightness = 0;
  288.   }
  289.   Serial.print("V10 = '");
  290.   Serial.print(btn_state);
  291.   Serial.println("'  BUTTON..");
  292.   setRGB(rgb_red, rgb_green, rgb_blue, rgb_brightness, GAMMA_CORRECT);
  293. } // BLYNK_WRITE(V10)
  294.  
  295.  
  296. BLYNK_WRITE(V2) {  
  297.   // Called when datastream for virtual pin V2 is updated
  298.   // V2    string, COLOR
  299.  
  300.   Serial.println("");
  301.   //Serial.println("All V2 array items:");
  302.   byte param_items_count = 0;
  303.   for (auto i = param.begin(); i < param.end(); ++i) {
  304.     //Serial.print("\t");
  305.     //Serial.print(param_items_count);
  306.     //Serial.print(" = '");
  307.     //Serial.print(i.asString());
  308.     //Serial.println("'");
  309.     if (param_items_count == 3) {
  310.       String button_mode = i.asString();
  311.       if (button_mode == "true") {
  312.         rgb_light_control_mode = 1; // Color Mode
  313.       } else if (button_mode == "false") {
  314.         rgb_light_control_mode = 2; // White Mode
  315.       }
  316.     }
  317.     if (param_items_count == 4) {
  318.       //Serial.println("\tparam_items_count == 4");
  319.       rgb_light_control_mode = 3; // Animation mode
  320.       int fade_strobe = param[4].asInt();
  321.       if (fade_strobe == 0) {
  322.         animation_fade_strobe = 2;  // fade
  323.       } else if (fade_strobe == 1) {
  324.         animation_fade_strobe = 1;  // strobe
  325.       } else {
  326.         animation_fade_strobe = 0;
  327.       }  
  328.     }
  329.     param_items_count++;
  330.   }
  331.   //Serial.print("param_items_count = "); Serial.println(param_items_count);
  332.  
  333.   rgb_color_white_mode.r = param[0].asInt();
  334.   rgb_color_white_mode.g = param[1].asInt();
  335.   rgb_color_white_mode.b = param[2].asInt();
  336.  
  337.   if (param_items_count > 4) {
  338.     rgb_animation_left.r = param[5].asInt();;
  339.     rgb_animation_left.g = param[6].asInt();;
  340.     rgb_animation_left.b = param[7].asInt();;
  341.   }
  342.   if (param_items_count == 11) {
  343.     animation_pattern_count = 2;
  344.     rgb_animation_top.r = 0;
  345.     rgb_animation_top.g = 0;
  346.     rgb_animation_top.b = 0;
  347.     rgb_animation_right.r = param[8].asInt();;
  348.     rgb_animation_right.g = param[9].asInt();;
  349.     rgb_animation_right.b = param[10].asInt();;
  350.   } else if (param_items_count == 14) {
  351.     animation_pattern_count = 3;
  352.     rgb_animation_top.r = param[8].asInt();;
  353.     rgb_animation_top.g = param[9].asInt();;
  354.     rgb_animation_top.b = param[10].asInt();;
  355.     rgb_animation_right.r = param[11].asInt();;
  356.     rgb_animation_right.g = param[12].asInt();;
  357.     rgb_animation_right.b = param[13].asInt();;  
  358.   } else {
  359.     animation_pattern_count = 0;
  360.   }
  361.  
  362.   // Using the populated global values for:
  363.   //  rgb_light_control_mode, animation_fade_strobe, rgb_light_control_mode
  364.   //  animation_fade_strobe, rgb_color_white_mode, rgb_animation_left
  365.   //  rgb_animation_right, rgb_animation_top, animation_pattern_count
  366.   switch (rgb_light_control_mode) {
  367.     case 0:
  368.       // button mode unknown
  369.       Serial.println("RGB Light Control button mode UNKNOWN");
  370.       break;
  371.     case 1:
  372.       // Color Mode
  373.       Serial.println("Color Mode");
  374.       Serial.print("R: "); Serial.print(rgb_color_white_mode.r); Serial.print("\tG:"); Serial.print(rgb_color_white_mode.g); Serial.print("\tB:"); Serial.println(rgb_color_white_mode.b);
  375.       break;
  376.     case 2:
  377.       // White Mode
  378.       Serial.println("White Mode");
  379.       Serial.print("R: "); Serial.print(rgb_color_white_mode.r); Serial.print("\tG:"); Serial.print(rgb_color_white_mode.g); Serial.print("\tB:"); Serial.println(rgb_color_white_mode.b);
  380.       break;
  381.     case 3:
  382.       // Animation Mode
  383.       if (animation_fade_strobe == 1) {
  384.         Serial.println("Animation Mode - strobe");        
  385.       } else if (animation_fade_strobe == 2) {
  386.         Serial.println("Animation Mode - fade");        
  387.       }
  388.       if (animation_fade_strobe > 0) {
  389.         Serial.print("\t"); Serial.print(animation_pattern_count); Serial.println("x Pattern: ");
  390.         Serial.print("\tLeft\tR: "); Serial.print(rgb_animation_left.r); Serial.print("\tG:"); Serial.print(rgb_animation_left.g); Serial.print("\tB:"); Serial.println(rgb_animation_left.b);
  391.         if (animation_pattern_count > 2) {
  392.           Serial.print("\tTop\tR: "); Serial.print(rgb_animation_top.r); Serial.print("\tG:"); Serial.print(rgb_animation_top.g); Serial.print("\tB:"); Serial.println(rgb_animation_top.b);
  393.         }
  394.         Serial.print("\tRight\tR: "); Serial.print(rgb_animation_right.r); Serial.print("\tG:"); Serial.print(rgb_animation_right.g); Serial.print("\tB:"); Serial.println(rgb_animation_right.b);
  395.       }
  396.       break;
  397.   } // switch
  398.   Serial.println("");
  399.  
  400.   setRGB(rgb_color_white_mode.r, rgb_color_white_mode.g, rgb_color_white_mode.b, rgb_brightness, GAMMA_CORRECT);
  401.  
  402. } // BLYNK_WRITE(V2)
  403.  
  404.  
  405. BLYNK_WRITE(V6) {  
  406.   // V6    integer, BRIGHTNESS. 0 to 100
  407.   rgb_brightness = param.asInt();
  408.   Serial.print("V6 = '");
  409.   Serial.print(rgb_brightness);
  410.   Serial.println("'  BRIGHTNESS..");
  411.   setRGB(rgb_red, rgb_green, rgb_blue, rgb_brightness, GAMMA_CORRECT);
  412. } // BLYNK_WRITE(V6)
  413.  
  414.  
  415. BLYNK_WRITE(V5) {  
  416.   // V5    integer, ANIMATION SPEED, 0 to 10000
  417.   int animation_speed = param.asInt();
  418.   Serial.print("V5 = '");
  419.   Serial.print(animation_speed);
  420.   Serial.println("'  ANIMATION SPEED");
  421. } // BLYNK_WRITE(V5)
  422.  
  423. BLYNK_CONNECTED() {
  424.   // Executes every time Blynk is connected to the cloud
  425.   // (typically only if WiFi connection is lost, otherwise Blynk stays connected)
  426.   Serial.println("BLYNK_CONNECTED() .. Blynk connected to the cloud.");
  427.  
  428.   // Request Blynk server to re-send latest values for all virtual pins
  429.   Blynk.syncAll();
  430. } // BLYNK_CONNECTED
  431.  
  432. /////////////////////////////////////////////////////////////////////////
  433.  
  434.  
  435. void setup() {
  436.   Serial.begin(115200);
  437.   while (!Serial) {
  438.     delay(1);
  439.   }
  440.   Serial.println("\nSerial ready");
  441.  
  442.   // RGB
  443.   pinMode(PIN_RED, OUTPUT);
  444.   pinMode(PIN_GREEN, OUTPUT);
  445.   pinMode(PIN_BLUE, OUTPUT);
  446.   setRGB(0, 0, 0, 0, GAMMA_CORRECT);
  447.  
  448.   rgb_color_white_mode.r = 0;
  449.   rgb_color_white_mode.g = 0;
  450.   rgb_color_white_mode.b = 0;
  451.  
  452.   rgb_animation_left.r = 0;
  453.   rgb_animation_left.g = 0;
  454.   rgb_animation_left.b = 0;
  455.  
  456.   rgb_animation_right.r = 0;
  457.   rgb_animation_right.g = 0;
  458.   rgb_animation_right.b = 0;
  459.  
  460.   rgb_animation_top.r = 0;
  461.   rgb_animation_top.g = 0;
  462.   rgb_animation_top.b = 0;
  463.  
  464.   // Try to connect to Blynk Cloud.
  465.   Serial.println("Connecting to Blynk..");
  466.   Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  467.  
  468.   Serial.println("\nSetup complete\n");
  469. } // setup()
  470.  
  471.  
  472. void loop() {
  473.  
  474.   Blynk.run();
  475.  
  476. } // loop()
  477.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement