Простой умный инкубатор.
- Войдите на сайт для отправки комментариев
Добрый день. С умным брудером получилось, пришло время заняться инкубатором.
Задача - сделать простое по материалам и стоимости, но надежное и точное устройство для маленьких и средних бытовых инкубаторов. Для замены примитивных аналоговых терморегуляторов в корпусах то мыльниц и розеток. Получилось не совсем дешево, но компактно и функционально.
Что мы имеем:
Термометр - народный DS18B20, с залитыми эпоксидным клеем контактами.
Влагомер и доп. термометр - SHT10.
Arduino ProMini в качестве мозга.
LCD 20х4 с I2C контроллером.
Пара твердотельных Omron-овских реле на плате.
Пищалка пьезо.
Двусторонняя плата 50х50мм.
Блок реле с опторазвязкой.
Что мы умеем:
ПИД регулятор с низкочастотным ШИМ в канале нагревателя.
Измерение и поддержани заданной влажности.
Управление поворотом лотков с периодом 1-12 часов или случайным образом.
Управление аварийным вытяжным вентелятором при перегреве.
Подачей звуковой сигнализации и включение аварийного реле при аварии.
В качестве бонуса вольтметр входного напряжения. Это для случая работы от резервного аккумулятора.
Возможность использовать нагревател, увлажнитель, вентиляторы как с питанием от сети 220в, так и от постоянки 12в.
Экранное меню где настраиваются все вышеперечисленные параметры и сохранение настроек в EEPROM.
Визуализация в графическом виде на компьютере температур для удобной настройки ПИД коэффициентов.
Устройство собрано и проверено. Заказал изготовление плат в Китае, на повестке дня тестирование в реальном инкубаторе. Естественно функционал будет добавляться. Часов нет.
Скетч.
#include <PID_v1.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <EEPROM2.h> #include <DallasTemperature.h> #include <OneWire.h> //#include <SimpleTimer.h> #include <Sensirion.h> int del = 80; // переменная ожидания между выборами меню unsigned int interval = 100; // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций) #define heater_pin 13 // нагреватель #define humidifer_pin 12 // увлажнитель #define fan_pin 11 // вентилятор #define alarm_pin 14 // пин аварии #define beeper_pin 9 //пищалка по аварии #define dataPin 5 //SHT10 #define clockPin 6 //SHT10 #define turn_pin 10 // управление поворотом #define button_minus_pin 2 //пин кнопки "минус" #define button_plus_pin 3 //пин кнопки "плюс" #define button_enter_pin 4 //пин кнопки "enter" #define DS18B20_Pin 7 //пин термометра #define setSampleTime 1000 //время цикла ПИД #define voltmeter_pin 1 //вход А1 через делитель (22к/10к) подключен к питанию модуля. Измеряет до 16В. boolean button_minus; boolean button_plus; boolean button_enter; boolean turnFlag = 0; // флаг поворота для случайного периода float humidity; // Влажность float temp1Ink; // Температура DS18B20 float temp2Ink; // Температура SHT10 float dewpoint; // Точка росы unsigned int rawData; unsigned long currentTime; // задаем переменные для тайминга поворота unsigned long loopTime; unsigned long serialTime; //this will help us know when to talk with processing unsigned long now; unsigned long trhMillis = 0; // период опроса датчиков byte measActive = false; byte measType = TEMP; const unsigned long TRHSTEP = 3000UL; // Sensor query period LiquidCrystal_I2C lcd(0x27, 20, 4); // инициализация библиотеки дисплея //SHT1x sht1x(dataPin, clockPin); OneWire oneWire(DS18B20_Pin); DallasTemperature sensors(&oneWire); Sensirion sht = Sensirion(dataPin, clockPin); double Setpoint, Input, Output; //объявляем переменные для ПИД PID myPID(&Input, &Output, &Setpoint, 10, 4, 3, DIRECT); //Инициализируем ПИД-библиотеку и коэффициенты int WindowSize = setSampleTime; // ширина окна терморегулятора 1 секунда. unsigned long windowStartTime; //SimpleTimer timer; /* EEPROM1 - tempInk EEPROM5 (13) - set_humidity EEPROM7 - alarmTemp EEPROM9 - fanTemp EEPROM11 - turnPeriod */ void setup() { Serial.begin(9600); lcd.init(); // Старт дисплея lcd.backlight(); // Включаем подсветку дисплея windowStartTime = millis(); byte stat; byte error = 0; delay(15); myPID.SetOutputLimits(0, WindowSize); //задаем лимиты ширины ПИД-импульса от 0 до 1 секунды. myPID.SetMode(AUTOMATIC); //включаем ПИД-регулирование myPID.SetSampleTime(setSampleTime); pinMode(8, OUTPUT); //пока не используемый 8 вывод. Переводим в 1 чтобы не включать реле. digitalWrite(8, HIGH); pinMode(heater_pin, OUTPUT); pinMode(turn_pin, OUTPUT); // устанавливаем выводы digitalWrite(turn_pin, HIGH); pinMode(humidifer_pin, OUTPUT); pinMode(fan_pin, OUTPUT); digitalWrite(fan_pin, HIGH); pinMode(alarm_pin, OUTPUT); digitalWrite(alarm_pin, HIGH); pinMode(button_minus_pin, INPUT_PULLUP); //подтягиваем входы кнопок к плюсу встроенными резисторами pinMode(button_plus_pin, INPUT_PULLUP); pinMode(button_enter_pin, INPUT_PULLUP); sensors.begin(); sensors.setResolution(12); // установить разрешение (точность) sensors.setWaitForConversion(false); // отключить ожидание //timer.setInterval(3000, getSensors); windowStartTime = millis(); currentTime = millis(); // считываем время, прошедшее с момента запуска программы loopTime = currentTime; //EEPROM_write(13, 61.0); } void loop() { // Input = getTemp(); unsigned long now = millis(); //timer.run(); button_read(); if (!button_enter) { delay(del); lcd.clear(); menu(); } if (!button_minus) { delay(del); lcd.clear(); //действие по нажатии кнопки "-" } if (!button_plus) { delay(del); lcd.clear(); //действие по нажатии кнопки "+" } //send-receive with processing if it's time if (millis() > serialTime) { SerialReceive(); SerialSend(); serialTime += 500; } getSensors(); thermostat(); humidifer(); turn(); fan(); alarm(); //unsigned long now1 = millis(); //Serial.println(now1-now); } void button_read() {//функция проверки нажатия кнопки button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки if (!button_minus || !button_plus || !button_enter) beeper(50); } //меню void menu() { temp_setup(); hum_setup(); turn_setup(); alarm_setup(); vent_setup(); //data_time_setup(); } //устанавливаем температуру в меню void temp_setup() { float tempInk; lcd.clear(); delay(del); button_read(); lcd.setCursor(2, 0); lcd.print("TEMP.INK SETUP"); delay(1000); int x = 0; while (1) { x++; if (x > interval) { break; } button_read(); //EEPROM_write(1, 37.5); EEPROM_read(1, tempInk); if (!button_enter) { delay(del); lcd.clear(); //очищаем экран break; } if (!button_minus) { EEPROM_write(1, tempInk + 0.1); if (tempInk > 40) { //проверяем, если выше 40, EEPROM_write(1, 40); //пишем в память 40 } lcd.clear(); } if (!button_plus) { EEPROM_write(1, tempInk - 0.1); if (tempInk < 30.0) { //проверяем, если выше 30, EEPROM_write(1, 30.0); //пишем в память 30 } lcd.clear(); } lcd.setCursor(2, 0); lcd.print("TEMP.INK = "); lcd.print(tempInk, 1); lcd.setCursor(0, 3); lcd.print("minus NEXT plus"); delay(del); } } //устанавливаем влажность void hum_setup() { float set_humidity; lcd.clear(); delay(del); button_read(); lcd.setCursor(3, 0); lcd.print("HUMIDITY SETUP"); delay(1000); int x = 0; while (1) { x++; if (x > interval) { break; } button_read(); //EEPROM_write(13, 65.0); //EEPROM_read_mem(13, &set_humidity, sizeof(set_humidity)); EEPROM_read(13, set_humidity); if (!button_enter) { delay(del); lcd.clear(); //очищаем экран break; } if (!button_minus) { EEPROM_write(13, set_humidity + 0.5); if (set_humidity > 100) { //проверяем, если выше 40, EEPROM_write(13, 100.0); //пишем в память 40 } lcd.clear(); } if (!button_plus) { EEPROM_write(13, set_humidity - 0.5); if (set_humidity < 20) { //проверяем, если выше 40, EEPROM_write(13, 20.0); //пишем в память 40 } lcd.clear(); } lcd.setCursor(2, 0); lcd.print("Humidity = "); lcd.print(set_humidity, 1); lcd.setCursor(0, 3); lcd.print("minus NEXT plus"); delay(del); } } //устанавливаем поворот void turn_setup() { int turnPeriod; lcd.clear(); delay(del); button_read(); lcd.setCursor(4, 0); lcd.print("TURN SETUP"); delay(1000); int x = 0; while (1) { x++; if (x > interval) { break; } button_read(); EEPROM_read(11, turnPeriod); if (!button_enter) { delay(del); lcd.clear(); //очищаем экран break; } if (!button_minus) { EEPROM_write(11, turnPeriod + 1); if (turnPeriod > 13) { //проверяем, если выше 40, EEPROM_write(11, 13); //пишем в память 40 } lcd.clear(); } if (!button_plus) { EEPROM_write(11, turnPeriod - 1); if (turnPeriod < 0) { //проверяем, если выше 40, EEPROM_write(11, 0); //пишем в память 40 } lcd.clear(); } EEPROM_read(11, turnPeriod); lcd.setCursor(2, 0); lcd.print("PERIOD = "); lcd.print(turnPeriod); lcd.print(" Hour"); lcd.setCursor(0, 3); lcd.print("minus NEXT plus"); delay(del); } } //устанавливаем сигнализацию void alarm_setup() { int alarmTemp; lcd.clear(); delay(del); button_read(); lcd.setCursor(4, 0); lcd.print("ALARM SETUP"); delay(1000); int x = 0; while (1) { x++; if (x > interval) { break; } button_read(); EEPROM_read(5, alarmTemp); if (!button_enter) { delay(del); lcd.clear(); //очищаем экран break; } if (!button_minus) { EEPROM_write(5, alarmTemp + 1); if (alarmTemp > 10) { //проверяем, если выше 40, EEPROM_write(5, 10); //пишем в память 40 } lcd.clear(); } if (!button_plus) { EEPROM_write(5, alarmTemp - 1); if (alarmTemp < 1) { //проверяем, если выше 40, EEPROM_write(5, 1); //пишем в память 40 } lcd.clear(); } lcd.setCursor(2, 0); lcd.print("T.Alarm + - "); lcd.print(alarmTemp); lcd.print((char)223); lcd.print("C"); lcd.setCursor(0, 3); lcd.print("minus NEXT plus"); delay(del); } } //устанавливаем вентиляцию void vent_setup() { int fanTemp; lcd.clear(); delay(del); button_read(); lcd.setCursor(4, 0); lcd.print("FAN SETUP"); delay(1000); int x = 0; while (1) { x++; if (x > interval) { break; } button_read(); EEPROM_read(9, fanTemp); if (!button_enter) { delay(del); lcd.clear(); //очищаем экран break; } if (!button_minus) { EEPROM_write(9, fanTemp + 1); if (fanTemp > 40) { //проверяем, если выше 40, EEPROM_write(9, 40); //пишем в память 40 } lcd.clear(); } if (!button_plus) { EEPROM_write(9, fanTemp - 1); if (fanTemp < 20) { //проверяем, если выше 40, EEPROM_write(9, 20); //пишем в память 40 } lcd.clear(); } lcd.setCursor(4, 0); lcd.print("T.Fan = "); lcd.print(fanTemp); lcd.print((char)223); lcd.print("C"); lcd.setCursor(0, 3); lcd.print("minus NEXT plus"); delay(del); } } void getSensors(){ unsigned long curMillis = millis(); // Get current time sensors.requestTemperatures(); // Demonstrate non-blocking calls if (curMillis - trhMillis >= TRHSTEP) { // Time for new measurements? measActive = true; measType = TEMP; sht.meas(TEMP, &rawData, NONBLOCK); // Start temp measurement trhMillis = curMillis; } if (measActive && sht.measRdy()) { // Check measurement status if (measType == TEMP) { // Process temp or humi? measType = HUMI; temp2Ink = sht.calcTemp(rawData); // Convert raw sensor data temp1Ink = sensors.getTempCByIndex(0); sht.meas(HUMI, &rawData, NONBLOCK); // Start humi measurement } else { measActive = false; humidity = sht.calcHumi(rawData, temp2Ink); // Convert raw sensor data dewpoint = sht.calcDewpoint(humidity, temp2Ink); } } // logData(); } //void logData() { // Serial.print("temp1Ink = "); // Serial.print(temp1Ink); // Serial.print("temp2Ink = "); // Serial.print(temp2Ink); // Serial.print(" C, Humidity = "); // Serial.print(humidity); // Serial.print(" %, Dewpoint = "); // Serial.print(dewpoint); // Serial.println(" C"); //} //используем терморегулятор void thermostat() { now = millis(); float tempPoint; EEPROM_read_mem(1, &tempPoint, sizeof(tempPoint)); EEPROM_read(1, tempPoint); Setpoint = tempPoint; myPID.Compute(); if (now - windowStartTime > WindowSize) { //время для перещелкивания периода окна windowStartTime = windowStartTime + WindowSize; voltmeter(); //запускаем функцию измерения напряжения Input = temp1Ink; lcd.setCursor(1, 0); // устанавливаем курсор в 0-ом столбце, 0 строка (начинается с 0) lcd.print("T1= "); lcd.print(temp1Ink, 1); // печать температуры на дисплей lcd.print((char)223); lcd.print(" ("); lcd.print(Setpoint, 1); lcd.print(")"); lcd.setCursor(1, 1); lcd.print("T2= "); lcd.print((temp2Ink - 0.4), 1); // печать температуры на дисплей lcd.print((char)223); lcd.setCursor(11, 1); lcd.print(" (*"); lcd.print(temp1Ink - temp2Ink, 1); lcd.print(")"); //lcd.print((char)223); //lcd.print(" ("); //lcd.print(Setpoint, 1); //lcd.print(")"); } if (Output > (now - windowStartTime)) digitalWrite(heater_pin, HIGH); else digitalWrite(heater_pin, LOW); } //управляем влажностью void humidifer() { //float humidity; float set_humidity; unsigned long humMillis = 0; unsigned long curMillis = millis(); // if (curMillis - humMillis >= humStep) { // Time to toggle the LED state? // humMillis = curMillis; // //humidity = sht1x.readHumidity(); // } EEPROM_read_mem(13, &set_humidity, sizeof(set_humidity)); EEPROM_read(13, set_humidity); lcd.setCursor(1, 2); // устанавливаем курсор в 0-ом столбце, 1 строка (начинается с 0) lcd.print(" H= "); lcd.print(humidity, 1); // печать влажности на дисплей lcd.print("%"); lcd.print(" ("); lcd.print(set_humidity, 1); lcd.print(")"); if (set_humidity > humidity) digitalWrite(humidifer_pin, HIGH); //сравниваем измеренную влажность с заданной else digitalWrite(humidifer_pin, LOW); //если влажность низкая, включаем увлажнитель } //управляем поворотом void turn() { int turnPeriod; //период поворота лотков в часах int turnCommand; EEPROM_read(11, turnPeriod); lcd.setCursor(12, 3); lcd.print("P"); lcd.print(turnPeriod); if (turnPeriod == 0) return; //если нулевой период поворота, то не поворачиваем яйца. if (turnPeriod < 13) turnCommand = turnPeriod; else if (turnPeriod > 12 && turnFlag == 0) { //если произошел поворот (сброшен флаг) и значение в памяти 13, то turnCommand = random(1, 6); //берем случайное значение часов 1-6 turnFlag = 1; //защелкиваем флаг вычисления случайных значений до следующего поворота } currentTime = millis(); if (currentTime >= (loopTime + turnCommand * 3600000)) { // 3600000 сравниваем текущий таймер с переменной loopTime + период поворота в часах. digitalWrite(turn_pin, !digitalRead(turn_pin)); // включаем/выключаем реле поворота loopTime = currentTime; // в loopTime записываем новое значение turnFlag = 0; //сбрасываем флаг поворота } } //управляем авариями void alarm() { float tempInk = sensors.getTempCByIndex(0); int alarmTemp; float setTemp; EEPROM_read(5, alarmTemp); EEPROM_read_mem(1, &setTemp, sizeof(setTemp)); EEPROM_read(1, setTemp); lcd.setCursor(0, 3); lcd.print("A"); lcd.print(setTemp + alarmTemp, 1); if (millis() > 1800000) { if (tempInk > (setTemp + alarmTemp) || tempInk < (setTemp - alarmTemp)) { beeper(10); digitalWrite(alarm_pin, LOW); //если измеренная температура выше заданной на величину аварии } else digitalWrite(alarm_pin, HIGH); //то включаем аварийный сигнал. } } void beeper(int duration) { tone(beeper_pin, 2000, duration); } //управляем вентиляторами void fan() { //float tempInk = sht1x.readTemperatureC(); float fanTemp; float setTemp; EEPROM_read(9, fanTemp); EEPROM_read_mem(1, &setTemp, sizeof(setTemp)); EEPROM_read(1, setTemp); lcd.setCursor(6, 3); lcd.print("F"); lcd.print(setTemp + fanTemp, 1); if (temp1Ink > (setTemp + fanTemp)) digitalWrite(fan_pin, LOW); //если измеренная температура выше заданной на величину аварии else digitalWrite(fan_pin, HIGH); //то включаем аварийный сигнал. } void voltmeter(){ float outputValue = 0; outputValue = float(analogRead(voltmeter_pin))/63,9; //Serial.print("Voltage = " ); //Serial.println(outputValue); lcd.setCursor(15, 3); lcd.print("V"); lcd.print(outputValue, 1); } /******************************************** * Serial Communication functions / helpers ********************************************/ union { // This Data structure lets byte asBytes[24]; // us take the byte array float asFloat[6]; // sent from processing and } // easily convert it to a foo; // float array // getting float values from processing into the arduino // was no small task. the way this program does it is // as follows: // * a float takes up 4 bytes. in processing, convert // the array of floats we want to send, into an array // of bytes. // * send the bytes to the arduino // * use a data structure known as a union to convert // the array of bytes back into an array of floats // the bytes coming from the arduino follow the following // format: // 0: 0=Manual, 1=Auto, else = ? error ? // 1: 0=Direct, 1=Reverse, else = ? error ? // 2-5: float setpoint // 6-9: float input // 10-13: float output // 14-17: float P_Param // 18-21: float I_Param // 22-245: float D_Param void SerialReceive() { // read the bytes sent from Processing int index = 0; byte Auto_Man = -1; byte Direct_Reverse = -1; while (Serial.available() && index < 26) { if (index == 0) Auto_Man = Serial.read(); else if (index == 1) Direct_Reverse = Serial.read(); else foo.asBytes[index - 2] = Serial.read(); index++; } // if the information we got was in the correct format, // read it into the system if (index == 26 && (Auto_Man == 0 || Auto_Man == 1) && (Direct_Reverse == 0 || Direct_Reverse == 1)) { Setpoint = double(foo.asFloat[0]); //Input=double(foo.asFloat[1]); // * the user has the ability to send the // value of "Input" in most cases (as // in this one) this is not needed. if (Auto_Man == 0) // * only change the output if we are in { // manual mode. otherwise we'll get an Output = double(foo.asFloat[2]); // output blip, then the controller will } // overwrite. double p, i, d; // * read in and set the controller tunings p = double(foo.asFloat[3]); // i = double(foo.asFloat[4]); // d = double(foo.asFloat[5]); // myPID.SetTunings(p, i, d); // if (Auto_Man == 0) myPID.SetMode(MANUAL); // * set the controller mode else myPID.SetMode(AUTOMATIC); // if (Direct_Reverse == 0) myPID.SetControllerDirection(DIRECT); // * set the controller Direction else myPID.SetControllerDirection(REVERSE); // } Serial.flush(); // * clear any random data from the serial buffer } // unlike our tiny microprocessor, the processing ap // has no problem converting strings into floats, so // we can just send strings. much easier than getting // floats from processing to here no? void SerialSend() { Serial.print("PID "); Serial.print(Setpoint); Serial.print(" "); Serial.print(Input); Serial.print(" "); Serial.print(Output); Serial.print(" "); Serial.print(myPID.GetKp()); Serial.print(" "); Serial.print(myPID.GetKi()); Serial.print(" "); Serial.print(myPID.GetKd()); Serial.print(" "); if (myPID.GetMode() == AUTOMATIC) Serial.print("Automatic"); else Serial.print("Manual"); Serial.print(" "); if (myPID.GetDirection() == DIRECT) Serial.println("Direct"); else Serial.println("Reverse"); }
Плата центрального модуля и плата датчика влажности с обвязкой.
Схему не рисовал, вроде и так понятно все и подписано. Дисплей, кнопки, блок реле подключаются к штыревым разъемам на мамке. Вместо двухамперных твердотельных релюшек на борту можно использовать внешние твердотельные реле или симисторы с опторазвязкой. Для этого сигналы управления выведены на отдельный разъем. Вместо стандатртного блока реле можно подвесить свой блок управления нагрузкой, например на силовых MOSFET ключах для 12В нагрузки. Термометр и гигрометр подключаются в телефонные RJ11 розетки. При подключении их не в свое гнездо ничего не сгорит т.к. контакты питания симметричны.
Вот так выглядит прототип устройства в корпусе из электрокоробки. Только там еще принт с надписями сверху приклеен, позже сфотографирую.
Ну вот как-то так. Не знаю что еще писать. Спрашивайте если интересно. Про инкубацию знаю много, сам птицевод с xx-летним стажем. Паять тоже умею, с Ардуиной пока учусь. Вот.
Да, саоме важное забыл сказать. Тут не Даллас не Сенсерион не дают задержки в библиотеках при измерении и скетч за 50 миллисекунд весь пробегает. Это важно для правильной работы ПИД. Пришлось замысловатую либу раскопать для SHT10, зато она умеет точку росы (!) вычислять. Не знаю только для чего мне в инкубаторе точка росы?
Качественно реализовано. Респект автору.
Спасибо. Я уж думал никто не зайдет сюда, всем веселее про загрузчик и программатор меня пинать.
Вот визуализатор - стандартный PID-Fronend на процессинге из ПИД библиотеки. Зеленая линия - заданная температура, красная - измеренная. Синяя - пропорциональный коэффициент. Обратите внимание как он бодро реагирует на изменения температуры (я пальцами термометр трогал).
А вот так пока внутренности выглядят.
Теперь вот так оно выглядит. В нижней строчке Т. аварии, Т. включения вентилятора, периодичность поворота и вольтметр. Во второй строке в скобочках разница в температуре между термометрами.
http://www.youtube.com/watch?v=ZGWFOssu-Bs&feature=youtu.be
Видео на котором почти ничего не понятно. Для интриги :)))
Код подправил немного:
Здравствуйте в начале указано что заказаны платы в Китае ,тоесть это будет шилд своего рода?Если да то какая цена?Сделал что-то похожее но пока до запуска руки не дошли.
Добрый. Ну вон же плата, чуть выше картинкой опубликована. Выглядеть будет как и эта самоделка, только заводского исполнения. Образец можно в моей прошлой теме про брудер посмотреть. http://arduino.ru/forum/proekty/bruder-avtomat
шилом на верное не совсем правильно называть плату для Про Мини.
Здравствуйте! Не подскажете какой датчик влажности используете, делаю себе подобный инкубатор но для паучьих коконов, там все тоже только параметры влажности и температуры отличаются, количество поворотов 4-6 в сутки... мне и код написали , но все равно куча проблем... датчик влажности завис на 99% иногда после отключения света не может проинициализироватся и вообще виснет...
Можно ли ваш код както подпилить под мое железо?
Здравствуйте. Датчик самый дешевый из хороших - SHT10. Мой код подпилить можно, не вижу проблем.
Вод код с автоматической программой. Периодичность поворота задается в меню.
В алгоритме заложено недостаточное кол-во проветриваний.
За 1 час весь объем воздуха нужно менять не менее 2-х раз. Для этого вентиляцию включают каждые 10 минут на 10 секунд. Иначе эмбрионы могут задохнуться (задохлики).
Выбор датчика температуры не ахти, его точность 0,5 градуса - это много. Нужно калибровать и вносить корректировки, чтобы на рабочем режиме (37-38 градусов) значения температуры были правильные.
Ну и главное - это конструкция самого инкубатора. Если сделать от балды - будет разброс по температуре внутри рабочей камеры. Правильный температурный гистерезис должен быть не более 0,3 градусов.
Спасибо. Я инкубирую яйца постоянно и сотнями. В курсе. Воздухообмен идет постоянно как и работа внутреннего вентилятора. Но проветривание это другое. Это отключение обогрева и охлаждние яиц. Имитация вставания наседеи с гнезда. Яйцо охлаждается, обьем содержимого уменьшается, через скорлупу в яйцо проникает воздух...
это особено актуально для крупных яиц.
По калибровке термометров - у меня есть доступ к поверенному лабораторному оборудованию и имею возможность точно откалибровать Далласы. С разбросом больше 0,3 мне еще не попадались.
гистерезиса нет, есть ПИД.
>>Но проветривание это другое.
>>Это отключение обогрева и охлаждние яиц.
НЕТ. Речь не об Охлаждении, а об Проветривании.
Проветривание - удаление углекислых газов выделяемых яйцом.
Охлаждать яйца совсем не обязательно, главное Проветривание. Для примера в промышленных инкубаторах яйца никогда не охлаждают, только проветривание.
>>гистерезиса нет, есть ПИД.
Вы не поняли. Я про разницу температуры внутри инкубатора.
В промышленных инкубаторах идет постоянная загрузка яйца партиями и один средний режим поддерживается постоянно. Поэтому и не охлаждают. Гусиные и страусиные с охлаждением лучше выводимость демонстрируют. Воздухообмен 6-кратный я при конструировании инкубатора сразу предусматриваю. 2 раза в час слишком мало, особенно для бройлеров. Вы вообще много сами вывели циплят?
Можете поястинить про переворот. Я так понал что переворот лотков включается через определенное настраеваемое время, но я не понял на какое время поворот включается? Когда реле поворота должно выключаться?
Концевик в конце хода лотков. Системы поворота разные могут быть. Есть редукторные асинхронники, шаговые двигатели, моторы постоянного тока и коллекторные. Актуаторы тоже можно. Соответственно и схема управления реверсом разная. Это не проблемы автоматики на самом деле.
>>2 раза в час слишком мало, особенно для бройлеров
Много/мало определяется количеством яиц и объемом камеры, производительностью вентилятора. У вас, как я понял, бытовой на 100 яиц. Проветривание каждый 10 минут по 10 секунд - хватит с головой.
>>Вы вообще много сами вывели циплят?
Мне много не нужно. Больше сотни за вывод не вывожу, только для себя.
Полезную информацию по конструкции и режимам инкубации можно посмотреть тут http://fermer.ru/forum/samodelnye-inkubatory/163938
Особено полезно видео с объяснениями насчет проветривания.
Можете поястинить про переворот. Я так понал что переворот лотков включается через определенное настраеваемое время, но я не понял на какое время поворот включается? Когда реле поворота должно выключаться?
Нет, не бытовой и не на 100. Скажем от 1000 и самострой. Не вижу смысла в цикличном проветривании при наличии постоянного притока свежего воздуха и оттока отработаного. В промышленных инкубаторах управляемые заслрнки видели?
Не дороговато ли с такой доставкой?
Народные РД09 я на Авите по 100-200р беру и от 220 работает с одним реле и 2 герконами.
позвольте людям иметь свое мнение пожалуйста. Вот так работает поворот в инкубаторе на 1000 яиц на РД09 http://m.youtube.com/watch?v=FydII7kDRq0
Ну, на вкус и цвет...
Чем больше в системе узлов и агрегатов - тем меньше надежность.
Для сравнения как это с применением линейных двигателей работает.
http://www.youtube.com/watch?v=E86fIIEwFik
Я же в небольших инкубаторах использую шаговые двигатели на 12V
Umka. Выше вы писали, что датчики не дают задержки. Собственно меня интересует DS18B20. Каким образом убрана задержка? Специальной библиотекой или вот этим
Самому датчику в любом случае нужно время для вычисления температуры. Этими строчками отключается delay в библиотеке и датчики опрашиваются по таймеру. Просто работа мк не останавливается на время конверсии. Иначе ПИД лажает.
Я видел инкубаторы Кравчика. Он их по 60тр и больше продает. Можно конечно купить и не морочится с Ардуинами. С другой стороны можно купить ципленка, курицу несушку или готовое мясо и не иметь сношений с инкубацией. Я жадный. Мне 200р дешевле 6000 за привод поворота.
В точку. +1000 )))
Доброно времени суток! Извените за дремучесть. очень хочется посмотреть схему устройства полностью. Я не профи в смысле электроники. Заранее благодарен
Вам придется сходить на перепел ком, найти не сложно. Без регистрации никак.
Да нету схемы, всё видно по описанию пинов и печатке. Не вижу смысла рисовать еще и схему. Плата по сути соединение в кучу двух датчиков, релюшек и Ардуины и диплеем.
Umke уважуха!!!
Суппер!!!!
Я этим летом для пробы взял 7 кур подрощеных, несушек. Очень понравилось. Планирую на следующий год стационарный курятник ставить и взять еще цесарок на яйца и разведение.
Ну и понятное дело потребуется инкубатор. Так что спасибо за труд.
Вот один в один ктото продает.
https://u-m.biz/shop/index.php?route=product/product&path=59&product_id=51
Но есть готовый и дешевле
http://ru.aliexpress.com/item/100-New-Dual-Digital-F-C-PID-Temperature-Controller-XM-26/608847660.html?spm=2114.031020208.3.1.m9jDY1&ws_ab_test=searchweb201556_6_71_72_73_74_75,searchweb201527_1,searchweb201560_9
Первый мой, а второй без ПИД и с реле электромагнитным на нагрев. Они на все пишут ПИД, но не в одном нет настроек этих коэффициентов. Разве что для паяльной станции термостат, там есть, но он не инкубаторный.
А xm-18 в остальном ничего блочек. Там 2 ступени нагрева, управление влажностью и поворотом, задумка нормальная, их даже в промышленные китайские шкафы ставят. Но вот реле я бы сразу на твердотельные поменял. Контроллер там свой китайский и доки только на китайском и прошивок я не встречал.
Благодарю за информацию. Но для меня 80 зелёных - дороговато. Наверное, придётся самому ковыряться.
Благодарю за информацию. Но для меня 80 зелёных - дороговато. Наверное, придётся самому ковыряться.
Так там вроде и голую плату за недорого предлагают. Детали в магазине, схема-скетч бесплатно. Куда уж демократичней.
Ну да плата 5 баксиков.
Чем отличается ПИД регулятор от релейного в эксплуатации для меня (эксплуатанта).
Так там вроде и голую плату за недорого предлагают. Детали в магазине, схема-скетч бесплатно. Куда уж демократичней.
Там не только голые платы, но и КИТ-наборы есть. И услуга по установке SMD-компоненов присутствует в дополнительных услугах. Если кого пугает. И не только по инкубаторам.
Ну не знаю, купить тестолит, пару дней на разводку потратить, повозиться с двухсторонкой и сэкономить 350р?
Практически ничем, не считая того, что реле с течением времени прикажет долго жить и искать аналогичное может оказаться еще тем геммороем. Пределы регулирования будут более грубыми. На всех подобных устройствах наиболее удобны электронные ключи.
Релейные регуляторы удобны на термостатировании мощных нагрузок, имеющих большую инерцию, типа бойлеров, систем отопления и т.п.
У Носова и вовсе обходились лампочкой и термометром.))))
Так человек сказал, что ему дорого. Хотя я плату за такие деньги поленился бы делать. ИМХО.
Чем отличается ПИД регулятор от релейного в эксплуатации для меня (эксплуатанта).
С ПИД температура поддерживается точнее, нет перегрева, это очень важно. На пальцах обЪясняю. Допустим в инкубаторе температура 37,6 градусов, соответственно ее нужно поднять. Если схема на реле то при его включении вся мошность обогревателей греет воздух к примеру +6 градусов, и на выходе получаем прегрев 43,6. При такой температуре яйца сварятся. Теперь про ПИД. Там все по другому температура 37,6 ПИД регулятор вычисляет нужную мощность и включает нагреватель не на всю мощность а только на +0,2 градуса. На выходе 37,8.
Благодарю за ответ.
скажите пожалуйста как в этом коде заменить sht10
на dth11
Категорически не советую использовать DHT11. Хотяб DHT22 возьмите или AM2123 например. https://drive.google.com/open?id=0B0vRuSZ7oRUeRGgwZlNnY3VVQzQ
Категорически не советую использовать DHT11. Хотяб DHT22 возьмите или AM2123 например. https://drive.google.com/open?id=0B0vRuSZ7oRUeRGgwZlNnY3VVQzQ
я очень уважаю ваше мнение
но уменя инкубатор на 25-30 яиц
неохота мне платить большие деньги
темболее что DHT11 уже имееться в наличии
вот с кодом проблема
а так бы уже все запустил время всетаки
мне вообщето таких наворотов как у вас ненужно
мне контроль темп. и автомат. переворот яиц
но поскольку с ардуино пока оочень далек
пытаюсь ваш код приспособить но ничего путнего не получаеться
Денег нет, наворотов не нужно, код не получается... даже не знаю что тут посоветовать. Может китайский термостат за 200р?
в начале все показывает, а вот в настройках пишет humidity:ноу
темп:ноу и т.д
в eeprom надо данные вбить.
а как часы выставить
и дату?
а то кнопками
немогу нет функции такой
часы и дату? Этого нет в основном скетче. А в автопрограммах есть закоментированная строчка вначале, установка с компа времени при компиляции. А еще я где-то делал по нажатию 2 кнопок меню установки даты-времени.
Кстати, если нужно подобрать коэффициенты ПИД регулятора можно воспользоваться библиотекой PID_AutoTune_v0.h.
Подбор коэффициентов происходит очень долго, несколько часов. У меня за ночь подобрались коэффициенты.
Категорически не советую использовать DHT11. Хотяб DHT22 возьмите или AM2123 например. https://drive.google.com/open?id=0B0vRuSZ7oRUeRGgwZlNnY3VVQzQ
Здравствуйте, чтобы не плодить темы, продолжу в этой, тем более, что взял за основу скеч от Umka, но так как с микроконтроллерами недавно занимаюсь, вопрос по датчику влажности Si7021, как правильно с ним работать? у него есть внутренний нагреватель, в демо примере он 30 сек включен, 20 выключен, измерения делаются раз в секунду. Сам вопрос: надо включать этот внутренний нагреватель или нет
?