Управление кулерами на основе ардуино


Стоит у меня домашний сервер, и вот проблема: или шумит жутко, или перегревается и виснет. Немного подумав решил что соорудив управление куллерами с этой проблемой хоть не окончательно, но справлюсь.

https://www.youtube.com/watch?v=ghqfvw53gIA


Контроллер решил использовать в корпксе TQFP32 (ATMEGA168-20AU). Куллеры у меня немного различаются — один имеер 2 вывода (только питание), на втором есть 3й контакт — скорость вращения. Скорость вращения регулировать решил через ШИМ. Отображать решил в процентах. На управление решил сделать два режима:
1)Управляется автоматически, в зависимости от температуры. При 45С скорость 70%. При 50С скорость 78%. Третий показатель температуры задается переменным резистером, и включает вращение на 100%. При этом режиме отображается: текущая температура, заданная температура и скорость куллеров в процентах.
2)Ручное управление. Два потенциометра регулируют скорость вращения каждый своего куллера. При этом режиме отображается: Скорость вращения кулера с датчиком в оборотах в минуту (rpm), скорость вращения в процентах, текущая температура.

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

Детали использовал:
HL1 = Светодиод по вкусу
HL2 = Светодиод по вкусу
IC1 = DS18B20
IC2 = ATMEGA168-20AU
LCD = WH1602M-YGH-CTK
M1 = Кулер 12v
M2 = Кулер 12В с датчиком
R1 = 1k
R2 = 10k
R3 = 4.7k
R4 = 50KПеременный с выключателем
R5 = 50KПеременный
R6 = 100
R7 = 100
R8 = 10k
R9 = 10k
S1 = Выключатель в резисторе
VD1 = диод любой smd
VD2 = диод любой smd
VD3 = диод любой smd
VD4 = диод любой smd
VT1 = КТ315б
VT2 = КТ315б
X = 16MHz
Схема spl7:



Плата lay



Скетч:

//Эта библиотека входит в комплект АРДУИНО ИДЕ
#include <LiquidCrystal.h> //библиотека ЛСД экранчика
//Эту библиотеку брал тут: /files/library/OneWire.zip
#include <OneWire.h> //Библиотека работы с 1-ware
//А эту тут: dallas.milesburton.com/index.php?title=Dallas_Temperature_Control_Library#Latest
#include <DallasTemperature.h>//Библиотека работы с термодатсиками 1-ware
#define pwmpinA 10 //Выход ШИМ 1
#define pwmpinB 11 //Выход ШИМ 2
#define HallSensor 2  // pin для датчика оборотов вентилятора (прерывание)
#define ONE_WIRE_BUS 1 //Датчик температуры на аналоговом входе 5
//переключатель встроен в переменный резистор, как только повернул ручку - включился управляемый в ручную режим
#define SWBTN 0 //Переключатель режима работы (Авто/Управляемый) 
OneWire oneWire(ONE_WIRE_BUS);//скажем библиотеке где у нас градусник
DallasTemperature sensors(&oneWire);//скажем библиотеке где у нас градусник
LiquidCrystal lcd(5,6,7,8,9,12); //пины подключения ЛСД
int potB=5; //потенциометр изменения оборотов 2
int potA=0; //потенциометр изменения оборотов 1
int NbTopsFan, Calc, fadeValue, fadeValueA, procfade, procfadeA, CtempA,CtempB;  //целочисленные переменные для расчетов
typedef struct{ // Вводим новый тип переменных для вентиляторов 
  char fantype;
  unsigned int fandiv;
}fanspec;
//Массив переменных нового типа
fanspec fanspace[3]={{0,1},{1,2},{2,8}};
//Переменная, отвечающая за выбор типа датчика вентилятора (1 – униполярный датчик Холла, 2 –биполярный датчик Холла)
char fan = 1;  
//Эта функция у нас будет вызываться при каждом прерывании
void rpm(){NbTopsFan++;}

void rpmcalk()//подсчитываем обороты кулера
{
 NbTopsFan = 0; // Обнуляем переменную, содержащую обороты
 delay (1000); //Ждем 1 секунду
 Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv);   //Рассчитываем величину оборотов за 60 секунд, поделенную на множитель вентилятора
}

void lcdprn()//отображаем информацию на экран
{
lcd.clear();//очистка экрана
lcd.setCursor(0, 0);//курсор на координаты
lcd.print("RPM:");//пишем текст
lcd.print(Calc);//пишем скорость кулера из переменной
lcd.setCursor(8, 0);//курсор на координаты
lcd.print("Spd1:");//пишем текст
lcd.print(procfade);//пишим проценты скорости кулера1
lcd.setCursor(0, 1);//курсор на координаты
lcd.print("Spd2:");//пишем текст
lcd.print(procfadeA);//пишим проценты скорости кулера2
lcd.setCursor(8, 1);//курсор на координаты
lcd.print("Temp:");//пишем текст
lcd.print(CtempA);//пишим температуру
lcd.print("C");//пишем текст
}

void lcdprnA()//отображаем информацию на экран в режиме автоконтроля
{
lcd.clear();//очистка экрана
lcd.setCursor(0, 1);//курсор на координаты
lcd.print("AUTO");//пишем текст значащий что выбран автоконтроль температуры
lcd.setCursor(9, 1);//курсор на координаты
lcd.print("Spd:");//пишем текст
lcd.print(procfade);//пишим проценты скорости кулеров
lcd.setCursor(0, 0);//курсор на координаты
lcd.print("Tmp:");//пишем текст
lcd.print(CtempA);//пишим текущюю температуру
lcd.print("C");//пишем текст
lcd.setCursor(8, 0);//курсор на координаты
lcd.print("CrT:");//пишем текст
lcd.print(CtempB);//пишим температуру КРИТИЧЕСКОГО реагирования
lcd.print("C");//пишем текст
}


void PotReadALL()//читаем и считаем потенциометры
{
  fadeValue=analogRead(potA);//читаем первый потенциометр
  fadeValueA=analogRead(potB);//читаем второй потенциометр
  fadeValue=fadeValue/4;//уменьшаем показания первого потенциометра до приемлимых для ШИМ вывода
  if (fadeValue<=128){fadeValue=128;}//Ограничиваем минимум оборотов до 50%
  procfade=(fadeValue/2.54);//пересчитываем показания первого потенциометра в проценты
  fadeValueA=fadeValueA/4;//уменьшаем показания второго потенциометра до приемлимых для ШИМ вывода
  procfadeA=(fadeValueA/2.54);//пересчитываем показания второго потенциометра в проценты
}

void TempTOvalue()//Читаем температуру с градусника
{
  sensors.requestTemperatures();//Опрашиваем градусники
  //градусник может быть не один, протокол 1-ware позволяет подключать
  //много устройств паралельно, но на моем дисплее место хватило токо на
  //один показатель температуры
  CtempA=sensors.getTempCByIndex(0);//присваиваем температуру переменной
}

//ручная регулировка скорости вращения
void manualcontrol(){

  PotReadALL();//читаем и считаем потенциометры
  rpmcalk();//считаем скорость кулера
  TempTOvalue();
  lcdprn();//Выводим информацию на дисплей
  analogWrite(pwmpinA, fadeValue);//задаем скорость вращения кулера 1         
  analogWrite(pwmpinB, fadeValueA);//задаем скорость вращения кулера 2         
  
}

void autocontrol()//Автоконтроль температуры
{
  PotReadALL();//читаки потенциомерты(с них получим установку критической температуры)
  CtempB=fadeValueA/3; //переводим результат потенциометра в температуру от 0 до 85
  TempTOvalue();//меряем температуру
  fadeValue=0;//сбрасываем показатель скорости
  if (CtempA>=45){fadeValue=180;}//сверяем скорость с критами
  if (CtempA>=50){fadeValue=200;}//сверяем скорость с критами
  if (CtempA>=CtempB){fadeValue=254;}//сверяем скорость с заданой температурой, если задана 
  //температура ниже предыдущих сверок скорость ВСЕГДА на максимуме.
  procfade=(fadeValue/2.54);//пересчитываем показания первого потенциометра в проценты
  lcdprnA();//Выводим информацию на дисплей
  analogWrite(pwmpinA, fadeValue);//задаем скорость вращения кулера 1         
  analogWrite(pwmpinB, fadeValue);//задаем скорость вращения кулера 2         
}

void setup()  { 
  pinMode(HallSensor, INPUT);  // Настраиваем pin на получение прерываний
  pinMode(SWBTN,INPUT); //пин на переключатель -на вход
  attachInterrupt(0, rpm, RISING);  //Привязываем прерывание по номеру 0 к нашей функции, причем высчитываться
 // она будет каждый раз при смене сигнала
  sensors.begin();//включаем сенсор температуры
  lcd.begin(16, 2);//Выставляем параметры экрана
  lcd.home();//очищаем экран и переводим курсор в начало
} 

void loop()  { 
 if (digitalRead(SWBTN)==HIGH){manualcontrol();}  //если переключатель включен - ручное управление вентиляторами
 else {autocontrol();}//иначе - автоконтроль
}

//При разработке этого устройствы использовал следующие статьи:
//http://mk90.blogspot.com/2010/08/arduino.html
///arduino/136.html

Здесь лежит архив со схемами, скетчем и библиотеками.


0 комментариев на «“Управление кулерами на основе ардуино”»

  1. Хаха-я тоже такое соорудил по статье из мк90. Только я делал шилдом к дуине, но потом забил на это и в итоге две платы и пучек проводов-выглядит не ахти, но в корпусе не видно 🙂
    Со временем тоже хочу переделать на одну плату-но не хватает знаний. как это делается? запрограммировал атмегу-выдернул, запаял?
    +еще ко всему у вас теряется возможность перепрошить атмегу, хотя выпаять перепрошить 🙂
    А почему контроль нескольких кулеров не сделали? или вы не сайленсфрик?
    а так вам жииирный плюс-за подробное описание, ибо когда приделывал экранчик не нашел внятного мануала на некоторые функции. правда мне уже не к чему-но новички ваш труд оценят

    • про несколько кулеров-я про цпу/гпу и два корпусных например 🙂 так то у вас два

  2. Два, 1 — 3 пиновый, на проц, 2й — 2 хпиновый на харды. Мне и два кулера слишком мешают спать.
    Возможность перепрошивки не теряется, и выпаивать не обязательно, для прошивки выведены пины sck miso mosi reset, через них шил изначально, т.к. микроконтроллер ради экономии размера использовал в корпусе TQFP32, это как на ардуино нано.

  3. ATmega168-20AU 89.50руб
    Дуины нано дешевле 600руб не видел.
    Да и по размерам с дуиной все равно больше получится.
    Имхо дуина хороша и удобна для прототипирования. Собрал все на макетке, посмотрел, проверил, 10 раз подумал нужно ли это устройство приводить в жизнь или просто поигратся собирал. Если решил что нужно -разводим плату, травим и паяем.

    • Эти от 400 руб.
      По поводу прототипирования согласен на 100%!
      Мне плату разводить, травить… на единичный девайс влом!
      Я возьму макетку и там распаяю :)))

  4. Ну, не знаю, как-то паячными макетками никогда не пользовался, и всегда считал их бесполезными. К тому же не уверен что есть макетки под smd компоненты (тотже TQFP32 например). Да и сомневаюсь на счет целесообразности делать платы ЛУТом массово (имхо для домашних условий удобнее и проще лазерного утюга ничего нет).

    • Что значит не можешь открыть? Он не открываться должен а скачиваться. Попробуй правой кнопкой — сохранить как.

    • Я не использовал эту схему и скетч. У меня всё проще, я использовал freeduino nano, подключил датчик температуры и вентилятор, без LCD и переменников. Использовал пример Oneware, который есть в ардуине, и который читает температуру с датчиков. Дальше используя несложную формулу для конвертации температуры в скорость делаете вызов analogWrite(pwmpinA, fadeValue);
      Всё просто ) Сейчас собираюсь повесить гирлянду датчиков чтобы мерить температуру внутри корпуса, снаружи, на улице и в квартире. А сам сервер будет в нише на балконе 🙂
      Еще бы клёво подключить датчик влажности, счетчик гейгера, тока они шибко дорогие.
      А LCD не нужен, сервер пусть публикует информацию с датчиков на web-страничку, которую можно увидеть с другого компутера, со смартфона, или с телика )

  5. Здравствуйте) я новичок, будте добры проясните ситуацию!
    Транзистор VT2 в роли ключа размыкает/замыкает землю, но на эту же землю замыкается провод Data кулера М2 при каждом обороте. В момент когда «ключ-транзистор» разомкнут, а а провод data замкнулся на землю, оборот считываться не будет, т.е. проподает! или я не прав? проясните ситуацию?

  6. Заливал прошивку через AVRdude, примерно как заливать описывал тут и тут. Сама прошивка создается при компиляции, путь к ней можно узнать если зажать шифт при нажатии кнопки компиляции (в ардиуно версии 0.22).

    Писк слышен из-за того что куллеры могут работать в роли динамиков (принцип устройства один, магнит + обмотка) убрать можно и конденцатером большой емкости или RC фильтром, я его к схеме не пририсовывал так как писк зависит от самого вентилятора, насколько свободно он сидит. Те на которых используется у меня свистят не слышно.

    Видео верну скорее всего не раньше чем после НГ.

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

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Arduino Bluetooth CraftDuino DIY Google IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение