Это старая версия документа!


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

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

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

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

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

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

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

Схема эксперимента остается без изменений Рисунок 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>

Сохрани эту страницу в корне файловой системы микроконтроллера под именем color.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. long number = strtoll(&html_color[1], NULL, 16);
  18. int duty_r = number >> 16;
  19. int duty_g = number >> 8 & 0xFF;
  20. int duty_b = number & 0xFF;
  21.  
  22. Serial.println(html_color);
  23. Serial.println(duty_r);
  24. Serial.println(duty_g);
  25. Serial.println(duty_b);
  26.  
  27. analogWrite(PIN_LED_R, 255 - duty_r);
  28. analogWrite(PIN_LED_G, 255 - duty_g);
  29. analogWrite(PIN_LED_B, 255 - duty_b);
  30.  
  31. String page = "<!DOCTYPE html>";
  32. page += "<html>";
  33. page += "<head>";
  34. page += "</head>";
  35. page += "<body>";
  36. page += "<h3>Select color:</h3>";
  37. page += R"(<form action="/">)";
  38. page += R"(<input type="color" style="height:50px;width:50%;" value="<=VALUE=>" name="color">)";
  39. page += R"(<input type="submit" value="Send">)";
  40. page += "</form>";
  41. page += "</body>";
  42. page += "</html>";
  43.  
  44. page.replace("<=VALUE=>", html_color);
  45. server.send(200, "text/html", page);
  46. }
  47.  
  48. void setup() {
  49. Serial.begin(9600);
  50. Serial.println();
  51. pinMode(PIN_LED_R, OUTPUT);
  52. pinMode(PIN_LED_G, OUTPUT);
  53. pinMode(PIN_LED_B, OUTPUT);
  54. analogWriteRange(256);
  55. analogWrite(PIN_LED_R, 255);
  56. analogWrite(PIN_LED_G, 255);
  57. analogWrite(PIN_LED_B, 255);
  58.  
  59. Serial.print("Connecting to WiFi");
  60. WiFi.mode(WIFI_STA);
  61. WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
  62. while (WiFi.status() != WL_CONNECTED) {
  63. Serial.print(".");
  64. delay(500);
  65. }
  66. Serial.println();
  67. Serial.println("WiFi connected");
  68. Serial.print("IP address: ");
  69. Serial.println(WiFi.localIP());
  70.  
  71. server.on("/", indexPage);
  72. server.begin();
  73. }
  74. void loop() {
  75. server.handleClient();
  76. }

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

Рассмотрим алгоритм преобразования цвета. Веб форма отправляет на наш сервер цвет в формате #FFFFFF. При этом символ # трансформируется в код символа %23. Поэтому в программе на Python в params['color'] будет что-то вроде %23c400be. С помощью оператора извлечение среза мы выбираем нужные нам символы, а именно с 3 по 9.

  1. html_color = params['color'][3:9]

Теперь в переменной html_color находится цвет в формате c400be. Точно так же «разрезаем» его на 3 части:

  1. r = html_color[0:2]
  2. g = html_color[2:4]
  3. b = html_color[4:6]

Теперь в переменных r, g и b у нас находятся соответствующие цвета записанные строкой в шестнадцатеричной форме. Их нужно перевести в числа:

  1. r = int(r, 16)
  2. g = int(g, 16)
  3. b = int(b, 16)

Теперь мы получили три числа, которые могут быть от 0 до 255. Нам нужно масштабировать их в диапазон от 0 до 1023. Иначе мы получим лишь четверть от максимальной яркости.

  1. r = int(r * 1023 / 255)
  2. g = int(g * 1023 / 255)
  3. b = int(b * 1023 / 255)

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

  1. LedR.duty(1023-r)
  2. LedG.duty(1023-g)
  3. LedB.duty(1023-b)

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

  1. html = html.replace('<=VALUE=>', '#' + html_color)

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

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