03.09.2014, 14:19
|
#1
|
Я тут недавно
Регистрация: 19.02.2014
Адрес: Харьков
Сообщений: 88
Поблагодарил(а) : 46
Поблагодарили 106 раз(а) в 49 сообщениях
|
Крышка с простым контроллером на Arduino (4-х канальный свет + нагрев/охлаждение) ===www.aquaforum.ua===
Привет всем форумчанам!
На днях смастерил крышечку с контроллером на Arduino, решил поделиться, может кому-то будет полезно.
Основными задачами, возложенными на контроллер были:
- управление четырьмя каналами света по расписанию;
- измерение температуры и ее контроль при помощи нагревателя и вентилятора;
- симпатичный экранчик с кучей букав, производящий на окружающих неизгладимое впечатление
Список покупок:
- БП 12В, 2А;
- стабилизатор 5В L7805ABV;
- Arduino Nano V3.0 AVR ATmega328 P-20AU;
- датчик температуры DS18B20;
- Real Time Clock Модуль (DS1307);
- 2х канальное реле 5В 10А;
- LCD 1602 I2C;
- светодиоды (1 x Hyper red, 1 x Royal Blue, 1 x Blue, 1 x Cyan, 1 x White 6000K, 1 x UV 420 nm);
- драйверы (2 x LDD350L, 2 x LDD600L);
- резисторы, конденсаторы, термоскотч и прочая мелочевка.
Схема соединения основных элементов (полноразмерная схема в приложении)
Программу для контроллера писал пару вечеров вооружившись гуглом и сочетаниями клавиш Ctrl+C, Ctrl+V. Получилось примерно так:
Скрытый текст
#include <Wire.h> // Подключаем библиотеки
#include "RTClib.h" // Подключаем библиотеки
#include <LiquidCrystal_I2C.h> // Подключаем библиотеки
#include <OneWire.h> // Подключаем библиотеки
OneWire ds(10); // Назначаем датчику температуры 10-й вывод
LiquidCrystal_I2C lcd(0x27,16,2); // Подключаем дисплей по i2c
RTC_DS1307 RTC; // Подключаем часики
int Hours_Start_Sunrise[4] = {5, 6, 8, 11}; // Начало рассвета по каналам час
int Minutes_Start_Sunrise[4] = {0, 0, 0, 0}; // Начало рассвета по каналам минута
int Hours_End_Sunrise[4] = {9, 10, 11, 11}; // Окончание рассвета по каналам час
int Minutes_End_Sunrise[4] = {0, 0, 0, 30}; // Окончание рассвета по каналам минута
int Hours_Start_Sunset[4] = {17, 16, 15, 17}; // Начало заката по каналам час
int Minutes_Start_Sunset[4] = {0, 0, 0, 0}; // Начало заката по каналам минута
int Hours_End_Sunset[4] = {20, 18, 18, 17}; // Окончание заката по каналам час
int Minutes_End_Sunset[4] = {0, 0, 0, 30}; // Окончание заката по каналам минута
int MinuteDay_Start_Sunrise[4]; // День в минутах для начала рассвета
int MinuteDay_End_Sunrise[4]; // День в минутах для окончания рассвета
int MinuteDay_Start_Sunset[4]; // День в минутах для начала заката
int MinuteDay_End_Sunset[4]; // День в минутах для окончания заката
int Current_MinuteDay; // Текущая минута суток
int Current_Period[4]; // Текущая часть суток 1-рассвет, 2-день, 3-закат, 4-ночь для каждого ШИМ
int Meridian_PWM[4] = {250, 250, 250, 250}; // Максимальное значение ШИМ
int Midnight_PWM[4] = {0, 2, 0, 0}; // Минимальное значение ШИМ
int Current_PWM[4] = {0, 2, 0, 0}; // Текущее значение ШИМ
int TargetTemp = 26; // Температура, которую нужно поддерживать
/* ******************************************** */
/* * * */
/* * ШИМ пин для UV+RB, B+C, CW, HR * */
/* * Пин - 3 - UV+RB - UV + Royal Blue * */
/* * Пин - 5 - B+C - Blue + Cyan * */
/* * Пин - 6 - CW - Cool White * */
/* * Пин - 9 - HR - Hyper Red * */
/* * * */
/* ******************************************** */
int PWM_Pin[4] = {3, 5, 6, 9}; // ШИМ пин для UV+RB, B+C, CW, HR
int Relay1 = 7; // Пин реле для включения вентилятора
int Relay2 = 8; // Пин реле для включения нагревателя
void setup()
{
lcd.init(); // Инициализация LCD
lcd.backlight(); // Включаем подсветку
lcd.clear(); // Очистка дисплея
Serial.begin(57600); // Подключаем порт
Wire.begin(); // Включаем шину часиков
RTC.begin(); // Включаем часики
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
//RTC.adjust(DateTime(__DATE__, __TIME__));
//RTC.adjust(DateTime(2012, 7, 12, 22, 48, 1));
}
for (int i=0; i<=3; i++)
{
pinMode(PWM_Pin[i], OUTPUT); // Установка пин для ШИМ
}
for (int i=0; i<=3; i++)
{
analogWrite(PWM_Pin[i], Midnight_PWM[i]); // Установка минимального значения ШИМ
Current_PWM[i]=Midnight_PWM[i]; // Установка текущих значений ШИМ в минимум
}
for (int i=0; i<=3; i++)
{
MinuteDay_Start_Sunrise[i]=60*Hours_Start_Sunrise[i] + Minutes_Start_Sunrise[i]; // Расчет минуты суток для начала рассвета
MinuteDay_End_Sunrise[i]=60*Hours_End_Sunrise[i] + Minutes_End_Sunrise[i]; // Расчет минуты суток для окончания рассвета
MinuteDay_Start_Sunset[i]=60*Hours_Start_Sunset[i] + Minutes_Start_Sunset[i]; // Расчет минуты суток для начала заката
MinuteDay_End_Sunset[i]=60*Hours_End_Sunset[i] + Minutes_End_Sunset[i]; // Расчет минуты суток для окончания заката
}
pinMode(Relay1, OUTPUT); // Подключаем пин реле 1 как выход
pinMode(Relay2, OUTPUT); // Подключаем пин реле 2 как выход
digitalWrite(Relay1, HIGH); // Переключаем реле в режим "Выкл" (для этого сигнал должен быть "HIGH")
digitalWrite(Relay2, HIGH); // Переключаем реле в режим "Выкл" (для этого сигнал должен быть "HIGH")
}
// Процедура расчета текущего периода и значения PWM по каналам
void Led_Dim_PWM()
{
DateTime now = RTC.now();
Current_MinuteDay = (now.hour() * 60) + now.minute();
for (int i=0; i<=3; i++)
{
Current_Period[i]=4;
if (Current_MinuteDay>=MinuteDay_Start_Sunrise[i] && Current_MinuteDay<=MinuteDay_End_Sunrise[i]) {Current_Period[i]=1;}
if (Current_MinuteDay>MinuteDay_End_Sunrise[i] && Current_MinuteDay<MinuteDay_Start_Sunset[i]) {Current_Period[i]=2;}
if (Current_MinuteDay>=MinuteDay_Start_Sunset[i] && Current_MinuteDay<=MinuteDay_End_Sunset[i]) {Current_Period[i]=3;}
if (Current_Period[i]==1)
{
Current_PWM[i]=(float)(((float)Current_MinuteDay-MinuteDay_Start_Sunrise[i])/((float)MinuteDay_End_Sunrise[i]-MinuteDay_Start_Sunrise[i]))*((float)Meridian_PWM[i]-Midnight_PWM[i]);
if (Current_PWM[i]<Midnight_PWM[i]) {Current_PWM[i]=Midnight_PWM[i];}
analogWrite(PWM_Pin[i], Current_PWM[i]);
}
if (Current_Period[i]==2)
{
if (Current_PWM[i]!=Meridian_PWM[i])
{
Current_PWM[i]=Meridian_PWM[i];
analogWrite(PWM_Pin[i], Current_PWM[i]);
}
}
if (Current_Period[i]==3)
{
Current_PWM[i]=(float)(((float)MinuteDay_End_Sunset[i]-Current_MinuteDay)/((float)MinuteDay_End_Sunset[i]-MinuteDay_Start_Sunset[i]))*((float)Meridian_PWM[i]-Midnight_PWM[i]);
analogWrite(PWM_Pin[i], Current_PWM[i]);
}
if (Current_Period[i]==4)
{
if (Current_PWM[i]!=Midnight_PWM[i])
{
Current_PWM[i]=Midnight_PWM[i];
if (Current_PWM[i]<Midnight_PWM[i]) {Current_PWM[i]=Midnight_PWM[i];}
analogWrite(PWM_Pin[i], Current_PWM[i]);
}
}
}
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.print(" Current_MinuteDay: ");
Serial.print(Current_MinuteDay, DEC);
Serial.println();
for (int i=0; i<=3; i++)
{
Serial.print("Channel #");
Serial.print(i, DEC);
Serial.print(", Current Period: ");
if (Current_Period[i]==1) {Serial.print("Sunrise");}
if (Current_Period[i]==2) {Serial.print("Meridian");}
if (Current_Period[i]==3) {Serial.print("Sunset");}
if (Current_Period[i]==4) {Serial.print("Midnight");}
Serial.print(", Current PWM: ");
Serial.print(Current_PWM[i], DEC);
Serial.println();
}
Serial.println();
// Выводим на дисплей текущее время
lcd.setCursor(0, 0);
lcd.print(now.hour(), DEC);
lcd.print(":");
if (now.minute() < 10) {lcd.print("0");}
lcd.print(now.minute(), DEC);
// Выводим на дисплей текущие значения PWM по каналам
lcd.setCursor(0, 1);
lcd.print(Current_PWM[0]);
lcd.print(" ");
lcd.setCursor(4, 1);
lcd.print(Current_PWM[1]);
lcd.print(" ");
lcd.setCursor(9, 1);
lcd.print(Current_PWM[2]);
lcd.print(" ");
lcd.setCursor(13, 1);
lcd.print(Current_PWM[3]);
lcd.print(" ");
}
void loop () {
// Вычисляем температуру
byte data[2];
ds.reset();
ds.write(0xCC);
ds.write(0x44);
delay(750);
ds.reset();
ds.write(0xCC);
ds.write(0xBE);
data[0] = ds.read();
data[1] = ds.read();
int Temp = (data[1]<< 8)+data[0];
Temp = Temp>>4;
Serial.print("Temperature = ");
Serial.print(Temp, DEC);
Serial.print(" C");
Serial.println();
// Выводим температуру на дисплей
lcd.setCursor(6, 0);
lcd.print("T=");
lcd.print(Temp);
lcd.print("C");
// Задаем режимы работы реле в зависимости от измеренной температуры
if (Temp > TargetTemp)
{
digitalWrite(Relay1, LOW);
digitalWrite(Relay2, HIGH);
lcd.setCursor(12, 0);
lcd.print("Cool");
Serial.println("Temp is high, cooling");
}
if (Temp == TargetTemp)
{
digitalWrite(Relay1, HIGH);
digitalWrite(Relay2, HIGH);
lcd.setCursor(12, 0);
lcd.print("None");
Serial.println("Temp is normal, standby");
}
if (Temp < TargetTemp)
{
digitalWrite(Relay1, HIGH);
digitalWrite(Relay2, LOW);
lcd.setCursor(12, 0);
lcd.print("Heat");
Serial.println("Temp is low, heating");
}
Led_Dim_PWM();
// Выставляем частоту обновления данных 10 секунд
delay(10000);
}
Все библиотеки в приложении, версия программы - arduino-1.0.5-r2
Итоговая конструкция выглядит вот так:
Лицевая панель
Дисплей показывает время, температуру, режим (нагрев или охлаждение), ШИМ по каждому каналу.
Начинка
Светодиоды и драйверы (да простят меня гуру паяльника и канифоли!)
Датчик температуры в гидроизолированном кожухе
З.Ы. Не судите строго, моя первая крышка!
Немножко подредактировал программу. Исправил мелкие недочеты в работе дисплея. Версию 1.0.7 приложил.
Последний раз редактировалось Alexander_Kharkov; 19.09.2014 в 22:18..
|
|
|
18 пользователей поблагодарили Alexander_Kharkov за данный пост:
|
***шерхан*** (17.12.2014), AQUAPLUS (08.10.2014), avk71 (10.09.2014), Dellmoon (13.11.2014), Gennadiy_Yer (24.09.2014), GreenD (10.09.2014), maksim_pw (05.09.2014), markel2771 (12.12.2014), mikhail.glushko (05.03.2015), mirashic (26.11.2014), Nox (16.09.2014), Oppozith (11.12.2014), Sergeys (05.02.2015), Skiff (02.10.2014), Spam4eg (02.10.2014), акв@фанат (12.09.2014), Андрій Шевчук (13.09.2014), Вбою (05.09.2014) |
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Текущее время: 03:52. Часовой пояс GMT +3.
|