Детектив "Безумная душевая"
Извините за долинный текст, но по простому тут не опишешь.
Давно решил отдать душевую под управление ESP8266. Из управляемого оборудования имеется:LED лента, вентилятор и бойлер.
Хотелось:
1. Включение света как выключателем (подключен на GPIО14) так и программно при записи в GPIО15 единицы. Причем включение и выключение плавное.
2. Вкл/выкл вентилятора по влажности.
3. Вкл/выкл бойлера по времени.
Начал со света и постепенно расширял функционал в конструкторе кода.
Два таймера: один периодически проверяет состояние выключателя и GPIО15, при событии запускается второй таймер, при каждом тике которого изменяется на единицу значение ШИМ, управляющего яркостью света. Прототип программы брал в данной ветке форума.
Все отлично работало. Периодически расширял программу.
В один черный день обнаружил, что душевая шизанулась. При перезапуске или при включении модуля выходы вытворяли все что хотели. При вкл одного выхода, может заодно изменить свое состояние и другой. Свет включался не плавно... Выход мог самопроизвольно включиться
Такое мракобесие творится минут пять, а потом все начинает нормально работать. Было две мысли: нахомутал с программой или наводки. Вначале начал откатывать программу- не помогло. От наводок избавился радикально - взял другой ESP8266 и в него прошил самую простую прошивку (только свет). Ничего не подключено. Эффект тот-же. К глубокому сожалению не сохранял готовые старые прошивки. Уже нет мыслей.
Описание прошивки:
Включено в конструкторе:
DHT 11/21/22, Время и NTP, Датчики GET запросом, GPIO, Обновление OTA, Программный PWM (ШИМ), Конструктор кода, Конструктор main page. ВСЕ.
Код
//03 - вкл бойлера (OUT инверсия)
//04 - PWM0 (OUT)
//05 - DHT (DATA)
//12 - реле включения БП LED ленты (OUT инверсия)
//13 - реле включения вентилятора (OUT инверсия)
//14 - выключатель света (IN)
//15 - виртуальный выключатель света (OUT)
static os_timer_t esp_timer1; //Объявляем первый таймер, он будет опрашивать пин
static os_timer_t esp_timer2; //Объявляем второй таймер, он будет отсчитывать задержку
int gpio = 15; // номер gpio управления
int gpior = 12; // номер gpio реле
int gpiov = 14; // номер gpio выключателя
int gpios = 13; // номер gpio вентилятора
int gpiob = 03; // номер gpio бойлера
int pw = 0; // ШИМ управления светом GPIO4
int w = 0; // Начальная яркость
int wmax = 200; // Максимальная яркость
int fade = 1; // Шаг изменения яркости
int g = 0; // начальное значение GPIO управления
int gv = 0; // начальное значение GPIO выключателя
int p = 20; // тик задержки в миллисекундах
pwn_wr(){ //функция записи ШИМ
w = w + fade;
analogWrite(pw,w);
if (w == wmax || w == 0) { // закончился цикл
os_timer_disarm(&esp_timer2); //выключаем второй таймер
if (g == 0) digitalWrite(gpior,0); //после затухания света выкл реле
os_timer_arm(&esp_timer1, 20, 1); //включаем обратно первый таймер
}
}
read_gpio(){ //функция, читающая GPIO
if (digitalRead(gpiov) != gv) { gv = digitalRead(gpiov); digitalWrite(gpio,gv); } //если на выключателе изменилось состояние, то ..
if (digitalRead(gpio) != g) { //если на gpio изменилось состояние, то ..
os_timer_disarm(&esp_timer1); //выключаем первый таймер, чтобы не тикал зря и не генерировал события
// os_timer_disarm(&esp_timer2); //выключаем второй таймер, если включен(он не включен, ну а вдруг?)
g = digitalRead(gpio);
if (g == 0) { w = wmax; fade = -1;} else { w = 0; fade = 1; digitalWrite(gpior,1); }; // проверяем режим
os_timer_setfn(&esp_timer2, (os_timer_func_t *) pwn_wr, NULL); //говорим, что при тике надо вызвать pwn_wr()
os_timer_arm(&esp_timer2, p, 1); //включаем таймер, говорим, что тик должен происходить раз в p мс
}
}
void ICACHE_FLASH_ATTR
startfunc(){ //функция, запускаемая при старте модуля
analogWrite(pw,0); //при старте выключаем ШИМ
digitalWrite(gpior,0); //при старте выключаем реле
digitalWrite(gpios,0); //при старте выключаем вентилятор
digitalWrite(gpiob,0); //при старте выключаем бойлер
//os_timer_disarm(&esp_timer1); //выключаем первый таймер, если включен(он тоже не включен, ну а вдруг?)
os_timer_setfn(&esp_timer1, (os_timer_func_t *) read_gpio, NULL); //говорим, что при каждом тике надо вызвать read_gpio()
os_timer_arm(&esp_timer1, 20, 1); //включаем таймер, говорим, что тик должен происходить каждые 10мс
}
void ICACHE_FLASH_ATTR
timerfunc(uint32_t timersrc) {
}
void webfunc(char *pbuf) {
os_sprintf(HTTPBUFF,"</div><div class=blockk>");
}
Main page
<h3> ДУШЕВАЯ <sub> v0.03 </sub> </h3>
<u>В душевой:</u><br>
Температура <b> _DHTT1_ °C</b> Влажность <b>_DHTH1_ %</b><br>
Вентилятор вытяжки ...._WGPIO13_ <br>
</div><div class=blockk>
<table border="1">
<tr>
<td colspan="2">Управление светом</td>
</tr>
<tr>
<td>Состояние выключателя</td>
<td>_GPIO14_</td>
</tr>
<tr>
<td>Выход вкл/выкл</td>
<td>_WGPIO15_</td>
</tr>
<tr>
<td>Реле включения света</td>
<td>_WGPIO12_</td>
</tr>
<tr>
<td>Яркость света</td>
<td>_PWM0_</td>
</tr>
<tr>
<td>Бойлер</td>
<td>_WGPIO3_</td>
</tr>
</table>
</div><div class=blockk>
Free memory: _MEM_ b.<hr>
Uptime: _UPTIME_<hr>
Local Time: _TIMES_<hr>
VDD: _VDD_
Забыл сказать GPIО12 управляет реле, включающим БП LED ленты.
Есть мысли?