"Народный" инкубатор

lean_74
Offline
Зарегистрирован: 22.12.2015

Почему "народный"? Потому что почитал я форум, взял за основу инкубатор от Umka, ПИД от  yul-i-an, часики от dimax , температуру с Далласа от Pyotr и слепил, что получилось. Главной целью было упростить по максимуму и использовать то что уже было куплено, LCD16x2, Даллас , но без даллосовской библиотеки, DHT11 или si7021, ардуино Нано с прошивкой оптибут. В первом моем инкубаторе я wdt не использовал, в итоге 150 перепелиных яиц испортил. Теперь сделал инкубатор поменьше из пенопластовой коробки. фотки позже выложу, если  кого заинтересует.

001#include <avr/wdt.h>
002#include <LiquidCrystal_I2C.h>
003#include <EEPROM.h>
004//#include "DHT.h"
005#include <Si7021.h> //мой датчик влажности
006#include <OneWire.h>
007#include <Wire.h>
008OneWire ds(7);
009#define START_CONVERT 0
010#define READ_TEMP 1
011 
012 
013 
014//#define DHTPIN 11     // what digital pin we're connected to
015//#define DHTTYPE DHT11   // DHT 11, DHT 22
016//DHT dht(DHTPIN, DHTTYPE);
017SI7021 si7021; //раскоментировать, если используем датчик si7021.
018 
019LiquidCrystal_I2C lcd(0x27, 16, 2);  // инициализация библиотеки дисплея
020 
021//номера выводов кнопок
022//#define EXT_HEATING                  // ИСПОЛЬЗУЕМ ДОП.НАГРЕВАТЕЛЬ ВМЕСТО УВЛАЖНИТЕЛЯ. Если нужен увлажнитель, просто закомментируйте эту строку.
023#define heater_pin 6                  // нагреватель
024#define humidifer_pin 12               // увлажнитель
025#define fan_pin 13                     // вентилятор
026#define alarm_pin 10                   // пин аварии
027#define beeper_pin 14                   //пищалка по аварии
028 
029#define turn_pin 8                     // управление поворотом вперед
030//#define turn_pin2 6                    // управление поворотом назад
031//#define extend_heater_pin 8         // дополнительный нагреватель
032#define button_minus_pin 3            //пин кнопки "минус"
033#define button_plus_pin 4             //пин кнопки "плюс"
034#define button_enter_pin 5           //пин кнопки "enter"
035#define DS18B20_Pin 7                 //пин термометра
036//Пин 2 Вход обработки прерывания для детектора нуля и управления семистором
037#define voltmeter_pin 15               //вход А1 через делитель (22к/10к) подключен к питанию модуля. Измеряет до 16В.
038 
039 
040boolean button_minus;                // статус нажатия кнопок
041boolean button_plus;
042boolean button_enter;
043 
044unsigned long currentTime;            // задаем переменные для тайминга поворота
045unsigned long loopTime;
046unsigned long serialTime; //this will help us know when to talk with processing
047 
048boolean hotFlag1 = 0;              // флаг включения обогревателя основного   1-ошибка, включать нельзя
049boolean fanFlag = 0;        // флаг включения вентилятора проветривания 1-включено проветривание
050unsigned long trhMillis = 0;
051 
052boolean flag = 0;
053int clockTime = 0; // флаг того что выводим температуру или влажность
054unsigned long lastMillis = millis();
055int TimeTemp = 4;  //время следующего измерения температуры в секундах
056int TimeTurn = 20;  //время поворота в десятых долях секунды
057 
058const unsigned long TRHSTEP   = 300UL;  // Период опроса датчиков
059 
060//int counter=0;//для проверки вачдога
061 
062volatile uint8_t minut=0;
063//volatile uint8_t chas=0;
064int chas=0;
065volatile uint8_t sec=0;
066int den=0;
067int oldden=0;
068int oldchas=0;
069 
070int temp=0; // температура Далласа
071float temp1=0; // температура Далласа с десятыми
072float temp2=0; // температура DHT, si7021
073float hum=0;
074 
075int del = 80;                     // переменная ожидания между выборами меню
076unsigned int interval = 200;      // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
077 
078boolean out=0;//управление симистором yul-i-an
079int reg,er,zad;//    yul-i-an
080double I,Kp=3,Ki=0.45,Kd=0.6,pre_err,err; //    yul-i-an
081 
082unsigned long alarmDelay;
083 
084float needTemp = 37.6;                  // нужная для текущего дня температура инкубации (по умолчанию)
085float needHum = 60.5;                   // ---- влажность
086int ventTime = 2;                       // длительность проветривания
087boolean needTurn = false;               // нужен ли поворот яиц?
088int bird=0;
089 
090// make some custom characters:
091byte znak_g[8] = {//г
092  0b11111,
093  0b10001,
094  0b10000,
095  0b10000,
096  0b10000,
097  0b10000,
098  0b10000,
099  0b00000
100};
101byte znak_b[8] = {//Б
102  0b11111,
103  0b10001,
104  0b10000,
105  0b11110,
106  0b10001,
107  0b10001,
108  0b11110,
109  0b00000
110};
111 
112byte znak_p[8] = {
113  0b11111,
114  0b10001,
115  0b10001,
116  0b10001,
117  0b10001,
118  0b10001,
119  0b10001,
120  0b00000
121};
122byte znak_i[8] = {
123  0b10001,
124  0b10001,
125  0b10011,
126  0b10101,
127  0b11001,
128  0b10001,
129  0b10001,
130  0b00000
131};
132 
133byte znak_l[8] = {
134  0b00111,
135  0b01001,
136  0b10001,
137  0b10001,
138  0b10001,
139  0b10001,
140  0b10001,
141  0b00000
142};
143 
144byte light_znak[8] = {
145  0b10000,
146  0b10000,
147  0b10000,
148  0b11110,
149  0b10001,
150  0b10001,
151  0b01110,
152  0b00000
153};
154 
155byte znak_u[8] = {
156  0b10001,
157  0b10001,
158  0b10001,
159  0b01111,
160  0b00001,
161  0b10001,
162  0b01110,
163  0b00000
164};
165 
166 
167byte znak_ia[8] = {
168  0b01111,
169  0b10001,
170  0b10001,
171  0b01111,
172  0b00101,
173  0b01001,
174  0b10001,
175  0b00000
176};
177byte znak_d[8] = {
178  0b01110,
179  0b01010,
180  0b01010,
181  0b01010,
182  0b01010,
183  0b11111,
184  0b10001,
185  0b00000
186};
187byte znak_ch[8] = {
188  0b10001,
189  0b10001,
190  0b10001,
191  0b01111,
192  0b00001,
193  0b00001,
194  0b00001,
195  0b00000
196};
197byte znak_c[8] = {
198  0b10010,
199  0b10010,
200  0b10010,
201  0b10010,
202  0b10010,
203  0b10010,
204  0b11111,
205  0b00001
206};
207 
208 
209 
210void readSet(){
211 den=EEPROM_int_read(100);
212 chas=EEPROM_int_read(102);
213  int bird;                  // выбор птицы
214  int r_array[6][4][5] = {
215  {{2, 382, 600, 0, 1}, {12, 376, 600, 3, 1}, {15, 374, 480, 10, 1}, {18, 370, 855, 10, 0}},
216  {{2, 378, 550, 0, 1}, {7, 378, 500, 3, 1}, {14, 378, 500, 10, 1}, {16, 375, 700, 0, 0}},
217  {{7, 382, 700, 0, 1}, {14, 378, 600, 0, 1}, {25, 378, 600, 10, 1}, {28, 375, 855, 0, 0}},
218  {{2, 380, 600, 0, 1}, {7, 378, 550, 0, 1}, {29, 375, 450, 10, 1}, {30, 370, 750, 0, 0}},
219  {{7, 378, 700, 0, 1}, {14, 378, 600, 0, 1}, {27, 378, 600, 15, 1}, {30, 375, 855, 0, 0}},
220  {{8, 377, 650, 0, 1}, {14, 377, 500, 0, 1}, {25, 375, 650, 10, 1}, {28, 375, 655, 10, 0}},
221  };
222//Serial.println("readset=");
223 
224bird=  EEPROM_int_read(110);
225  for (int d=4; d>=0; d--){
226  if(den <= r_array[bird][d][0]){
227  needTemp = float(r_array[bird][d][1])/10;//
228  needHum = float(r_array[bird][d][2])/10; //
229  ventTime = r_array[bird][d][3];
230  needTurn = r_array[bird][d][4];
231  }
232  }
233 
234  if (den>36 || den<0){
235    den=0; //
236  }
237  if (chas>24){
238    chas=0; //
239  }
240  if (minut>60){
241    minut=0; //
242  }
243   
244}
245   
246void setup(){
247   wdt_disable(); // запретили как можно скорее собаку, что-бы не уйти в бесконечный ребут
248//   Serial.begin(9600);
249//   readSet();
250    lcd.begin();
251    lcd.backlight();     // Включаем подсветку дисплея
252    lcd.clear();
253     
254  // create a new character
255//  lcd.createChar(5, znak_g);//г
256  lcd.createChar(5, znak_b);//Б
257  lcd.createChar(1, znak_i);//И
258  lcd.createChar(2, znak_p);//П
259  lcd.createChar(3, znak_l);//Л 
260  lcd.createChar(4, light_znak);  // мягкий хнак
261  lcd.createChar(7, znak_d);  //Д
262  lcd.createChar(8, znak_c); //Ц
263  lcd.createChar(6, znak_u);//У
264    
265  lcd.setCursor(0, 0);
266 
267  lcd.print("   HAPO");
268  lcd.write(7);
269  lcd.print("H");
270  lcd.write(4);
271  lcd.print("|");
272  lcd.write(1);
273  lcd.setCursor(0, 1);
274  lcd.print("   ");
275  lcd.write(1);
276  lcd.print("HK");
277  lcd.write(6);
278  lcd.write(5);
279  lcd.print("ATOP");
280 
281 
282   
283  Wire.begin();        // старт I2C
284  
285//   dht.begin();
286  si7021.begin(); // Runs : Wire.begin() + reset() // старт датчика влажности
287  delay(3000);// подождем пока датчик запуститься, и завтавка погорит
288  si7021.setHumidityRes(12); // Humidity = 12-bit / Temperature = 14-bit //максимальное разрешение
289    
290 
291lcd.createChar(5, znak_g);//г
292  readSet();  // читаем настройки из еепром
293   
294 
295 
296// настройкa часов
297TCCR1A=(1<<WGM11); //режим14 FAST PWM
298TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
299ICR1=62499;  // (16000000MHz /div256) -1 = 1 раз в секунду
300TIMSK1=(1<<TOIE1); //разрешить прерывание
301 
302  tempProcess(START_CONVERT);//конвентируем dallas
303 
304  attachInterrupt(0, zero_crosss_int, RISING);//внешнее прерывание на D2
305  
306  //pinMode(extend_heater_pin, OUTPUT);      //пин дополнительного нагревателя. Переводим в 1 чтобы не включать реле.
307  //digitalWrite(extend_heater_pin, HIGH);
308  pinMode(heater_pin, OUTPUT);
309  pinMode(turn_pin, OUTPUT);      // устанавливаем выводы
310  //pinMode(turn_pin2, OUTPUT);      // устанавливаем выводы
311  digitalWrite(turn_pin, HIGH);
312  //digitalWrite(turn_pin2, HIGH);
313  pinMode(humidifer_pin, OUTPUT);
314  pinMode(fan_pin, OUTPUT);
315  digitalWrite(fan_pin, HIGH);
316  pinMode(alarm_pin, OUTPUT);
317  digitalWrite(alarm_pin, HIGH);
318  pinMode(button_minus_pin, INPUT_PULLUP); //подтягиваем входы кнопок к плюсу встроенными резисторами
319  pinMode(button_plus_pin, INPUT_PULLUP);
320  pinMode(button_enter_pin, INPUT_PULLUP);
321  alarmDelay = millis();
322 
323  wdt_enable(WDTO_8S); // активировали таймер, каждые 8 секунд его нужно сбрасывать
324 
325}
326 
327ISR (TIMER1_OVF_vect) {
328sec++ ; //инкремент переменной каждую секунду
329if (sec>59){sec=0; minut++;}
330if (minut>59){minut=0; chas++;} // при записи каждый час хватит памяти на 11 лет
331if (chas>23){chas=0;den++;}//readSet(); но нам главное знать день инкубации
332if (den>36){den=0; } // частный случай для нас не принципиальный, у нас день инкубации
333}
334 
335void loop(){
336 wdt_reset(); // говорим собаке что "В Багдаде все спокойно", начинается очередной отсчет 8-х секунд.
337  
338 if (oldchas!=chas){ // раз в час сохраняем время
339 EEPROM_int_write(102, chas);
340 oldchas=chas;
341 }
342 if (oldden!=den){ // раз в день читаем настройки заново
343 EEPROM_int_write(100, den);
344 readSet();
345 oldden=den;
346 }
347   button_read();
348  if (!button_enter) {
349    delay(del); //
350    lcd.clear();
351    menu();
352  }
353  if (!button_minus) {
354    delay(del);
355    lcd.clear();
356    alarmDelay = millis();    // задержка аварии по нажатии кнопки Минус
357  }
358  if (!button_plus) {
359    delay(del);
360    lcd.clear();
361    digitalWrite(turn_pin, !digitalRead(turn_pin));       // включаем/выключаем реле поворота по кнопке Плюс
362  }
363 
364  lcd.setCursor(0, 0);
365  if (millis() > serialTime)
366  {
367    PID();//расчитываем ПИД yul-i-an
368    serialTime += 1200;
369    
370  }
371 
372    if (flag == 0)
373  {
374     lastMillis = millis();
375    clockTime=!clockTime;
376    flag = 1;
377  }
378 
379  if (millis() - lastMillis >=TimeTemp*1000) {
380    flag = 0;
381}
382  if (clockTime == 1){
383  lcd.setCursor(0, 0); // выводим часы и день инкубации
384  if (chas < 10) lcd.print(" ");
385  lcd.print(chas, DEC);
386  lcd.print(":");
387  if (minut < 10)lcd.print(0);
388  lcd.print(minut, DEC);
389  lcd.print(" ");
390   lcd.write(7);
391    lcd.print("EH");
392   lcd.write(4);  
393  lcd.print(" ");
394  lcd.print(den, DEC);
395  lcd.print("     ");
396    lcd.setCursor(0, 1);
397//    lcd.print("      ");
398   lcd.print(temp2, 1);              // печать температуры на дисплей temp%10
399   lcd.print((char)223);
400   lcd.print(" ");
401    printbird(bird);
402  }
403  else {
404    lcd.setCursor(0, 0);                 // устанавливаем курсор в 0-ом столбце, 0 строка (начинается с 0)
405    lcd.print("T1=");
406    lcd.print(temp/10, 1);              // печать температуры на дисплей temp
407    lcd.print(".");
408    lcd.print(temp%10, 1);              // печать температуры на дисплей temp%10
409     
410    lcd.print((char)223);
411    lcd.print(" (");
412    lcd.print(needTemp, 1);
413    lcd.print((char)223);
414    lcd.print(")   ");
415    lcd.setCursor(0, 1);                
416    lcd.print("H =");
417    lcd.print(hum, 1);           // печать влажности на дисплей
418    lcd.print("%");
419    lcd.print(" (");
420    lcd.print(needHum, 1);
421    lcd.print("%) ");
422  //  lcd.setCursor(15, 3);
423  //  lcd.print("   ");
424 
425    }
426 
427  getSensors(); // получаем данные с датчиков
428  humidifer(needHum);
429  turn(needTurn);
430  fan(ventTime);
431  alarm(needTemp);
432}
433 
434 
435//регулятор ПИД
436 void PID(){
437   err=needTemp-temp1;
438    if (hotFlag1 ==0) I=I+err;//если проветривание или авария не включаем
439  
440   zad=Kp*err+(Ki*I*0.25)+(Kd*(err-pre_err)/0.25);
441   pre_err=err;
442   if (temp1>=39.5) //это при перегреве
443   {
444   zad=0;
445    I=0;
446   }
447  if (zad<0){ zad=0;I=0;}
448  if (zad>100){zad=100;}
449 }
450 //Внешнее прерывание детектора нуля
451//управление симистором
452void zero_crosss_int(){
453  delayMicroseconds(1230);//для попадания в ноль
454  reg = zad + er;
455  if (reg < 50){
456    out=0;
457    er = reg ;
458  
459  }
460  else {
461    out=1;
462 
463    er=reg-100;
464    }
465 if (hotFlag1 ==0){
466 digitalWrite(heater_pin,out); //если проветривание или авария не включаем
467 }
468 else {
469 digitalWrite(heater_pin,LOW);
470    
471  }
472 }
473  
474 //Авто настройка коэффициентов ПИД
475void AutoPIDSet(){
476  //тут будет автонастройка
477}
478 
479 
480void button_read() {//функция проверки нажатия кнопки
481  button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
482  button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
483  button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
484  if (!button_minus || !button_plus || !button_enter) beeper(50);
485  wdt_reset();
486}
487 
488 
489//меню
490void menu() {
491  startInk();
492  time_setup_chas();
493  time_setup_minut();
494  bird_setup(); 
495  turn_setup();
496  alarm_setup();
497  vent_setup();
498}
499 
500// записываем в память день начала инкубации
501void startInk() {
502String str_menu= "START INK";
503int perem_menu=den;
504int adress_errom=100;
505int perem_max=30;
506String str_perem="Day";
507den= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
508}
509//устанавливаем часы
510void time_setup_chas() {
511String str_menu= "SETUP HOUR";
512int perem_menu=chas;
513int adress_errom=102;
514int perem_max=23;
515String str_perem="Hour";
516chas= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
517}
518//устанавливаем минуты
519void time_setup_minut() {
520String str_menu= "SETUP minute";
521int perem_menu=minut;
522int adress_errom=0;
523int perem_max=59;
524String str_perem="minute";
525minut= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
526}
527 
528//выбираем птицу /////////////////////////////////////////////////////////
529 
530void bird_setup() {
531String str_menu= "SETUP bird";
532int perem_menu=bird;
533int adress_errom=110;
534int perem_max=5;
535String str_perem="bird";
536bird= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
537}
538 
539 
540//устанавливаем поворот
541void turn_setup() {
542int turnPeriod=EEPROM_int_read(104);                //период поворота лотков в часах
543   
544String str_menu= "TURN SETUP";
545int perem_menu=turnPeriod;
546int adress_errom=104;
547int perem_max=12;
548String str_perem="TURN Hour";
549turnPeriod= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
550}
551 
552 
553//устанавливаем сигнализацию
554void alarm_setup() {
555 int  alarmTemp=EEPROM_int_read(106);
556String str_menu= "ALARM SETUP";
557int perem_menu=alarmTemp;
558int adress_errom=106;
559int perem_max=10;
560String str_perem="T.Alarm +- C";
561alarmTemp= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
562}
563 
564//устанавливаем вентиляцию
565void vent_setup() {
566int fanTemp=EEPROM_int_read(108);
567String str_menu= "A.FAN SETUP";
568int perem_menu=fanTemp;
569int adress_errom=108;
570int perem_max=40;
571String str_perem="T.Fan C";
572fanTemp= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
573}
574 
575int setup_menu(String str_menu,int perem_menu,int adress_errom,int perem_max,String str_perem) {
576  lcd.clear();
577  delay(del);
578  button_read();
579  lcd.setCursor(0, 0);
580  lcd.print(str_menu);
581  lcd.print("         ");
582  delay(1000);
583  int x = 0;
584  while (1) {
585    x++;
586    if (x > interval) break;
587    button_read();
588     if (adress_errom!=0) perem_menu=EEPROM_int_read(adress_errom);
589    if (!button_enter) {
590      delay(del);
591      lcd.clear(); //очищаем экран
592      break;
593    }
594    if (!button_minus) {
595      perem_menu--;
596  if (perem_menu<0) perem_menu=perem_max;
597      if (adress_errom!=0) EEPROM_int_write(adress_errom, perem_menu);
598      lcd.clear();
599      readSet();
600    }
601 
602    if (!button_plus) {
603      perem_menu++;
604      if (perem_menu>perem_max) perem_menu=0;
605      if (adress_errom!=0) EEPROM_int_write(adress_errom, perem_menu);
606      lcd.clear();
607      readSet();
608    }
609    if (adress_errom!=0) perem_menu= EEPROM_int_read(adress_errom);
610     
611    lcd.setCursor(0, 0);
612    if (str_perem=="bird"){
613    lcd.print("BIRD ");
614    printbird(perem_menu);
615  
616    lcd.print("           ");
617     
618      }else{
619    lcd.print(str_perem);
620    lcd.print("= ");
621    lcd.print(perem_menu);
622    lcd.print("           ");
623      }
624    lcd.setCursor(0, 1);
625    lcd.print("START NEXT +1");
626    delay(del);
627  }
628 return perem_menu;
629}
630 
631void printbird(int nbird){
632    switch (nbird) {
633      case 0:
634        lcd.print("K");  // курица
635        lcd.write(6);
636        lcd.print("P");  // курица
637        lcd.write(1);
638        lcd.write(8);
639        lcd.print("A    ");  // курица
640        break;
641      case 1:
642        lcd.write(2);
643        lcd.print("EPE");  // перепелка
644        lcd.write(2);
645        lcd.print("E");  // перепелка
646        lcd.write(3);
647        lcd.print("KA ");  // перепелка
648        break;
649      case 2:
650        lcd.write(6);
651        lcd.print("TKA      ");   // утка
652        break;
653      case 3:
654        lcd.write(1);
655        lcd.print("H");  // индоутка
656        lcd.write(7);
657        lcd.print("O");  // индоутка
658        lcd.write(6);
659        lcd.print("TKA  ");   // утка
660        break;
661      case 4:
662         lcd.write(5);
663         lcd.write(6);
664         lcd.print("C");  // гусь
665         lcd.write(4);
666         lcd.print("      ");  // гусь
667        break;
668      case 5:
669        lcd.write(1);
670        lcd.print("H"); // индюк
671        lcd.write(7);
672        lcd.print("|OK    "); // индюк
673         
674        break;
675    }
676 
677}
678 
679 
680void getSensors() {
681  unsigned long curMillis = millis();          // Получаем текущее время работы
682  if (curMillis - trhMillis >= TRHSTEP) {    // время для нового измерения?
683  temp= tempProcess(READ_TEMP);//читаем темпратуру с далласа
684  temp1=float(temp)/10;
685  tempProcess(START_CONVERT); // сразу запрос на конвертацию
686  }
687 
688  // Demonstrate non-blocking calls
689  if (curMillis - trhMillis >= TRHSTEP * 4) {    // время для нового измерения?
690     
691//    hum = dht.readHumidity(); //получение темпрературы и влажности с DHT11
692//    temp2 = dht.readTemperature();
693    temp2=si7021.readTemp(); //получение темпрературы и влажности с si7021
694    hum = si7021.readHumidity();
695     
696    trhMillis = curMillis;
697  }
698 
699}
700 
701//управляем влажностью
702void humidifer(float set_humidity) {
703  //float humidity;
704  unsigned long humMillis = 0;
705  unsigned long curMillis = millis();
706   if (set_humidity > hum) digitalWrite(humidifer_pin, HIGH); //сравниваем измеренную влажность с заданной
707  else if (set_humidity -5 < hum) digitalWrite(humidifer_pin, LOW); //если влажность низкая, включаем увлажнитель
708 
709}
710 
711//управляем поворотом
712void turn(boolean needTurn) {
713  int turnPeriod=EEPROM_int_read(104);                //период поворота лотков в часах
714  int turnCommand;
715  if (turnPeriod == 0) return;           //если нулевой период поворота, то не поворачиваем яйца.
716    turnCommand = turnPeriod;
717  currentTime = millis();
718  if (needTurn == true) {
719    if (currentTime >= (loopTime + turnCommand * 3600000)) {  // 3600000 сравниваем текущий таймер с переменной loopTime + период поворота в часах.
720 //     if (turnFlagUp){
721       digitalWrite(turn_pin,LOW);
722       delay(TimeTurn*100); //время поворота
723       digitalWrite(turn_pin,HIGH);
724      loopTime = currentTime;    // в loopTime записываем новое значение
725    }
726  }
727}
728 
729//управляем авариями
730void alarm(float needTemp) {
731  int alarmTemp=EEPROM_int_read(106);
732    if (temp1> (needTemp + alarmTemp) || temp1 < (needTemp - alarmTemp)) {
733      beeper(10);
734      digitalWrite(alarm_pin, LOW); //если измеренная температура выше заданной на величину аварии
735    }
736    else digitalWrite(alarm_pin, HIGH); //то включаем аварийный сигнал.
737 
738}
739 
740void beeper(int duration) {
741  tone(beeper_pin, 2000, duration);
742}
743 
744 
745//управляем вентиляторами
746void fan(int fanTime) {
747   int fanTemp=EEPROM_int_read(108);
748  if ((chas == 7 && minut < fanTime) || (chas == 19 && minut < fanTime) || (temp1 > fanTemp)) {
749   // digitalWrite( fan_pin, LOW);
750    fanFlag=1;
751   
752    //если наступило время проветривания или измеренная температура выше заданной на величину авариито включаем продувку.
753//    digitalWrite(extend_heater_pin, HIGH);  // при этом отключаем обогрев
754//    digitalWrite(heater_pin, LOW);
755    hotFlag1 = 1;
756 //   hotFlag2 = 1;
757  }
758  else {
759    fanFlag=0;
760    hotFlag1 = 0;
761  }
762   
763  //digitalWrite(fan_pin, HIGH); //иначе выключаем.
764     
765//    hotFlag1 = 1;
766//    hotFlag2 = 1;
767//
768 
769}
770 
771// вольтметр
772//void voltmeter() {
773//  float outputValue = 0;
774//  outputValue = float(analogRead(voltmeter_pin)) / 63, 9;
775//  //if(outputValue < 4.5) beeper(50);
776//  //Serial.print("Voltage = " );
777//  //Serial.println(outputValue);
778//  lcd.setCursor(14, 3);
779//  lcd.print("V");
780//  lcd.print(outputValue, 1);
781//}
782//
783//// Печать мощности нагрвателя
784//void outpuPower() {
785//  lcd.setCursor(14, 3);
786//  lcd.print("W");
787//  lcd.print(Output, 0);
788//  lcd.print(" ");
789//}
790 
791 
792//==============================
793int tempProcess(boolean ch){
794  int t=0;
795  if(!ch){
796    ds.reset();
797    ds.write(0xCC);
798    ds.write(0x44);
799  }
800  else{
801    ds.reset();
802    ds.write(0xCC);
803    ds.write(0xBE);
804    t= ds.read();
805    t = t | (ds.read()<<8);
806    //return  t>>4;//целые *C, десятые отброшены
807    //return  (t+8)>>4;//целые *С с округлением
808    return  (t*10)>>4;//целое в десятых *C (214=>21,4*C)
809  }
810}
811// чтение
812int EEPROM_int_read(int addr) {   
813  byte raw[2];
814  for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i);
815  int &num = (int&)raw;
816  return num;
817}
818 
819// запись
820void EEPROM_int_write(int addr, int num) {
821  byte raw[2];
822  (int&)raw = num;
823  for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]);
824}
825//пример int
826//// запись
827//EEPROM_int_write(12, 1000); // адрес 12 (+2 байта)
828//EEPROM_int_write(14, 2000); // адрес 14 (+2 байта)
829//EEPROM_int_write(16, 3000); // адрес 16 (+2 байта)
830//// чтение
831//int d = EEPROM_int_read(12);
832//int e = EEPROM_int_read(14);
833//int f = EEPROM_int_read(16);

  

BigVal
BigVal аватар
Offline
Зарегистрирован: 10.01.2017

lean_74 меня интересует. Пока начинаю с нуля, но есть большое желание сделать такой девайс. Раньше делал инкубатор на плате W1209. Хочу автоматизировать. Поэтому для начала интересует список оборудования и схема соединений, буду очень признателен.

 

lean_74
Offline
Зарегистрирован: 22.12.2015

Оборудование : 1. Ардуино Нано(у ней надо перешить загрузчик на optiboot чтобы нормально работал wdt -"вачдог"). https://ru.aliexpress.com/item/Freeshipping-Nano-3-0-controller-compatible-for-arduino-nano-CH340-USB-driver-NO-CABLE/32242032996.html?spm=2114.13010608.0.0.dAXz9E

2. DS18b20- датчик температуры (вывод D7 Нано ) . https://ru.aliexpress.com/item/Free-shipping-DS18B20-Stainless-steel1-meters-waterproof-temperature-probe-temperature-sensor/1885949662.html?spm=2114.13010608.0.0.qYVKGw

3. si7021 - датчик температуры и влажностиподключенный по I2C: A4 (SDA) и A5 (SCL) .https://ru.aliexpress.com/item/J34-Free-Shipping-Industrial-High-Precision-Si7021-Humidity-Sensor-with-I2C-Interface/32581660471.html?

4. LCD16x2 подключенная по I2C: A4 (SDA) и A5 (SCL) .https://ru.aliexpress.com/item/15959-Free-Shipping-1602-2004-LCD-Adapter-Plate-IIC-I2C-Interface-i2c-lcd-adapter-for-arduino/32358255501.html?spm=2114.13010608.0.0.Wozd7H

https://ru.aliexpress.com/item/Free-Shipping-LCD1602-1602-module-Blue-screen-16x2-Character-LCD-Display-Module-HD44780-Controller-blue-blacklight/32357804531.html?spm=2114.13010608.0.0.Wozd7H

5. схема подключения двух подключенных паралельно 40-ватных лампочек в качестве нагревателей,  взята отсюда http://cxem.net/arduino/arduino71.php, 

6.увлажнитель.https://ru.aliexpress.com/item/New-Ultrasonic-Mist-Maker-Fogger-Water-Fountain-Pond-Atomizer-Air-Humidifier-free-shipping/32317739179.html?spm=2114.13010608.0.0.dAXz9E

7.переворот яиц https://ru.aliexpress.com/item/Quail-Incubator-16-eggs-64-birds-eggs-AutomaticTurn-eggs-tray-Hand-Incubator-Accessories-Laboratory-incubators/32436706594.html?spm=2114.13010608.0.0.Wozd7H

Схему соединений видна из скетча, я распаял пока на макетке, как все отлажу буду плату разводить, по отдельности все работало нормально, когда все в кучу соединил,  перестала работать схема с ПИД регулированием - сейчас с ней разбираюсь.

BigVal
BigVal аватар
Offline
Зарегистрирован: 10.01.2017

lean_74 спасибо за ответ. Начинаю заказывать оборудование, кое-что заказал ранее, правда еще не получил.

BigVal
BigVal аватар
Offline
Зарегистрирован: 10.01.2017

lean_74 есть вопрос. На сколько вольт двигатель в поворотных лотках, по ссылке не понятно.

lean_74
Offline
Зарегистрирован: 22.12.2015

у меня на 220в, но следующий раз я бы 12в заказал, на случай пропадания 220в в сети и переключения на резервное питание от 12в

MVN123P
Offline
Зарегистрирован: 29.07.2016

Если возможно, снимите небольшое видео экрана инкубатора (меню, настройки и.т.д).

lean_74
Offline
Зарегистрирован: 22.12.2015

MVN123P пишет:

Если возможно, снимите небольшое видео экрана инкубатора (меню, настройки и.т.д).

Снимал телефоном, так что качество так себе https://youtu.be/LEt51o0bDeY

MVN123P
Offline
Зарегистрирован: 29.07.2016

Спасибо.

lean_74
Offline
Зарегистрирован: 22.12.2015

Добавил автоподстройку вых мощности от yul-i-an

001#include <avr/wdt.h>
002#include <LiquidCrystal_I2C.h>
003#include <EEPROM.h>
004//#include "DHT.h"
005#include <Si7021.h> //мой датчик влажности
006#include <OneWire.h>
007#include <Wire.h>
008OneWire ds(7);
009#define START_CONVERT 0
010#define READ_TEMP 1
011 
012 
013 
014//#define DHTPIN 11     // what digital pin we're connected to
015//#define DHTTYPE DHT11   // DHT 11, DHT 22
016//DHT dht(DHTPIN, DHTTYPE);
017SI7021 si7021; //раскоментировать, если используем датчик si7021.
018 
019LiquidCrystal_I2C lcd(0x27, 16, 2);  // инициализация библиотеки дисплея
020 
021//номера выводов кнопок
022//#define EXT_HEATING                  // ИСПОЛЬЗУЕМ ДОП.НАГРЕВАТЕЛЬ ВМЕСТО УВЛАЖНИТЕЛЯ. Если нужен увлажнитель, просто закомментируйте эту строку.
023#define heater_pin 6                  // нагреватель
024#define humidifer_pin 12               // увлажнитель
025#define fan_pin 13                     // вентилятор
026#define alarm_pin 10                   // пин аварии
027#define beeper_pin 14                   //пищалка по аварии
028 
029#define turn_pin 8                     // управление поворотом вперед
030//#define pin9 9                    // проверка
031//#define extend_heater_pin 8         // дополнительный нагреватель
032#define button_minus_pin 3            //пин кнопки "минус"
033#define button_plus_pin 4             //пин кнопки "плюс"
034#define button_enter_pin 5           //пин кнопки "enter"
035#define DS18B20_Pin 7                 //пин термометра
036//Пин 2 Вход обработки прерывания для детектора нуля и управления семистором
037#define voltmeter_pin 15               //вход А1 через делитель (22к/10к) подключен к питанию модуля. Измеряет до 16В.
038 
039 
040boolean button_minus;                // статус нажатия кнопок
041boolean button_plus;
042boolean button_enter;
043 
044unsigned long currentTime;            // задаем переменные для тайминга поворота
045unsigned long loopTime;
046unsigned long serialTime; //this will help us know when to talk with processing
047 
048boolean hotFlag1 = 0;              // флаг включения обогревателя основного   1-ошибка, включать нельзя
049boolean fanFlag = 0;        // флаг включения вентилятора проветривания 1-включено проветривание
050unsigned long trhMillis = 0;
051 
052boolean flag = 0;
053int clockTime = 0; // флаг того что выводим температуру или влажность
054unsigned long lastMillis = millis();
055int TimeTemp = 4;  //время следующего измерения температуры в секундах
056int TimeTurn = 20;  //время поворота в десятых долях секунды
057 
058const unsigned long TRHSTEP   = 300UL;  // Период опроса датчиков
059 
060//int counter=0;//для проверки вачдога
061 
062volatile uint8_t minut=0;
063//volatile uint8_t chas=0;
064int chas=0;
065volatile uint8_t sec=0;
066int den=0;
067int oldden=0;
068int oldchas=0;
069 
070int temp=0; // температура Далласа
071float temp1=0; // температура Далласа с десятыми
072float temp2=0; // температура DHT, si7021
073float hum=0;
074 
075int del = 80;                     // переменная ожидания между выборами меню
076unsigned int interval = 200;      // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
077 
078boolean out=0;//управление симистором yul-i-an
079int reg,er,zad;//    yul-i-an
080double I,Kp=3,Ki=0.45,Kd=0.6,pre_err,err; //    yul-i-an
081 
082unsigned long alarmDelay;
083 
084float needTemp = 37.6;                  // нужная для текущего дня температура инкубации (по умолчанию)
085float needHum = 60.5;                   // ---- влажность
086int ventTime = 2;                       // длительность проветривания
087boolean needTurn = false;               // нужен ли поворот яиц?
088int bird=0;
089 
090// make some custom characters:
091byte znak_g[8] = {//г
092  0b11111,
093  0b10001,
094  0b10000,
095  0b10000,
096  0b10000,
097  0b10000,
098  0b10000,
099  0b00000
100};
101byte znak_b[8] = {//Б
102  0b11111,
103  0b10001,
104  0b10000,
105  0b11110,
106  0b10001,
107  0b10001,
108  0b11110,
109  0b00000
110};
111 
112byte znak_p[8] = {
113  0b11111,
114  0b10001,
115  0b10001,
116  0b10001,
117  0b10001,
118  0b10001,
119  0b10001,
120  0b00000
121};
122byte znak_i[8] = {
123  0b10001,
124  0b10001,
125  0b10011,
126  0b10101,
127  0b11001,
128  0b10001,
129  0b10001,
130  0b00000
131};
132 
133byte znak_l[8] = {
134  0b00111,
135  0b01001,
136  0b10001,
137  0b10001,
138  0b10001,
139  0b10001,
140  0b10001,
141  0b00000
142};
143 
144byte light_znak[8] = {
145  0b10000,
146  0b10000,
147  0b10000,
148  0b11110,
149  0b10001,
150  0b10001,
151  0b01110,
152  0b00000
153};
154 
155byte znak_u[8] = {
156  0b10001,
157  0b10001,
158  0b10001,
159  0b01111,
160  0b00001,
161  0b10001,
162  0b01110,
163  0b00000
164};
165 
166 
167byte znak_ia[8] = {
168  0b01111,
169  0b10001,
170  0b10001,
171  0b01111,
172  0b00101,
173  0b01001,
174  0b10001,
175  0b00000
176};
177byte znak_d[8] = {
178  0b01110,
179  0b01010,
180  0b01010,
181  0b01010,
182  0b01010,
183  0b11111,
184  0b10001,
185  0b00000
186};
187byte znak_ch[8] = {
188  0b10001,
189  0b10001,
190  0b10001,
191  0b01111,
192  0b00001,
193  0b00001,
194  0b00001,
195  0b00000
196};
197byte znak_c[8] = {
198  0b10010,
199  0b10010,
200  0b10010,
201  0b10010,
202  0b10010,
203  0b10010,
204  0b11111,
205  0b00001
206};
207 
208//расчет мощности по ПИД закону регулирования
209//_------------------------------------------------------------
210#define kP 6//коэффициент пропорциональности 6
211#define p_min 0.0//минимум П составляющей - не < 0
212#define p_max 100.0//максимум П составляющей - не > 100
213#define kI 0.100//коэффициент интегрирования 0.025
214#define i_min 0.0//минимум И составляющей
215#define i_max 30.0//максимум И составляющей
216#define kd 0//коэффициент диференциирования
217#define d_ctl 7.0//зона пропорциональности ust-d_ctl
218#define out_min 0//минимальный выходной %
219#define out_max 100//максимальный выходной %
220//возвращает необходимую мощность
221uint8_t PIctl(float temp, float ust) {
222 
223  uint8_t out = 0; //uint8_t
224  static float i = 0;
225  static float ed=0;///
226  float e, p;
227  float d;///
228  e = (ust - temp); //ошибка регулирования
229  p=(temp<ust-d_ctl)?p_max:(temp>ust)?p_min:(kP*e);//П составляющая
230  i=(i<i_min)?i_min:(i>i_max)?i_max:i+(kI*e);//И составляющая
231  d=kd*(e-ed);//Д составляющая
232  ed=e;///
233  out=(p+i+d<out_min)?out_min:(p+i+d>out_max)?out_max:p+i+d;
234  //вывод для настройки
235     Serial.print(" e  ");
236      Serial.print(e);
237      Serial.print("  p ");
238      Serial.print(p);
239      Serial.print("  i ");
240      Serial.print(i);
241      Serial.print("  out ");
242      Serial.println(out);
243  return out;
244}
245//---------------------------------------------------------------
246 
247 
248 
249void readSet(){
250 den=EEPROM_int_read(100);
251 chas=EEPROM_int_read(102);
252  int bird;                  // выбор птицы
253  int r_array[6][4][5] = {
254  {{2, 382, 600, 0, 1}, {12, 376, 600, 3, 1}, {15, 374, 480, 10, 1}, {18, 370, 855, 10, 0}},
255  {{2, 378, 550, 0, 1}, {7, 378, 500, 3, 1}, {14, 378, 500, 10, 1}, {16, 375, 700, 0, 0}},
256  {{7, 382, 700, 0, 1}, {14, 378, 600, 0, 1}, {25, 378, 600, 10, 1}, {28, 375, 855, 0, 0}},
257  {{2, 380, 600, 0, 1}, {7, 378, 550, 0, 1}, {29, 375, 450, 10, 1}, {30, 370, 750, 0, 0}},
258  {{7, 378, 700, 0, 1}, {14, 378, 600, 0, 1}, {27, 378, 600, 15, 1}, {30, 375, 855, 0, 0}},
259  {{8, 377, 650, 0, 1}, {14, 377, 500, 0, 1}, {25, 375, 650, 10, 1}, {28, 375, 655, 10, 0}},
260  };
261//Serial.println("readset=");
262 
263bird=  EEPROM_int_read(110);
264  for (int d=4; d>=0; d--){
265  if(den <= r_array[bird][d][0]){
266  needTemp = float(r_array[bird][d][1])/10;//
267  needHum = float(r_array[bird][d][2])/10; //
268  ventTime = r_array[bird][d][3];
269  needTurn = r_array[bird][d][4];
270  }
271  }
272 
273  if (den>36 || den<0){
274    den=0; //
275  }
276  if (chas>24){
277    chas=0; //
278  }
279  if (minut>60){
280    minut=0; //
281  }
282   
283}
284   
285void setup(){
286   wdt_disable(); // запретили как можно скорее собаку, что-бы не уйти в бесконечный ребут
287   Serial.begin(9600);
288//   readSet();
289    lcd.begin();
290    lcd.backlight();     // Включаем подсветку дисплея
291    lcd.clear();
292     
293  // create a new character
294//  lcd.createChar(5, znak_g);//г
295  lcd.createChar(5, znak_b);//Б
296  lcd.createChar(1, znak_i);//И
297  lcd.createChar(2, znak_p);//П
298  lcd.createChar(3, znak_l);//Л 
299  lcd.createChar(4, light_znak);  // мягкий хнак
300  lcd.createChar(7, znak_d);  //Д
301  lcd.createChar(8, znak_c); //Ц
302  lcd.createChar(6, znak_u);//У
303    
304  lcd.setCursor(0, 0);
305 
306  lcd.print("   HAPO");
307  lcd.write(7);
308  lcd.print("H");
309  lcd.write(4);
310  lcd.print("|");
311  lcd.write(1);
312  lcd.setCursor(0, 1);
313  lcd.print("   ");
314  lcd.write(1);
315  lcd.print("HK");
316  lcd.write(6);
317  lcd.write(5);
318  lcd.print("ATOP");
319 
320 
321   
322  Wire.begin();        // старт I2C
323  
324//   dht.begin();
325  si7021.begin(); // Runs : Wire.begin() + reset() // старт датчика влажности
326  delay(3000);// подождем пока датчик запуститься, и завтавка погорит
327  si7021.setHumidityRes(12); // Humidity = 12-bit / Temperature = 14-bit //максимальное разрешение
328    
329 
330lcd.createChar(5, znak_g);//г
331  readSet();  // читаем настройки из еепром
332   
333 
334 
335// настройкa часов
336TCCR1A=(1<<WGM11); //режим14 FAST PWM
337TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
338ICR1=62499;  // (16000000MHz /div256) -1 = 1 раз в секунду
339TIMSK1=(1<<TOIE1); //разрешить прерывание
340 
341  tempProcess(START_CONVERT);//конвентируем dallas
342 
343  attachInterrupt(0, zero_crosss_int, RISING);//внешнее прерывание на D2
344  
345  //pinMode(extend_heater_pin, OUTPUT);      //пин дополнительного нагревателя. Переводим в 1 чтобы не включать реле.
346  //digitalWrite(extend_heater_pin, HIGH);
347  pinMode(heater_pin, OUTPUT);
348  pinMode(turn_pin, OUTPUT);      // устанавливаем выводы
349//  pinMode(pin9, INPUT);      // устанавливаем выводы
350  digitalWrite(turn_pin, HIGH);
351  //digitalWrite(turn_pin2, HIGH);
352  pinMode(humidifer_pin, OUTPUT);
353  pinMode(fan_pin, OUTPUT);
354  digitalWrite(fan_pin, HIGH);
355  pinMode(alarm_pin, OUTPUT);
356  digitalWrite(alarm_pin, HIGH);
357  pinMode(button_minus_pin, INPUT_PULLUP); //подтягиваем входы кнопок к плюсу встроенными резисторами
358  pinMode(button_plus_pin, INPUT_PULLUP);
359  pinMode(button_enter_pin, INPUT_PULLUP);
360  alarmDelay = millis();
361 
362  wdt_enable(WDTO_8S); // активировали таймер, каждые 8 секунд его нужно сбрасывать
363 
364}
365 
366ISR (TIMER1_OVF_vect) {
367sec++ ; //инкремент переменной каждую секунду
368if (sec>59){sec=0; minut++;}
369if (minut>59){minut=0; chas++;} // при записи каждый час хватит памяти на 11 лет
370if (chas>23){chas=0;den++;}//readSet(); но нам главное знать день инкубации
371if (den>36){den=0; } // частный случай для нас не принципиальный, у нас день инкубации
372}
373 
374void loop(){
375 wdt_reset(); // говорим собаке что "В Багдаде все спокойно", начинается очередной отсчет 8-х секунд.
376// Serial.print("pin9=");
377// Serial.println(digitalRead(pin9));
378// Serial.println("   ");
379 
380 if (oldchas!=chas){ // раз в час сохраняем время
381 EEPROM_int_write(102, chas);
382 oldchas=chas;
383 }
384 if (oldden!=den){ // раз в день читаем настройки заново
385 EEPROM_int_write(100, den);
386 readSet();
387 oldden=den;
388 }
389   button_read();
390  if (!button_enter) {
391    delay(del); //
392    lcd.clear();
393    menu();
394  }
395  if (!button_minus) {
396    delay(del);
397    lcd.clear();
398    alarmDelay = millis();    // задержка аварии по нажатии кнопки Минус
399  }
400  if (!button_plus) {
401    delay(del);
402    lcd.clear();
403    digitalWrite(turn_pin, !digitalRead(turn_pin));       // включаем/выключаем реле поворота по кнопке Плюс
404  }
405 
406  lcd.setCursor(0, 0);
407  if (millis() > serialTime)
408  {
409    PID();//расчитываем ПИД yul-i-an
410    serialTime += 1200;
411 // err=needTemp-temp1
412 Serial.print("needTemp=");
413 Serial.println(needTemp);
414 Serial.print("temp1=");
415 Serial.println(temp1);
416 Serial.print("err=");
417 Serial.println(err);
418 Serial.print("zad=");
419 Serial.println(zad);
420// Serial.print("serialTime=");
421// Serial.println(serialTime);
422// Serial.print("hotFlag1=");
423// Serial.println(hotFlag1);
424  }
425 
426    if (flag == 0)
427  {
428     lastMillis = millis();
429    clockTime=!clockTime;
430    flag = 1;
431  }
432 
433  if (millis() - lastMillis >=TimeTemp*1000) {
434    flag = 0;
435}
436  if (clockTime == 1){
437  lcd.setCursor(0, 0); // выводим часы и день инкубации
438  if (chas < 10) lcd.print(" ");
439  lcd.print(chas, DEC);
440  lcd.print(":");
441  if (minut < 10)lcd.print(0);
442  lcd.print(minut, DEC);
443  lcd.print(" ");
444   lcd.write(7);
445    lcd.print("EH");
446   lcd.write(4);  
447  lcd.print(" ");
448  lcd.print(den, DEC);
449  lcd.print("     ");
450    lcd.setCursor(0, 1);
451//    lcd.print("      ");
452   lcd.print(temp2, 1);              // печать температуры на дисплей temp%10
453   lcd.print((char)223);
454   lcd.print(" ");
455    printbird(bird);
456  }
457  else {
458    lcd.setCursor(0, 0);                 // устанавливаем курсор в 0-ом столбце, 0 строка (начинается с 0)
459    lcd.print("T1=");
460    lcd.print(temp/10, 1);              // печать температуры на дисплей temp
461    lcd.print(".");
462    lcd.print(temp%10, 1);              // печать температуры на дисплей temp%10
463     
464    lcd.print((char)223);
465    lcd.print(" (");
466    lcd.print(needTemp, 1);
467    lcd.print((char)223);
468    lcd.print(")   ");
469    lcd.setCursor(0, 1);                
470    lcd.print("H =");
471    lcd.print(hum, 1);           // печать влажности на дисплей
472    lcd.print("%");
473    lcd.print(" (");
474    lcd.print(needHum, 1);
475    lcd.print("%) ");
476  //  lcd.setCursor(15, 3);
477  //  lcd.print("   ");
478 
479    }
480 
481  getSensors(); // получаем данные с датчиков
482  humidifer(needHum);
483  turn(needTurn);
484  fan(ventTime);
485  alarm(needTemp);
486}
487 
488 
489//регулятор ПИД
490 void PID(){
491   err=needTemp-temp1;
492    if (hotFlag1 ==0) I=I+err;//если проветривание или авария не включаем
493  
494//   zad=Kp*err+(Ki*I*0.25)+(Kd*(err-pre_err)/0.25);
495   zad = PIctl(temp1, needTemp); //расчет мощности
496   pre_err=err;
497   if (temp1>=39.5) //это при перегреве
498   {
499   zad=0;
500    I=0;
501   }
502  if (zad<0){ zad=0;I=0;}
503  if (zad>100){zad=100;}
504//   Serial.print("reg=");
505//   Serial.println(reg);
506 
507 }
508 //Внешнее прерывание детектора нуля
509 void zero_crosss_int()
510{
511      ResOut();//Вызов функции управления симистором по алгоритму Брезенхема
512}
513 
514//управление симистором
515void ResOut(){
516  delayMicroseconds(1230);//для попадания в ноль
517  reg = zad + er;
518  if (reg < 50){
519    out=0;
520    er = reg ;
521  
522  }
523  else {
524    out=1;
525 
526    er=reg-100;
527    }
528 if (hotFlag1 ==0){
529 digitalWrite(heater_pin,out); //если проветривание или авария не включаем
530 }
531 else {
532 digitalWrite(heater_pin,LOW);
533    
534  }
535 }
536  
537 //Авто настройка коэффициентов ПИД
538void AutoPIDSet(){
539  //тут будет автонастройка
540}
541 
542 
543void button_read() {//функция проверки нажатия кнопки
544  button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
545  button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
546  button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
547  if (!button_minus || !button_plus || !button_enter) beeper(50);
548  wdt_reset();
549}
550 
551 
552//меню
553void menu() {
554  startInk();
555  time_setup_chas();
556  time_setup_minut();
557  bird_setup(); 
558  turn_setup();
559  alarm_setup();
560  vent_setup();
561}
562 
563// записываем в память день начала инкубации
564void startInk() {
565String str_menu= "START INK";
566int perem_menu=den;
567int adress_errom=100;
568int perem_max=36;
569String str_perem="Day";
570den= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
571}
572//устанавливаем часы
573void time_setup_chas() {
574String str_menu= "SETUP HOUR";
575int perem_menu=chas;
576int adress_errom=102;
577int perem_max=23;
578String str_perem="Hour";
579chas= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
580}
581//устанавливаем минуты
582void time_setup_minut() {
583String str_menu= "SETUP minute";
584int perem_menu=minut;
585int adress_errom=0;
586int perem_max=59;
587String str_perem="minute";
588minut= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
589}
590 
591//выбираем птицу /////////////////////////////////////////////////////////
592 
593void bird_setup() {
594String str_menu= "SETUP bird";
595int perem_menu=bird;
596int adress_errom=110;
597int perem_max=5;
598String str_perem="bird";
599bird= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
600}
601 
602 
603//устанавливаем поворот
604void turn_setup() {
605int turnPeriod=EEPROM_int_read(104);                //период поворота лотков в часах
606   
607String str_menu= "TURN SETUP";
608int perem_menu=turnPeriod;
609int adress_errom=104;
610int perem_max=12;
611String str_perem="TURN Hour";
612turnPeriod= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
613}
614 
615 
616//устанавливаем сигнализацию
617void alarm_setup() {
618 int  alarmTemp=EEPROM_int_read(106);
619String str_menu= "ALARM SETUP";
620int perem_menu=alarmTemp;
621int adress_errom=106;
622int perem_max=10;
623String str_perem="T.Alarm +- C";
624alarmTemp= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
625}
626 
627//устанавливаем вентиляцию
628void vent_setup() {
629int fanTemp=EEPROM_int_read(108);
630String str_menu= "A.FAN SETUP";
631int perem_menu=fanTemp;
632int adress_errom=108;
633int perem_max=40;
634String str_perem="T.Fan C";
635fanTemp= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
636}
637 
638int setup_menu(String str_menu,int perem_menu,int adress_errom,int perem_max,String str_perem) {
639  lcd.clear();
640  delay(del);
641  button_read();
642  lcd.setCursor(0, 0);
643  lcd.print(str_menu);
644  lcd.print("         ");
645  delay(1000);
646  int x = 0;
647  while (1) {
648    x++;
649    if (x > interval) break;
650    button_read();
651     if (adress_errom!=0) perem_menu=EEPROM_int_read(adress_errom);
652    if (!button_enter) {
653      delay(del);
654      lcd.clear(); //очищаем экран
655      break;
656    }
657    if (!button_minus) {
658      perem_menu--;
659  if (perem_menu<0) perem_menu=perem_max;
660      if (adress_errom!=0) EEPROM_int_write(adress_errom, perem_menu);
661      lcd.clear();
662      readSet();
663    }
664 
665    if (!button_plus) {
666      perem_menu++;
667      if (perem_menu>perem_max) perem_menu=0;
668      if (adress_errom!=0) EEPROM_int_write(adress_errom, perem_menu);
669      lcd.clear();
670      readSet();
671    }
672    if (adress_errom!=0) perem_menu= EEPROM_int_read(adress_errom);
673     
674    lcd.setCursor(0, 0);
675    if (str_perem=="bird"){
676    lcd.print("BIRD ");
677    printbird(perem_menu);
678  
679    lcd.print("           ");
680     
681      }else{
682    lcd.print(str_perem);
683    lcd.print("= ");
684    lcd.print(perem_menu);
685    lcd.print("           ");
686      }
687    lcd.setCursor(0, 1);
688    lcd.print("START NEXT +1");
689    delay(del);
690  }
691 return perem_menu;
692}
693 
694void printbird(int nbird){
695    switch (nbird) {
696      case 0:
697        lcd.print("K");  // курица
698        lcd.write(6);
699        lcd.print("P");  // курица
700        lcd.write(1);
701        lcd.write(8);
702        lcd.print("A    ");  // курица
703        break;
704      case 1:
705        lcd.write(2);
706        lcd.print("EPE");  // перепелка
707        lcd.write(2);
708        lcd.print("E");  // перепелка
709        lcd.write(3);
710        lcd.print("KA ");  // перепелка
711        break;
712      case 2:
713        lcd.write(6);
714        lcd.print("TKA      ");   // утка
715        break;
716      case 3:
717        lcd.write(1);
718        lcd.print("H");  // индоутка
719        lcd.write(7);
720        lcd.print("O");  // индоутка
721        lcd.write(6);
722        lcd.print("TKA  ");   // утка
723        break;
724      case 4:
725         lcd.write(5);
726         lcd.write(6);
727         lcd.print("C");  // гусь
728         lcd.write(4);
729         lcd.print("      ");  // гусь
730        break;
731      case 5:
732        lcd.write(1);
733        lcd.print("H"); // индюк
734        lcd.write(7);
735        lcd.print("|OK    "); // индюк
736         
737        break;
738    }
739 
740}
741 
742 
743void getSensors() {
744  unsigned long curMillis = millis();          // Получаем текущее время работы
745  if (curMillis - trhMillis >= TRHSTEP) {    // время для нового измерения?
746  temp= tempProcess(READ_TEMP);//читаем темпратуру с далласа
747  temp1=float(temp)/10;
748  tempProcess(START_CONVERT); // сразу запрос на конвертацию
749  }
750 
751  // Demonstrate non-blocking calls
752  if (curMillis - trhMillis >= TRHSTEP * 4) {    // время для нового измерения?
753     
754//    hum = dht.readHumidity(); //получение темпрературы и влажности с DHT11
755//    temp2 = dht.readTemperature();
756    temp2=si7021.readTemp(); //получение темпрературы и влажности с si7021
757    hum = si7021.readHumidity();
758     
759    trhMillis = curMillis;
760  }
761 
762}
763 
764//управляем влажностью
765void humidifer(float set_humidity) {
766  //float humidity;
767  unsigned long humMillis = 0;
768  unsigned long curMillis = millis();
769   if (set_humidity > hum) digitalWrite(humidifer_pin, HIGH); //сравниваем измеренную влажность с заданной
770  else if (set_humidity -5 < hum) digitalWrite(humidifer_pin, LOW); //если влажность низкая, включаем увлажнитель
771 
772}
773 
774//управляем поворотом
775void turn(boolean needTurn) {
776  int turnPeriod=EEPROM_int_read(104);                //период поворота лотков в часах
777  int turnCommand;
778  if (turnPeriod == 0) return;           //если нулевой период поворота, то не поворачиваем яйца.
779    turnCommand = turnPeriod;
780  currentTime = millis();
781  if (needTurn == true) {
782    if (currentTime >= (loopTime + turnCommand * 3600000)) {  // 3600000 сравниваем текущий таймер с переменной loopTime + период поворота в часах.
783 //     if (turnFlagUp){
784       digitalWrite(turn_pin,LOW);
785       delay(TimeTurn*100); //время поворота
786       digitalWrite(turn_pin,HIGH);
787      loopTime = currentTime;    // в loopTime записываем новое значение
788    }
789  }
790}
791 
792//управляем авариями
793void alarm(float needTemp) {
794  int alarmTemp=EEPROM_int_read(106);
795    if (temp1> (needTemp + alarmTemp) || temp1 < (needTemp - alarmTemp)) {
796      beeper(10);
797      digitalWrite(alarm_pin, LOW); //если измеренная температура выше заданной на величину аварии
798    }
799    else digitalWrite(alarm_pin, HIGH); //то включаем аварийный сигнал.
800 
801}
802 
803void beeper(int duration) {
804  tone(beeper_pin, 2000, duration);
805}
806 
807 
808//управляем вентиляторами
809void fan(int fanTime) {
810   int fanTemp=EEPROM_int_read(108);
811  if ((chas == 7 && minut < fanTime) || (chas == 19 && minut < fanTime) || (temp1 > 39.5)) { //fanTemp=395
812   // digitalWrite( fan_pin, LOW);
813    fanFlag=1;
814   
815    //если наступило время проветривания или измеренная температура выше заданной на величину авариито включаем продувку.
816//    digitalWrite(extend_heater_pin, HIGH);  // при этом отключаем обогрев
817//    digitalWrite(heater_pin, LOW);
818    hotFlag1 = 1;
819 //   hotFlag2 = 1;
820  }
821  else {
822    fanFlag=0;
823    hotFlag1 = 0;
824  }
825   
826  //digitalWrite(fan_pin, HIGH); //иначе выключаем.
827     
828//    hotFlag1 = 1;
829//    hotFlag2 = 1;
830//
831 
832}
833 
834// вольтметр
835//void voltmeter() {
836//  float outputValue = 0;
837//  outputValue = float(analogRead(voltmeter_pin)) / 63, 9;
838//  //if(outputValue < 4.5) beeper(50);
839//  //Serial.print("Voltage = " );
840//  //Serial.println(outputValue);
841//  lcd.setCursor(14, 3);
842//  lcd.print("V");
843//  lcd.print(outputValue, 1);
844//}
845//
846//// Печать мощности нагрвателя
847//void outpuPower() {
848//  lcd.setCursor(14, 3);
849//  lcd.print("W");
850//  lcd.print(Output, 0);
851//  lcd.print(" ");
852//}
853 
854 
855//==============================
856int tempProcess(boolean ch){
857  int t=0;
858  if(!ch){
859    ds.reset();
860    ds.write(0xCC);
861    ds.write(0x44);
862  }
863  else{
864    ds.reset();
865    ds.write(0xCC);
866    ds.write(0xBE);
867    t= ds.read();
868    t = t | (ds.read()<<8);
869    //return  t>>4;//целые *C, десятые отброшены
870    //return  (t+8)>>4;//целые *С с округлением
871    return  (t*10)>>4;//целое в десятых *C (214=>21,4*C)
872  }
873}
874// чтение
875int EEPROM_int_read(int addr) {   
876  byte raw[2];
877  for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i);
878  int &num = (int&)raw;
879  return num;
880}
881 
882// запись
883void EEPROM_int_write(int addr, int num) {
884  byte raw[2];
885  (int&)raw = num;
886  for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]);
887}
888//пример int
889//// запись
890//EEPROM_int_write(12, 1000); // адрес 12 (+2 байта)
891//EEPROM_int_write(14, 2000); // адрес 14 (+2 байта)
892//EEPROM_int_write(16, 3000); // адрес 16 (+2 байта)
893//// чтение
894//int d = EEPROM_int_read(12);
895//int e = EEPROM_int_read(14);
896//int f = EEPROM_int_read(16);

 

BigVal
BigVal аватар
Offline
Зарегистрирован: 10.01.2017

Lean_74

Какие семисторы использовали в ПИД. Не могу найти TIC206.

Часы такие?

https://www.aliexpress.com/item-img/Free-Shipping-1PCS-DS3231-AT24C32-II...

lean_74
Offline
Зарегистрирован: 22.12.2015

BigVal пишет:

Lean_74

Какие семисторы использовали в ПИД. Не могу найти TIC206.

Часы такие?

https://www.aliexpress.com/item-img/Free-Shipping-1PCS-DS3231-AT24C32-II...

Тиристор у меня BT138-800E(хотя можно любой из серии ВТ с напряжением пробоя более 300В и ток от 0.5 ампера, я просто попросил в магазине самые дешевые) он там кстати без радиатора и вообше не греется.

Аппаратных часов нет, они программные на таймере 1 у dimax-a позаимствовал.

BigVal
BigVal аватар
Offline
Зарегистрирован: 10.01.2017

lean_74  пока едет из поднебесной заказанное "железо" а я усиленно штудирую (как у Ардуино Нано надо перешить загрузчик на optiboot чтобы нормально работал wdt -"вачдог"), возникло несколько вопросов. Если в электронике я еще более менее разбираюсь, то в програмировании я "чайник", поэтому простите если, что не так спрошу.

1) Вы писали в последнем посте  "Аппаратных часов нет, они программные на таймере 1 у dimax-a позаимствовал". По возможности дайте ссылку. А то я по форуму полазил но ни чего не нашел. Только то, что  dimax писал про реализацию часов на LCD.

2) По схеме  http://cxem.net/arduino/arduino71.php,  ( По подключению: вход сигнала демирования это с 6 пина МК, это понятно, а выход детектора нуля куда подключается не вижу, в скетче 036 строка закоментирована

//Пин 2 Вход обработки прерывания для детектора нуля и управления семистором

3) По пинам:

а) Что подключаете на пин аварии.

б) Вентилятор который сидит на пин 13, он продувочный или он же и тепло гоняет 

На сегодня хватит, заранее благодарен.

 

lean_74
Offline
Зарегистрирован: 22.12.2015

1.http://arduino.ru/forum/proekty/net-sosed-ili-domofon-avtomat#comment-136153

2.ответ в вопросе //Пин 2  http://arduino.ru/Reference/AttachInterrupt

3. Пока ничего не подключал, это осталось от Um-ka, но надо полагать а) светодиод, б) "продувочный"

те что постоянно воздух гоняют у меня напрямую к 12В

MVN123P
Offline
Зарегистрирован: 29.07.2016

lean_74 Скажите пожайлуста, как эти часы будут работать после отключения и включения питания?

lean_74
Offline
Зарегистрирован: 22.12.2015

Нарисовал плату, правда это всего лишь 3-я моя плата в Sprint-Layout, посему сильно просьба не пинать.

https://yadi.sk/d/nCYIDGV73E2aRv

lean_74
Offline
Зарегистрирован: 22.12.2015

MVN123P пишет:

lean_74 Скажите пожайлуста, как эти часы будут работать после отключения и включения питания?

В памяти сохраняется день и час инкубации, я думаю без присмотра все равно инкубатор не оставите, если время не соответствует действительному, то значит были какие-то сбои в работе, главное нам надо знать день инкубации, он в памяти сохраняется.

BigVal
BigVal аватар
Offline
Зарегистрирован: 10.01.2017

Плата очень даже нормальная. Марка реле под которые разводил? 

BigVal
BigVal аватар
Offline
Зарегистрирован: 10.01.2017

Пару вопросов по плате.

1) Что за микросхема на 16 ножек

2) Посмотри по плате 7805 по моему наоборот должен стоять

3) 2 -й семистор под нагреватель увлажнителя

lean_74
Offline
Зарегистрирован: 22.12.2015

https://kealan.ru/catalog/124/913/

1.ULN2003 - появилось попутно желание сменить моторчик на перевороте яиц на лежащий без дела шаговик 28BYJ-48

2. Да я его по мере разводки развернул, 

3.Ну это может и дополнительный нагреватель быть, так с запасом сделал, чтобы все ноги атмеги использовать. у нас в Челябинске можно быстро и недорого заказать платы, чем самому травить www.pcb74.ru . 

BigVal
BigVal аватар
Offline
Зарегистрирован: 10.01.2017

lean _74 по поводу платы могу войти в долю, правда мне за доставку придется заплатить но бог с ним

lean_74
Offline
Зарегистрирован: 22.12.2015

BigVal пишет:
lean _74 по поводу платы могу войти в долю, правда мне за доставку придется заплатить но бог с ним

Я четыре штуки уже заказал, могу одной поделиться, как будет готова. пиши на почту МойНик@mail.ru

MVN123P
Offline
Зарегистрирован: 29.07.2016

Решил собрать этот блок управления инкубатором по блочной схеме (в наличии есть все элементы) в корпусе от старого модема. Управление нагревателями - твердотельные реле OMRON (два квадратика рядом с ардуинкой). Остальное управление через блок на 4 реле. Питание ардуинки через DC-DC преобразователь на LM2596S. На данный момент - крепеж и слесарка.

lean_74
Offline
Зарегистрирован: 22.12.2015

[quote=MVN123P]

Решил собрать этот блок управления инкубатором по блочной схеме (в наличии есть все элементы) в корпусе от старого модема. Управление нагревателями - твердотельные реле OMRON (два квадратика рядом с ардуинкой). Остальное управление через блок на 4 реле. Питание ардуинки через DC-DC преобразователь на LM2596S. На данный момент - крепеж и слесарка.

 

/quote]

Детектор нуля все равно нужен, его пока не вижу, а так зачетно!

BigVal
BigVal аватар
Offline
Зарегистрирован: 10.01.2017

lean_74 посмотрел в нете видео по шаговику 28BYJ-48. Внутренности у него пластиковые. Я так понимаю двигатель будет стоять внутри инкубатора, хоть 38 градусов небольшая температура, не будет ли этот пластик пересыхать. Интересно есть у кого-либо опыт эксплуатации в тааких условиях данного девайса.

Rihos
Offline
Зарегистрирован: 16.02.2017

lean_74 очень интерестная тема .Тут PID плавная регулировка (диммирование)?. Дело в том что у меня на инкубаторе ПИД мигает. Это влияет на освещение в соседней комнате.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Знакомый почерк :)

Вижу в хорошие руки мои труды попали. 

Ну вот вам тогда плата и большая часть наработок и ветвлений. https://drive.google.com/open?id=0B0vRuSZ7oRUeR2tyeG9pSHZ4R2M

Там энкодер есть, остановка ПИД при открытии дверцы, разные датчики, мостик для передачи метрик через ESP8266 в облака. Кстати, DHT11 крайне не советую. Дрянь влагомер.

Вот вам диммер самостоятельный http://arduino.ru/forum/programmirovanie/attiny85-i-preryvanie , я так понимаю что от библиотек ушли чтобы диммировалось ровнее? С этим таких проблем не будет.

Пин аварии ой как нужен. Реле на него нормальнозамкнутое, симисторы иногда пробиваются, особенно с лампами накаливания, и тогда вся мощность жарит яйца. А реле аварии клац - и спасены! Вот знакомый недавно 2 короба (по 360) яиц бройлера выкинул, на 20-й день инкубации твердотельное квакнуло. Ну и (или) вентилятор принудительной продувки.

Симисторы BT и BTB имеют "фазу" на радиаторе, а BTA изолированные. Цена почти одинаковая.

Моторы шаговые лучше с драйверами Step/Dir использовать, там 1 дорожку надо перерезать в моторчике. Тогда 2 пина потребуется вместо 4 и под все драйверы подходит. 

А чего часы то не использовал? МК не точно миллисекунды считает и забывает при выключении.

Ну и хочется посмотреть на результат всей работы. Пока неплохо, но надо все в бою проверять обязательно. Успехов!

ЗЫ: забавная разводка...

lean_74
Offline
Зарегистрирован: 22.12.2015

Umka пишет:

Вижу в хорошие руки мои труды попали. 

Спасибо за поддержку! 

Umka пишет:

Ну вот вам тогда плата и большая часть наработок и ветвлений. https://drive.google.com/open?id=0B0vRuSZ7oRUeR2tyeG9pSHZ4R2M

Тут без пузыря не разобраться, файлик бы с пояснением, где, что и для чего. 

Umka пишет:

Пин аварии ой как нужен. Реле на него нормальнозамкнутое, симисторы иногда пробиваются, особенно с лампами накаливания, и тогда вся мощность жарит яйца. А реле аварии клац - и спасены! Вот знакомый недавно 2 короба (по 360) яиц бройлера выкинул, на 20-й день инкубации твердотельное квакнуло. Ну и (или) вентилятор принудительной продувки.

Симисторы BT и BTB имеют "фазу" на радиаторе, а BTA изолированные. Цена почти одинаковая.

У меня тиристор вообще не греется, надо полагать потому, что переключения происходят при переходе через ноль, и мощьности на нем не рассеивается, почему тогда он может выйти из строя? Понятно, когда ШИМом регулируется и часть мощности рассеивается на самом тиристоре. 

Umka пишет:

Моторы шаговые лучше с драйверами Step/Dir использовать, там 1 дорожку надо перерезать в моторчике. Тогда 2 пина потребуется вместо 4 и под все драйверы подходит. 

ну это пока для меня темный лес, попробовал покрутить шаговиком -получилось, усилие для переворота лотков у него вполне приличное и концевики ставить не надо.

Umka пишет:

А чего часы то не использовал? МК не точно миллисекунды считает и забывает при выключении.

Все же хотелось сделать попроще и легче для повторения. в первой версии часы были, но 150 перепелиных яиц на 15 день все равно выкинул, просто все зависло и поджарило до 52 градусов, а днем на работе, сколько там часов ини жарились ХЗ. С растройства даже отложил на время свои эксперименты, и решил подготовиться более основательно.

Umka пишет:

Ну и хочется посмотреть на результат всей работы. Пока неплохо, но надо все в бою проверять обязательно. Успехов!

Еще раз Спасибо! Результаты будем выкладывать.

Umka пишет:

ЗЫ: забавная разводка...

 

:)) ну не волшебник я - только учусь.

Rihos
Offline
Зарегистрирован: 16.02.2017

А Детектор нуля в заводском исполнение есть у ардуины как модуль?

lean_74
Offline
Зарегистрирован: 22.12.2015

Rihos пишет:
А Детектор нуля в заводском исполнение есть у ардуины как модуль?

вон  же у Umka есть готовые http://arduino.ru/forum/programmirovanie/attiny85-i-preryvanie#comment-243118

Rihos
Offline
Зарегистрирован: 16.02.2017

Я с Али заказывал Ардуино думал есть готовый модуль на него чтобы вместе заказать.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

lean_74,

1. все файлы и папки подписаны. Плату точно найдешь. Мы их, кстати, заводские, по 5 баксов продаем.

2. Симистор. Не греется потому что мощность нагревателя маленькая. Да и не должен он греться, это же ключ. Ноль тут не виноват, это от помех делается.

3. Нормальные шаговики драйверами управляются. Драйверы делают нужный ток, удержание микрошаг... а драйверы рулятся двумя сигналами. Шаг и направление. Стоят не дорого и можно любой Nema17 из старого принтера зацепить. Только вот этот редукторный мотор придется вскрывать, там общая точка у обмоток, ее отрезать надо.

4. Проще с часами. Ни пинов дополнительных не надо, ни коррекции. А так свет мигнул и сбились дни. 

5. Я 7 лет в птицеводстве и инкубации и начинал с перепелок тоже. Они и сейчас есть. Всяко бывало. Ты если что спрашивай. Брудер есть? Вот мой видосик по теме и там на канале еще много по железкам https://www.youtube.com/watch?v=W4xM8h5iBI8

Rihos, если сильно надо, то вот такие платы по 2 бакса есть https://www.youtube.com/watch?v=wXA2jGXWzno

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

Вообще не совсем понятно зачем тут детектор ноля, если он не диммирует? В бОльшей части оптосимисторов, например MOC3061 есть встроенный детектор ноля. В твердотельных реле тоже. А диммер не тянет контроллер с таким скетчем, мигают лампы из-за запрета прерываний. Автономный диммер хорошее решение.

 

Rihos
Offline
Зарегистрирован: 16.02.2017

Роман я слежку за вашими разработками здорово...
У меня инкубатор из витринного холодильника. Яйца ложу ступенчато первый выводок был удачным. Второй сварил под утро был 52°. Дело в том терморегулятор был заказан ПИД Rex-c100 потом выяснелось что отправили релейный. Из-за частого срабатовании реле залипло температура поднелась до критической. Потом выпаял электромагнитное реле поставил перемычки и подключил SSR. Но плавного накала ламп там я не смог добиться. В этом году хотел заказать регулятор влажности. Передумал заказал УНО (чтобы инкубатор стал смартом) дисплей 16/2 датчики. Вот думаю может и перевотот нагрев, влажность смогу перевести на ардуино. Если добьюсь плавного накала ламп было бы здорово!

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

У меня тоже есть инкубаторы из витрины. Неплохо выводят. Реле залипло, бывает. А вото тут в комментариях товарищи до усёру спорят что реле это нормально https://www.youtube.com/watch?v=zcLj_6EfYgY 

Вот расскажите им! Я не смог переубедить барыг от птицеводства.

Что значит поворот нагрев и влажность перевести на Ардуино? Все же готово уже. И плавный накал тоже. Я же дал уже все. ПИД считает свою математику и на выходе выплевывает некий коэффициент мощности, которую надо подать в нагреватель. Ну мы этот коэффициент мапим в байт и отсылаем по wire в диммер. И всё. И будет очень плавно. Только... а зачем в витрине лампами греть? Есть же ТЭНы воздушные и керамика. Ладно в пенопластовой коробочке...

Rihos
Offline
Зарегистрирован: 16.02.2017

Umka пишет:

Что значит поворот нагрев и влажность перевести на Ардуино? Все же готово уже. И плавный накал тоже. Я же дал уже все.


Спасибо. Я так понимаю теперь мне нужен ваш автономный диммер либо делитель нуля для того чтобы залить скейтч с этой темы И регулировать плавненько? И ещё у меня стоит мотор от стеклоподьемника. Я пологаю нужно корректировать код чтобы он менял полярность и приходил в горизонтальное положение по кнопке чтобы заложить яйца!?

Umka пишет:

Только... а зачем в витрине лампами греть? Есть же ТЭНы воздушные и керамика. Ладно в пенопластовой коробочке...


Я ставил углеродный кабель 15 метров а лампы на разогрев. Но кабель не справляется весной. Наверное не правильно рассчитал. Сейчас работают вместе.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Вот про скетч из этой темы лучше у его автора спрашивать. Я вижу тут многое из моего инкубатора и многое сделано иначе. Думаете мне охота досконально в нем разбираться и понимать все замыслы его создателя? Я только даю варианты своих наработок, а как и где их использовать сами смотрите. Если Вы не сможете самостоятельно прикрутить диммер к ПИД, то либо вы покупатель, либо просите кого-то это сделать. Объясните, какой смысл греть витрину углеродным кабелем да еще и с ПИД-регулятором? 

MVN123P
Offline
Зарегистрирован: 29.07.2016

lean_74 

Собрал схему - но не пойму как должен работать вентилятор?

lean_74
Offline
Зарегистрирован: 22.12.2015

MVN123P пишет:

lean_74 

Собрал схему - но не пойму как должен работать вентилятор?

Вентилятор пока не тестировал, но по задумке он работает во время плановых проветриваний два раза в день, когла они есть и во время аварии, т.е превышении максимально установленной температуры.

 

lean_74
Offline
Зарегистрирован: 22.12.2015

Rihos пишет:
Я ставил углеродный кабель 15 метров а лампы на разогрев. Но кабель не справляется весной. Наверное не правильно рассчитал. Сейчас работают вместе.

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

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

По перевороту с помощью мотора для стеклоподъемника, надо корректировать не только код, но схему подключения, она кстати там у Umka  по его ссылке тоже есть, на двух реле сделана и ручкой соединения дорисованы.

Rihos
Offline
Зарегистрирован: 16.02.2017

lean_74
Спасибо за информацию. Тогда не буду на этом сильно заморачиваться.
По поводу схемы мне едут мосфеты.

lean_74
Offline
Зарегистрирован: 22.12.2015

Rihos пишет:
lean_74 Спасибо за информацию. Тогда не буду на этом сильно заморачиваться. По поводу схемы мне едут мосфеты.

Если на мосфетах то придется что-то типа этого городить: https://yadi.sk/i/gKCXBpA03EEM2N

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Насчет инерции. Не только нагреватель надо учитвыать, надо всю систему брать. https://www.youtube.com/watch?v=leY_ptjJLcE

Насчет поворота двигателя постоянного тока. Код корректировать не надо. 2 НЗ концевика надо и сам мотор. http://u-m.biz/shop/index.php?route=product/product&path=62&product_id=62

Насчет МОСФЕТов http://u-m.biz/shop/index.php?route=product/product&path=62&product_id=60

Схемы не рисовал, в интернетах найдете если что. Там же и автоматическая переключалска на 220/12 есть.

 

 

lean_74
Offline
Зарегистрирован: 22.12.2015

Запуталли меня тут с миганием - не миганием лампочек, так при таком способе регулирования обязательно должно мигать, т.к. мощность мы регулируем не отрезанием части полуволны, а всей полуволны, т.е за секунду у нас 100 полуволн, нужно пропустить 50 процентов мощности - пропускаем 50 полуволн, это все равно что диод последовательно с лампочкой включить, уже заметно что мигает, если только 1% то 1 полуволну в секунду - раз в секунду и будет мигать. вот тут популярно написано: https://habrahabr.ru/post/254719/

и действтвительно схему можно еще более упростить, а управление сделать прерываниями по таймеру.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Сам же и запутал своим детектором, человек теперь ищет у китайцев "делитель на ноль" чтобы плавно светило. А я говорю - вот он готовый плавный самостоятельный диммер. В него надо писать по шине I2C нужный уровень, а можно и читать. Ну или при помощи ШИМ обычного и ничего не мигает. Но меня не слушают. Хотя каждый же сам как хочет...

lean_74
Offline
Зарегистрирован: 22.12.2015

Вот сделал заготовку для автопереворота яиц по принципу китайского, только они даже за одну пластмассу больше тысячи просят, тут себестоимость без учета собственного труда - ноль, все из остатков после ремонта. https://youtu.be/VQ0mPMOu_wo

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Хочешь совет хороший по поводу профиля?

lean_74
Offline
Зарегистрирован: 22.12.2015

Umka пишет:

Хочешь совет хороший по поводу профиля?

От тебя любой совет, я думаю, хороший , думаешь оцинковка будет вредно действовать? тогда покрашу.

lean_74
Offline
Зарегистрирован: 22.12.2015

вот и платки сделали.

плата инкбатора

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Совет - делай лотки из сетки оцинкованной. Профиль нифига не продувается. Тем более корыто такое.

lean_74
Offline
Зарегистрирован: 22.12.2015

В печатной плате незначительная ошибочка, у МОС3021 землю завел на 3-ю ногу, вместо 2-й. т.к 3-я не задействована просто соединяем ее со второй. 

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Лучше бы исходник с Layout дал или в чем ты там рисуешь. По фотке же не видно половину дорожек. Все в тумане. Думаешь кто-то будет по фотке плату повторять и еще потом ошибку исправлять?