Эксперимент 63. RGB-ночник

В прошлом эксперименте мы уже сделали Wi-Fi RGB-ночник. Это светодиод яркостью и цветом которого можно управлять по Wi-Fi. Его можно использовать в качестве ночника. Но в нем есть один недостаток — нет наглядного выбора цвета. Для установки цвета нам нужно вводить три цифры, три яркости R, G и B. Заранее сложно предсказать какой цвет получится в результате ввода цифр. Также не понятно какие цифры нужно вводить, чтобы получить оранжевый, бирюзовый и другие цвета.

Для упрощения выбора цветов в веб-формах есть специальные типы полей ввода. Например есть текстовые поля, есть кнопки, есть выпадающие списки. Есть и специальное поле для ввода цвета с наглядной палитрой. Можно использовать этот элемент формы для ввода цвета и у нас. Единственная проблема — в HTML принято записывать цвет совсем не так, как мы его устанавливаем в своих программах.

Мы устанавливаем яркость светодиода с помощью сигнала ШИМ со значением от 0 до 1023. А в HTML цвет записывается с помощью 6 шестнадцатеричных символов и символа # перед ними. Например

Первые 2 символа отвечают за красный цвет, вторые два за зеленый и последние за синий цвет. Цвета могут принимать значения от 00 до FF. Это запись в шестнадцатеричной системе счисления чисел от 0 до 255.

Поэтому нам необходимо конвертировать цвет из формата записи в HTML в наш формат трех чисел от 0 до 255.

Схема эксперимента

Схема эксперимента остается без изменений Рисунок 1. Монтажная схема эксперимента

Программный код эксперимента

color.html
  1. <head>
  2. </head>
  3. <body>
  4. <h3>Select color:</h3>
  5. <form action="/">
  6. <input type="color" style="height:50px;width:50%;" value="<=VALUE=>" name="color">
  7. <input type="submit" value="Send">
  8. </form>
  9. </body>
  10. </html>

Код программы:

Exp63.ino
  1. #include <ESP8266WiFi.h>
  2. #include <ESP8266WebServer.h>
  3.  
  4. #define WIFI_NAME "WiFi_Name"
  5. #define WIFI_PASSWORD "WiFi_Password"
  6.  
  7. #define PIN_LED_R 13
  8. #define PIN_LED_G 14
  9. #define PIN_LED_B 15
  10.  
  11. ESP8266WebServer server(80);
  12.  
  13. void indexPage() {
  14. String html_color = "#4AD686";
  15. if (server.hasArg("color")) html_color = server.arg("color");
  16.  
  17. int duty_r = strtol(html_color.substring(1,3).c_str(), NULL, 16);
  18. int duty_g = strtol(html_color.substring(3,5).c_str(), NULL, 16);
  19. int duty_b = strtol(html_color.substring(5).c_str(), NULL, 16);
  20.  
  21. analogWrite(PIN_LED_R, 255 - duty_r);
  22. analogWrite(PIN_LED_G, 255 - duty_g);
  23. analogWrite(PIN_LED_B, 255 - duty_b);
  24.  
  25. String page = "<!DOCTYPE html>";
  26. page += "<html>";
  27. page += "<head>";
  28. page += "</head>";
  29. page += "<body>";
  30. page += "<h3>Select color:</h3>";
  31. page += R"(<form action="/">)";
  32. page += R"(<input type="color" style="height:50px;width:50%;" value="<=VALUE=>" name="color">)";
  33. page += R"(<input type="submit" value="Send">)";
  34. page += "</form>";
  35. page += "</body>";
  36. page += "</html>";
  37.  
  38. page.replace("<=VALUE=>", html_color);
  39. server.send(200, "text/html", page);
  40. }
  41.  
  42. void setup() {
  43. Serial.begin(9600);
  44. Serial.println();
  45. pinMode(PIN_LED_R, OUTPUT);
  46. pinMode(PIN_LED_G, OUTPUT);
  47. pinMode(PIN_LED_B, OUTPUT);
  48. analogWriteRange(256);
  49. analogWrite(PIN_LED_R, 255);
  50. analogWrite(PIN_LED_G, 255);
  51. analogWrite(PIN_LED_B, 255);
  52.  
  53. Serial.print("Connecting to WiFi");
  54. WiFi.mode(WIFI_STA);
  55. WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
  56. while (WiFi.status() != WL_CONNECTED) {
  57. Serial.print(".");
  58. delay(500);
  59. }
  60. Serial.println();
  61. Serial.println("WiFi connected");
  62. Serial.print("IP address: ");
  63. Serial.println(WiFi.localIP());
  64.  
  65. server.on("/", indexPage);
  66. server.begin();
  67. }
  68. void loop() {
  69. server.handleClient();
  70. }

Первым делом в коде программы нужно заменить WiFi_Name на имя нужной сети, а WiFi_Password на пароль от нее.

Рассмотрим алгоритм преобразования цвета. Веб форма отправляет на наш сервер цвет в формате #FFFFFF и получает аналогичный ответ.

  1. String html_color = "#4AD686";
  2. if (server.hasArg("color")) html_color = server.arg("color");

Теперь в переменной html_color находится цвет в формате #FFFFFF. Для получения нужной пары символов используем метод получения подстроки substring(), первый аргумент которого указывает на позицию начала подстроки, а второй — на конец (не включая). Если второй аргумент не указан, то концом подстроки считается конец строки. Полученную подстроку, преобразовав с помощью метода c_str(), передаем в качестве первого аргумента в специальную функцию strtol(), которая преобразует нашу пару символов в число от 0 до 255. Подробно на работе функции strtol() и метода c_str() останавливаться не будем.

  1. int duty_r = strtol(html_color.substring(1,3).c_str(), NULL, 16);
  2. int duty_g = strtol(html_color.substring(3,5).c_str(), NULL, 16);
  3. int duty_b = strtol(html_color.substring(5).c_str(), NULL, 16);

Теперь мы имеем данные для управления ШИМ сигналом светодиода. Остается только не забыть, что светодиод с общим анодом, поэтому для получения нужного результата наши значения нужно вычесть из 255.

  1. analogWrite(PIN_LED_R, 255 - duty_r);
  2. analogWrite(PIN_LED_G, 255 - duty_g);
  3. analogWrite(PIN_LED_B, 255 - duty_b);

При выводе страницы в браузер мы должны заменить метку в шаблоне страницы на актуальный цвет.

  1. page.replace("<=VALUE=>", html_color);

Вот так это выглядит у нас. Но отображение может быть разным в зависимости от браузера.

Теперь управлять цветом светодиода легко и наглядно.