1. Контроллер своими руками

<< 2345678 10 >>

Посетитель





78
Palestinian Territory Ramallah
6 мес. назад
1. Контроллер своими руками
В данной теме я постараюсь изложить материал так, чтобы он был доступен самому неопытному в части электроники и программирования пользователю.
Позже тема будет развиваться. В итоге я расскажу как изготовить устройство, которое по своим характеристикам не уступает тому, что можно преобрести в готовом исполнении. Точнее в готовом ничего даже близко подходящего Вы не найдете.

В качестве платформы будем использовать Arduino. Это устройство может работать как автономно (запитав его любым адаптером 7-12V или батарейкой), так и подключенным к компьютеру. Имеет 20 цифровых вводов/выводов, 6 из которых могут быть использованы как аналого-цифровые преобразователи, еще 6 могут работать в режиме широтно-импульсной модуляции. Встроенные интерфейсы I2C и SPI. И много чего еще. Более подробно: http://arduino.ru/Hardware/ArduinoBoardUno. Такая организация позволяет подключить к Arduino практически любое электронное приспособление. Простой язык программирования и наличие в сети готовых библиотек для популярных устройств позволяет без труда реализовать на базе Arduino любой проект.

Грубо говоря, до знакомства с Arduino мои знания в электроние ограничивались законом Ома. Через пару часов после приобретения я уже реализовывал простые проекты, а еще через пару дней террариум был оборудован контроллером.

Что нам понадобиться:
1. Контроллер Ардуино. Arduino на E-bay
Вариант Nano удобнее всего использовать в итоговом устройстве (стоит около 450р, есть варианты и дешевле, но по USB они напрямую не подключаются, поэтому лучше немного переплатить, и использовать более удобное). Для прототипирования лучше использовать UNO (цена ~600р)
2. Датчик влажности и температуры. Датчики DHT* на E-bay
Цена от 100р в зависимости от точности. Желательно использовать DHT21 или DHT22. У DHT11 погрешность измерения температуры +-2 градуса, что существенно.
3. Релейный модуль. Релейный модуль (цена от 100р)
Такие модули бывают от 1, 2, 4, 8 до 16 (видел и 32 для маньяков) выводов, т.е. чем больше устройств надо заюзають, тем больше модуль.
4. Резистор на 10 kOm 1шт. Купить можно в ближайшем магазине радиодеталей. Цена 3р (не в ближайшем 60коп ).
5. Провода. Удобные шнуры для датчика и соединений.

Не буду рассказывать об Arduino. Вот ссылка, где о нем есть несколько статей Амперка, которые позволят быстро подружить это устройство с компьютером (см. видео Первые шаги). Кстати кто не хочет связываться с E-bay по тем или иным причинам, практически все причендалы можно купить в их интернет магазине (не сочтите за рекламу).
Но поверьте, в покупках на E-bay нет ничего сложного. Правда ждать посылку придется около месяца, но зато бюджет устройства будет в разы меньше.

Так же нам понадобится библиотека для работы с датчиком, взять ее можно здесь: https://github.com/adafruit/DHT-sensor-library. Папку поместить в каталог libraries\ установленной программы Arduino

Вот прототип (его я собрал и запрограммировал за 5 минут из того, что валялось под рукой):


Подключение датчика (Подробно тут):
1-й пин датчика подключаем к 5v от Arduino
2-й пин датчика к 8-му (или любому понравившимуся) пину Arduino. Так же через резистро 10 кOm этот пин надо подтянуть к 5v.
3-й никуда не подключаем.
4-й пин к Земле.

Подлюкчаем Реле (все еще проще чем с датчиком).
1. Соединяем с питанием. На модуле будет указано, какой пин отвечает за 5v (VCC) и Землю (GND)
2. Цифровые пины Arduino подключаем к управляющим пинам модуля (In1, In2 и т.д.). В данном случае к 6 и 7.

Железо готово! Через реле подлючаем необходимые устройства и доставляем радость животному.


Мы использовали всего 3 из 18-ти возможных управляющих пинов. Это значит, что мы уже знаем как к тому же самому контроллеру подлючить еще 5 террариумов с независимым управлением (обладая более углубленными знаниями мы бы знали, как подлючить еще не один десяток...).

Чуть не забыл, вот текст программы, который надо загрузить в устройство, чтобы все заработало (программа максимально упрощена, для удобства восприятия и возможности внесений изменений. Используем простой принцип, если температура опустилась ниже указанной отметки, то включаем обогрев; с влажностью аналогично):

#include <DHT.h> // Подключаем библиотеку для работы с датчиком

#define DHTPIN 8 // Считывающий пин с датчика
#define DHTTYPE DHT11 // Модель датчика
#define tPIN 7 // Пин управления температурой
#define hPIN 6 // Пин управления влажностью

DHT dht(DHTPIN, DHTTYPE); // Создаем объект dht

int tStatus = HIGH; // определяем переменную, отвечающую за состоянеие нагревателя HIGH=выкл, LOW=вкл
int temp = 28; // Желаемая температура в градусах Цельсия (изменить на нужную)
int hStatus = HIGH; // определяем переменную, отвечающую за состоянеие увлажнителя HIGH=выкл, LOW=вкл
int hum = 45; // Желаемая влажность (изменить на нужную)

void setup() // инициализация основных данных
{
Serial.begin(9600); // Инициализируем COM-порт
dht.begin(); // Инициализируем датчик
pinMode(tPIN, OUTPUT); // Определяем пин для управления температурой как Вывод
digitalWrite(tPIN, tStatus); // Притягиваем пин к начальному статусу (Выкл)
}

void loop() // зацикливание (код управляющей программы)
{
int h = dht.readHumidity(); // Считываем влажность
int t = dht.readTemperature(); // Считываем температуру
tStatus = (t < temp) ? LOW:HIGH; // Если температура меньше желаемой, то статус обогревателя=Вкл, в противном случае Выкл
digitalWrite(tPIN, tStatus);
if (h < hum) hStatus = LOW; else hStatus = HIGH; // Если влажность меньше желаемой, то статус увлажнителя=Вкл, в противном случае Выкл
digitalWrite(hPIN, hStatus);
delay(1000); // Задержка в 1 секунду
Serial.print("t="); Serial.print(t); Serial.print(" h="); Serial.println(h); // Отправляем информацю о климате на COM-порт
}


Примечание (бонус ). При подключении к компютеру с COM порта можно будет считать информацию о температуре и влажности в цифрах. В самой программе Arduino можно открыть COM-монитор с помощью меню Tools/Serial Monitor и с периодичность в 1 сек будет обновляться инфа о температуре и влажности

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

Если тема будет интересна то:
1. В следующий раз я расскажу, как наше устойство "научить" работать со времененем. И в зависимости от времени суток менять характеристики климата, а так же к реле подключить Освещение, которое будет включаться утром и выключаться вечером (если у Вас останутся свободные каналы...).
2. И по нарастающей... LCD-Дисплей с информацией; эффект рассвета и заката; управление с пульта ДУ, ПК или сенсорной панели; использование транзисторов вместо реле для устройств работающих от малого постоянного тока; и пр.

С вопросами и пожеланиями не стесняемся. Кому интересно, помогу чем смогу.

Изменено 27-4-2012 автор CiberRus
2012-03-26 добавлено 26/03/2012 13:37:26#365640

Новенький





46
Russian Federation Kazan
16 час. назад
aleksjet

Слушай,они ночью-то стекочат наверное очень?

CiberRus извини пожалуйста. За то,что в твоей теме флуд развели

Изменено 12-2-2013 автор Rust

Изменено 12-2-2013 автор Rust
2013-02-12 добавлено 12/02/2013 15:33:18#397689

Новенький





5
Russian Federation Chelyabinsk
6 г. назад
Мой вариант скетча
Этот вариант работает на моем терре
пришлось воспользоваться другой библиотекой для ds1307
и еще у меня время устанавливается кнопками, вход в режим установки времени - долгим нажатием на кнопку 3


#include <DHT.h> // Подключаем библиотеку для работы с датчиком
#include <DS1307.h> // Подключаем библиотеку управления модулем реального времени
//#include <Time.h> // Подключаем библиотеку работы с часами
//#include <DS1307new.h>
#include <LiquidCrystalExt.h> // Подключаем библиотеку управления экраном
#include <LineDriver.h> // Далее вспомогательные библиотеки для реализации интерфейса SPI
#include <SPI.h>
#include <SPI_Bus.h>
#include <Wire.h>
//#include <LiquidCrystal.h> // Подключаем стандартную библиотеку управления экраном
#include <EEPROM.h> // Подключаем библиотеку для работы с энергонезависимой памятью

// 13 пин к 11 ножке
// 11 пин к 14 ножке
// 5 пин к 12 ножке
// 2, 3 и 4 пины на кнопки
// 12 пин на светодиод режима редактирования



static unsigned long lastTimeDHT = 0; // Декларируем переменную Датчика DHT и устанавливаем ее начальное значение в 0
// static unsigned long lastTimeLCD = 0; // Декларируем переменную для LCD и устанавливаем ее начальное значение в 0
static unsigned long lastTimeSerial = 0; // Декларируем переменную длявывода на монитор и устанавливаем ее начальное значение в 0
unsigned long lastTimeButton = 0; // Декларируем переменную для кнопок управления и устанавливаем ее начальное значение в 0
int setHour;
int setMinute;
int Hour ; // Получаем значение текущего часа
int Minute; // Получаем значение минут
int Second ; // Получаем значение секунд


#define switchPIN_1 2 // Кнопка №1 на 3-ем контакте
#define switchPIN_2 3 // Кнопка №2 на 2-ом контакте
#define switchPIN_3 4 // Кнопка №2 на 2-ом контакте
#define DHTPIN 5 // Считывающий пин с датчика
#define hPIN 6 // Пин управления влажностью
DS1307 rtc (7,8);
#define ledPIN 9 // Пин управления светодиодной лентой
#define tPIN 12 // Пин управления температурой



#define DHTTYPE DHT22 // Модель датчика

Time clock;

int tStatus = HIGH; // определяем переменную, отвечающую за состоянеие нагревателя HIGH=выкл, LOW=вкл
int tempDay ; // Желаемая дневная температура в градусах Цельсия
int tempNight ; // Желаемая ночная температура в градусах Цельсия
int hStatus = HIGH; // определяем переменную, отвечающую за состоянеие увлажнителя HIGH=выкл, LOW=вкл
int humDay ; // Желаемая дневная влажность
int humNight; // Желаемая ночная влажность
int Bright ; //Переменная яркости ленты
int lightOn ; //Начало дня
int lightOff ; //Конец дня
int edit = 0;

long timeSetMicros = 0;
long last_micros = 0; // Вспомогательная переменная, используется для определения сколько микросекунд прошло после предыдущей операции
int lastButton1 = LOW; // Предыдущее состояние кнопки №1
int currentButton1 = LOW; // Текущее состояние кнопки №1
int lastButton2 = LOW; // Предыдущее состояние кнопки №2
int currentButton2 = LOW; // Текущее состояние кнопки №2
int lastButton3 = LOW; // Предыдущее состояние кнопки №3
int currentButton3 = LOW; // Текущее состояние кнопки №3


SPI_Bus shreg(_8bit, 10); // Подключаем сдвиговый регистр
LiquidCrystal lcd(1, 2, 3, 4, 5, 6, &shreg, 7); // Инициализируем дисплей
DHT dht(DHTPIN, DHTTYPE); // Создаем объект dht

//unsigned long lastTimeDHT = 0; // Декларируем переменную и устанавливаем ее начальное значение в 0
float h = 50;
float t = 50;


void setup() // инициализация основных данных
{
Serial.begin(9600); // Инициализируем COM-порт
dht.begin(); // Инициализируем датчик
pinMode(tPIN, OUTPUT); // Определяем пин для управления температурой как Вывод
pinMode(hPIN, OUTPUT);
pinMode(ledPIN, OUTPUT);
pinMode(DHTPIN, INPUT);
digitalWrite(DHTPIN, HIGH);
pinMode(switchPIN_1, INPUT); // Устанавливаем тип контакта Кнопки №1 как Вход
pinMode(switchPIN_2, INPUT); // Устанавливаем тип контакта Кнопки №2 как Вход
pinMode(switchPIN_3, INPUT); // Устанавливаем тип контакта Кнопки №3 как Вход
pinMode(0, OUTPUT);
lcd.begin(16,2); // устанавливаем размеры экрана




tempDay = EEPROM.read(1); // Получаем параметр из первой ячейки
if (tempDay == 255) tempDay = 28; // Если ячейка пуста, т.е. ее значение = 255, то устанавливаем параметр температуры в значение по умолчанию, в данном случае 28С.
tempNight = EEPROM.read(3); // Получаем параметр из второй ячейки
if (tempNight == 255) tempNight = 24; // Если ячейка пуста, т.е. ее значение = 255, то устанавливаем параметр температуры в значение по умолчанию, в данном случае 28С.
lightOn = EEPROM.read(4); // Получаем параметр из первой ячейки
if (lightOn == 255) lightOn = 8; // Если ячейка пуста, т.е. ее значение = 255, то устанавливаем параметр температуры в значение по умолчанию, в данном случае 28С.
lightOff = EEPROM.read(5); // Получаем параметр из первой ячейки
if (lightOff == 255) lightOff = 21; // Если ячейка пуста, т.е. ее значение = 255, то устанавливаем параметр температуры в значение по умолчанию, в данном случае 28С.
// rtc.setTime(21,15,0);
humNight = EEPROM.read(6); // Получаем параметр из шестой ячейки
if (humNight == 255) humNight = 60; // Если ячейка пуста, то установим параметр в 60%
humDay = EEPROM.read(7); // Получаем параметр из второй ячейки
if (humDay == 255) humDay = 60; // Если ячейка пуста, то установим параметр в 60%
rtc.setTime(21,31,0);

}


void loop() // зацикливание (код управляющей программы)
{
clock = rtc.getTime();
if (Serial.available() > 0) SetTime(); // Если на COM-порт поступила информация, то изменим системное время
static unsigned long lastTimeLCD = 0; // Декларируем переменную для LCD и устанавливаем ее начальное значение в 0
//Считываем влажность и температуру каждые 5 сек
if (millis() - lastTimeDHT > 5000) {
h = dht.readHumidity(); // Считываем влажность
t = dht.readTemperature(); // Считываем температуру
lastTimeDHT = millis();
}

int Hour = (clock.hour); // Получаем значение текущего часа
int Minute = (clock.min); // Получаем значение минут
int Second = (clock.sec); // Получаем значение секунд
boolean Day = (Hour >= lightOn & Hour <lightOff); // Если текущий час находится в промежутке от 8 до 20, то действуют дневные параметры
tStatus = (t < ((Day) ? tempDay : tempNight)) ? HIGH:LOW; // Если температура меньше желаемой, то статус обогревателя=Вкл, в противном случае Выкл
digitalWrite(tPIN, tStatus);
hStatus = (h < ((Day) ? humDay : humNight)) ? LOW:HIGH; // Если влажность меньше желаемой, то статус увлажнителя=Вкл, в противном случае Выкл
digitalWrite(hPIN, hStatus);
//digitalWrite(lPIN, (Day) ? LOW:HIGH); // Если дневное время, то включим подсветку

//Закат/Рассвет
if (Hour==lightOn-1) Bright=1+sq(Minute)/15;
else if (Hour==lightOff) Bright=1+sq(60-Minute)/15;
else Bright = (Day) ? 255:0;
analogWrite(ledPIN, Bright);
////

if (millis() - lastTimeSerial >2000) {
{
Serial.print("t=");
Serial.print(t,1);
Serial.print(" h=");
Serial.println(h,1); // Отправляем информацю о климате на COM-порт
Serial.print(Hour);
Serial.print(":");
Serial.print(Minute);
Serial.print(":");
Serial.println(Second);
Serial.println(Bright);
Serial.print("Edit=");
Serial.println(edit);
lastTimeSerial=millis();
};
}



if ( (millis() - lastTimeLCD >150)) // Не используем в данном случае задержку Delay, т.к. это приведет к запаздыванию нажатий кнопок
{
lcd.setCursor(0,0); // устанавливаем позицию курсора на экране (на один символ правее левого верхнего угла)
lcd.print(t, 1);
lcd.print("C");
// lcd.setCursor(6,0);lcd.print("*"); lcd.print(Bright/255, 0); lcd.print("%");
lcd.setCursor(13,0);
lcd.print(h, 0);
lcd.print("%"); // Выводим информацию о климате
if (edit==0){

lcd.setCursor(1,1);
lcd.print((tStatus == HIGH) ? "+ ":" "); // Выводим индикатор работы подогрева
lcd.setCursor(4,1); // устанавливаем курсор для вывода времени
lcd.print(addZero(Hour));
lcd.print(":");
lcd.print(addZero(Minute));
lcd.print(":");
lcd.println(addZero(Second)+" "); // Выводим время
lcd.setCursor(14,1);
lcd.print((hStatus == HIGH) ? "+ ":" "); // Выводим индикатор работы увлажнения
}
lastTimeLCD = millis();
}


// ******************* Опрос для режима редактирования *********************************
Switch();



// ***************************************************
}



/*
ReadDHT ***************************************************************************** /
void ReadDHT()
{ h = dht.readHumidity(); // Считываем влажность
t = dht.readTemperature(); // Считываем температуру
lastTimeDHT = millis();}
//********************ReadDHT**************************************************** */



/* PrintSerial *************************************************************************
void PrintSerial()
{
Serial.print("t=");
Serial.print(t,1);
Serial.print(" h=");
Serial.println(h,1); // Отправляем информацю о климате на COM-порт
Serial.print(Hour);
Serial.print(":");
Serial.print(Minute);
Serial.print(":");
Serial.println(Second);
Serial.println(Bright);
Serial.print("Edit=");
Serial.println(edit);
lastTimeSerial=millis();
}// Отправляем информацию о времени на COM
/* PrintSerial *************************************************************************/



/* SetTime *************************************************************************/
void SetTime() // установка времени из шаблона tчч:мм
{
if (Serial.read() == 't' // Если первый символ t, то установим указанное время
{
byte h = (Serial.read() - '0' * 10 + (Serial.read() - '0';
Serial.read();
byte m = (Serial.read() - '0' * 10 + (Serial.read() - '0';
rtc.setTime(h,m,0);
}
Serial.flush();
}
/* SetTime *************************************************************************/




String addZero(int val)
{
if (val<10) return "0" + String(val);
else return String(val);
}



//*********************Режим редактпрования******************************************************************************************
void Switch() {

if (millis() - last_micros >= 200) // Производим опрос кнопок каждую треть секунды, это необходимо, чтобы избежать повторных выполнений кода в следствие дребезга контатов
{
last_micros = millis();
currentButton1 = digitalRead(switchPIN_1); // Считываем текущее состояние кнопки №1
currentButton2 = digitalRead(switchPIN_2); // Считываем текущее состояние кнопки №1
currentButton3 = digitalRead(switchPIN_3); // Считываем текущее состояние кнопки №3
if (lastButton1 == LOW && currentButton1 == HIGH) // Если Кнопка №1 изменила состояние на Нажатие
{
long t_millis = millis(); // Фиксируем начальное время нажатие кнопки, чтобы определить, не была ли она зажата
while (digitalRead(switchPIN_1) == HIGH && millis() - t_millis <= 2000 && edit==0 ) {
lcd.clear();
} // Пока кнопка зажата не даем программе двигаться дальше


if (millis() - t_millis > 2000) // Если кнопка была нажата дольше 2-х секунд, то переведем состояние в режим программирования
{
edit = 1;
// digitalWrite(0, HIGH); // Зажгем сигнальный светодиод, чтобы понять что "чудо" произошло
lcd.clear(); lcd.setCursor(1, 1); lcd.print("TempD: ");lcd.print(tempDay); lcd.println("C");lcd.print(" *");
}

// Иначе отрабатываем короткое нажатие при различных условиях
else if (edit==1) { edit = 3;lcd.clear();lcd.setCursor(0, 1);lcd.print("TempN: ");lcd.print(tempNight);lcd.println("C");lcd.print(" *");} // Если программа была в режиме изменения первого параметра, переведем ее на изменение 3 параметра

else if (edit==3) { edit = 4; lcd.clear();lcd.setCursor(0, 1); lcd.print("DaySt: ");lcd.println(lightOn); lcd.print(" *");} //Если программа была в режиме изменения 8 параметра, переведем ее на изменение 9 параметра

else if (edit==4) { edit = 5;lcd.clear();lcd.setCursor(0, 1); lcd.print("DayFin: ");lcd.println(lightOff); lcd.print(" *");}//Если программа была в режиме изменения 9 параметра, переведем ее на изменение 5 параметра

else if (edit==5) { edit = 6;lcd.clear();lcd.setCursor(0, 1); lcd.print("NumDay: ");lcd.println(humDay); lcd.print(" *");}//Если программа была в режиме изменения 9 параметра, переведем ее на изменение 5 параметра

else if (edit==6) { edit = 10;lcd.clear();lcd.setCursor(0, 1); lcd.print("HumNght: ");lcd.println(humNight); lcd.print(" *");}//Если программа была в режиме изменения 9 параметра, переведем ее на изменение 5 параметра

// else if (edit==5) { edit = 98;lcd.clear();lcd.setCursor(0, 1); lcd.print("Set Hour: ");lcd.println(Hour); lcd.print(" *");}//Если программа была в режиме изменения 9 параметра, переведем ее на изменение 5 параметра

else if (edit==98) { edit = 99;lcd.clear();lcd.setCursor(0, 1); lcd.print("Set Minute: ");lcd.println(Minute); lcd.print(" *");}//Если программа была в режиме изменения 9 параметра, переведем ее на изменение 5 параметра

else if (edit==10){ edit = 0;
lcd.clear();
digitalWrite(0, LOW); // Зажгем сигнальный светодиод, чтобы понять что "чудо" произошло
EEPROM.write(1, tempDay); // Запимываем параметр температуры в 1-ю ячейку памямти
EEPROM.write(3, tempNight);
EEPROM.write(4, lightOn);
EEPROM.write(5, lightOff);
EEPROM.write(6, humNight);
EEPROM.write(7, humDay);
}

else if (edit==99){ edit = 0;
lcd.clear();
rtc.setTime(setHour,setMinute,0); }

else {
}; // Если программа не была в режиме редактирования, то можно выполнить тоже какое-то действие, для этого в фигурных скобках необходи описать его функционал
}



if (currentButton2 == HIGH && edit != 0) // Если нажата Кнопка №2, при состоянии редактирования параметров то...
{
if (edit == 1) // ...если режим изменения температуры
{
tempDay = (tempDay == 35) ? 20tempDay+1);
lcd.setCursor(0, 1); lcd.print("TempD: "); lcd.print(tempDay); lcd.print("C +");
}

else if (edit == 3) // ...если режим изменения влажности
{
tempNight = (tempNight == 30) ? 15tempNight+1);
lcd.setCursor(0, 1); lcd.print("TempN: "); lcd.print(tempNight); lcd.print("C +");
}

else if (edit == 4) // ...если режим изменения EC
{
lightOn = (lightOn == 23) ? 0lightOn+1);
lcd.setCursor(0, 1); lcd.print("DaySt: "); lcd.print(lightOn); lcd.print(" + ");
}

else if (edit == 5) // ...если режим изменения DayFin
{
lightOff = (lightOff == 23) ? 0lightOff+1);
lcd.setCursor(0, 1); lcd.print("DayFin: "); lcd.print(lightOff); lcd.print(" + ");
}


else if (edit == 6) // ...если режим изменения DayFin
{
humDay = (humDay == 80) ? 20humDay+5);
lcd.setCursor(0, 1); lcd.print("humDay: "); lcd.print(humDay); lcd.print(" + ");
}

else if (edit == 10) // ...если режим изменения DayFin
{
humNight = (humNight == 80) ? 20humNight+5);
lcd.setCursor(0, 1); lcd.print("humNght: "); lcd.print(humNight); lcd.print(" + ");
}

else if (edit == 98) // ...если режим изменения DayFin
{
setHour = (setHour == 23) ? 0setHour+1);
lcd.setCursor(0, 1); lcd.print("Set Hour: "); lcd.print(setHour); lcd.print(" + ");
}


else if (edit == 99) // ...если режим изменения DayFin
{
setMinute = (setMinute == 59) ? 0setMinute+1);
lcd.setCursor(0, 1); lcd.print("Set Minute: "); lcd.print(setMinute); lcd.print(" + ");
}
}


else if (lastButton2 == LOW && currentButton2 == HIGH) // Если было короткое нажатие на Кнопку №2 не в режиме редактирования, то можно выполнить какое либо действие, если описать его в фирных скобках ниже
{
lcd.clear(); lcd.setCursor(0,0);lcd.print("Led Bright");lcd.setCursor(5,1); lcd.print(Bright/255); lcd.print("%");
delay (2000);
lcd.clear();
}



if (currentButton3 == HIGH && edit != 0) // Если нажата Кнопка №3, при состоянии редактирования параметров то...
{

if (edit == 1) // ...если режим изменения температуры
{
tempDay = (tempDay == 20) ? 35tempDay-1);
lcd.setCursor(0, 1); lcd.print("TempD: "); lcd.print(tempDay); lcd.print("C -");
}

else if (edit == 3) // ...если режим изменения влажности
{
tempNight = (tempNight == 15) ? 30tempNight-1);
lcd.setCursor(0, 1); lcd.print("TempN: "); lcd.print(tempNight); lcd.print("C -");
}

else if (edit == 4) // ...если режим изменения LightOn
{
lightOn = (lightOn == 0) ? 23lightOn-1);
lcd.setCursor(0, 1); lcd.print("DaySt: "); lcd.print(lightOn); lcd.print(" - ");
}

else if (edit == 5) // ...если режим изменения LightOff
{
lightOff = (lightOff == 0) ? 23lightOff-1);
lcd.setCursor(0, 1); lcd.print("DayFin: "); lcd.print(lightOff); lcd.print(" - ");
}

else if (edit == 6) // ...если режим изменения DayFin
{
humDay = (humDay == 20) ? 80humDay-5);
lcd.setCursor(0, 1); lcd.print("humDay: "); lcd.print(humDay); lcd.print(" - ");
}

else if (edit == 10) // ...если режим изменения DayFin
{
humNight = (humNight == 20) ? 80humNight-5);
lcd.setCursor(0, 1); lcd.print("humNght: "); lcd.print(humNight); lcd.print(" - ");
}

else if (edit == 98) // ...если режим изменения DayFin
{
setHour = (setHour == 0) ? 23setHour-1);
lcd.setCursor(0, 1); lcd.print("Set Hour: "); lcd.print(setHour); lcd.print(" - ");
}


else if (edit == 99) // ...если режим изменения DayFin
{
setMinute = (setMinute == 0) ? 59setMinute-1);
lcd.setCursor(0, 1); lcd.print("Set Minute: "); lcd.print(setMinute); lcd.print(" - ");
}
}

else if (lastButton3 == LOW && currentButton3 == HIGH) // Если было короткое нажатие на Кнопку №3 не в режиме редактирования, то можно выполнить какое либо действие, если описать его в фирных скобках ниже
{long t_millis = millis(); // Фиксируем начальное время нажатие кнопки, чтобы определить, не была ли она зажата
while (digitalRead(switchPIN_3) == HIGH && millis() - t_millis <= 2000 && edit==0 ) {lcd.clear();} // Пока кнопка зажата не даем программе двигаться дальше

if (millis() - t_millis > 2000) // Если кнопка была нажата дольше 2-х секунд, то переведем состояние в режим программирования
{ edit = 98;}
}
lastButton1 = currentButton1; // Запоминаем предыдущее значение Кнопки №1
lastButton2 = currentButton2; // Запоминаем предыдущее значение Кнопки №2
lastButton3 = currentButton3; // Запоминаем предыдущее значение Кнопки №23
}


}

Изменено 19-2-2013 автор Zygomant
2013-02-19 добавлено 19/02/2013 08:42:56#398499

Посетитель





65
4 г. назад
Получается что у тебя в устройстве всего 3 кнопки ?
я просто все мучаюсь с энкодером вместо кнопок

Изменено 19-2-2013 автор aleksjet
2013-02-19 добавлено 19/02/2013 09:12:43#398501

Новенький





5
Russian Federation Chelyabinsk
6 г. назад
aleksjet

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

Я с энкодером тоже пытался но не получилось
я тупой, у меня с первого раза ничего не получатся. Нужно чтоб мозги привыкли и обдумали. так что думаю щас за энкодер взяться.
2013-02-19 добавлено 19/02/2013 16:29:18#398536

Посетитель





65
4 г. назад
Zygomant

да у меня тоже особо мало что получилось с энкодером и кнопками
вот без кнопок все работает и через прошивку передерживаются параметры а с кнопками и энкодером как то не сложилось (
2013-02-19 добавлено 19/02/2013 16:37:28#398537

Новенький





5
Russian Federation Chelyabinsk
6 г. назад
aleksjet

Дорогу осилит идущий
2013-02-19 добавлено 19/02/2013 17:33:32#398541

Посетитель





65
Russian Federation Moscow
4 г. назад
Zygomant

Согласен на все сто
2013-02-19 добавлено 19/02/2013 19:49:21#398563

Новенький





8
Russian Federation Vladikavkaz
6 г. назад
не могу разобраться с таймером кто может подскажет (простой код накидал)



#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>
#define timePIN 10

void setup()
{
Serial.begin(9600);
pinMode(10, OUTPUT);
}

void loop()
{

int Hour = RTC.get(DS1307_HR,true);
int Minute = RTC.get(DS1307_MIN,false);
int Second = RTC.get(DS1307_SEC,false);
int FullMinutes = Hour * 60 + Minute;

boolean Day = (FullMinutes >= 12 * 60 + 46 && FullMinutes <= 3 * 60 + 10);
digitalWrite(timePIN, (Day) ? HIGH:LOW);


delay(1000);
Serial.print(Hour);
Serial.print(":");
Serial.print(Minute);
Serial.print(":");
Serial.println(Second);
}

void SetTime()
{
if (Serial.read() == 't'
{
int h = (Serial.read() - '0' * 10 + (Serial.read() - '0';
Serial.read();
int m = (Serial.read() - '0' * 10 + (Serial.read() - '0';
RTC.stop();
RTC.set(DS1307_SEC,0);
RTC.set(DS1307_MIN,m);
RTC.set(DS1307_HR,h);
RTC.start();
}
Serial.flush();
}

проблема в том что если задать параметры времени (Day) как 8(однозначное) и 12 то не срабатывает ((( таймер работает только если указывать двухзначное число, что пролема подскажите ?

Изменено 20-2-2013 автор Snecky

Изменено 20-2-2013 автор Snecky
2013-02-20 добавлено 20/02/2013 11:57:17#398636

Посетитель





78
Russian Federation Moscow
6 мес. назад
сообщение Snecky

boolean Day = (FullMinutes >= 12 * 60 + 46 && FullMinutes <= 3 * 60 + 10);


При такой постановке значение Day будет всегда false. (Начало интервала больше его конца)


проблема в том что если задать параметры времени (Day) как 8(однозначное) и 12 то не срабатывает ((( таймер работает только если указывать двухзначное число, что пролема подскажите ?


Не совсем понятно, что имеется ввиду. Если Вы пытаетесь отправить на COM значение "t8:12", то время не будет установлено как 8:12, т.к. функция SetTime последовательно считывает символы и не производит дополнительных проверок корректности маски, найдя букву t следующие 2 символа (а точнее их коды) она будет трактовать как час, т.е. "8:" будет преобразовано в часы, далее любой символ "1" пропускается, и в качестве минут будет "2 ". Т.е. Вам необходимо отправлять "t08:12", тогда все будет Ок.
2013-02-21 добавлено 20/02/2013 23:32:47#398749

Новенький





8
Russian Federation Vladikavkaz
6 г. назад

Вам необходимо отправлять "t08:12", тогда все будет Ок.


не знаю как я до этого менял время (не помню) но отправляю через сериал "t11:00" и не чего не происходит т.е. время не меняется (

Изменено 21-2-2013 автор Snecky
2013-02-21 добавлено 21/02/2013 09:54:24#398778

Посетитель





78
Palestinian Territory Ramallah
6 мес. назад
Энкодер
У меня нет энкодера под рукой, но подключение его к arduino не составляет труда, если разобраться с тем, что он из себя представляет.

Энкодер - это две кнопки, замыкание которых представляет определенную закономерность в зависимости от того, в какую сторону вращается ручка.

Т.о. подключается энкодер аналогично кнопкам, например так:


В зависимости от стороны вращения на выходе будет получен один из следующих сигналов на пинах 2 и 3:



Т.о. если А переходит из состояния 0 в 1, то если В=0 - ручка вращается вперед, если В=1 - назад.
Этого достаточно, чтобы заставить энкодер работать.
Чтобы повысить его чувствительность в 2 раза, можно так же отрабатывать переход А из состояния 1->0
Максимальной чувствительности можно добиться, если добавить переход состояний В.

Вращение вперед, если: А0->1,B=0; A1->0,B=1; B0->1,A=1; B1->0;A=0
Вращение назад, если: А0->1,B=1; A1->0,B=0; B0->1,A=0; B1->0;A=1

Скетч (скетч для работы с кнопками, изменено лишь условие, которое определяет вращение ручки):

#define switchPIN_1 3 // Выход A на 3-ем контакте
#define switchPIN_2 2 // Выход В на 2-ом контакте

long last_micros = 0; // Вспомогательная переменная, используется для определения сколько микросекунд прошло после предыдущей операции
int lastButton1; // Предыдущее состояние А
int currentButton1; // Текущее состояние А
int lastButton2; // Предыдущее состояние В
int currentButton2; // Текущее состояние В
int Test = 100; // Значение, которое будет изменяться вращением ручки энкодера

void setup() // инициализация основных данных
{
Serial.begin(9600); // Инициализируем COM-порт
pinMode(switchPIN_1, INPUT); // Устанавливаем тип контакта Кнопки №1 как Вход
pinMode(switchPIN_2, INPUT); // Устанавливаем тип контакта Кнопки №2 как Вход
currentButton1 = digitalRead(switchPIN_1); // Текущее состояние А
lastButton1 = currentButton1; // Предыдущее состояние А
currentButton2 = digitalRead(switchPIN_2); // Текущее состояние В
lastButton2 = currentButton2; // Предыдущее состояние В
}

void loop() // зацикливание (код управляющей программы)
{
Switch();
}

void Switch()
{
if (millis() - last_micros >= 20) // Производим опрос состояний каждые 20 милисекунд, это необходимо, чтобы избежать повторных выполнений кода в следствие дребезга контактов
{
last_micros = millis();
currentButton1 = digitalRead(switchPIN_1); // Считываем текущее состояние А
currentButton2 = digitalRead(switchPIN_2); // Считываем текущее состояние В
if (lastButton1 == LOW && currentButton1 == HIGH) // Если А изменила состояние на Нажатие
{
if (currentButton2 == LOW) Test++; else Test--;
Serial.println(Test); // Отправляем информацю на COM-порт
}
lastButton1 = currentButton1; // Запоминаем предыдущее значение А
lastButton2 = currentButton2; // Запоминаем предыдущее значение В
}
}


В примере рассмотрена обработка одного из переходных состояний, при необходимости остальные 3 добавляются по аналогии.
На Serial Monitor смотрим как реагирует переменная Test на вращение ручки энкодера.

Примечание. Значение 20 милисекунд выбрано на вскидку, если появляется многократное изменение переменной за один щелчок, то значение необходимо увеличить; если наоборот происходит проскальзывание, то значение необходимо уменьшить.

PS. Работоспособность не проверялась, но работать должно.

Изменено 22-2-2013 автор CiberRus
2013-02-21 добавлено 21/02/2013 10:37:55#398783

Посетитель





65
4 г. назад
CiberRus

Спасибо за разъяснение.
мне на днях пришли энкодеры 10 шт. могу парочку дать для экспериментов кстати этот энкодер еще и с кнопкой
2013-02-21 добавлено 21/02/2013 11:02:06#398786

Новенький





8
Russian Federation Gornoe
6 г. назад
Ребята кто-нить может помоч кодом рабочего таймера на DS1307 уже устал натыкатся на всякие грабли ((
2013-02-25 добавлено 25/02/2013 10:48:58#399157

Посетитель





65
4 г. назад
Snecky

а что не работает ? я тоже долго искал подходящую библиотеку ((
и мучил установку времени

Изменено 25-2-2013 автор aleksjet
2013-02-25 добавлено 25/02/2013 10:55:41#399159

Новенький





2
Russian Federation
5 г. назад
Добрый день всем. Меня зовут Роман. Очень заинтересовала данная тема, я сам пытаюсь соорудить похожую автоматику на Arduino, но катастрофически не хватает знаний и опыта. Собственно говоря я не занимаюсь рептилиями, я перепеловод (бить не будете?). Домашние перепелки не умеют высиживать и водить пенцов как квочки, поэтому приходится инкубировать яйца. Инкубаторную автоматику я уже разработал (могу дать ссылку на другой форум) , а вот для брудера не получается. Брудер это такие ясли для вылупившихся малышей, специальная клетка (или батарея клеток) с обогревом, специальными кормушками и поилками и мелкой сеткой на полу. Там птенцы растут 3-4 недели, а потом переселяются во взрослые клетки, а куры в вольер. Это преамбула была. Теперь сама амбула:

Имеется батарея из 4-х брудеров с обогревом галогенными лампами от сети 220В, Ардуино, модуль часов реального времени на DS1307 и LCD дисплей 1602 и термометры DS18B20. Задача - сделать умную автоматику для 4 брудеров, которая будет автоматически поддерживать нужную температуру в брудерах, постепенно снижая ее по дням. То есть первые три дня температура должна быть 37,0 градусов, а дальше линейно снижаться до 25 градусов к 21-му дню. Часы реального времени нужны чтоб не зависить от перебоев с электричеством. То есть, с точки зрения пользователя, нужно стремиться к тому, чтобы достать малышей из инкубатора в брудер, нажать кнопку "ПУСК" и заниматься другими делами, а контроль за температурой возьмет на себя автоматика. На дисплее будет показывать день проживания малышей и текущую температуру. Ну и ручной режим хотелось бы предусмотреть, чтоб можно было в любой момент вмешаться в процесс или остановить его.
Управление нагрузкой удобнее всего реализовать на симисторах с драйверами на MOC3053 или аналогичными, с этим проблем нет. Я вот набросал макет:



Для простоты я условно заменил модули управления лампами простыми светодиодами, а термометры забыл прикрутить, исправлюсь. С кодом для термометров Dallas вроде все понятно. Проблема в алгоритме управления лампами для поддержания температуры. Проблема в том, что лампы не желательно релейно гасить и зажигать т.к. световой день в первые 3 недели должен быть круглосуточный. Можно сделать светодиодную подсветку конечно, но это не лучший вариант. Хочется сделать плавное снижение мощности ламп, а вот с этим и есть проблемы. Для питания постоянным током можно использовать функцию Analogwrite и MOSFET. На переменке не уверен. Знаю что делают вход на контроллер сети переменного тока через оптрон, для синхронизации фазы, но я не знаю, как это программно реализовать. Если же не обращать внимание на фазу сети, то не уверен что что-то путное получится. Частота ШИМ аналоговых выходов Ардуино - 500Гц (хотя ее вроде можно менять специальным управляющим битом), большинство драйверов симисторов с zero-cross модулем, который открывает симистор только в момент перехода сетевой фазы через ноль. В общем мозгов не хватает и дальше строчки #include <time.h> я не продвинулся. Прошу помощи у топикстартера! Может кому еще будет интересна эта тема?

Изменено 6-7-2013 автор Um-ka
2013-07-06 добавлено 06/07/2013 10:28:51#411016

Посетитель





78
Russian Federation Krasnodar
6 мес. назад
Um-ka

Набросок схемы работы устройства
1. При удержании кнопки "Настройка" переходим в режим программирования. По короткому нажатию на кнопку "Настройка" последовательно переходим к:
- Установке/коррекции номера начального дня каждого брудера (по умолчанию 0/или 255. Если 0 то не используется)
- Установке даты и времени (год, месяц, день, час, минута) // Возможно эти 5 пунктов настройки стоит исключить, т.к. вероятность того что таймер сброситься или потребуется его перенастройка мала, а постоянно пропускать эти 5 пунктов при настройке - лишние манипуляции.
Т.о. минимально рекомендуемое количество кнопок 3: "Настройка", "-", "+". Такая методика организации меню описана в данной ветке, поэтому разберитесь с примером работы кнопок, а так же скетчем от Alex1503.
2. После выхода из режима программирования в память EEPROM записывается например дата начала процесса для каждого брудера. Это необходимо, чтобы при повторном включении устройство не "забыло" возраст птенцов. Пример работы с EEPROM есть в этой ветке. Там все просто, проблем возникнуть не должно. (Чтобы сохранить дату, потребуется использовать несколько ячеек памяти)
3.... Все остальное зависит от фантазии и личных предпочтений (индикация, алгоритмы управления и пр.)

Рекомендации:
В реализации алгоритма обогрева я бы выбрал вариант: свет отдельно, тепло отдельно. Это на порядок упростит схему и алгоритм, а так же избавит от возможных внештатных ситуаций (Например, если температура без ламп в брудере 28С, то птенцы будут сидеть без света).
Если все же Вы хотите реализовать симисторный регулятор, то ознакомьтесь с этой ссылкой http://cxem.net/arduino/arduino71.php. Там все очень доступно и с простым примером.
Так же мне в голову приходит еще один вариант реализации (без оптрона), с помощью внутренних таймеров. Но т.к. в arduino таймеров 2, то этот вариант подходит максимум для 2-х брудеров, да и по прошествии месяца у птенцов глаза будут "квадратные". Кратко: Настраиваем выходы ШИМ например на 5Гц (10 синусоид) и в выдаем импульс на необходимое количество гармоник (Грубо говоря каждые 0-10 синусоид из 10 блокируем. Для уровня 7 имеем в среднем ток: 11111110001111111000....).

Далее Вам необходимо определиться со схемой и написать скетч к ней. Если возникнут проблемы с реализацией того или иного участка кода, обращайтесь.
Напомню, что вероятность решения проблем тем больше, чем структура обращения ближе к: Локальная цель; Участок кода; Результат/или его отсутствие; Ошибки компиляции при их наличии.

Изменено 9-7-2013 автор CiberRus
2013-07-09 добавлено 09/07/2013 11:25:17#411174

Новенький





2
Russian Federation Moscow
5 г. назад
Спасибо.
1. Этот пункт не ясен. Зачем программировать начальный день 0-255? А если сделать проще, считать время в unix формате от момента пуска и до +21 дня (1814400 "погонных" секунд)? Тогда нужно чтобы просто шли часы, а установленная дата значения не имеет. Правильно? Тогда две кнопки хватит, выбор брудера и пуск-стоп.

2. С EEPROM проблем нет, она и в часах есть и в контроллере. Именно так и планировал делать.

3. Думал про свет отдельно, тепло отдельно. Но тогда не хватит ножек у Arduino UNO для включения света или придется регистры сдвига ставить. Ну или просто выключатели света, тоже вариант. Но зато при таком подходе упрощается сильно алгоритм терморегуляции. Делаю гистерезис на 0,2 градуса между включением и отключением и щелкаю симистором. С симисторами тоже вопросов нет в таком варианте. Только пожалуй плавное включение и выключение ламп стоит реализовать, да хоть на fade примере. И можно вместо ламп греющий шнур или пленку использовать. Это безопасней по пожару.

4. На таймерах не пойдет, либо в память писать постоянно придется, либо зависить от перебоев питания.

Схему нарисовал уже вроде, мне бы решить глобальные вопросы, как сделать все максимально просто и эффективно? Вот с ручным режимом еще вопрос открыт, для него уже 3 кнопки нужно. А может и не нужен ручной режим, а достаточно только пуск-стоп? А может лучше сделать возможность стартовать не с первого дня (по температуре и времени), а с какого хочется? И на финише чтобы сигнал какой брудер подавал. Хоть светодиод красный зажигал (один на все секции), что кого-то вынимать пора. Наверное последний вариант наиболее практичный, но боюсь запутаюсь с этими днями и кнопками. В общем я начинаю макет набрасывать, а потом покажу и буду дальше ума пытать. Лады?
2013-07-09 добавлено 09/07/2013 14:07:41#411178

Посетитель





78
Russian Federation Krasnodar
6 мес. назад
сообщение Um-ka
1. Этот пункт не ясен. Зачем программировать начальный день 0-255? А если сделать проще, считать время в unix формате от момента пуска и до +21 дня (1814400 "погонных" секунд)? Тогда нужно чтобы просто шли часы, а установленная дата значения не имеет. Правильно? Тогда две кнопки хватит, выбор брудера и пуск-стоп.

Это необходимо для того, чтобы иметь возможность запустить программу не с 1-го дня, а с произвольного. А так же определить необходимые данные при выключении/включении устройства.
Возможные значения 0-21.
Значение 0 - "Откл". Значения 1-21 при записи в EEPROM пересчитываем в день рождения (Т.е. если сегодня 09.07.13, а мы запускаем программу с 5-го дня, то в память пишем дату 05.07.13), так всегда будет иметься возможность определить возраст цыплят.
(255 означает что ячейка памяти пустая. Поэтому я его привел как памятку. Если пользователь установил значение 0, то в память рекомендуется записать год: 255, месяц: 255, день: 255, то же самое мы будем иметь в ячейках при первом запуске контроллера)


4. На таймерах не пойдет, либо в память писать постоянно придется, либо зависить от перебоев питания.


Я имел ввиду таймеры, которые управляют периодичностью импульсов ШИМ. Есть возможность использовать 9-ю и 10-ю ногу не с штатными 500Гц, а с любыми другими.

Изменено 9-7-2013 автор CiberRus
2013-07-09 добавлено 09/07/2013 14:46:51#411182

Новенький





13
Russian Federation Moscow
4 г. назад
сообщение CiberRus
К контроллеру Arduino можно подключить различные дисплеи, для вывода информации. Рассмотрим один из наиболее распространенных. Купить можно здесь: LCD Display. Цена от 100р.

В стандартной комплектации данный дисплей подключается напрямую. Минимальное количество каналов, которые при этом необходимо занять - 6. 2 для команд, 4 для передачи данных. В сети есть масса примеров, как это сделать, к примеру тут: Подключение LCD
Есть вариант подключения по I2C интерфейсу (наилучший вариант, но такие дисплеи самые дорогие)
Или подключить с помощью сдвигового регистра по SPI интерфейсу. Очень подробно, с сылками на необходимые библиотеки: Подключаем кучу устройств по 5 проводам. В программе я использовал библиотеки из данной статьи.

В данном примере я использовал дисплей с интерфейсом SPI. Скетчи будут отличаться незначительно, поэтому я приведу их для обоих вариантов.
Для удобства интерфейс SPI разведен на плате сзади экрана с помощью сдвигового регистра, так что из него выходят всего 5 контактов.


Немного слов про сдвиговые регистры. С помощью них можно теоретически неограниченно увеличить количество вводов/выводов контроллера. Поэтому если требуется одним контроллером управлять больши количеством террариумов, то стоит рассматривать SPI интерфейс и сдвиговые регистры для решения данной задачи. Стоимость 8-битного сдвигового регистра 10-30р, при этом он превращает 1 вывод контроллера в 8. А каскадное подключение нескольких регистров делает из 1 вывода 16, 24 и тд.
Неприятным моментом является то, что сдвиговый регистр превращает 1 ввод/вывод в несколько либо только вводов, либо только выводов, что немного ограничивает их область применения, но большинство задач позволяют решать. (К примеру 8-канальный релейный блок, который я использую в примерах можно подключить через сдвиговый регистр, заняв всего 1 вывод контроллера вместо 8-ми) Дисплей, на фото выше при прямом подключении использовал бы 6 контактов Arduino - это треть из возможных, а с SPI всего один.

Прототип:


Итак, на экран выводим информацию о текущей температуре и влажности, ниже текущее время.
Если в данный момент работает обогрев или увлажнение, то под соответствующим показателем выводим "+".

Скетч (Для варианта SPI - зеленый цвет/ прямое подключение экрана - красный. В зависимости от использованного варианта лишнее удалить. Иные отличия от предыдующего кода - синий):
#include <DHT.h> // Подключаем библиотеку для работы с датчиком
#include <DS1307.h> // Подключаем библиотеку управления модулем реального времени

#include <LiquidCrystalExt.h> // Подключаем библиотеку управления экраном
#include <LineDriver.h> // Далее вспомогательные библиотеки для реализации интерфейса SPI
#include <SPI.h>
#include <SPI_Bus.h>
#include <Wire.h>


#include <LiquidCrystal.h> // Подключаем стандартную библиотеку управления экраном

#define DHTPIN 8 // Считывающий пин с датчика
#define DHTTYPE DHT11 // Модель датчика
#define tPIN 7 // Пин управления температурой
#define hPIN 6 // Пин управления влажностью
#define lPIN 5 // Пин управления светом
#define sdPIN 3 // Пин управления светодиодной лентой

DHT dht(DHTPIN, DHTTYPE); // Создаем объект dht

int tStatus = HIGH; // определяем переменную, отвечающую за состоянеие нагревателя HIGH=выкл, LOW=вкл
int tempDay = 28; // Желаемая дневная температура в градусах Цельсия
int tempNight = 25; // Желаемая ночная температура в градусах Цельсия
int hStatus = HIGH; // определяем переменную, отвечающую за состоянеие увлажнителя HIGH=выкл, LOW=вкл
int humDay = 45; // Желаемая дневная влажность
int humNight = 40; // Желаемая ночная влажность

SPI_Bus shreg(_8bit, 10); // Подключаем сдвиговый регистр
LiquidCrystal lcd(1, 2, 3, 4, 5, 6, &shreg, 7); // Инициализируем дисплей


LiquidCrystal lcd(12, 11, 10, 9, 4, 2); // Инициализируем дисплей

void setup() // инициализация основных данных
{
Serial.begin(9600); // Инициализируем COM-порт
dht.begin(); // Инициализируем датчик
pinMode(tPIN, OUTPUT); // Определяем пин для управления температурой как Вывод
pinMode(hPIN, OUTPUT);
pinMode(lPIN, OUTPUT);
lcd.begin(16,2); // устанавливаем размеры экрана
lcd.backlight(true); // Указываем использование подсветки экрана
}

void loop() // зацикливание (код управляющей программы)
{
if (Serial.available() > 0) SetTime(); // Если на COM-порт поступила информация, то изменим системное время
float h = dht.readHumidity(); // Считываем влажность
float t = dht.readTemperature(); // Считываем температуру
int Hour = RTC.get(DS1307_HR,true); // Получаем значение текущего часа
int Minute = RTC.get(DS1307_MIN,false);
int Second = RTC.get(DS1307_SEC,false);
boolean Day = (Hour >= 8 & Hour <20); // Если текущий час находится в промежутке от 8 до 20, то действуют дневные параметры
tStatus = (t < ((Day) ? tempDay : tempNight)) ? LOW:HIGH; // Если температура меньше желаемой, то статус обогревателя=Вкл, в противном случае Выкл
//Relay.lineWrite(tPIN, tStatus);
digitalWrite(tPIN, tStatus);
if (h < ((Day) ? humDay : humNight)) hStatus = LOW; else hStatus = HIGH; // Если влажность меньше желаемой, то статус увлажнителя=Вкл, в противном случае Выкл
digitalWrite(hPIN, hStatus);
digitalWrite(lPIN, (Day) ? LOW:HIGH); // Если дневное время, то включим подсветку
switch(Hour) // в зависимости от времени меняем яркость светодиодной ленты
{
case 7:analogWrite(sdPIN, map(Minute, 0, 59, 0, 255)); break;
case 20:analogWrite(sdPIN, map(Minute, 0, 59, 255, 0)); break;
default:analogWrite(sdPIN, (Day) ? 255:0);
}
lcd.setCursor(1,0); // устанавливаем позицию курсора на экране (на один символ правее левого верхнего угла)
lcd.print(t, 1); lcd.print("C "); lcd.print(h, 1); lcd.print("%"); // Выводим информацию о климате
lcd.setCursor(4,1); // устанавливаем курсор для вывода времени
lcd.print(addZero(Hour));lcd.print(":");lcd.print(addZero(Minute));lcd.print(":");lcd.println(addZero(Second)+ " "); // Выводим время
lcd.setCursor(1,1);lcd.print((tStatus == LOW) ? "+":" "); // Выводим индикатор работы подогрева
lcd.setCursor(13,1);lcd.print((hStatus == LOW) ? "+":" "); // Выводим индикатор работы увлажнения

delay(500); // Задержка в пол секунды
}

void SetTime() // установка времени из шаблона tчч:мм
{
if (Serial.read() == 't') // Если первый символ t, то установим указанное время
{
int h = (Serial.read() - '0') * 10 + (Serial.read() - '0');
Serial.read();
int m = (Serial.read() - '0') * 10 + (Serial.read() - '0');
RTC.stop();
RTC.set(DS1307_SEC,0); //set the seconds
RTC.set(DS1307_MIN,m); //set the minutes
RTC.set(DS1307_HR,h); //set the hours
RTC.start();
}
Serial.flush();
}

String addZero(int val)
{
if (val<10) return "0" + String(val);else return String(val);
}


Примечание 1. Возможно Ваши номера контактов SPI шины, использованные при инициализации дисплея будут отличаться.
Примечание 2. В стандатном варианте подключения дисплея соединить контакты Arduino c контактами экрана соответственно: 12 - RS, 11 - E, 10 - DB4, 9 - DB5, 4 - DB6, 2 - DB7. Остальные контакты экрана разводим как в ссылке: http://audio.probudget.ru/arduino/arduino-i-lcd-ekran
Примечание 3. Форматирование сообщения съедает лишние пробелы, поэтому чтобы информация на экране отображалась так, как на фото, необходимо добавить пробелы вручную. lcd.print("C ") - после С 5 пробелов, lcd.print("%") - после % 2 пробела, lcd.println(addZero(Second)+ " ") - в кавычках 5 пробелов.

Изменено 19-10-2012 автор CiberRus

Изменено 23-10-2012 автор CiberRus
2014-08-06 добавлено 06/08/2014 13:27:03#433692

Новенький





13
Russian Federation Engels
4 г. назад
Добрый День!!! У меня огромная проблема. Меня очень интересует контроллер , тот вариант который опубликован на первой странице! Но дело в том, что скеч у меня не компилируется. Не могли-бы Вы дать некоторые пояснения, а именно: какую версию Arduino Вы использовали, а также дайте пожалуйста ссылочки на ВСЕ используемые в проекте библиотеки,где их можно качнуть и куда вставить !!! Ну не дружу я с програмированием, а контроллеров мне нужно много, т.к. увлекаюсь перепеловодством и гидропоникой! Я понимаю, что Вы эту тему прожевали и выплюнули и наверно уже забыли, но для меня она КРАЙНЕ важна. Если Вам не трудно--помогите плиззззз.... P.S. Железо собрано уже как пол-года, делал несколько десятков "подходов" на тему скомпилировать скеч, ну не идёт и всё. Вот решил написать Вам. С Уважением Игорь.
2014-08-23 добавлено 23/08/2014 14:46:00#434341

Посетитель





78
Russian Federation Moscow
6 мес. назад
сообщение Rey Bred
Добрый День!!! У меня огромная проблема. Меня очень интересует контроллер , тот вариант который опубликован на первой странице! Но дело в том, что скеч у меня не компилируется. Не могли-бы Вы дать некоторые пояснения, а именно: какую версию Arduino Вы использовали, а также дайте пожалуйста ссылочки на ВСЕ используемые в проекте библиотеки,где их можно качнуть и куда вставить !!! Ну не дружу я с програмированием, а контроллеров мне нужно много, т.к. увлекаюсь перепеловодством и гидропоникой! Я понимаю, что Вы эту тему прожевали и выплюнули и наверно уже забыли, но для меня она КРАЙНЕ важна. Если Вам не трудно--помогите плиззззз.... P.S. Железо собрано уже как пол-года, делал несколько десятков "подходов" на тему скомпилировать скеч, ну не идёт и всё. Вот решил написать Вам. С Уважением Игорь.


Добрый день.
1. Во всех примерах я использовал версию IDE 0.23.
2. Если я правильно понял, о какой из статей Вы ведете речь (№5, если нет, то уточните), то в ней есть ссылка на первоисточник, в котором есть ссылки на библиотеки для SPI: Подключаем кучу устройств к Arduino по 5 проводам. Ссылка на библиотеку для датчика есть в статье №1, для часов в №4. Перечень подключаемых библиотек можно понять из текста скетча, каждая библиотека объявляется инструкцией #include
3. Каталог с библиотекой необходимо поместить в папку libraries каталога программы (..\arduino-0023\libraries\). Если библиотека заархивирована, то предварительно распаковать.
4. Пришлите текст ошибок из окна сообщений, которые появляются при компиляции.
2014-08-26 добавлено 26/08/2014 11:04:08#434405

Новенький





13
Russian Federation Rostov-on-don
4 г. назад
CiberRus
Уважаемый CiberRus, Добрый День! Огромное спасибо что отозвались! Меня конечно же интересует скетч № 5. Итак, по порядку: Как я уже писал, с этим скетчем и возникла проблема. Сразу оговорюсь - использую версию 0023, все необходимые библиотеки распакованы и добавлены, но скетч всё таки не компилируется. Пол года назад, я решил пойти поэтапно : начал загружать скетчи по порядку. Первые три скетча " влетали " без проблем, а вот из-за четвёртого я и просидел пол года( это тот скетч , где добавляются часы реального времени ). Ну не идёт и всё! И вот буквально вчера я "досмотрелся" - в скетче не подключена библиотека #include <Wire.h>. Я её включил , и произошло чудо - скетч " влетел "!!! Ужасно довольный я перешёл к пятому скетчу ,но УВЫ - не компилируется. Вот сообщение об ошибке : 0023\hardware\arduino\cores\arduino\main.cpp:10:undefined reference to "loop". Подскажите пожалуйста, в чём проблема??? С Уважением Игорь.
2014-09-19 добавлено 19/09/2014 15:51:57#435172

Новенький





13
Russian Federation Rostov-on-don
4 г. назад
Rey Bred
Прошу прощения, не ту ошибку написал, выдаёт -- SPI_BUS does not name a type error:Lcd was not deklared in this score in function void loop. Так же в " окне " ( не знаю как правильно назвать , ну это там где я пытаюсь загрузить скетч ) выскакивает выделенная жёлтым строка :SPI_Bus shreg(_8bit, 10);// Подключаем сдвиговый регистр. Вот теперь кажется всё!
2014-09-19 добавлено 19/09/2014 16:16:24#435173

Посетитель





78
Russian Federation Moscow
6 мес. назад
сообщение Rey Bred
в скетче не подключена библиотека #include <Wire.h>. Я её включил , и произошло чудо - скетч " влетел "!!!


Да, действительно пропустил библиотеку. Жаль нельзя редактировать статью.
Странно что никто до этого не жаловался, видимо до 4-го никто не доходил...
Зря Вы раньше не обратились с ошибкой, не пришлось бы мучаться пол года...

сообщение Rey Bred
Прошу прощения, не ту ошибку написал, выдаёт -- SPI_BUS does not name a type error:Lcd was not deklared in this score in function void loop. Так же в " окне " ( не знаю как правильно назвать , ну это там где я пытаюсь загрузить скетч ) выскакивает выделенная жёлтым строка :SPI_Bus shreg(_8bit, 10);// Подключаем сдвиговый регистр. Вот теперь кажется всё!


Скорее всего Вы не добавили библиотеку SPI_Bus: Библиотека SPI_Bus.
Но я думаю, что Вам нет особого смысла заморачиваться со сдвиговым регистром, если Вы не энтузиаст. Поэтому удалите все зеленые строки, кроме строки #include <Wire.h>, а экран подключите напрямую, точно так, как указано по ссылке из статьи Подключение LCD дисплея

Если все же у Вас деффицит выводов, то стоит рассмотреть альтернативу, интерфейс I2C Поиск на e-bay
Мне такой вариант понравлися больше. Все что надо, скачать библиотеку Библиотека LiquidCristal_I2C; заменить #include <LiquidCrystal.h> на #include <LiquidCrystal_I2C.h>; и строку инициализации LiquidCrystal lcd(12, 11, 10, 9, 4, 2); на LiquidCrystal_I2C lcd(0x27,16,2);

Да, и еще. Могли бы Вы не перепечатывать текст ошибки в будущем, а копировать (сочетанием Ctrl+C) и вставлять (Ctrl+V) как она есть, а то помимо орфографии (deklared вместо declared, score вместо scope), может потеряться и более существенная информация...

Изменено 22-9-2014 автор CiberRus
2014-09-22 добавлено 22/09/2014 08:20:46#435262

Посетитель





57
Новый Уренгой
1 г. назад
день добрый всем.
кто то повторил все это на малинке (raspberry pi)?
2014-10-10 добавлено 10/10/2014 05:53:42#436046

<< 2345678 10 >> Создать новую темуБыстрый ответ