Исправленный текст: Официальное ограничение для выходной частоты esp8266pwm составляет 1 кГц, что может вызвать ошибку программы.
Провел тестирование схемы и программы от эксперта и обнаружил, что существуют некие нелинейные отклонения, не соответствующие цели программы, например, при следующих параметрах: цветовая температура 50, яркость 3 и ниже, теплый свет не выдает выход, хотя должен был. После изучения документации выяснилось, что рекомендованная частота PWM для работы составляет 1 кГц и выше, при этом точность может достигать 14 бит. Программа автора работает отлично при частоте 20 кГц, что тоже является удивительным. Я изменил частоту PWM на 1 кГц и точность на 14 бит, что позволяет более точно регулировать яркость, особенно при комбинировании цветовой температуры, что делает цвет более точным (хотя это и не обязательно). Более полезным является использование этих 4 бит для логарифмической регулировки яркости.
Примечание: возможно, что последующие платы и программы от автора также имеют те же проблемы, что указывает на некоторые ограничения PWM модуля ESP8266, которые делают его менее подходящим для высокочастотных выходов, таких как управление электродвигателями.
#include <ESP8266WiFi.h>
#include <EEPROM.h>
// Замените на свои сетевые учетные данные
const char* ssid = "sl";
const char* password = "123@789ABC";
// Установите номер порта веб-сервера на 80
WiFiServer server(80);
```// Декодирование значения HTTP GET
String redString = "0";
String colorString = "0";
int colorValue = 0;
String greenString = "0";
String brightString = "0";
int brightValue = 0;
int warmValue = 0;
int coldValue = 0;
String funcString = "0";
int funcValue = 0;
int pos1 = 0;
int pos2 = 0;
int pos3 = 0;
int pos4 = 0;
String header;// Настройка вывода PWM
const int warmPin = 13; // D1mini -> D7
const int coldPin = 12; // D1mini -> D6
// Настройка разрешения PWM
const int resolution = 16000;
// Текущее время
unsigned long currentTime = millis();
// Предыдущее время
unsigned long previousTime = 0;
// Определение времени таймаута в миллисекундах (например: 2000 мс = 2 с)
const long timeoutTime = 2000;
String readFromEP = "";
void setup() {
Serial.begin(115200);
EEPROM.begin(128);
analogWriteRange(resolution);
analogWriteFreq(1000);
readValue();
analogOut();
// Подключение к Wi-Fi сети с SSID и паролем
Serial.print("Подключение к ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// while (WiFi.status() != WL_CONNECTED) {
while (WiFi.localIP().toString() == "0.0.0.0") {
delay(500);
Serial.print(".");
}
// Serial.println("");
// Serial.println("WiFi подключено.");
// Serial.println("IP адрес: ");
// Serial.println(WiFi.localIP());
server.begin();
}```cpp
void loop() {
WiFiClient client = server.available(); // Слушаем входящих клиентов
if (client)
{ // Если новый клиент подключается,
currentTime = millis();
previousTime = currentTime;
// Serial.println("New Client."); // выводим сообщение в последовательный порт
String currentLine = ""; // создаем строку для хранения входящих данных от клиента
while (client.connected() && currentTime - previousTime <= timeoutTime)
{ // цикл пока клиент подключен
currentTime = millis();
if (client.available())
{ // если есть байты для чтения от клиента,
char c = client.read(); // читаем байт, затем
Serial.write(c); // выводим его в последовательный монитор
header += c;
if (c == '\n') { // если байт - это символ новой строки
// если текущая строка пустая, вы получили два символа новой строки подряд.
// это конец HTTP-запроса клиента, поэтому отправляем ответ:
if (currentLine.length() == 0) {
// HTTP-заголовки всегда начинаются с кода ответа (например, HTTP/1.1 200 OK)
// и типа содержимого, чтобы клиент знал, что ожидать, затем пустая строка:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// Отображаем HTML-страницу
client.println("<!DOCTYPE html><html>");
client.println("<head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.print("</head><body><a id=\"lightupdate\" href=\"#\" ></a><input id=\"colorRange\" type=\"range\" min=\"0\" max=\"100\" value=\"");
client.print(colorString);
``` client.print("\"step=\"1\" onchange=\"change()\" orient=\"vertical\" style=\"-webkit-appearance: slider-vertical; height: 300px;\">Температура<span id=\"colorValue\">");
client.print(colorString);
client.print("</span><input id=\"bright\" type=\"range\" min=\"0\" max=\"100\" value=\"");
client.print(brightString);
client.print("\" step=\"1\" onchange=\"change()\" orient=\"vertical\" style=\"-webkit-appearance: slider-vertical; height: 300px;\">Яркость<span id=\"brightValue\">");
client.print(brightString);
client.println("</span><br><button type=\"button\" onclick=\"onoff()\">Вкл/Выкл</button><button type=\"button\" onclick=\"savedata()\">Сохранить</button>");
client.println("<script type='text/javascript'>function change() {var colorValue = document.getElementById('colorRange').value;");
client.println("document.getElementById('colorValue').innerHTML = colorValue;var brightValue = document.getElementById('bright').value;document.getElementById('brightValue').innerHTML = brightValue;");
client.println("var url = document.getElementById('lightupdate').href = \"?c\" + colorValue + \"b\" + brightValue + \"&\";");
client.println("var request = new XMLHttpRequest();request.open(\"GET\", url);request.send();}");
client.print("function savedata() {var url = document.getElementById('lightupdate').href = \"?f3&\";");
client.println("var request = new XMLHttpRequest();request.open(\"GET\", url);request.send();}");
client.print("function onoff() {var url = document.getElementById('lightupdate').href = \"?f1&\";");
client.println("var request = new XMLHttpRequest();request.open(\"GET\", url);request.send();}");
client.println("</script></body></html>");
// HTTP-ответ завершается пустой строкой
client.println();
// Пример запроса: /?c50b69&
// Пример запроса: /?f1&
// colorTemp = 50 | Яркость = 69 | f1 = переключение, f3 = установка значения
if(header.indexOf("GET /?c") >= 0) {
pos1 = header.indexOf('c');
pos2 = header.indexOf('b');
pos3 = header.indexOf('&');
colorString = header.substring(pos1 + 1, pos2);
brightString = header.substring(pos2 + 1, pos3);
/*Serial.println(redString.toInt());
Serial.println(greenString.toInt());
Serial.println(blueString.toInt());*/
colorValue = colorString.toInt();
brightValue = brightString.toInt();
analogOut();
}
if (header.indexOf("GET /? f") >= 0) {
pos1 = header.indexOf('f');
pos2 = header.indexOf('&');
funcString = header.substring(pos1 + 1, pos2);
funcValue = funcString.toInt();
switch (funcValue)
{
case 1:
toggleLight();
break;
case 2:
readValue();
break;
case 3:
saveData();
break;
default:
break;
}
}
// Выход из цикла while
break;
} else { // если получено новое значение строки, то очистить currentLine
currentLine = "";
}
} else if (c != '\r') { // если получено что-то другое, кроме символа возврата каретки,
currentLine += c; // добавить его в конец currentLine
}
}
}
// Очистить переменную header
header = "";
// Закрыть соединение
client.stop();
// Serial.println("Client disconnected. ");
// Serial.println("");
}
}
void toggleLight()
{
if (brightValue > 0)
{
brightValue = 0;
analogOut();
} else
{
readValue();
analogOut();
}
}
void saveData()
{
String saveString = "c" + colorString + "b" + brightString + "&;";
for (int n = 0; n < saveString.length(); n++)
{
EEPROM.write(n, saveString[n]);
}
EEPROM.commit();
// Serial.println("SaveDataSuccess");
// Serial.println(saveString);
}
String readData(int l, int p)
{
String temp;
for (int n = p; n < l + p; ++n)
{
if (char(EEPROM.read(n)) == '&')
{
break;
}
temp += char(EEPROM.read(n));
}
return temp;
}```java
read(n)) != ';')
{
if (isWhitespace(char(EEPROM.read(n))))
{
// ничего не делать
}
else
{
temp += String(char(EEPROM.read(n)));
}
}
else
{
n = l + p;
}
}
return temp;
}
void analogOut()
{
if (brightValue == 0)
{
warmValue = 0;
coldValue = 0;
}
else if (colorValue >= 50)
{
warmValue = 160 * brightValue;
coldValue = int((1 - ((colorValue - 50) / 50.0)) * brightValue * 160);
}
else
{
warmValue = int((1 - ((50 - colorValue) / 50.0)) * brightValue * 160);
coldValue = brightValue * 160;
}
analogWrite(warmPin, warmValue);
analogWrite(coldPin, coldValue);
}
void readValue()
{
readFromEP = readData(128, 0);
pos1 = readFromEP.indexOf('c');
pos2 = readFromEP.indexOf('b');
pos3 = readFromEP.indexOf('&');
colorString = readFromEP.substring(pos1 + 1, pos2);
brightString = readFromEP.substring(pos2 + 1, pos3);
colorValue = colorString.toInt();
brightValue = brightString.toInt();
}