24.08.2010

Термоконтроллер на Arduino

Уважаемые читатели!

Эта статья написана не мной, посему - прошу любить и жаловать: сегодня Vergellan поделится с вами опытом создания умного регулятора вращения вентиляторов, с участием термодатчика, LCD-дисплея и, конечно же, Arduino.

Несколько месяцев назад я прочел ряд статей об Arduino и весьма заинтересовался данным девайсом, а вскоре решил приобрести. Надо отметить, что я далек от микроэлектроники, поэтому плата расположила к себе прежде всего относительной простотой в освоении. Набаловавшись с LED-ами и «Hello world»-ами, захотелось сделать что-нибудь практичное, заодно более детально ознакомиться с возможностями Arduino. Памятуя об аномально жарком лете 2010 года, возникла идея собрать регулятор оборотов кулера в зависимости от температуры с выводом всех сопутствующих характеристик на LCD. Надеюсь, что кому-нибудь данная схема или ее вариации смогут пригодиться, поэтому решил выложить свои наброски.


Для данной схемы нам понадобится:
  • Собственно сама плата Arduino или аналог;
  • Макетная плата для сборки компонентов схемы;
  • Дисплей WH1601A-NGG-CT с подстроечным резистором на 20 кОм или аналогичный;
  • Резисторы – 220 Ом, 10 кОм, 4.7 кОм;
  • Биполярный транзистор SS8050D или аналогичный ему;
  • Цифровой температурный датчик DS18B20;
  • Диод 1N4148 или аналог;
  • Вентилятор осевой трехпроводной (на 12В), например - компьютерный;
  • Разъем гнезда питания 2,1/5,5 мм.
Компьютерный кулер имеет три провода, два из которых - красный (+12V) и черный (GND) используются для питания, а третий  (желтый) связан с таходатчиком, построенном на элементе Холла. К сожалению,  5V с платы нам явно недостаточно, но 6 цифровых выходов Arduino могут работать в режиме ШИМ (они отмечены на самой плате белыми квадратиками, либо буквами PWM), поэтому мы можем регулировать подачу сигнала с платы на реле, которое будет отвечать за изменение напряжения, подаваемого на вентилятор.


Получать информацию об оборотах мы будем с третьего провода от таходатчика, воспользовавшись модифицированным способом, основанным на реализации прерываний, которые у большинства Arduino могут приходить на цифровые pin 2 (прерывание 0) и 3 (прерывание  1). Кстати, у Arduino Mega наличествует еще 4 дополнительных пина с возможностью получения прерываний.

Теперь необходимо расположить цифровой датчик температуры, данные которого мы будем использовать для регулирования напряжения, подаваемого на цифровой выход с ШИМ, а следовательно для «открытия» канала напряжения  вентилятора. Для датчиков фирмы Dallas существует собственная библиотека Arduino – DallasTemperature, которую впоследствии мы и будем подключать в скетче. Библиотеку необходимо распаковать в каталог arduino-0018/libraries/.

Осталось последнее – подключить LCD, где у нас будет отображаться вся текущая информация о температуре и скорости вентилятора. Поскольку я использовал для сборки экран WH1601A, могут иметь место известные проблемы с отображением строк. Для их устранения мы воспользуемся библиотекой LiquidCrystalRus, которую необходимо также распаковать  в каталог arduino-0018/libraries/.

//Подключаем библиотеку для термодатчика 
#include <dallastemperature.h>
//Подключаем библиотеку для LCD
#include <LiquidCrystalRus.h> 

#define PowerPin 9    // pin для контроля питания вентилятора
#define HallSensor 2  // pin для датчика оборотов вентилятора (прерывание)
#define TempPin 7 // pin для датчика температуры

LiquidCrystalRus lcd(12, 11, 10, 6, 5, 4, 3); //Подключение LCD
DallasTemperature tempSensor;                            

int NbTopsFan, Calc, fadeValue;  //целочисленные переменные для расчетов
float temper;  //вещественная переменная для хранения температуры

typedef struct{ // Вводим новый тип переменных для вентиляторов 
  char fantype;
  unsigned int fandiv;
}fanspec;

//Массив переменных нового типа
fanspec fanspace[3]={{0,1},{1,2},{2,8}};

//Переменная, отвечающая за выбор типа датчика вентилятора (1 – униполярный датчик Холла, 2 –биполярный датчик Холла)
char fan = 2;   

//Эта функция у нас будет вызываться при каждом прерывании
void rpm () 
{
  NbTopsFan++; 
}

// Функция расчета подаваемого напряжения на цифровой pin с ШИМ
void temp ()   
{
  fadeValue = min(int(temper*7),255);  // Умножаем температуру на коэффициент, 
                                       // берем от произведения целое число
}  // Т.к. максимальное значение ШИМ составляет 255, то подавать больше не имеет смысла – берем минимум из двух

void setup()
{
    tempSensor.begin(TempPin);  //Запускаем температурный датчик
    lcd.begin(16, 2); //Задаем характеристики LCD
    lcd.setDRAMModel(LCD_DRAM_WH1601); //И тип дисплея
    pinMode(HallSensor, INPUT);  // Настраиваем pin на получение прерываний
    attachInterrupt(0, rpm, RISING);  //Привязываем прерывание по номеру 0 к нашей функции, причем высчитываться она будет каждый раз при смене сигнала
}

void loop ()
{
   temper = tempSensor.getTemperature(); // Получаем температуру
   temp(); // Высчитываем подаваемое напряжение на ШИМ
   analogWrite(PowerPin, fadeValue); // Подаем его
   NbTopsFan = 0; // Обнуляем переменную, содержащую обороты
   delay (1000); //Ждем 1 секунду
   Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv);   //Рассчитываем величину оборотов за 60 секунд, поделенную на множитель вентилятора
   lcd.print (Calc, DEC); //Выводим рассчитанную величину в десятичном виде
   lcd.print (" rpm - "); 
   lcd.print(temper); //Выводим температуру
   lcd.home(); 
}


У меня финальная схемка выглядит так (часть компонентов перенес с макетки на дополнительную плату, т.к. планирую сделать уже готовый регулятор в нормальном корпусе):


В завершение хотел бы выразить огромную благодарность Илье Данилову (idanilov) за «привитый» интерес к Arduino и за помощь в освоении данной платформы.

UPD: Последняя версия LiquidCrystalRus доступна на github.

4 комментария:

  1. Собрал по схеме, счетчик оборотов постоянно скачет и показывает не реальные значения то 5382, то 940, возможно ли такое из-за того, что у меня источник питания 12В 0,15А, а вентилятор требует 12В 0,16А =)

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

    int fanspeed = map(val, 25, 28, 50, 255);
    analogWrite(FAN, fanspeed);

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

    ОтветитьУдалить
  2. То, что написано на вентиляторе, особенно китайского производства, далеко от реальности. Как обычно завышено. На вентиляторе написано: 12V 0,14A. Подключив к источнику питания через LM7812 получаем 12В и 0,09A на полных оборотах.

    ОтветитьУдалить
  3. #include На сайте мертва ссылка на эту библиотеку. А новая 372 бета, не поддерживает это название, она распознает только #include Но после даже этой замены не компилируется
    ошибка в этой строке: DallasTemperature tempSensor; (текст ошибки в командной строке: no matching function for call to 'DallasTemperature::DallasTemperature()')

    ОтветитьУдалить