Да, простые капельницы тоже копейки стоят. Я много разных капельниц и спринклеров перепробовал, но больше всего с колышками и капеллярками понравились. Их легко перемонтировать на любую длину и количество и льет прямо под корень.
а можно ссылки в студию. очень интересно какие лучше брать и где.
Я на украинских остановился, завод Факел в донецке. http://fakel.dn.ua гарантия 3 года на всю продукцию, капельницы с клапаном, цена вполне по карману, разборные и легко моются... похоже на рекламу. Это только мое мнение, есть много достойных капельниц такого формата и регулируемых и с фиксированным расходом. Есть наборы готовые, есть рассыпухой. Италия, Израиль, Киталия, отечественные...
Цена за новый 80-250 руб, рассчитан на уличное применение и нетребователен к химсоставу воды.
Спалил штук 5 таких насосов в инкубаторе (система поддержания влажности). Разных заводов покупал. Они если больше минуты непрерывно работают, то плавятся и сгорают. Только импульсами короткими можно использовать. В режиме 5 секунд качаем, 10 минут отдыхаем моторчик служит третий год. Для полива совершенно не подходит.
Когда был произведён первый запуск обнаружилось, что блок реле на красном текстолите работают наоборт в отличии от блоков реле на синем текстолите. т.е. при логическом 0 на реле - включенно. 1 - выключенно. Это специально китайцы так придумали?=) пришлось сменить на синий блок.
стоит около 1600, напряжение 12 В, ток замерянный на машине 1,2-1,5 А. Сколько прокачивает литров точно не скажу, но капельницам хвати за глаза это точно. По давлению: ДТ (солярку) поднимала на 2,5 метра на ура (хотя вообще качает тосол). Разъём подходит от форсунки ВАЗ стоит 30-50 руб. Парт номер для заказа в отделе иномарок 0392020034 Бош. Есть отечественные аналоги, но они стоят на 100 руб дешевле, потребляют около 3 А, гудят и текут
3. Что используете в качестве крана для открытия полива? Что все-таки выбрали?
У меня включался насос, без крана. А алгоритм такой: включение насоса по времени, отключение по уровню! Пришло время, полил сколько надо, отключил насос и заполнил емкость.
Обратный клапан - он для того, чтоб поток обратно не пропускать. Тут клапан используется не по прямому назначению. Используется в качестве перепускного клапана. Если емкость будет высокая, то давление высоты водяного столба может продавить и через обратный клапан. Тогда нужно подбирать перепускной клапан, они бывают регулируемые.
Часы для дуины интереснее. Можно зависимости полива от датчиков более гибкими способами прописать. Эта штука с Е-бея на зависимости от времени года и температуры не настроить. Таким же макаром можно пищалку с будильника снять и на цифровой вход на INPUT провод цепануть или старую мобилу. Решение неполноценно.
Ну, если теплицей будет управлять дуина, то да. Но 7 лет назад я о дуине еще не знал и делал тем, что было в продаже. Тогда у меня в теплице балом правил "ОВЕН".
Всем привет. Здорово, что такая тема жива. Делюсь своими наработками.
// Термодатчик DS18B20
#include <OneWire.h>
#include <DallasTemperature.h>
// Спящий режим
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
// Остальное
#include <EEPROM.h>
#include <Streaming.h>
// Часы реального времени
byte day = 0;
byte hours = 0;
byte minutes = 0;
byte seconds = 0;
// Время в гексаминутах ;)
// Так в 1 байт помещается.
// 1440 минут в сутках (24 часа), делим на 6 = 240.
// Можно хранить максимум 24 часа в байте с точностью до 1/6 минуты
byte time; // Время суток
byte water_time = 120; // Время последнего полива. 120 для проверки
// Флаги состояния
byte t1_online, t2_online; // Наличие термодатчиков
byte t1_val, t2_val; // Значение термодатчиков
byte online = 1; // если 0 - система на паузе
// Сдвиговый регистр
int switches = 0; // Состояние выводов сдвигового регистра
byte LIGHT = 0;
byte WATER = 1;
byte T1_UP = 2;
byte T1_DOWN = 3;
byte T2_UP = 4;
byte T2_DOWN = 5;
// Выводы Arduino
byte PIN_LATCH = 8; // Затвор сдвигового регистра (ST_CP)
byte PIN_ONEWIRE = 10; // Шина для датчиков температуры (OneWire)
byte PIN_DATA = 11; // Данные для сдвигового регистра (DS)
byte PIN_CLOCK = 12; // Тактирование сдвигового регистра (SH_CP)
byte PIN_LED = 13; // Индикаторный светодиод
// Настройки (EEPROM)
byte CONF_ADDR = 32; // Смещение структуры в EEPROM
byte CONF_VER = 2; // Версия настроек. Если версия не совпадает, то загрузятся настройки по-умолчанию
struct ConfigStruct {
byte version;
byte t1_id[8], t2_id[8]; // Идентификаторы датчиков демпературы
float t1_min, t1_max; // Настройки термостата 1
float t2_min, t2_max; // Настройки термостата 2
float delta_temp; // Разница температур, как условие для полива. Если разница небольшая, то датчик в земле сухой.
byte water_period; // Время проверки необходимости полива в гексаминутах.
byte light[200]; // Световая схема на каждый из 200 дней. В гексаминутах.
} config = {
CONF_VER,
{}, {},
22.00, 26.00,
21.00, 25.00,
1.50, 10,
{120,120,120,120}
};
OneWire oneWire(PIN_ONEWIRE);
DallasTemperature sensors(&oneWire);
// Прерывания
ISR(WDT_vect)
{
digitalWrite(PIN_LED, !digitalRead(PIN_LED));
}
void serialEvent() {
while (Serial.available()) {
cmd_receive();
// char inChar = (char)Serial.read();
// inputString += inChar;
// if (inChar == '\n') {
// stringComplete = true;
// }
}
}
// Main code
void setup() {
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_LATCH, OUTPUT);
pinMode(PIN_CLOCK, OUTPUT);
pinMode(PIN_DATA, OUTPUT);
Serial.begin(9600);
config_load();
sensors.begin();
// Watchdog timer
MCUSR &= ~(1<<WDRF); /* Clear the reset flag. */
WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */ /* set new watchdog timeout prescaler value */
WDTCSR |= _BV(WDIE); /* Enable the WD interrupt (note no reset). */
// Инициализация прошла
for(byte i = 0; i < 10; i++) {
digitalWrite(PIN_LED, !digitalRead(PIN_LED));
delay(200);
}
}
void loop() {
////// Каждые 8 секунд
// Часы тикают
seconds += 8;
if (seconds >= 60) {
minutes++; seconds -= 60;
if (minutes == 60) {
hours++; minutes=0;
if (hours == 24) {
day++; hours = 0;
}
}
////// Каждую минуту
// Текущее время в гексаминутах, округляем, да.
time = hours * 10 + minutes / 6; // В одном часе 10 гексаминут
// Свет
switch_set(LIGHT, ((time >= config.light[day]) ? HIGH : LOW));
// Опрос термометров
sensors.setResolution(config.t1_id, 10);
sensors.setResolution(config.t2_id, 10);
sensors.requestTemperatures();
t1_val = sensors.getTempC(config.t1_id);
if (t1_val == -127.00) { t1_online = 0; } else { t1_online = 1; }
t2_val = sensors.getTempC(config.t2_id);
if (t2_val == -127.00) { t2_online = 0; } else { t2_online = 1; }
// Полив
if (t1_online && t2_online) {
if ((t1_val - t2_val) < config.delta_temp) {
if (max(time, water_time) - min(time, water_time) >= config.water_period) {
water_time = time;
switch_set(WATER, HIGH);
delay(1000);
switch_set(WATER, LOW);
}
}
}
// Термостат
if (t1_online) {
switch_set(T1_DOWN, ((t1_val > config.t1_max) ? HIGH : LOW));
switch_set(T1_UP, ((t1_val < config.t1_min) ? HIGH : LOW));
}
if (t2_online) {
switch_set(T2_DOWN, ((t2_val > config.t2_max) ? HIGH : LOW));
switch_set(T2_UP, ((t2_val < config.t2_min) ? HIGH : LOW));
}
}
do_sleep(); // В спящий режим
}
// Функции
void cmd_receive() {
// формат: команда[ параметр[ значение]]
// пример: set t1_max 26.80
// исключение light второй параметр 200 байт
char param[6] = {0,0,0,0,0,0};
// Принять команду, до пробела
serial_read_param(param);
switch (param[0]) {
case '0': // Вывести всю информацию
status_show();
break;
case '1':
Serial << "(under construction)" << endl;
break;
case '2':
config_save();
break;
case '3':
Serial << "(under construction)" << endl;
break;
default:
Serial << "Commands:" << endl << "0 - view status" << endl << "1 - set parameter" << endl << "2 - save settings to EEPROM" << endl << "3 - list online termometers" << endl;
}
Serial.flush();
}
// это скорее всего не работает, но смысл ясен
void serial_read_param(char* param) {
byte rx = 0, i = 0;
do {
rx = (byte)Serial.read();
switch (rx) {
case 0:
case 10:
case 13:
case 32:
return;
}
*(param + i) = (char)rx;
i++;
} while (i < 5);
}
void status_show() {
Serial << "Status: " << ((online == 1) ? "Online" : "Offline") << endl;
Serial << "Time: "; // DDD:HH:MM:SS
Serial << ((day < 100) ? "0" : "") << ((day < 10) ? "0" : "") << day << ":";
Serial << ((hours < 10) ? "0" : "") << hours << ":";
Serial << ((minutes < 10) ? "0" : "") << minutes << ":";
Serial << ((seconds < 10) ? "0" : "") << seconds << endl;
Serial << "Last watering: ";
byte water_time_h = water_time / 10;
Serial << ((water_time_h < 10) ? "0" : "") << water_time_h << ":";
byte water_time_m = (water_time % 10) * 6;
Serial << ((water_time_m < 10) ? "0" : "") << water_time_m << endl;
Serial << "Termostat 1: " << ((t1_online == 1) ? "Online" : "Offline") << endl;
// if (t1_online) {
Serial << _FLOAT(t1_val, 2) << " (" << _FLOAT(config.t1_min, 2) << ".." << _FLOAT(config.t1_max, 2) << ")" << endl;
// }
Serial << "Termostat 2: " << ((t2_online == 1) ? "Online" : "Offline") << endl;
// if (t2_online) {
Serial << _FLOAT(t2_val, 2) << " (" << _FLOAT(config.t2_min, 2) << ".." << _FLOAT(config.t2_max, 2) << ")" << endl;
// }
Serial << "Watering: 1 second every " << (config.water_period * 6) << " minutes, if (temp 1 - temp 2) < " << _FLOAT(config.delta_temp, 2) << endl;
}
void config_load() {
Serial << "Loading config... ";
if (EEPROM.read(CONF_ADDR) != CONF_VER) {
Serial << "DEFAULT" << endl;
return;
}
for (unsigned int t = 0; t < sizeof(config); t++)
*((char *)&config + t) = EEPROM.read(CONF_ADDR + t);
Serial << "EEPROM" << endl;
}
void config_save() {
Serial << "Saving config to EEPROM... ";
for (unsigned int t = 0; t < sizeof(config); t++) {
EEPROM.write(CONF_ADDR + t, *((char *)&config + t));
}
Serial << "OK" << endl;
}
void switch_set(byte pos, byte state) {
bitWrite(switches, pos, state);
if (online == 1) switches_update();
}
void switches_update() {
digitalWrite(PIN_LATCH, LOW);
// Вывод будет MSBFIRST с первого (левого) бита
shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, (switches >> 8));
shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, switches);
digitalWrite(PIN_LATCH, HIGH);
}
void do_sleep(void) {
Serial << "(sleep)" << endl;
delay(1000); // Ждем периферию, на всякий
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
// Отрубаем лишнюю периферию
power_adc_disable();
power_spi_disable();
power_timer0_disable();
power_timer1_disable();
power_timer2_disable();
power_twi_disable();
sleep_mode();
sleep_disable();
power_all_enable();
}
Фишки:
1. Часы реального времени на сторожевом таймере. Тикают раз в 8 секунд. Основной цикл спит.
2. Управление настройками и просмотр состояния по терминалу. Возможно потом экранчик 16х2 прикручу.
3. Два термостата с управлением охлаждением/нагревом
4. Полив включается, если разница температур между датчиков меньше заданной. Смысл что один датчик в земле, пока она мокрая, полив не включится.
5. Возможность указать световую схему на 200 дней. Для каждого дня можно указать время включения освещения с точностью до 1/6 минуты. Например, сначала месяц 18 часовой "день", потом плавно уменьшается до 12 часов.
6. Управление нагрузками через сдвиговый регистр (свет, полив, нагреватель1, нагреватель2, охладитель1, охладитель2)
Есть пара вопросов:
1. Почему происходит сброс при каждом подключении COM?
2. Как лучше организовать работу с настройками по терминалу? Помогите написать обработчик команд.
3. Нужно ли отдельную тему на форуме под этот проект создавать?
Тебя интересует сброс при подключении USB ? Так задумано. Смотрим схему, при подключении инициализируется USB-Serial - FT232R, а он уже и выдает сигнал DTR(Data Terminal Ready) на 2 пин - готовность подключенного устройства, который через конденсатор C13 "проскакивает" коротким импульсом на RESET и таким образом сбрасывает CPU. Это нужно, тк иначе можно потерять возможность выполнить загрузчик и перепрошить чип через USB, то есть без программатора. Потому что если он занимается чем то, выполняет программу пользователя, то ему совсем не интересен прошивальщик.
Если эта функция очень мешает, а перепрошивка не планируется то можно попытать нештатное но решение и "нейтрализовать", совсем выпаивать его не комильфо, но можно например повесить дополнитльно сопротивлюшку в 200-500(можно подобрать) Ом в параллель имеющемуся R3, между контактами X1(+5В) и X1(Reset) подбирать нужно от макс к мин, пока не перестанет реагировать на сброс от USB
ZagZag пишет:
Может ресет надо подтянуть или пины поменять? Хотя RX/TX - это же пины 0 и 1, они свободны у меня.
По сути так и есть, reset там подтянут, но можно его притянуть еще сильнее, только не спалить бы ногу FT232...
Кстати если подключаься к сериалу не через разьем USB а напрямую к ногам RX/TX, (пины D0 и D1) то сериал будет вполне адекватно работать и меняться данными без инициализации сброса
а смысл? или ты просто хочешь сделать обмен с компом через ЮСБ? ни чего не изменяя? попробуй с доп сопротивлюшкой, сложности ни какой а разьемчик снять-поставить на X1 дело одной секунды. для работы нацепить, для прошивки снять... красота.
Вечером попробую убрать перемычку. У меня Uno, я ее там видел.
Вообще, хотелось бы обойтись минимумом компонентов. Например, есть модуль RTC 1307, но встроенного таймера вполне хватает. Даже если точность будет не идеальная, можно будет внести корректирующую секунду/минуту в сутки.
Вечером попробую убрать перемычку. У меня Uno, я ее там видел.
Тогда считай совсем повезло, просто перемычечка это не на всех платах есть.
ZagZag пишет:
Например, есть модуль RTC 1307, но встроенного таймера вполне хватает. Даже если точность будет не идеальная, можно будет внести корректирующую секунду/минуту в сутки.
"А потом мне дали овса. Песок не важная замена овсу"(с) О`Генри "Вождь краснокожих"
Все же 1307 это не просто таймер, а часы плюс энергонезависимая память. Незаменимые вещи на случай непоняток с питанием и все такое.
Удобная разводка проводов по перфорированному коробу(избавился от макетки),arduino mega вместо uno, 4х строчный lcd дисплей вместо 2х строчного, запись логов на sdшку, часы реального времени, хранение и изменение параметров работы ящика в энергонезависимой памяти контролера, 4х зонный капельный полив.
Добрый день. Решил автоматизировать две теплички и полив огорода. Приобрел всякие железяки ардуино. И тут началось, мозги закипели, комп практически тоже. Самому с кодом сложновато поэтому решил воспользоваться Вашим кодом для уно и попытаться адаптировать его под свои условия. При компиляции Вашего кода выдало кучу ошибок. Несколько победил установкой библиотек ))). А с очередной, засада, пишет "OneWire does not name a type" не пойму в чем дело. Если Вам не трудно помогите победить ее.
Вы в какой IDE компилируете? я просто компилировал в 1.5.3, а попробовал в 1.0 - не получилось....Если надо могу скинуть вам свои библиотеки, может траблы в них...
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
int outPin = 8;//
LiquidCrystal_I2C lcd(0x27,16,2);
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
void setup(void)
{
// start serial port
// Serial.begin(9600);
// Serial.println("Dallas Temperature IC Control Library Demo");
pinMode(outPin, OUTPUT);
lcd.init(); // initialize the lcd
// Print a message to the LCD.
lcd.backlight();
// Start up the library
sensors.begin();
int t_out = sensors.getTempCByIndex(0);
}
void loop(void)
{
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
// Serial.print(" Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperatures
// Serial.println("DONE");
// Serial.print("Temperature for Device 1 is: ");
// Serial.print(sensors.getTempCByIndex(0)); // Why "byIndex"?
lcd.setCursor(0,0);
lcd.print("t_out=");
lcd.setCursor(6,0);
lcd.print(sensors.getTempCByIndex(0));
if (sensors.getTempCByIndex(0) > 30 && digitalRead(outPin) == LOW)
{
digitalWrite(outPin, HIGH);
lcd.setCursor(13,0);
lcd.print("ON ");
}
if (sensors.getTempCByIndex(0) < 29 && digitalRead(outPin) == HIGH)
{
digitalWrite(outPin, LOW);
lcd.setCursor(13,0);
lcd.print("OFF");
}
//
lcd.setCursor(0,1);
lcd.print("t_in =");
lcd.setCursor(6,1);
lcd.print(sensors.getTempCByIndex(1));
//delay(1000);
// You can have more than one IC on the same bus.
// 0 refers to the first IC on the wire
}
Пишет туже ошибку и выделяет вот эту строку в коде: OneWire oneWire(ONE_WIRE_BUS);
Обнаружил, что если из списка вызвать библиотеку ONEWIRE, то в коде появляется пустая строка. Хотя эта же библиотека уже прописана в коде и окрашена в рыжий цвет.
Да, простые капельницы тоже копейки стоят. Я много разных капельниц и спринклеров перепробовал, но больше всего с колышками и капеллярками понравились. Их легко перемонтировать на любую длину и количество и льет прямо под корень.
а можно ссылки в студию. очень интересно какие лучше брать и где.
Заранее спасибо
а можно ссылки в студию. очень интересно какие лучше брать и где.
Заранее спасибо
в яндексе пиши "капельный полив", очень много чего нашел и не дорого
Я на украинских остановился, завод Факел в донецке. http://fakel.dn.ua гарантия 3 года на всю продукцию, капельницы с клапаном, цена вполне по карману, разборные и легко моются... похоже на рекламу. Это только мое мнение, есть много достойных капельниц такого формата и регулируемых и с фиксированным расходом. Есть наборы готовые, есть рассыпухой. Италия, Израиль, Киталия, отечественные...
Насос омывателя стекла ВАЗ - давление 2,5 кг/см2 , производительность - 16 мл/сек.
Цена за новый 80-250 руб, рассчитан на уличное применение и нетребователен к химсоставу воды.
Спалил штук 5 таких насосов в инкубаторе (система поддержания влажности). Разных заводов покупал. Они если больше минуты непрерывно работают, то плавятся и сгорают. Только импульсами короткими можно использовать. В режиме 5 секунд качаем, 10 минут отдыхаем моторчик служит третий год. Для полива совершенно не подходит.
Спасибо, будем знать.
Привет всем! дайте код, уважаемый dachnik!
Купил девайс вчера, вкурить побыстрее методы настройки хочется. Спасибо!
/* adress eeprom EEPROM 0 Минимальное значение температуры актуатора EEPROM 1 Максимальное значение темп актуатора 1 линия полива EEPROM 2 1/0 включение отключение полива (0=off / 1=on) EEPROM 3 Продолжительность минут полива EEPROM 4 минута полива EEPROM 5 час полива 2 линия полива EEPROM 6 1/0 включение отключение полива (0=off / 1=on) EEPROM 7 Продолжительность минут полива EEPROM 8 минута полива EEPROM 9 час полива 3 линия полива EEPROM 10 1/0 включение отключение полива (0=off / 1=on) EEPROM 11 Продолжительность минут полива EEPROM 12 минута полива EEPROM 13 час полива 4 линия полива EEPROM 14 1/0 включение отключение полива (0=off / 1=on) EEPROM 15 Продолжительность минут полива EEPROM 16 минута полива EEPROM 17 час полива */ //LCD I2C 20x4 #include <EEPROM.h> #include <LiquidCrystal_I2C.h> #include <Wire.h> LiquidCrystal_I2C lcd(0x27,20,4); //LCD //DHT SENSOR #include <DHT.h> #define DHTPIN 2 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); //DHT //кнопка // задаем константы кнопок и присваиваем им пины const int buttonPin = 15; // центральная кнопка const int buttonPin_1 = 14; //левая кнопка const int buttonPin_0 = 16; //правая кнопка const int ledPin = 13; // номер выхода светодиода индикатора const int irr_valve_1 = 32; //№ pin'a первая линия полива const int irr_valve_2 = 33; //№ pin'a вторая линия полива const int irr_valve_3 = 34; //№ pin'a третья линия полива const int irr_valve_4 = 35; //№ pin'a четвёртая линия полива const int rele_7 = 36; //№ pin'a четвёртая линия полива const int rele_8 = 37; //№ pin'a четвёртая линия полива // пины управления актуатором const int open_actuator = 30; //открыть актуатор пином 34 const int close_actuator = 31; //закрыть актуатор пином 35 //пин управления насосом, который заполняет бочку для полива const int nasos = 36; const int sensor_min_level_tank = 26; //дискретный датчик нижнего уровня воды на 26 пине. const int sensor_max_level_tank = 27; int sensor_min_level_state= 1; // int sensor_max_level_state= 1; /* int on_off_1 = EEPROM.read(2); int dur_1 = EEPROM.read(3); int min_dur_1 = EEPROM.read(4); int hour_dur_1 = EEPROM.read(5); int on_off_2 = EEPROM.read(6); int dur_2 = EEPROM.read(7); int min_dur_2 = EEPROM.read(8); int hour_dur_2 = EEPROM.read(9); int on_off_3 = EEPROM.read(10); int dur_3 = EEPROM.read(11); int min_dur_3 = EEPROM.read(12); int hour_dur_3 = EEPROM.read(13); int on_off_4 = EEPROM.read(14); int dur_4 = EEPROM.read(15); int min_dur_4 = EEPROM.read(16); int hour_dur_4 = EEPROM.read(17); */ // глобальные переменные int centreBtn = 0; // переменная для хранения состояния центральной кнопки int leftbtn = 0; // переменная для хранения состояния левой кнопки int rightbtn = 0; // переменная для хранения состояния правой кнопки /* String irr_time =""; //переменная строки времени полива String irr_time_2 =""; //переменная строки времени полива String irr_time_3 =""; //переменная строки времени полива String irr_time_4 =""; //переменная строки времени полива String end_irr_time =""; String end_irr_time_2 =""; String end_irr_time_3 =""; String end_irr_time_4 =""; */ int del = 500; // переменная ожидания между выборами меню(время горения ledpin в милисек) //подсветка LCD //int r=0; long previousMillis = 0; // храним время long interval_2 = 10000; //задержка подсветки long interval_3 = 1000; //задержка записи на SD // интервал //переменные автовозврата в loop int interval = 50; // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций) // int valve_1[5] = {1,2,3,4,5}; int valve_2[5] = {2,6,7,8,9}; int valve_3[5] = {3,10,11,12,13}; int valve_4[5] = {4,14,15,16,17}; //ds1307 модуль часов реального времени #include <Wire.h> #include "RTClib.h" RTC_DS1307 rtc; //строка времени String Date; //строка даты String Time; //времени //--ds1307 //ds1820 temp #include <OneWire.h> #include <DallasTemperature.h> // Data wire is plugged into port 2 on the Arduino #define ONE_WIRE_BUS 3 // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); //float in_tempC; //float out_tempC; //--ds1820 //SD card #include <SPI.h> #include <SD.h> File myFile; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void setup() { //LCD #ifdef AVR Wire.begin(); #else Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due #endif lcd.init(); // initialize the lcd lcd.backlight(); //--LCD // initialize the button pin as a input: // initialize the LED as an output: pinMode(ledPin, OUTPUT); pinMode(irr_valve_1, OUTPUT); pinMode(irr_valve_2, OUTPUT); pinMode(irr_valve_3, OUTPUT); pinMode(irr_valve_4, OUTPUT); pinMode(open_actuator, OUTPUT); pinMode(close_actuator, OUTPUT); pinMode(rele_7, OUTPUT); pinMode(rele_8, OUTPUT); digitalWrite(irr_valve_1, HIGH); digitalWrite(irr_valve_2, HIGH); digitalWrite(irr_valve_3, HIGH); digitalWrite(irr_valve_4, HIGH); digitalWrite(open_actuator, HIGH); digitalWrite(close_actuator, HIGH); digitalWrite(rele_7, HIGH); digitalWrite(rele_8, HIGH); digitalWrite(ledPin, HIGH); // initialize serial communication: Serial.begin(9600); // инициализируем пин, подключенный к кнопке, как вход pinMode(buttonPin, INPUT); pinMode(buttonPin_0, INPUT); pinMode(buttonPin_1, INPUT); pinMode(nasos, OUTPUT); pinMode(sensor_min_level_tank, INPUT); pinMode(sensor_max_level_tank, INPUT); //ds1307 #ifdef AVR Wire.begin(); #else Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due #endif rtc.begin(); if (! rtc.isrunning()) { Serial.println("RTC is NOT running!"); // following line sets the RTC to the date & time this sketch was compiled rtc.adjust(DateTime(__DATE__, __TIME__)); //строка установки системного времени во время компиляции скеча } //--ds1307 //sd pinMode(53, OUTPUT); if (!SD.begin(53)) { Serial.println("initialization SD flash card failed!"); return; } Serial.println("initialization SD flash card done."); //sd //DHT dht.begin(); //DHT close_windows(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //######################################################################################################### void loop() { //if (LCD_LED){lcd.backlight();} time(); termostat(); //temp(); irrigation(valve_1[0],valve_1[1],valve_1[2],valve_1[3],valve_1[4], irr_valve_1); irrigation(valve_2[0],valve_2[1],valve_2[2],valve_2[3],valve_2[4], irr_valve_2); irrigation(valve_3[0],valve_3[1],valve_3[2],valve_3[3],valve_3[4], irr_valve_3); irrigation(valve_4[0],valve_4[1],valve_4[2],valve_4[3],valve_4[4], irr_valve_4); lcd.setCursor(0,0); lcd.print("in= "); lcd.print(temp_in()); lcd.print(" out= "); lcd.print(temp_out()); // lcd.setCursor(0,1); // lcd.print(irr_time); lcd.print(""); // lcd.print(end_irr_time); lcd.print(""); // lcd.print(EEPROM.read(2)); lcd.setCursor(0,2); lcd.print(Date); lcd.print(" "); lcd.print(Time); lcd.setCursor(0,3); lcd.print("h="); lcd.print(Humidity()); lcd.setCursor(7,3); lcd.print("MENU"); button_read(); //читаем кнопки // проверяем нажата ли кнопка if (centreBtn) { // проверяем нажата ли кнопка если нажата, то // LCD_LED = 1; // lcd.backlight(); lcd.backlight(); digitalWrite(ledPin, LOW); delay(del);// включаем светодиод lcd.clear(); //очищаем экран digitalWrite(ledPin, HIGH); menu(); } if (leftbtn) { //включить подсветочку lcd.backlight(); open_windows(); //digitalWrite(ledPin, LOW); //LCD_LED(); //delay(del); //digitalWrite(ledPin, HIGH); } if (rightbtn) { lcd.backlight(); close_windows(); } LCD_LED_OFF(); //таймер отключения подсветки } //##########################################################################################################33 void menu() { actuator_setup(); irrigtion_setup(); irrigation_set_time(); } void actuator_setup() { int x =0; lcd.clear(); //очищаем экран while(1){ // цикл x++; if (x>interval){break;} button_read(); lcd.setCursor(0,0); lcd.print(" -=ACTUATOR SETUP=- "); int t_mini = EEPROM.read(0); lcd.setCursor(0,1); lcd.print("min = "); lcd.print(t_mini); lcd.print((char)223); int t_maxi = EEPROM.read(1); lcd.setCursor(11,1); lcd.print("max = "); lcd.print(t_maxi); lcd.print((char)223); lcd.setCursor(0,2); lcd.print("____________________"); lcd.setCursor(0,3); lcd.print("T_MIN NEXT T_MAX"); digitalWrite(ledPin, HIGH); if (centreBtn) { digitalWrite(ledPin, LOW); delay(del);// включаем светодиод lcd.clear(); //очищаем экран digitalWrite(ledPin, HIGH); break; } if (leftbtn) { digitalWrite(ledPin, LOW); lcd.clear(); t_min(); delay(del); lcd.clear(); //очищаем экран x =0; digitalWrite(ledPin, HIGH); } if (rightbtn) { digitalWrite(ledPin, LOW); lcd.clear(); t_max(); delay(del);// включаем светодиод lcd.clear(); //очищаем экран x =0; digitalWrite(ledPin, HIGH); } }} void irrigtion_setup() { int y =0; lcd.clear(); //очищаем экран while(1){ //бесконечный цикл y++; if (y>interval){break;} //выйти из цикла при y>interval button_read(); lcd.setCursor(0,0); lcd.print("-=IRRIGATION SETUP=-"); // int on_off = EEPROM.read(2); //String x; // if (on_off == 1) {x="ON";} // if (on_off == 0) {x="OFF";} lcd.setCursor(0,1); lcd.print("1 ch="); lcd.print(on_or_off(valve_1[1])); //вызываем функцию on_or_off передаём ей параметр 2 символ массива, возвращаем string ON или OFF lcd.setCursor(10,1); lcd.print("3 ch="); lcd.print(on_or_off(valve_3[1])); lcd.setCursor(0,2); lcd.print("2 ch="); lcd.print(on_or_off(valve_2[1])); lcd.setCursor(10,2); lcd.print("4 ch="); lcd.print(on_or_off(valve_4[1])); /* int duration = EEPROM.read(3); lcd.setCursor(10,1); lcd.print("dur="); lcd.print(duration); lcd.print("min"); lcd.setCursor(0,2); lcd.print("____________________"); */ lcd.setCursor(0,3); lcd.print("ON/OFF NEXT DURATION"); // digitalWrite(ledPin, HIGH); if (centreBtn) { digitalWrite(ledPin, LOW); delay(del);// включаем светодиод lcd.clear(); //очищаем экран break; } if (rightbtn) { digitalWrite(ledPin, LOW); lcd.clear(); durration_irrigation(valve_1[0],valve_1[1],valve_1[2],valve_1[3],valve_1[4]); durration_irrigation(valve_2[0],valve_2[1],valve_2[2],valve_2[3],valve_2[4]); durration_irrigation(valve_3[0],valve_3[1],valve_3[2],valve_3[3],valve_3[4]); durration_irrigation(valve_4[0],valve_4[1],valve_4[2],valve_4[3],valve_4[4]); delay(del);// включаем светодиод lcd.clear(); //очищаем экран y =0; digitalWrite(ledPin, HIGH); } if (leftbtn) { digitalWrite(ledPin, LOW); lcd.clear(); on_off_irrigation(valve_1[0],valve_1[1]); on_off_irrigation(valve_2[0],valve_2[1]); on_off_irrigation(valve_3[0],valve_3[1]); on_off_irrigation(valve_4[0],valve_4[1]); //on_off_irrigation(); delay(del);// включаем светодиод lcd.clear(); //очищаем экран y =0; digitalWrite(ledPin, HIGH); } }} void irrigation_set_time() { int x =0; lcd.clear(); //очищаем экран while(1){ //бесконечный цикл x++; if (x>interval){break;} button_read(); //string_irrigation_time(); //выполняем функцию строки времени полива для отображения переменной irr_time lcd.setCursor(0,0); lcd.print("IRRIGATION SET TIME"); lcd.setCursor(0,1); lcd.print("1: "); lcd.print(string_irrigation_time(valve_1[0],valve_1[1],valve_1[2],valve_1[3],valve_1[4])); lcd.print(" "); lcd.print(string_irrigation_time(valve_3[0],valve_3[1],valve_3[2],valve_3[3],valve_3[4])); lcd.setCursor(0,2); lcd.print("2: "); lcd.print(string_irrigation_time(valve_2[0],valve_2[1],valve_2[2],valve_2[3],valve_2[4])); lcd.print(" "); lcd.print(string_irrigation_time(valve_4[0],valve_4[1],valve_4[2],valve_4[3],valve_4[4])); // lcd.print(irr_time); //выводим переменную строки времени полива lcd.setCursor(0,3); lcd.print("hours NEXT minuts"); digitalWrite(ledPin, HIGH); if (centreBtn) { digitalWrite(ledPin, LOW); delay(del);// включаем светодиод lcd.clear(); //очищаем экран digitalWrite(ledPin, HIGH); break; } if (leftbtn) { digitalWrite(ledPin, LOW); lcd.clear(); irrigation_set_hours(valve_1[0],valve_1[1],valve_1[2],valve_1[3],valve_1[4]); irrigation_set_hours(valve_2[0],valve_2[1],valve_2[2],valve_2[3],valve_2[4]); irrigation_set_hours(valve_3[0],valve_3[1],valve_3[2],valve_3[3],valve_3[4]); irrigation_set_hours(valve_4[0],valve_4[1],valve_4[2],valve_4[3],valve_4[4]); delay(del); lcd.clear(); //очищаем экран x =0; digitalWrite(ledPin, HIGH); } if (rightbtn) { digitalWrite(ledPin, LOW); lcd.clear(); irrigation_set_minuts(valve_1[0],valve_1[1],valve_1[2],valve_1[3],valve_1[4]); irrigation_set_minuts(valve_2[0],valve_2[1],valve_2[2],valve_2[3],valve_2[4]); irrigation_set_minuts(valve_3[0],valve_3[1],valve_3[2],valve_3[3],valve_3[4]); irrigation_set_minuts(valve_4[0],valve_4[1],valve_4[2],valve_4[3],valve_4[4]); delay(del);// включаем светодиод lcd.clear(); //очищаем экран x =0; digitalWrite(ledPin, HIGH); } }} //////-------------------------------------------------------------------------- //SUB MENU void t_min() { lcd.clear(); //очищаем экран delay(del); while(1){ //бесконечный цикл button_read(); lcd.setCursor(0,0); lcd.print(" TEMP MINIMUM SETUP"); int t_min = EEPROM.read(0); lcd.setCursor(0,1); lcd.print("t = "); lcd.print(t_min); lcd.print((char)223); lcd.print("C"); lcd.setCursor(0,3); lcd.print("t_min-1 NEXT t_min+1"); lcd.setCursor(0,2); lcd.print("____________________"); digitalWrite(ledPin, HIGH); if (centreBtn) { digitalWrite(ledPin, LOW); delay(del);// включаем светодиод lcd.clear(); //очищаем экран digitalWrite(ledPin, HIGH); break; } if (rightbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); EEPROM.write(0, t_min + 1); digitalWrite(ledPin, HIGH); } if (leftbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); EEPROM.write(0, t_min - 1); digitalWrite(ledPin, HIGH); } } } void t_max() { lcd.clear(); //очищаем экран delay(del); while(1){ //бесконечный цикл button_read(); lcd.setCursor(0,0); lcd.print(" TEMP MAXIMUM SETUP"); int t_max = EEPROM.read(1); lcd.setCursor(0,1); lcd.print("t = "); lcd.print(t_max); lcd.print((char)223); lcd.print("C"); lcd.setCursor(0,3); lcd.print("t_max-1 NEXT t_max+1"); lcd.setCursor(0,2); lcd.print("____________________"); digitalWrite(ledPin, HIGH); if (centreBtn) { digitalWrite(ledPin, LOW); delay(del);// включаем светодиод lcd.clear(); //очищаем экран digitalWrite(ledPin, HIGH); break; } if (rightbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); EEPROM.write(1, t_max + 1); digitalWrite(ledPin, HIGH); } if (leftbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); EEPROM.write(1, t_max - 1); digitalWrite(ledPin, HIGH); } } } void on_off_irrigation(int ch,int on_off_x) { lcd.clear(); //очищаем экран delay(del); while(1){ //бесконечный цикл button_read(); lcd.setCursor(0,0); lcd.print("ON/OFF IRRIGATION"); //int on_off = EEPROM.read(on_off_x); //String x; //if (on_off == 1) {x="ON";} //if (on_off == 0) {x="OFF";} lcd.setCursor(0,2); lcd.print("irrigation = "); lcd.print(on_or_off(on_off_x)); //lcd.print(on_off); lcd.setCursor(0,1); lcd.print("chanel N="); lcd.print(ch); lcd.setCursor(0,3); lcd.print("ON NEXT OFF"); digitalWrite(ledPin, HIGH); if (centreBtn) { digitalWrite(ledPin, LOW); delay(del);// включаем светодиод lcd.clear(); //очищаем экран digitalWrite(ledPin, HIGH); break; } if (rightbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); EEPROM.write(on_off_x, 0); digitalWrite(ledPin, HIGH); } if (leftbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); EEPROM.write(on_off_x, 1); digitalWrite(ledPin, HIGH); } } } void durration_irrigation(int ch,int on_off_x, int dur, int min_dur, int hour_dur) { lcd.clear(); //очищаем экран delay(del); while(1){ //бесконечный цикл button_read(); string_end_irrigation_time(ch, on_off_x, dur, min_dur, hour_dur); lcd.setCursor(0,0); lcd.print("DURRATION IRRIGATIN"); int duration = EEPROM.read(dur); lcd.setCursor(0,1); lcd.print("ch N="); lcd.print(ch); lcd.print(" dur="); lcd.print(duration); lcd.print(" min"); lcd.setCursor(0,3); lcd.print("-1min NEXT +1min"); lcd.setCursor(0,2); lcd.print(string_irrigation_time(ch, on_off_x, dur, min_dur, hour_dur)); lcd.print(" "); lcd.print(string_end_irrigation_time(ch, on_off_x, dur, min_dur, hour_dur)); digitalWrite(ledPin, HIGH); if (centreBtn) { digitalWrite(ledPin, LOW); delay(del);// включаем светодиод lcd.clear(); //очищаем экран digitalWrite(ledPin, HIGH); break; } if (rightbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); EEPROM.write(dur, duration + 1); digitalWrite(ledPin, HIGH); } if (leftbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); EEPROM.write(dur, duration - 1); digitalWrite(ledPin, HIGH); } } } void irrigation_set_minuts(int ch,int on_off_x, int dur, int min_dur, int hour_dur) { lcd.clear(); //очищаем экран delay(del); while(1){ //бесконечный цикл button_read(); //string_irrigation_time(); lcd.setCursor(0,0); lcd.print("SET IRR-TION MINUTES"); int minuts = EEPROM.read(min_dur); lcd.setCursor(0,1); lcd.print("ch N_"); lcd.print(ch); lcd.print("= "); lcd.print(string_irrigation_time(ch, on_off_x, dur, min_dur, hour_dur)); // lcd.print("min"); lcd.setCursor(0,2); lcd.print("____________________"); lcd.setCursor(0,3); lcd.print("-1min NEXT +1min"); digitalWrite(ledPin, HIGH); if (centreBtn) { digitalWrite(ledPin, LOW); delay(del);// включаем светодиод lcd.clear(); //очищаем экран digitalWrite(ledPin, HIGH); break; } if (rightbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); minuts = minuts + 1; if (minuts >59){minuts=0;} EEPROM.write(min_dur, minuts); digitalWrite(ledPin, HIGH); } if (leftbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); minuts = minuts - 1; if (minuts < 0) {minuts=59;} EEPROM.write(min_dur, minuts); digitalWrite(ledPin, HIGH); } } } void irrigation_set_hours(int ch,int on_off_x, int dur, int min_dur, int hour_dur) { lcd.clear(); //очищаем экран delay(del); while(1){ //бесконечный цикл button_read(); //string_irrigation_time(); lcd.setCursor(0,0); lcd.print(" SET IRR-TION HOURS"); int hours = EEPROM.read(hour_dur); lcd.setCursor(0,1); lcd.print("ch N_"); lcd.print(ch); lcd.print("= "); lcd.print(string_irrigation_time(ch, on_off_x, dur, min_dur, hour_dur)); // lcd.print("min"); lcd.setCursor(0,2); lcd.print("____________________"); lcd.setCursor(0,3); lcd.print("-1hour NEXT +1hour"); digitalWrite(ledPin, HIGH); if (centreBtn) { digitalWrite(ledPin, LOW); delay(del);// включаем светодиод lcd.clear(); //очищаем экран digitalWrite(ledPin, HIGH); break; } if (rightbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); hours = hours + 1; if (hours >23){hours=0;} EEPROM.write(hour_dur, hours); digitalWrite(ledPin, HIGH); } if (leftbtn) { delay(del); digitalWrite(ledPin, LOW); lcd.clear(); hours = hours - 1; if (hours < 0) {hours=23;} EEPROM.write(hour_dur, hours); digitalWrite(ledPin, HIGH); } } } String string_irrigation_time(int ch, int on_off_x, int dur, int min_dur, int hour_dur) // функция формирования строки времни полива { String irr_time = ""; //очистим глобальную переменную навсякий случай. int minuts = EEPROM.read(min_dur); //читаем память int hours = EEPROM.read(hour_dur); if (hours >= 0 && hours <=9) {irr_time += 0; irr_time += hours;} else{irr_time += hours;} //дописываем нолик для hours irr_time += ":"; if (minuts >= 0 && minuts <=9){irr_time += 0; irr_time += minuts;} else{irr_time += minuts;} //дописываем нолик для minuts irr_time += ":"; irr_time += "00"; //собрали строку времени полива // lcd.setCursor(0,1); // lcd.print("irr_time="); // lcd.print(irr_time); return irr_time; } String string_end_irrigation_time(int ch, int on_off_x, int dur, int min_dur, int hour_dur) // функция формирования строки времни полива { String end_irr_time = ""; //очистим глобальную переменную навсякий случай. int minuts = EEPROM.read(min_dur) + EEPROM.read(dur); //читаем память int hours = EEPROM.read(hour_dur); if (minuts > 59) {int x = minuts / 60; hours += x; int y = x * 60; minuts -= y;} if (hours >= 0 && hours <=9) {end_irr_time += 0; end_irr_time += hours;} else{end_irr_time += hours;} //дописываем нолик для hours end_irr_time += ":"; if (minuts >= 0 && minuts <=9){end_irr_time += 0; end_irr_time += minuts;} else{end_irr_time += minuts;} //дописываем нолик для minuts end_irr_time += ":"; end_irr_time += "00"; //собрали строку времени полива // lcd.setCursor(0,1); // lcd.print("irr_time="); // lcd.print(irr_time); return end_irr_time; } void button_read() //функция проверки нажатия кнопки { centreBtn = digitalRead(buttonPin); //запоминаем значение кнопки rightbtn = digitalRead(buttonPin_0); //запоминаем значение кнопки leftbtn = digitalRead(buttonPin_1); //запоминаем значение кнопки } void LCD_LED_OFF()//таймер отключения подсветки { unsigned long currentMillis = millis(); //проверяем не прошел ли нужный интервал, если прошел то if(currentMillis - previousMillis > interval_2) { // сохраняем время последнего переключения previousMillis = currentMillis; lcd.noBacklight(); // lcd.setCursor(0,3); // lcd.print("led"); // if(r==0) // {lcd.print("led off"); r=1; lcd.noBacklight(); } // else if(r==1)//если кнопка НЕ нажата // {lcd.print("led on"); r=0; lcd.backlight(); } } } void time() //функция строки времени { // int x; DateTime now = rtc.now(); Date = ""; Date += now.year(); Date += "/"; if (now.month() >=0 && now.month() <=9) { Date += "0"; Date += now.month(); } else {Date += now.month();} Date += "/"; if (now.day() >= 0 && now.day() <=9) { Date += "0"; Date += now.day(); } else {Date += now.day();} //dataString += " "; Time =""; if (now.hour() >= 0 && now.hour() <=9 ) { Time += "0"; Time += now.hour(); } else {Time += now.hour();} Time += ":"; if (now.minute() >= 0 && now.minute() <=9 ) { Time += "0"; Time += now.minute(); } else {Time += now.minute();} Time += ":"; if (now.second() >= 0 && now.second() <= 9) { Time += "0"; Time += now.second(); } else {Time += now.second();} // Time += " "; } float temp_in() { sensors.requestTemperatures(); // Send the command to get temperatures float in_tempC = sensors.getTempCByIndex(0); return in_tempC; } float temp_out() { sensors.requestTemperatures(); // Send the command to get temperatures float out_tempC = sensors.getTempCByIndex(1); return out_tempC; } void irrigation(int ch, int on_off_x, int dur, int min_dur, int hour_dur, int irr_valve) { int x=EEPROM.read(on_off_x); if (x == 1){ // string_irrigation_time(ch, on_off_x, dur, min_dur, hour_dur); // string_end_irrigation_time(ch, on_off_x, dur, min_dur, hour_dur); if(string_irrigation_time(ch, on_off_x, dur, min_dur, hour_dur) == Time) { digitalWrite(irr_valve, LOW); Serial.print("ch: "); Serial.print(ch); Serial.print(" "); Serial.print("pin: "); Serial.print(irr_valve); Serial.print(" "); Serial.print("Status: "); Serial.println(" ON"); String file_name = "irrigat.txt"; String value = ""; value += ch; value += ";1;"; sd_write (file_name, value); } if(string_end_irrigation_time(ch, on_off_x, dur, min_dur, hour_dur) == Time) { digitalWrite(irr_valve, HIGH); Serial.print("ch: "); Serial.print(ch); Serial.print(" "); Serial.print("pin: "); Serial.print(irr_valve); Serial.print(" "); Serial.print("Status: "); Serial.println(" OFF"); String file_name = "irrigat.txt"; String value = "" ; value += ch; value += ";0;"; sd_write (file_name, value); } } } String on_or_off (int on_off) { int z = EEPROM.read(on_off); String x; if (z == 1) {x="ON";} if (z == 0) {x="OFF";} return x; } int termostat () { int temp_min = EEPROM.read(0); int temp_max = EEPROM.read(1); if (temp_out() > temp_max && digitalRead(close_actuator)==LOW) { open_windows(); } if (temp_out() < temp_min && digitalRead(open_actuator)==LOW) { close_windows(); } } void open_windows() { digitalWrite(close_actuator, HIGH); delay(1000); digitalWrite(open_actuator, LOW); // lcd.setCursor(0,0); // lcd.print("Open window"); lcd.setCursor(0,1); lcd.print("OPEN ACTUATOR"); String file_name = "actuator.txt"; String value = "1"; sd_write (file_name, value); } void close_windows() { digitalWrite(open_actuator, HIGH); delay(1000); digitalWrite(close_actuator, LOW); // lcd.setCursor(0,0); // lcd.print("Open window"); lcd.setCursor(0,1); lcd.print("CLOSE ACTUATOR"); String file_name = "actuator.txt"; String value = "0"; sd_write (file_name, value); } int _nasos() { sensor_min_level_state = digitalRead(sensor_min_level_tank); sensor_max_level_state = digitalRead(sensor_max_level_tank); if (sensor_min_level_state == LOW) { digitalWrite(nasos, HIGH); String file_name = "nasos.txt"; String value = "0"; sd_write (file_name, value); } if (sensor_max_level_state == HIGH) { digitalWrite(nasos,LOW); String file_name = "nasos.txt"; String value = "1"; sd_write (file_name, value); } } int sd_write (String file_name, String value) { unsigned long currentMillis = millis(); //проверяем не прошел ли нужный интервал, если прошел то if(currentMillis - previousMillis > interval_3) { // сохраняем время последнего переключения previousMillis = currentMillis; char f_n[file_name.length()+1]; file_name.toCharArray(f_n, file_name.length()+1); myFile = SD.open(f_n , FILE_WRITE); //myFile = SD.open(file_name.c_str() , FILE_WRITE); // if the file opened okay, write to it: if (myFile) { Serial.print("Writing to "); Serial.print(f_n); // Serial.print(file_name.c_str()); Serial.print(" "); myFile.print(Date); myFile.print(";"); myFile.print(Time); myFile.print(";"); myFile.println(value); // close the file: myFile.close(); Serial.print("done. Writed: "); Serial.print(Date); Serial.print(";"); Serial.print(Time); Serial.print(";"); Serial.println(value); return(1); } else { // if the file didn't open, print an error: Serial.println("error opening sd card. File: "); Serial.print(file_name.c_str()); return(0); } } } int Humidity() { int h = dht.readHumidity(); return h; }Тут две "соосные" темы появились вернее по сути то это дубли одной.
Управление микроклиматом теплицы
Контроль климата в теплице
Даа а чего?! Интересная такая тема... Родители старики, тяжело поливать каждый вечер. А помогать некогда. Либо работать, либо помогать...
а тем временем идёт сборка ящега управления.
потроха:
Когда был произведён первый запуск обнаружилось, что блок реле на красном текстолите работают наоборт в отличии от блоков реле на синем текстолите. т.е. при логическом 0 на реле - включенно. 1 - выключенно. Это специально китайцы так придумали?=) пришлось сменить на синий блок.
Про насосы, возьмите дополнительную помпу Бош
стоит около 1600, напряжение 12 В, ток замерянный на машине 1,2-1,5 А. Сколько прокачивает литров точно не скажу, но капельницам хвати за глаза это точно. По давлению: ДТ (солярку) поднимала на 2,5 метра на ура (хотя вообще качает тосол). Разъём подходит от форсунки ВАЗ стоит 30-50 руб. Парт номер для заказа в отделе иномарок 0392020034 Бош. Есть отечественные аналоги, но они стоят на 100 руб дешевле, потребляют около 3 А, гудят и текут
вот видео работы
http://www.youtube.com/watch?v=RaqqusQ5EGA
(как тут у Вас видео вставить чтобы сразу окошко было?)
Несколько вопросов появилось! Будьте добры, ответьте))
1. Как реализованы физически датчики уровня воды в бочке?
Нужно ведь чтоб не окислялись они. Латунь?
2. Как включается полив по времени?
Плата часов нужна по ходу. Хотя можно и будильник на первых порах попробовать.
3. Что используете в качестве крана для открытия полива? Что все-таки выбрали?
Несколько вопросов появилось! Будьте добры, ответьте))
1. Как реализованы физически датчики уровня воды в бочке?
Нужно ведь чтоб не окислялись они. Латунь?
Дачики пластиковые они не окисляюся такие.
2. Как включается полив по времени?
Плата часов нужна по ходу. Хотя можно и будильник на первых порах попробовать.
Нужно ведь чтоб не окислялись они. Латунь?
Задал во сколько старт и продолжиельность. и понеслось.
3. Что используете в качестве крана для открытия полива? Что все-таки выбрали?
если вы про клапана, то я о них писал уже. 12 вольовые, расчитанные на слабое давление.
Несколько вопросов появилось! Будьте добры, ответьте))
1. Как реализованы физически датчики уровня воды в бочке?
Нужно ведь чтоб не окислялись они. Латунь?
Я использовал нержавеющие электроды для дуговой сварки.
2. Как включается полив по времени?
Плата часов нужна по ходу. Хотя можно и будильник на первых порах попробовать.
Часы реального времени для дуины или http://www.ebay.com/itm/THC-15A-Digital-LCD-Weekly-Programmable-Timer-AC-220V-Time-Relay-Switch-04-/271031555181?pt=LH_DefaultDomain_0&hash=item3f1abd546d
3. Что используете в качестве крана для открытия полива? Что все-таки выбрали?
У меня включался насос, без крана. А алгоритм такой: включение насоса по времени, отключение по уровню! Пришло время, полил сколько надо, отключил насос и заполнил емкость.
Да, и еще, кран не ставил. Вместо него поставил обычный обратный клапан. Самотеком воде вытечь не хватает давления, а насос его открывает на ура.
обратный клапан на то и обратный, чтоб воде не вытечь.... Не понятно! Где насос стоит? резервуар -> клапан -> насос???
ИЛИ все-таки резервуар -> насос -> клапан???
резервуар--> насос -> клапан.
Обратный клапан - он для того, чтоб поток обратно не пропускать. Тут клапан используется не по прямому назначению. Используется в качестве перепускного клапана. Если емкость будет высокая, то давление высоты водяного столба может продавить и через обратный клапан. Тогда нужно подбирать перепускной клапан, они бывают регулируемые.
а есть фоточка?
к сожалению нет. Эта теплица у меня была лет 6-7 назад. теплицу уже снесли...
Часы для дуины интереснее. Можно зависимости полива от датчиков более гибкими способами прописать. Эта штука с Е-бея на зависимости от времени года и температуры не настроить. Таким же макаром можно пищалку с будильника снять и на цифровой вход на INPUT провод цепануть или старую мобилу. Решение неполноценно.
Ну, если теплицей будет управлять дуина, то да. Но 7 лет назад я о дуине еще не знал и делал тем, что было в продаже. Тогда у меня в теплице балом правил "ОВЕН".
Несколько вопросов появилось! Будьте добры, ответьте))
1. Как реализованы физически датчики уровня воды в бочке?
У меня за уровнем воды следит система из двух герконов ( Мин и Мах ), шланг и поплавок с магнитом.
Магнит проходит Мин включает насос, доходит до Мах выключает.
Интересная задумка. Заводского изготовления или колхоз?
Идея не нова. Схему подглядели где то. Основную работу проделал Тесть. Использовали корпус ббп-20, оттуда же брали питание 12V для реле.
Всем привет. Здорово, что такая тема жива. Делюсь своими наработками.
// Термодатчик DS18B20 #include <OneWire.h> #include <DallasTemperature.h> // Спящий режим #include <avr/sleep.h> #include <avr/power.h> #include <avr/wdt.h> // Остальное #include <EEPROM.h> #include <Streaming.h> // Часы реального времени byte day = 0; byte hours = 0; byte minutes = 0; byte seconds = 0; // Время в гексаминутах ;) // Так в 1 байт помещается. // 1440 минут в сутках (24 часа), делим на 6 = 240. // Можно хранить максимум 24 часа в байте с точностью до 1/6 минуты byte time; // Время суток byte water_time = 120; // Время последнего полива. 120 для проверки // Флаги состояния byte t1_online, t2_online; // Наличие термодатчиков byte t1_val, t2_val; // Значение термодатчиков byte online = 1; // если 0 - система на паузе // Сдвиговый регистр int switches = 0; // Состояние выводов сдвигового регистра byte LIGHT = 0; byte WATER = 1; byte T1_UP = 2; byte T1_DOWN = 3; byte T2_UP = 4; byte T2_DOWN = 5; // Выводы Arduino byte PIN_LATCH = 8; // Затвор сдвигового регистра (ST_CP) byte PIN_ONEWIRE = 10; // Шина для датчиков температуры (OneWire) byte PIN_DATA = 11; // Данные для сдвигового регистра (DS) byte PIN_CLOCK = 12; // Тактирование сдвигового регистра (SH_CP) byte PIN_LED = 13; // Индикаторный светодиод // Настройки (EEPROM) byte CONF_ADDR = 32; // Смещение структуры в EEPROM byte CONF_VER = 2; // Версия настроек. Если версия не совпадает, то загрузятся настройки по-умолчанию struct ConfigStruct { byte version; byte t1_id[8], t2_id[8]; // Идентификаторы датчиков демпературы float t1_min, t1_max; // Настройки термостата 1 float t2_min, t2_max; // Настройки термостата 2 float delta_temp; // Разница температур, как условие для полива. Если разница небольшая, то датчик в земле сухой. byte water_period; // Время проверки необходимости полива в гексаминутах. byte light[200]; // Световая схема на каждый из 200 дней. В гексаминутах. } config = { CONF_VER, {}, {}, 22.00, 26.00, 21.00, 25.00, 1.50, 10, {120,120,120,120} }; OneWire oneWire(PIN_ONEWIRE); DallasTemperature sensors(&oneWire); // Прерывания ISR(WDT_vect) { digitalWrite(PIN_LED, !digitalRead(PIN_LED)); } void serialEvent() { while (Serial.available()) { cmd_receive(); // char inChar = (char)Serial.read(); // inputString += inChar; // if (inChar == '\n') { // stringComplete = true; // } } } // Main code void setup() { pinMode(PIN_LED, OUTPUT); pinMode(PIN_LATCH, OUTPUT); pinMode(PIN_CLOCK, OUTPUT); pinMode(PIN_DATA, OUTPUT); Serial.begin(9600); config_load(); sensors.begin(); // Watchdog timer MCUSR &= ~(1<<WDRF); /* Clear the reset flag. */ WDTCSR |= (1<<WDCE) | (1<<WDE); WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */ /* set new watchdog timeout prescaler value */ WDTCSR |= _BV(WDIE); /* Enable the WD interrupt (note no reset). */ // Инициализация прошла for(byte i = 0; i < 10; i++) { digitalWrite(PIN_LED, !digitalRead(PIN_LED)); delay(200); } } void loop() { ////// Каждые 8 секунд // Часы тикают seconds += 8; if (seconds >= 60) { minutes++; seconds -= 60; if (minutes == 60) { hours++; minutes=0; if (hours == 24) { day++; hours = 0; } } ////// Каждую минуту // Текущее время в гексаминутах, округляем, да. time = hours * 10 + minutes / 6; // В одном часе 10 гексаминут // Свет switch_set(LIGHT, ((time >= config.light[day]) ? HIGH : LOW)); // Опрос термометров sensors.setResolution(config.t1_id, 10); sensors.setResolution(config.t2_id, 10); sensors.requestTemperatures(); t1_val = sensors.getTempC(config.t1_id); if (t1_val == -127.00) { t1_online = 0; } else { t1_online = 1; } t2_val = sensors.getTempC(config.t2_id); if (t2_val == -127.00) { t2_online = 0; } else { t2_online = 1; } // Полив if (t1_online && t2_online) { if ((t1_val - t2_val) < config.delta_temp) { if (max(time, water_time) - min(time, water_time) >= config.water_period) { water_time = time; switch_set(WATER, HIGH); delay(1000); switch_set(WATER, LOW); } } } // Термостат if (t1_online) { switch_set(T1_DOWN, ((t1_val > config.t1_max) ? HIGH : LOW)); switch_set(T1_UP, ((t1_val < config.t1_min) ? HIGH : LOW)); } if (t2_online) { switch_set(T2_DOWN, ((t2_val > config.t2_max) ? HIGH : LOW)); switch_set(T2_UP, ((t2_val < config.t2_min) ? HIGH : LOW)); } } do_sleep(); // В спящий режим } // Функции void cmd_receive() { // формат: команда[ параметр[ значение]] // пример: set t1_max 26.80 // исключение light второй параметр 200 байт char param[6] = {0,0,0,0,0,0}; // Принять команду, до пробела serial_read_param(param); switch (param[0]) { case '0': // Вывести всю информацию status_show(); break; case '1': Serial << "(under construction)" << endl; break; case '2': config_save(); break; case '3': Serial << "(under construction)" << endl; break; default: Serial << "Commands:" << endl << "0 - view status" << endl << "1 - set parameter" << endl << "2 - save settings to EEPROM" << endl << "3 - list online termometers" << endl; } Serial.flush(); } // это скорее всего не работает, но смысл ясен void serial_read_param(char* param) { byte rx = 0, i = 0; do { rx = (byte)Serial.read(); switch (rx) { case 0: case 10: case 13: case 32: return; } *(param + i) = (char)rx; i++; } while (i < 5); } void status_show() { Serial << "Status: " << ((online == 1) ? "Online" : "Offline") << endl; Serial << "Time: "; // DDD:HH:MM:SS Serial << ((day < 100) ? "0" : "") << ((day < 10) ? "0" : "") << day << ":"; Serial << ((hours < 10) ? "0" : "") << hours << ":"; Serial << ((minutes < 10) ? "0" : "") << minutes << ":"; Serial << ((seconds < 10) ? "0" : "") << seconds << endl; Serial << "Last watering: "; byte water_time_h = water_time / 10; Serial << ((water_time_h < 10) ? "0" : "") << water_time_h << ":"; byte water_time_m = (water_time % 10) * 6; Serial << ((water_time_m < 10) ? "0" : "") << water_time_m << endl; Serial << "Termostat 1: " << ((t1_online == 1) ? "Online" : "Offline") << endl; // if (t1_online) { Serial << _FLOAT(t1_val, 2) << " (" << _FLOAT(config.t1_min, 2) << ".." << _FLOAT(config.t1_max, 2) << ")" << endl; // } Serial << "Termostat 2: " << ((t2_online == 1) ? "Online" : "Offline") << endl; // if (t2_online) { Serial << _FLOAT(t2_val, 2) << " (" << _FLOAT(config.t2_min, 2) << ".." << _FLOAT(config.t2_max, 2) << ")" << endl; // } Serial << "Watering: 1 second every " << (config.water_period * 6) << " minutes, if (temp 1 - temp 2) < " << _FLOAT(config.delta_temp, 2) << endl; } void config_load() { Serial << "Loading config... "; if (EEPROM.read(CONF_ADDR) != CONF_VER) { Serial << "DEFAULT" << endl; return; } for (unsigned int t = 0; t < sizeof(config); t++) *((char *)&config + t) = EEPROM.read(CONF_ADDR + t); Serial << "EEPROM" << endl; } void config_save() { Serial << "Saving config to EEPROM... "; for (unsigned int t = 0; t < sizeof(config); t++) { EEPROM.write(CONF_ADDR + t, *((char *)&config + t)); } Serial << "OK" << endl; } void switch_set(byte pos, byte state) { bitWrite(switches, pos, state); if (online == 1) switches_update(); } void switches_update() { digitalWrite(PIN_LATCH, LOW); // Вывод будет MSBFIRST с первого (левого) бита shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, (switches >> 8)); shiftOut(PIN_DATA, PIN_CLOCK, MSBFIRST, switches); digitalWrite(PIN_LATCH, HIGH); } void do_sleep(void) { Serial << "(sleep)" << endl; delay(1000); // Ждем периферию, на всякий set_sleep_mode(SLEEP_MODE_IDLE); sleep_enable(); // Отрубаем лишнюю периферию power_adc_disable(); power_spi_disable(); power_timer0_disable(); power_timer1_disable(); power_timer2_disable(); power_twi_disable(); sleep_mode(); sleep_disable(); power_all_enable(); }Фишки:
1. Часы реального времени на сторожевом таймере. Тикают раз в 8 секунд. Основной цикл спит.
2. Управление настройками и просмотр состояния по терминалу. Возможно потом экранчик 16х2 прикручу.
3. Два термостата с управлением охлаждением/нагревом
4. Полив включается, если разница температур между датчиков меньше заданной. Смысл что один датчик в земле, пока она мокрая, полив не включится.
5. Возможность указать световую схему на 200 дней. Для каждого дня можно указать время включения освещения с точностью до 1/6 минуты. Например, сначала месяц 18 часовой "день", потом плавно уменьшается до 12 часов.
6. Управление нагрузками через сдвиговый регистр (свет, полив, нагреватель1, нагреватель2, охладитель1, охладитель2)
Есть пара вопросов:
1. Почему происходит сброс при каждом подключении COM?
2. Как лучше организовать работу с настройками по терминалу? Помогите написать обработчик команд.
3. Нужно ли отдельную тему на форуме под этот проект создавать?
Проект еще сырой, просто на вопросах застрял.
Лучше отдельную тему, потом искать будет проще
Уже параллельно существуют 3 одинаковые темы. Куда уже еще одну?
Почему сброс происходит? Может ресет надо подтянуть или пины поменять? Хотя RX/TX - это же пины 0 и 1, они свободны у меня.
Да вообще сейчас ничего не подключено, кроме встроенного светодиода. Я в Ардуине новичок.
Вечером попробую пустой проект, только прерывания и Serial. Нужно локализовать проблему.
Тебя интересует сброс при подключении USB ? Так задумано. Смотрим схему, при подключении инициализируется USB-Serial - FT232R, а он уже и выдает сигнал DTR(Data Terminal Ready) на 2 пин - готовность подключенного устройства, который через конденсатор C13 "проскакивает" коротким импульсом на RESET и таким образом сбрасывает CPU. Это нужно, тк иначе можно потерять возможность выполнить загрузчик и перепрошить чип через USB, то есть без программатора. Потому что если он занимается чем то, выполняет программу пользователя, то ему совсем не интересен прошивальщик.
Если эта функция очень мешает, а перепрошивка не планируется то можно попытать нештатное но решение и "нейтрализовать", совсем выпаивать его не комильфо, но можно например повесить дополнитльно сопротивлюшку в 200-500(можно подобрать) Ом в параллель имеющемуся R3, между контактами X1(+5В) и X1(Reset) подбирать нужно от макс к мин, пока не перестанет реагировать на сброс от USB
По сути так и есть, reset там подтянут, но можно его притянуть еще сильнее, только не спалить бы ногу FT232...
Кстати если подключаься к сериалу не через разьем USB а напрямую к ногам RX/TX, (пины D0 и D1) то сериал будет вполне адекватно работать и меняться данными без инициализации сброса
Спасибо. Приделаю внешний USB-RS232.
а смысл? или ты просто хочешь сделать обмен с компом через ЮСБ? ни чего не изменяя? попробуй с доп сопротивлюшкой, сложности ни какой а разьемчик снять-поставить на X1 дело одной секунды. для работы нацепить, для прошивки снять... красота.
Нашел как отключить перезагрузку http://atroshin.ru/ru/content/avtomaticheskaya-perezagruzka-arduino-pri-podklyuchenii-terminala
Вечером попробую убрать перемычку. У меня Uno, я ее там видел.
Вообще, хотелось бы обойтись минимумом компонентов. Например, есть модуль RTC 1307, но встроенного таймера вполне хватает. Даже если точность будет не идеальная, можно будет внести корректирующую секунду/минуту в сутки.
Офф. Для себя заметочку оставлю http://atroshin.ru/ru/content/avtomatizaciya-grouboksa
Вечером попробую убрать перемычку. У меня Uno, я ее там видел.
Тогда считай совсем повезло, просто перемычечка это не на всех платах есть.
"А потом мне дали овса. Песок не важная замена овсу"(с) О`Генри "Вождь краснокожих"
Все же 1307 это не просто таймер, а часы плюс энергонезависимая память. Незаменимые вещи на случай непоняток с питанием и все такое.
Как отключить сброс при подключении Serial
Рабочий способ. Перед прошивкой приходится зажимать кнопку Reset
Модуль управления теплицей v2 установлен и запущен =)
Что нового во второй версии?
Что нового во второй версии?
Ящик прежде всего =),
Удобная разводка проводов по перфорированному коробу(избавился от макетки),arduino mega вместо uno, 4х строчный lcd дисплей вместо 2х строчного, запись логов на sdшку, часы реального времени, хранение и изменение параметров работы ящика в энергонезависимой памяти контролера, 4х зонный капельный полив.
А скетч можно увидеть?
пост #207
Добрый день. Решил автоматизировать две теплички и полив огорода. Приобрел всякие железяки ардуино. И тут началось, мозги закипели, комп практически тоже. Самому с кодом сложновато поэтому решил воспользоваться Вашим кодом для уно и попытаться адаптировать его под свои условия. При компиляции Вашего кода выдало кучу ошибок. Несколько победил установкой библиотек ))). А с очередной, засада, пишет "OneWire does not name a type" не пойму в чем дело. Если Вам не трудно помогите победить ее.
Вы в какой IDE компилируете? я просто компилировал в 1.5.3, а попробовал в 1.0 - не получилось....Если надо могу скинуть вам свои библиотеки, может траблы в них...
В Ide 1.5.6 компилировал. Буду признателен за библиотеки, может в них засада т.к. устанавливал какие нашел.
http://gfile.ru/a5O5e качай
Переустановил библиотеки, все равно таже ошибка.
Все библиотеки в скетче рыжего цвета, а библиотека DHT.h осталась черным. Может в этом проблема?
по 1wire работают датчики темп ds1820 смотри в коде может что-то стёр лишнее?при компиляции должно выдавать номер строки с ошибкой.
Типо этого? teplicaUNO:34: error: 'OneWire' does not name a type
ага, ссылается на 34 строку.
попробуй залить этот код, простой термостат
#include <OneWire.h> #include <DallasTemperature.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> int outPin = 8;// LiquidCrystal_I2C lcd(0x27,16,2); // Data wire is plugged into pin 2 on the Arduino #define ONE_WIRE_BUS 2 // Setup a oneWire instance to communicate with any OneWire devices // (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); void setup(void) { // start serial port // Serial.begin(9600); // Serial.println("Dallas Temperature IC Control Library Demo"); pinMode(outPin, OUTPUT); lcd.init(); // initialize the lcd // Print a message to the LCD. lcd.backlight(); // Start up the library sensors.begin(); int t_out = sensors.getTempCByIndex(0); } void loop(void) { // call sensors.requestTemperatures() to issue a global temperature // request to all devices on the bus // Serial.print(" Requesting temperatures..."); sensors.requestTemperatures(); // Send the command to get temperatures // Serial.println("DONE"); // Serial.print("Temperature for Device 1 is: "); // Serial.print(sensors.getTempCByIndex(0)); // Why "byIndex"? lcd.setCursor(0,0); lcd.print("t_out="); lcd.setCursor(6,0); lcd.print(sensors.getTempCByIndex(0)); if (sensors.getTempCByIndex(0) > 30 && digitalRead(outPin) == LOW) { digitalWrite(outPin, HIGH); lcd.setCursor(13,0); lcd.print("ON "); } if (sensors.getTempCByIndex(0) < 29 && digitalRead(outPin) == HIGH) { digitalWrite(outPin, LOW); lcd.setCursor(13,0); lcd.print("OFF"); } // lcd.setCursor(0,1); lcd.print("t_in ="); lcd.setCursor(6,1); lcd.print(sensors.getTempCByIndex(1)); //delay(1000); // You can have more than one IC on the same bus. // 0 refers to the first IC on the wire }Пишет туже ошибку и выделяет вот эту строку в коде: OneWire oneWire(ONE_WIRE_BUS);
Обнаружил, что если из списка вызвать библиотеку ONEWIRE, то в коде появляется пустая строка. Хотя эта же библиотека уже прописана в коде и окрашена в рыжий цвет.
попробуй в другой IDE
Пробовал, не помогает. А каких нибудь особенностей при загрузке библиотеки OneWire нет? В папку examples нужно чего нибудь вставлять?