Товары из Китая

Управление компьютерными вентиляторами при помощи ESP8266 — теория и практика.


Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Небольшой топик в DIY сообщество который нацелен на раскрытие темы управления компьютерными вентиляторами (3Pin и 4Pin) при помощи контроллера Esp8266. В статье изучим алгоритм управления шим сигналом напрямую и через мосфет, считывание оборотов вентилятора, а так же добавление девайса в умный дом силами HomeAssistant. 

Если тема интересна то добро пожаловать под кат.  

Начнем статью со спецификаций. Компьютерные вентиляторы стандартизированы, и если обозначить рамки моделей в пределах обычных домашних пк, то можно взять документ от Intel который описывает требования для этих девайсов. 

(может не открываться в Рф и Белоруссии, используйте впн)

https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/intel-4wire-pwm-fans-specs.pdf

Сразу добавлю сюда ссылки на свои даташиы от крупных производителей таких как NCOTUA 

https://noctua.at/pub/media/wysiwyg/Noctua_PWM_specifications_white_paper.pdf

и DELTA 

https://www.delta-fan.com/Upload/PWM/Delta_PWM.pdf

 

Открыв документ от интела, станет понятно что стандарт очень старый и датирован аж 2003 годом а его последнее обновление было в 2005 и видимо стандарт настолько идеален что его изменение с тех лет не потребовалось. 

Если говорить про стандарт кратко то 4пин стандарт максимально прост и требует выполнение таковых условий: 

  • Питание вентилятора в пределах 12в +-5%
  • Ток вентилятора не должен превышать 1,5А при напряжении вплоть но 12,6в но при этом разрешаются пики 2,2А но не более 1 секунды. 
  • Тахометр должен выдавать 2 импульса на 1 оборот крыльчатки
  • Шим сигнал для управления вентилятором должен иметь частоту 25кгц (допускается 21-28кгц, с логическим уровнем от 0,8 до 5,25в, а максимальный ток по этому контакту может составлять 5мА. 

В сноске можно заметить что производитель настойчиво предлагает установить подтяжку 3,3в для пина шим сигнала.

 

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Для подсчета оборотов вентилятор делает 2 импульса на оборот крыльчатки, на выходе квадратная волна которую мы должны считать микроконтроллером. 

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Управление вентилятором не сильно сложнее, на вход подается ве та же квадратная волна разной скважности от которой будет зависеть скорость вращения вентилятора. Заполнение может быть от 0 до 100% но никто не обещает что вентиляторы будут останавливаться, а так же без ШИМ сигнала, все компьютерные вентиляторы будут крутиться на 100% оборотах так как не инвертирован.

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Распиловку коннектора так же лучше взять из документов NOCTUA так как их документ выполнен значительно нагляднее.

Стоит игнорировать 5в и 24в вентиляторы так как это более редкие вариант которые не просто встретить в обычном пк. 

Правда 12в вариант никак не отличается по распиновке от других, и вот как она выглядит:

  1. Черный — земля
  2. Желтый — питание 12в 
  3. Зеленый — Тахометр 
  4. Синий — Шим сигнал

 

Для вентиляторов 3пин ситуация идентичная но из уравнения убирается четвертый (синий) контакт шим управления. При этом дизайн разьема выполнен так что в 4пин можно установить вентилятор с 3пин подключением, и наоборот. 

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Для тестов я буду использовать вентиляторы XPG Vento PRO, так как они есть у меня в наличии, они поддерживают PWM а главное то что я делал обзор на них и прекрасно знаю их характеристики дабы сравнить их с тем что я получаю от микроконтроллера. https://mysku.club/blog/russia-stores/88421.html 

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Практика

Управление ШИМ

Начнем с самого простого, а именно управление вентилятора по ШИМ сигналу. 

Современные микроконтроллеры очень быстры, а огромное комьюнити и поддержка от производителя сделала данную задачу максимально тривиальной.

Для начала надо выбрать пины которые поддерживают ШИМ модуляцию. Все сильно зависит от того какое исполнение у вайшей платы с ESP8266, но зачастую нет никаких проблем поискать рапиновку по запросу «esp8266 вашаплата pinout». 

Вот так для примера выглядит распиновка Wemos D1 mini, а пины с шим сигналом легко определить по небольшой загогулине вместо ровной линии от платы до номера контакта в инфографике. 

Так же советую выбирать пины которые минимально заняты в сервисной жизни контроллера,  например не лучшей идеей будет занимать пины Serial порта, пины общения с памятью или I2c который может понадобиться в будущем. 

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Подробнее про пины, шим и прерывания на ESP8266 можно почитать тут: https://arduino-esp8266.readthedocs.io/en/latest/reference.html

Для управления вентилятором я решил взять пин 6 (GPIO 12) так как он ничем не занят, а так же поддерживает PWM выход.  

В начале кода я объявляю переменную для указания пина который будет использоваться под управление вентилятором.  Можно делать это напрямую в коде но проще и удобнее заранее определить переменные дабы не искать их по коду если их понадобится изменить.

#define Fan_Pin_PWM 12

 

После чего надо настроить выбранный нами пин на выход. 

pinMode(Fan_Pin_PWM, OUTPUT);

 

А теперь важный момент. В стандартном виде частота PWM выходов составляет всего 1кгц и она нам не подходит, ее нужно изменить до 25кгц в соответствии со стандартами для PWM вентиляторов. ЕSP8266 поддерживает частоту от 100гц до 40Кгц, но как говорит документация, чем выше частота и больше портов на высокой частоте, тем выше нагрузка на центральный процессор и меньше циклов процессора на выполнение нашего кода. 

Для установки частоты заедем еще одну переменную настроек на 25000 и применим ее к шим выходам. 

#define Fan_PWM_FRQ 25000

analogWriteFreq(Fan_PWM_FRQ);

 

Для управления сделаем небольшую функцию которая принимает проценты и устанавливает значение на пин. Я использовал простую функцию MAP которая превращает диапазон 0-100 до 0-1024.

void SetFanLevel(int percent) {

analogWrite(Fan_Pin_PWM, map(percent, 0, 100, 0, 1024));
}

 

А теперь все вместе. Я завел .h файл дабы не захламлять основной скетч функциями которым не требуется постоянная модификация.

//Fan.h

//Settings
#define Fan_Pin_PWM 12
#define Fan_PWM_FRQ 25000
//Functions
void InitFan(){
pinMode(Fan_Pin_PWM, OUTPUT);
analogWriteFreq(Fan_PWM_FRQ);
}
void SetFanLevel(int percent) {
analogWrite(Fan_Pin_PWM, map(percent, 0, 100, 0, 254));
}

 

Подсчет оборотов

Теперь код немного усложняется. Но логика очень простая. Мы будем использовать аппаратные прерывания на пине, выставим условие при котором будет вызываться функция, которая будет считать обороты. 

Для начала заведем переменную в которой будут храниться обороты. Приставка volatile  говорит микроконтроллеру что данная переменная должна храниться в RAM а не постоянной памяти.  

//Data

volatile int Fan_InterrupCount;

 

Далее мы добавляем новую переменную для пина тахометра, пин так же выбран по поддерживаемыми фичам и нулевой загруженности сервисными задачами. 

#define Fan_Pin_Tach 14

 

Для пина тахометра включим аппаратную подтяжку как это требует спецификация вентиляторов, напряжение контроллера как раз 3,3в.

pinMode(Fan_Pin_Tach, INPUT_PULLUP);

 

Теперь начинается самое интересное. Нам надо подписаться на изменение состояния пина. Для этого мы пишем данную строку, в ней м указываем какой пин будет вызывать прерывание, какая функция будет вызвана, а так же при каком условии вызывать прерывание. Состояний для вызова всего 3:

  • FALLING — при падение напряжения на пине
  • RISING — при поднятии напряжения на пине
  • CHANGE — при каком либо изменении на пине
attachInterrupt(digitalPinToInterrupt(Fan_Pin_Tach), HandleInterrupt, FALLING);

 

Далее надо написать функцию которая будет обрабатывать прерывание, в моем случае это простейший счетчик который считает +1 если произошел импульс.  Для того что бы функция могла быть вызвана прерыванием, она должна иметь атрибут IRAM_ATTR

void ICACHE_RAM_ATTR HandleInterrupt() { 

Fan_InterrupCount++;
}

 

Таким образом контроллер уже будет считать импульсы от вентилятора, но теперь надо пересчитать их в обороты/секунда. 

Для этого заведем 3 переменных, в первой мы настраиваем частоту опроса вентилятора, во второй будем хранить время для подсчета промежутка между расчётами оборотов, а в третей будут лежать последние рассчитанные обороты вентилятора.

#define Fan_RPM_Update_Period 1000

unsigned long Fan_PrevMills =0;
int Fan_RPM =0;

 

А так же заведем функцию подсчета оборотов.  Она каждые 1000мс (или то как мы настроили) берет последнее кол-во прерываний, пересчитывает в обороты/сек, умножает результат на 60 (тк мы считаем обороты/минута, а получаем обороты за 1 секунду), обнуляет счетчик прерываний и записывает данные в переменную. 

Данная функция должна работать в Loop и абсолютно не дружит с большими Delay(x) а так же зависаниями контроллера. Тут есть свои минусы и плюсы разных решений подсчета, но мне нравится именно это, когда каждую секунду ты просто получаешь данные от вентилятора. 

void CalcFanRPM(){

if ((millis() - Fan_PrevMills) > Fan_RPM_Update_Period) {
Fan_PrevMills = millis();
int count = Fan_InterrupCount;
Fan_RPM = count / 2 * 60;
Fan_InterrupCount=0;
}
}

 

Для удобства в функцию расчета я добавил вызов функции  DisplayFanRPM(), и теперь каждую 1сек в сериал порт выводятся данные об оборотах вентилятора.

void DisplayFanRPM() {

Serial.print(Fan_RPM, DEC);
Serial.print(" RPMrn");
}

 

Немного доработаем тестовый скетч и проверим результат.

#include "Fan.h"

int brightness = 0; // how bright the LED is
int fadeAmount = 1; // how many points to fade the LED by

void setup() {
InitFan();
}

void loop() {
CalcFanRPM();
SetFanLevel(brightness);
brightness = brightness + fadeAmount;
if (brightness <= 0 || brightness >= 100) {
fadeAmount = -fadeAmount;
}

//Добавим вывод данных об уровне для удобства.
Serial.print(brightness, DEC);
Serial.print(" Levelrn");

delay(300);
}

 

Максимальные обороты как и ожидалось оказались на уровне 2300об/мин, минимальные обороты аж 260, что немного больше чем должно быть но в целом в рамках нормы. 

На графике видно что при понижении напряжения можно добиться еще меньше оборотов но об этом дальше.

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

 

А так выглядит наша импровизированная библиотека:



//Settings
#define Fan_Pin_Tach 14
#define Fan_Pin_PWM 12
#define Fan_PWM_FRQ 25000
#define Fan_RPM_Update_Period 1000
//Data
volatile int Fan_InterrupCount;
unsigned long Fan_PrevMills;
int Fan_RPM;
void ICACHE_RAM_ATTR HandleInterrupt() { //This is the function called by the interrupt
Fan_InterrupCount++;
}
void InitFan(){
Fan_InterrupCount=0;
Fan_RPM=0;
Fan_InterrupCount=0;
//Fan Controls
analogWriteFreq(Fan_PWM_FRQ);
pinMode(Fan_Pin_PWM, OUTPUT);

//Fan data
pinMode(Fan_Pin_Tach, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(Fan_Pin_Tach), HandleInterrupt, FALLING);
}
void SetFanLevel(int percent) {
analogWrite(Fan_Pin_PWM, map(percent, 0, 100, 0, 255));
}
void DisplayFanRPM() {
Serial.print(Fan_RPM, DEC);
Serial.print(" RPMrn");
}
void CalcFanRPM(){
if ((millis() - Fan_PrevMills) > Fan_RPM_Update_Period) {
Fan_PrevMills = millis();
int count = Fan_InterrupCount;
Fan_InterrupCount=0;
Fan_RPM = count / 2 * 60;

DisplayFanRPM();
}
}

 

Теперь опробуем управлять сразу двумя вентиляторами. На этом пункте придется убрать функционал замера оборотов, так как он начинает выдавать полную ерунду. 

Дорабатываем функции инициализации вентилятора и применении уровня оборотов. 

Теперь каждая из функций будет принимать сначала пин на котором находится вентилятор. 

//Settings 

#define Fan_PWM_FRQ 25000

void InitFan(int fanpin){
//Fan Controls
analogWriteFreq(Fan_PWM_FRQ);
pinMode(fanpin, OUTPUT);
}
void SetFanLevel(int fanpin,int percent) {
analogWrite(fanpin, map(percent, 0, 100, 0, 255));
}

 

Заменим код тестового скетча, теперь вентиляторы меняют свою скорость относительно друг друга. 

#include "Fan.h"

int brightness = 0;
int fadeAmount = 1;
void setup() {
Serial.begin(115200);
InitFan(14);
InitFan(12);
}
void loop() {
brightness = brightness + fadeAmount;
if (brightness <= 0 || brightness >= 100) {
fadeAmount = -fadeAmount;
}
Serial.print(brightness, DEC);
Serial.print(" Fan levelrn");
SetFanLevel(14, brightness);
SetFanLevel(12, 100-brightness);
delay(300);
}

 

Для более наглядной демонстрации я поставил статичные обороты, левый крутится на 100% а правый на 1%

#include "Fan.h"

void setup() {
Serial.begin(115200);
InitFan(14);
InitFan(12);
SetFanLevel(14, 1);
SetFanLevel(12, 1);
}
void loop() {
}
Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

 

Подключение к умному дому HomeAssistant

Теперь перейдем к более практичному примеру управления вентилятором. 

 

Первым делом конечно же создаем прошивку в ESPHOME и прошиваем ее в контроллер. 

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

И теперь можно начать писать YAML файл для управления вентилятором. 

fan:

- platform: speed
output: Vento_Pro_PWM
name: "XPG Vento PRO Test"
output:
- platform: esp8266_pwm
id: Vento_Pro_PWM
#Пин вентилятора
pin: 14
#Частота шим для управления вентилятором
frequency: "25000 Hz"
#Диапазон оборотов вентилятора
min_power: 1%
max_power: 100%

 

Для управления вентилятором я добавил карточку на тестовую страницу, это Mushrom карточка которой нет в обычном HomeAssistant.

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

А вот так работает управление из панели умного дома. Как видно все работает но при этом отключить вентилятор полностью не удастся, ниже минимальных оборотов он по PWM сигналу крутиться не может. 

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Решить проблему выключения вентилятора можно двумя возможными вариантами. 

1 — Поставить мосфет. Достаточно любого мосфета на ток 2+А и с управлением от 3в, в коде ESPHOME добавить автоматизацию которая будет следить за выставленным уровнем вентилятора и если он более 0 то включить мосфет, а если 0 то выключить. Тем самым можно полностью выключать вертушку. В теории можно управлять питанием вентилятора через этот мосфет, но на практике я пробовал разную частоту контроллера но периодически вентиляторы пищали и сильно роняли обороты (хотя некоторые вентиляторы работают нормально), в общем не везде подойдет этот вариант. 

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

 

 2 — Поставить не мосфет а транзистор, за счет чего можно получить плавную регулировку напряжения (подавать шим сигнал не на вентилятор а на транзистор который управляет питанием вентилятора). С таким вариантом управления можно не только останавливать вентилятор, но и получить более низкие обороты чем заявлены производителем !

Cхема еще проще чем с мосфетом если взять не просто транзистор а сборку Дарлингтона (например TIP122). 

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Например вентилятор XPG VENTO PRO имеет заявленный диапазон от 450 до 2150 оборотов, при управлении сигналом PWM самые низкие обороты составили 242!

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Но если регулировать его входное напряжение то можно добиться еще меньших оборотов, вплоть до 141!

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Единственный минус такого способа это конечно же кпд, транзистор будет греться, но потребление обычных домашних вертушек достаточно низкое и небольшой радиатор может решить эту проблему.

При желании можно добавить еще один вентилятор в конфиг и управлять уже парой PWM вертушек, но не забываем ограничения PWM из документации, высокая частота требует много производительности от столь малого чипа, поэтому если вы хотите управлять несколькими вертушками то стоит взять контроллер помощнее (например ESP32)

Управление компьютерными вентиляторами при помощи ESP8266 - теория и практика.

Собственно в таком виде 2 вентилятора и контроллер отправились в серверную стойку где они управляются через NodeRed в зависимости от температуры воздуха в стойке. 

На этом я закончу данный материал. Всем удачных самоделок и самых умных домов!


СМОТРИ ТАКЖЕ

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *