"Народный" инкубатор
- 1
- 2
- 3
- 4
- 5
- следующая ›
- последняя »
- Войдите на сайт для отправки комментариев
Втр, 07/02/2017 - 19:07
Почему "народный"? Потому что почитал я форум, взял за основу инкубатор от 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> |
008 | OneWire 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); |
017 | SI7021 si7021; //раскоментировать, если используем датчик si7021. |
018 |
019 | LiquidCrystal_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 |
040 | boolean button_minus; // статус нажатия кнопок |
041 | boolean button_plus; |
042 | boolean button_enter; |
043 |
044 | unsigned long currentTime; // задаем переменные для тайминга поворота |
045 | unsigned long loopTime; |
046 | unsigned long serialTime; //this will help us know when to talk with processing |
047 |
048 | boolean hotFlag1 = 0; // флаг включения обогревателя основного 1-ошибка, включать нельзя |
049 | boolean fanFlag = 0; // флаг включения вентилятора проветривания 1-включено проветривание |
050 | unsigned long trhMillis = 0; |
051 |
052 | boolean flag = 0; |
053 | int clockTime = 0; // флаг того что выводим температуру или влажность |
054 | unsigned long lastMillis = millis(); |
055 | int TimeTemp = 4; //время следующего измерения температуры в секундах |
056 | int TimeTurn = 20; //время поворота в десятых долях секунды |
057 |
058 | const unsigned long TRHSTEP = 300UL; // Период опроса датчиков |
059 |
060 | //int counter=0;//для проверки вачдога |
061 |
062 | volatile uint8_t minut=0; |
063 | //volatile uint8_t chas=0; |
064 | int chas=0; |
065 | volatile uint8_t sec=0; |
066 | int den=0; |
067 | int oldden=0; |
068 | int oldchas=0; |
069 |
070 | int temp=0; // температура Далласа |
071 | float temp1=0; // температура Далласа с десятыми |
072 | float temp2=0; // температура DHT, si7021 |
073 | float hum=0; |
074 |
075 | int del = 80; // переменная ожидания между выборами меню |
076 | unsigned int interval = 200; // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций) |
077 |
078 | boolean out =0; //управление симистором yul-i-an |
079 | int reg,er,zad; // yul-i-an |
080 | double I,Kp=3,Ki=0.45,Kd=0.6,pre_err,err; // yul-i-an |
081 |
082 | unsigned long alarmDelay; |
083 |
084 | float needTemp = 37.6; // нужная для текущего дня температура инкубации (по умолчанию) |
085 | float needHum = 60.5; // ---- влажность |
086 | int ventTime = 2; // длительность проветривания |
087 | boolean needTurn = false ; // нужен ли поворот яиц? |
088 | int bird=0; |
089 |
090 | // make some custom characters: |
091 | byte znak_g[8] = { //г |
092 | 0b11111, |
093 | 0b10001, |
094 | 0b10000, |
095 | 0b10000, |
096 | 0b10000, |
097 | 0b10000, |
098 | 0b10000, |
099 | 0b00000 |
100 | }; |
101 | byte znak_b[8] = { //Б |
102 | 0b11111, |
103 | 0b10001, |
104 | 0b10000, |
105 | 0b11110, |
106 | 0b10001, |
107 | 0b10001, |
108 | 0b11110, |
109 | 0b00000 |
110 | }; |
111 |
112 | byte znak_p[8] = { |
113 | 0b11111, |
114 | 0b10001, |
115 | 0b10001, |
116 | 0b10001, |
117 | 0b10001, |
118 | 0b10001, |
119 | 0b10001, |
120 | 0b00000 |
121 | }; |
122 | byte znak_i[8] = { |
123 | 0b10001, |
124 | 0b10001, |
125 | 0b10011, |
126 | 0b10101, |
127 | 0b11001, |
128 | 0b10001, |
129 | 0b10001, |
130 | 0b00000 |
131 | }; |
132 |
133 | byte znak_l[8] = { |
134 | 0b00111, |
135 | 0b01001, |
136 | 0b10001, |
137 | 0b10001, |
138 | 0b10001, |
139 | 0b10001, |
140 | 0b10001, |
141 | 0b00000 |
142 | }; |
143 |
144 | byte light_znak[8] = { |
145 | 0b10000, |
146 | 0b10000, |
147 | 0b10000, |
148 | 0b11110, |
149 | 0b10001, |
150 | 0b10001, |
151 | 0b01110, |
152 | 0b00000 |
153 | }; |
154 |
155 | byte znak_u[8] = { |
156 | 0b10001, |
157 | 0b10001, |
158 | 0b10001, |
159 | 0b01111, |
160 | 0b00001, |
161 | 0b10001, |
162 | 0b01110, |
163 | 0b00000 |
164 | }; |
165 |
166 |
167 | byte znak_ia[8] = { |
168 | 0b01111, |
169 | 0b10001, |
170 | 0b10001, |
171 | 0b01111, |
172 | 0b00101, |
173 | 0b01001, |
174 | 0b10001, |
175 | 0b00000 |
176 | }; |
177 | byte znak_d[8] = { |
178 | 0b01110, |
179 | 0b01010, |
180 | 0b01010, |
181 | 0b01010, |
182 | 0b01010, |
183 | 0b11111, |
184 | 0b10001, |
185 | 0b00000 |
186 | }; |
187 | byte znak_ch[8] = { |
188 | 0b10001, |
189 | 0b10001, |
190 | 0b10001, |
191 | 0b01111, |
192 | 0b00001, |
193 | 0b00001, |
194 | 0b00001, |
195 | 0b00000 |
196 | }; |
197 | byte znak_c[8] = { |
198 | 0b10010, |
199 | 0b10010, |
200 | 0b10010, |
201 | 0b10010, |
202 | 0b10010, |
203 | 0b10010, |
204 | 0b11111, |
205 | 0b00001 |
206 | }; |
207 |
208 |
209 |
210 | void 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 |
224 | bird= 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 | |
246 | void 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 |
291 | lcd.createChar(5, znak_g); //г |
292 | readSet(); // читаем настройки из еепром |
293 | |
294 |
295 |
296 | // настройкa часов |
297 | TCCR1A=(1<<WGM11); //режим14 FAST PWM |
298 | TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256 |
299 | ICR1=62499; // (16000000MHz /div256) -1 = 1 раз в секунду |
300 | TIMSK1=(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 |
327 | ISR (TIMER1_OVF_vect) { |
328 | sec++ ; //инкремент переменной каждую секунду |
329 | if (sec>59){sec=0; minut++;} |
330 | if (minut>59){minut=0; chas++;} // при записи каждый час хватит памяти на 11 лет |
331 | if (chas>23){chas=0;den++;} //readSet(); но нам главное знать день инкубации |
332 | if (den>36){den=0; } // частный случай для нас не принципиальный, у нас день инкубации |
333 | } |
334 |
335 | void 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 | //управление симистором |
452 | void 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 | //Авто настройка коэффициентов ПИД |
475 | void AutoPIDSet(){ |
476 | //тут будет автонастройка |
477 | } |
478 |
479 |
480 | void 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 | //меню |
490 | void 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 | // записываем в память день начала инкубации |
501 | void startInk() { |
502 | String str_menu= "START INK" ; |
503 | int perem_menu=den; |
504 | int adress_errom=100; |
505 | int perem_max=30; |
506 | String str_perem= "Day" ; |
507 | den= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem); |
508 | } |
509 | //устанавливаем часы |
510 | void time_setup_chas() { |
511 | String str_menu= "SETUP HOUR" ; |
512 | int perem_menu=chas; |
513 | int adress_errom=102; |
514 | int perem_max=23; |
515 | String str_perem= "Hour" ; |
516 | chas= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem); |
517 | } |
518 | //устанавливаем минуты |
519 | void time_setup_minut() { |
520 | String str_menu= "SETUP minute" ; |
521 | int perem_menu=minut; |
522 | int adress_errom=0; |
523 | int perem_max=59; |
524 | String str_perem= "minute" ; |
525 | minut= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem); |
526 | } |
527 |
528 | //выбираем птицу ///////////////////////////////////////////////////////// |
529 |
530 | void bird_setup() { |
531 | String str_menu= "SETUP bird" ; |
532 | int perem_menu=bird; |
533 | int adress_errom=110; |
534 | int perem_max=5; |
535 | String str_perem= "bird" ; |
536 | bird= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem); |
537 | } |
538 |
539 |
540 | //устанавливаем поворот |
541 | void turn_setup() { |
542 | int turnPeriod=EEPROM_int_read(104); //период поворота лотков в часах |
543 | |
544 | String str_menu= "TURN SETUP" ; |
545 | int perem_menu=turnPeriod; |
546 | int adress_errom=104; |
547 | int perem_max=12; |
548 | String str_perem= "TURN Hour" ; |
549 | turnPeriod= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem); |
550 | } |
551 |
552 |
553 | //устанавливаем сигнализацию |
554 | void alarm_setup() { |
555 | int alarmTemp=EEPROM_int_read(106); |
556 | String str_menu= "ALARM SETUP" ; |
557 | int perem_menu=alarmTemp; |
558 | int adress_errom=106; |
559 | int perem_max=10; |
560 | String str_perem= "T.Alarm +- C" ; |
561 | alarmTemp= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem); |
562 | } |
563 |
564 | //устанавливаем вентиляцию |
565 | void vent_setup() { |
566 | int fanTemp=EEPROM_int_read(108); |
567 | String str_menu= "A.FAN SETUP" ; |
568 | int perem_menu=fanTemp; |
569 | int adress_errom=108; |
570 | int perem_max=40; |
571 | String str_perem= "T.Fan C" ; |
572 | fanTemp= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem); |
573 | } |
574 |
575 | int 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 |
631 | void 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 |
680 | void 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 | //управляем влажностью |
702 | void 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 | //управляем поворотом |
712 | void 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 | //управляем авариями |
730 | void 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 |
740 | void beeper( int duration) { |
741 | tone(beeper_pin, 2000, duration); |
742 | } |
743 |
744 |
745 | //управляем вентиляторами |
746 | void 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 | //============================== |
793 | int 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 | // чтение |
812 | int 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 | // запись |
820 | void 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); |
lean_74 меня интересует. Пока начинаю с нуля, но есть большое желание сделать такой девайс. Раньше делал инкубатор на плате W1209. Хочу автоматизировать. Поэтому для начала интересует список оборудования и схема соединений, буду очень признателен.
Оборудование : 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
Схему соединений видна из скетча, я распаял пока на макетке, как все отлажу буду плату разводить, по отдельности все работало нормально, когда все в кучу соединил, перестала работать схема с ПИД регулированием - сейчас с ней разбираюсь.
lean_74 спасибо за ответ. Начинаю заказывать оборудование, кое-что заказал ранее, правда еще не получил.
lean_74 есть вопрос. На сколько вольт двигатель в поворотных лотках, по ссылке не понятно.
у меня на 220в, но следующий раз я бы 12в заказал, на случай пропадания 220в в сети и переключения на резервное питание от 12в
Если возможно, снимите небольшое видео экрана инкубатора (меню, настройки и.т.д).
Если возможно, снимите небольшое видео экрана инкубатора (меню, настройки и.т.д).
Снимал телефоном, так что качество так себе https://youtu.be/LEt51o0bDeY
Спасибо.
Добавил автоподстройку вых мощности от 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>
008
OneWire 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);
017
SI7021 si7021;
//раскоментировать, если используем датчик si7021.
018
019
LiquidCrystal_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
040
boolean button_minus;
// статус нажатия кнопок
041
boolean button_plus;
042
boolean button_enter;
043
044
unsigned
long
currentTime;
// задаем переменные для тайминга поворота
045
unsigned
long
loopTime;
046
unsigned
long
serialTime;
//this will help us know when to talk with processing
047
048
boolean hotFlag1 = 0;
// флаг включения обогревателя основного 1-ошибка, включать нельзя
049
boolean fanFlag = 0;
// флаг включения вентилятора проветривания 1-включено проветривание
050
unsigned
long
trhMillis = 0;
051
052
boolean flag = 0;
053
int
clockTime = 0;
// флаг того что выводим температуру или влажность
054
unsigned
long
lastMillis = millis();
055
int
TimeTemp = 4;
//время следующего измерения температуры в секундах
056
int
TimeTurn = 20;
//время поворота в десятых долях секунды
057
058
const
unsigned
long
TRHSTEP = 300UL;
// Период опроса датчиков
059
060
//int counter=0;//для проверки вачдога
061
062
volatile uint8_t minut=0;
063
//volatile uint8_t chas=0;
064
int
chas=0;
065
volatile uint8_t sec=0;
066
int
den=0;
067
int
oldden=0;
068
int
oldchas=0;
069
070
int
temp=0;
// температура Далласа
071
float
temp1=0;
// температура Далласа с десятыми
072
float
temp2=0;
// температура DHT, si7021
073
float
hum=0;
074
075
int
del = 80;
// переменная ожидания между выборами меню
076
unsigned
int
interval = 200;
// интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
077
078
boolean
out
=0;
//управление симистором yul-i-an
079
int
reg,er,zad;
// yul-i-an
080
double
I,Kp=3,Ki=0.45,Kd=0.6,pre_err,err;
// yul-i-an
081
082
unsigned
long
alarmDelay;
083
084
float
needTemp = 37.6;
// нужная для текущего дня температура инкубации (по умолчанию)
085
float
needHum = 60.5;
// ---- влажность
086
int
ventTime = 2;
// длительность проветривания
087
boolean needTurn =
false
;
// нужен ли поворот яиц?
088
int
bird=0;
089
090
// make some custom characters:
091
byte
znak_g[8] = {
//г
092
0b11111,
093
0b10001,
094
0b10000,
095
0b10000,
096
0b10000,
097
0b10000,
098
0b10000,
099
0b00000
100
};
101
byte
znak_b[8] = {
//Б
102
0b11111,
103
0b10001,
104
0b10000,
105
0b11110,
106
0b10001,
107
0b10001,
108
0b11110,
109
0b00000
110
};
111
112
byte
znak_p[8] = {
113
0b11111,
114
0b10001,
115
0b10001,
116
0b10001,
117
0b10001,
118
0b10001,
119
0b10001,
120
0b00000
121
};
122
byte
znak_i[8] = {
123
0b10001,
124
0b10001,
125
0b10011,
126
0b10101,
127
0b11001,
128
0b10001,
129
0b10001,
130
0b00000
131
};
132
133
byte
znak_l[8] = {
134
0b00111,
135
0b01001,
136
0b10001,
137
0b10001,
138
0b10001,
139
0b10001,
140
0b10001,
141
0b00000
142
};
143
144
byte
light_znak[8] = {
145
0b10000,
146
0b10000,
147
0b10000,
148
0b11110,
149
0b10001,
150
0b10001,
151
0b01110,
152
0b00000
153
};
154
155
byte
znak_u[8] = {
156
0b10001,
157
0b10001,
158
0b10001,
159
0b01111,
160
0b00001,
161
0b10001,
162
0b01110,
163
0b00000
164
};
165
166
167
byte
znak_ia[8] = {
168
0b01111,
169
0b10001,
170
0b10001,
171
0b01111,
172
0b00101,
173
0b01001,
174
0b10001,
175
0b00000
176
};
177
byte
znak_d[8] = {
178
0b01110,
179
0b01010,
180
0b01010,
181
0b01010,
182
0b01010,
183
0b11111,
184
0b10001,
185
0b00000
186
};
187
byte
znak_ch[8] = {
188
0b10001,
189
0b10001,
190
0b10001,
191
0b01111,
192
0b00001,
193
0b00001,
194
0b00001,
195
0b00000
196
};
197
byte
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
//возвращает необходимую мощность
221
uint8_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
249
void
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
263
bird= 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
285
void
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
330
lcd.createChar(5, znak_g);
//г
331
readSet();
// читаем настройки из еепром
332
333
334
335
// настройкa часов
336
TCCR1A=(1<<WGM11);
//режим14 FAST PWM
337
TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12);
//делить частоту CPU на 256
338
ICR1=62499;
// (16000000MHz /div256) -1 = 1 раз в секунду
339
TIMSK1=(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
366
ISR (TIMER1_OVF_vect) {
367
sec++ ;
//инкремент переменной каждую секунду
368
if
(sec>59){sec=0; minut++;}
369
if
(minut>59){minut=0; chas++;}
// при записи каждый час хватит памяти на 11 лет
370
if
(chas>23){chas=0;den++;}
//readSet(); но нам главное знать день инкубации
371
if
(den>36){den=0; }
// частный случай для нас не принципиальный, у нас день инкубации
372
}
373
374
void
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
//управление симистором
515
void
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
//Авто настройка коэффициентов ПИД
538
void
AutoPIDSet(){
539
//тут будет автонастройка
540
}
541
542
543
void
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
//меню
553
void
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
// записываем в память день начала инкубации
564
void
startInk() {
565
String str_menu=
"START INK"
;
566
int
perem_menu=den;
567
int
adress_errom=100;
568
int
perem_max=36;
569
String str_perem=
"Day"
;
570
den= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
571
}
572
//устанавливаем часы
573
void
time_setup_chas() {
574
String str_menu=
"SETUP HOUR"
;
575
int
perem_menu=chas;
576
int
adress_errom=102;
577
int
perem_max=23;
578
String str_perem=
"Hour"
;
579
chas= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
580
}
581
//устанавливаем минуты
582
void
time_setup_minut() {
583
String str_menu=
"SETUP minute"
;
584
int
perem_menu=minut;
585
int
adress_errom=0;
586
int
perem_max=59;
587
String str_perem=
"minute"
;
588
minut= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
589
}
590
591
//выбираем птицу /////////////////////////////////////////////////////////
592
593
void
bird_setup() {
594
String str_menu=
"SETUP bird"
;
595
int
perem_menu=bird;
596
int
adress_errom=110;
597
int
perem_max=5;
598
String str_perem=
"bird"
;
599
bird= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
600
}
601
602
603
//устанавливаем поворот
604
void
turn_setup() {
605
int
turnPeriod=EEPROM_int_read(104);
//период поворота лотков в часах
606
607
String str_menu=
"TURN SETUP"
;
608
int
perem_menu=turnPeriod;
609
int
adress_errom=104;
610
int
perem_max=12;
611
String str_perem=
"TURN Hour"
;
612
turnPeriod= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
613
}
614
615
616
//устанавливаем сигнализацию
617
void
alarm_setup() {
618
int
alarmTemp=EEPROM_int_read(106);
619
String str_menu=
"ALARM SETUP"
;
620
int
perem_menu=alarmTemp;
621
int
adress_errom=106;
622
int
perem_max=10;
623
String str_perem=
"T.Alarm +- C"
;
624
alarmTemp= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
625
}
626
627
//устанавливаем вентиляцию
628
void
vent_setup() {
629
int
fanTemp=EEPROM_int_read(108);
630
String str_menu=
"A.FAN SETUP"
;
631
int
perem_menu=fanTemp;
632
int
adress_errom=108;
633
int
perem_max=40;
634
String str_perem=
"T.Fan C"
;
635
fanTemp= setup_menu(str_menu,perem_menu,adress_errom,perem_max,str_perem);
636
}
637
638
int
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
694
void
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
743
void
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
//управляем влажностью
765
void
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
//управляем поворотом
775
void
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
//управляем авариями
793
void
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
803
void
beeper(
int
duration) {
804
tone(beeper_pin, 2000, duration);
805
}
806
807
808
//управляем вентиляторами
809
void
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
//==============================
856
int
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
// чтение
875
int
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
// запись
883
void
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);
Lean_74
Какие семисторы использовали в ПИД. Не могу найти TIC206.
Часы такие?
https://www.aliexpress.com/item-img/Free-Shipping-1PCS-DS3231-AT24C32-II...
Lean_74
Какие семисторы использовали в ПИД. Не могу найти TIC206.
Часы такие?
https://www.aliexpress.com/item-img/Free-Shipping-1PCS-DS3231-AT24C32-II...
Тиристор у меня BT138-800E(хотя можно любой из серии ВТ с напряжением пробоя более 300В и ток от 0.5 ампера, я просто попросил в магазине самые дешевые) он там кстати без радиатора и вообше не греется.
Аппаратных часов нет, они программные на таймере 1 у dimax-a позаимствовал.
lean_74 пока едет из поднебесной заказанное "железо" а я усиленно штудирую (как у Ардуино Нано надо перешить загрузчик на optiboot чтобы нормально работал wdt -"вачдог"), возникло несколько вопросов. Если в электронике я еще более менее разбираюсь, то в програмировании я "чайник", поэтому простите если, что не так спрошу.
1) Вы писали в последнем посте "Аппаратных часов нет, они программные на таймере 1 у dimax-a позаимствовал". По возможности дайте ссылку. А то я по форуму полазил но ни чего не нашел. Только то, что dimax писал про реализацию часов на LCD.
2) По схеме http://cxem.net/arduino/arduino71.php, ( По подключению: вход сигнала демирования это с 6 пина МК, это понятно, а выход детектора нуля куда подключается не вижу, в скетче 036 строка закоментирована
//Пин 2 Вход обработки прерывания для детектора нуля и управления семистором
3) По пинам:
а) Что подключаете на пин аварии.
б) Вентилятор который сидит на пин 13, он продувочный или он же и тепло гоняет
На сегодня хватит, заранее благодарен.
1.http://arduino.ru/forum/proekty/net-sosed-ili-domofon-avtomat#comment-136153
2.ответ в вопросе //Пин 2 http://arduino.ru/Reference/AttachInterrupt
3. Пока ничего не подключал, это осталось от Um-ka, но надо полагать а) светодиод, б) "продувочный"
те что постоянно воздух гоняют у меня напрямую к 12В
lean_74 Скажите пожайлуста, как эти часы будут работать после отключения и включения питания?
Нарисовал плату, правда это всего лишь 3-я моя плата в Sprint-Layout, посему сильно просьба не пинать.
https://yadi.sk/d/nCYIDGV73E2aRv
lean_74 Скажите пожайлуста, как эти часы будут работать после отключения и включения питания?
В памяти сохраняется день и час инкубации, я думаю без присмотра все равно инкубатор не оставите, если время не соответствует действительному, то значит были какие-то сбои в работе, главное нам надо знать день инкубации, он в памяти сохраняется.
Плата очень даже нормальная. Марка реле под которые разводил?
Пару вопросов по плате.
1) Что за микросхема на 16 ножек
2) Посмотри по плате 7805 по моему наоборот должен стоять
3) 2 -й семистор под нагреватель увлажнителя
https://kealan.ru/catalog/124/913/
1.ULN2003 - появилось попутно желание сменить моторчик на перевороте яиц на лежащий без дела шаговик 28BYJ-48
2. Да я его по мере разводки развернул,
3.Ну это может и дополнительный нагреватель быть, так с запасом сделал, чтобы все ноги атмеги использовать. у нас в Челябинске можно быстро и недорого заказать платы, чем самому травить www.pcb74.ru .
lean _74 по поводу платы могу войти в долю, правда мне за доставку придется заплатить но бог с ним
Я четыре штуки уже заказал, могу одной поделиться, как будет готова. пиши на почту МойНик@mail.ru
Решил собрать этот блок управления инкубатором по блочной схеме (в наличии есть все элементы) в корпусе от старого модема. Управление нагревателями - твердотельные реле OMRON (два квадратика рядом с ардуинкой). Остальное управление через блок на 4 реле. Питание ардуинки через DC-DC преобразователь на LM2596S. На данный момент - крепеж и слесарка.
[quote=MVN123P]
Решил собрать этот блок управления инкубатором по блочной схеме (в наличии есть все элементы) в корпусе от старого модема. Управление нагревателями - твердотельные реле OMRON (два квадратика рядом с ардуинкой). Остальное управление через блок на 4 реле. Питание ардуинки через DC-DC преобразователь на LM2596S. На данный момент - крепеж и слесарка.
/quote]
Детектор нуля все равно нужен, его пока не вижу, а так зачетно!
lean_74 посмотрел в нете видео по шаговику 28BYJ-48. Внутренности у него пластиковые. Я так понимаю двигатель будет стоять внутри инкубатора, хоть 38 градусов небольшая температура, не будет ли этот пластик пересыхать. Интересно есть у кого-либо опыт эксплуатации в тааких условиях данного девайса.
lean_74 очень интерестная тема .Тут PID плавная регулировка (диммирование)?. Дело в том что у меня на инкубаторе ПИД мигает. Это влияет на освещение в соседней комнате.
Знакомый почерк :)
Вижу в хорошие руки мои труды попали.
Ну вот вам тогда плата и большая часть наработок и ветвлений. 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 и под все драйверы подходит.
А чего часы то не использовал? МК не точно миллисекунды считает и забывает при выключении.
Ну и хочется посмотреть на результат всей работы. Пока неплохо, но надо все в бою проверять обязательно. Успехов!
ЗЫ: забавная разводка...
Вижу в хорошие руки мои труды попали.
Спасибо за поддержку!
Ну вот вам тогда плата и большая часть наработок и ветвлений. https://drive.google.com/open?id=0B0vRuSZ7oRUeR2tyeG9pSHZ4R2M
Тут без пузыря не разобраться, файлик бы с пояснением, где, что и для чего.
Пин аварии ой как нужен. Реле на него нормальнозамкнутое, симисторы иногда пробиваются, особенно с лампами накаливания, и тогда вся мощность жарит яйца. А реле аварии клац - и спасены! Вот знакомый недавно 2 короба (по 360) яиц бройлера выкинул, на 20-й день инкубации твердотельное квакнуло. Ну и (или) вентилятор принудительной продувки.
Симисторы BT и BTB имеют "фазу" на радиаторе, а BTA изолированные. Цена почти одинаковая.
У меня тиристор вообще не греется, надо полагать потому, что переключения происходят при переходе через ноль, и мощьности на нем не рассеивается, почему тогда он может выйти из строя? Понятно, когда ШИМом регулируется и часть мощности рассеивается на самом тиристоре.
Моторы шаговые лучше с драйверами Step/Dir использовать, там 1 дорожку надо перерезать в моторчике. Тогда 2 пина потребуется вместо 4 и под все драйверы подходит.
ну это пока для меня темный лес, попробовал покрутить шаговиком -получилось, усилие для переворота лотков у него вполне приличное и концевики ставить не надо.
А чего часы то не использовал? МК не точно миллисекунды считает и забывает при выключении.
Все же хотелось сделать попроще и легче для повторения. в первой версии часы были, но 150 перепелиных яиц на 15 день все равно выкинул, просто все зависло и поджарило до 52 градусов, а днем на работе, сколько там часов ини жарились ХЗ. С растройства даже отложил на время свои эксперименты, и решил подготовиться более основательно.
Ну и хочется посмотреть на результат всей работы. Пока неплохо, но надо все в бою проверять обязательно. Успехов!
Еще раз Спасибо! Результаты будем выкладывать.
ЗЫ: забавная разводка...
:)) ну не волшебник я - только учусь.
А Детектор нуля в заводском исполнение есть у ардуины как модуль?
вон же у Umka есть готовые http://arduino.ru/forum/programmirovanie/attiny85-i-preryvanie#comment-243118
Я с Али заказывал Ардуино думал есть готовый модуль на него чтобы вместе заказать.
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 есть встроенный детектор ноля. В твердотельных реле тоже. А диммер не тянет контроллер с таким скетчем, мигают лампы из-за запрета прерываний. Автономный диммер хорошее решение.
Роман я слежку за вашими разработками здорово...
У меня инкубатор из витринного холодильника. Яйца ложу ступенчато первый выводок был удачным. Второй сварил под утро был 52°. Дело в том терморегулятор был заказан ПИД Rex-c100 потом выяснелось что отправили релейный. Из-за частого срабатовании реле залипло температура поднелась до критической. Потом выпаял электромагнитное реле поставил перемычки и подключил SSR. Но плавного накала ламп там я не смог добиться. В этом году хотел заказать регулятор влажности. Передумал заказал УНО (чтобы инкубатор стал смартом) дисплей 16/2 датчики. Вот думаю может и перевотот нагрев, влажность смогу перевести на ардуино. Если добьюсь плавного накала ламп было бы здорово!
У меня тоже есть инкубаторы из витрины. Неплохо выводят. Реле залипло, бывает. А вото тут в комментариях товарищи до усёру спорят что реле это нормально https://www.youtube.com/watch?v=zcLj_6EfYgY
Вот расскажите им! Я не смог переубедить барыг от птицеводства.
Что значит поворот нагрев и влажность перевести на Ардуино? Все же готово уже. И плавный накал тоже. Я же дал уже все. ПИД считает свою математику и на выходе выплевывает некий коэффициент мощности, которую надо подать в нагреватель. Ну мы этот коэффициент мапим в байт и отсылаем по wire в диммер. И всё. И будет очень плавно. Только... а зачем в витрине лампами греть? Есть же ТЭНы воздушные и керамика. Ладно в пенопластовой коробочке...
Что значит поворот нагрев и влажность перевести на Ардуино? Все же готово уже. И плавный накал тоже. Я же дал уже все.
Спасибо. Я так понимаю теперь мне нужен ваш автономный диммер либо делитель нуля для того чтобы залить скейтч с этой темы И регулировать плавненько? И ещё у меня стоит мотор от стеклоподьемника. Я пологаю нужно корректировать код чтобы он менял полярность и приходил в горизонтальное положение по кнопке чтобы заложить яйца!?
Только... а зачем в витрине лампами греть? Есть же ТЭНы воздушные и керамика. Ладно в пенопластовой коробочке...
Я ставил углеродный кабель 15 метров а лампы на разогрев. Но кабель не справляется весной. Наверное не правильно рассчитал. Сейчас работают вместе.
Вот про скетч из этой темы лучше у его автора спрашивать. Я вижу тут многое из моего инкубатора и многое сделано иначе. Думаете мне охота досконально в нем разбираться и понимать все замыслы его создателя? Я только даю варианты своих наработок, а как и где их использовать сами смотрите. Если Вы не сможете самостоятельно прикрутить диммер к ПИД, то либо вы покупатель, либо просите кого-то это сделать. Объясните, какой смысл греть витрину углеродным кабелем да еще и с ПИД-регулятором?
lean_74
Собрал схему - но не пойму как должен работать вентилятор?
lean_74
Собрал схему - но не пойму как должен работать вентилятор?
Вентилятор пока не тестировал, но по задумке он работает во время плановых проветриваний два раза в день, когла они есть и во время аварии, т.е превышении максимально установленной температуры.
Пид нужен, когда нагреватель инерционный, тены, лампочки т.п., когда эл.энергию отключили, а они продолжают греть, углеродный кабель практически безинерционный, т.е ему достаточно простого терморегулятора.
По скетчу: он подмигивает,но не сильно и то, я думаю, потому, что накладываются друг на друга аппаратные прерывания и прерывания по таймеру, я в этом пока не сильно разбираюсь, но думаю со времением эту проблему решу, если производительности микроконтроллера хватит.
По перевороту с помощью мотора для стеклоподъемника, надо корректировать не только код, но схему подключения, она кстати там у Umka по его ссылке тоже есть, на двух реле сделана и ручкой соединения дорисованы.
lean_74
Спасибо за информацию. Тогда не буду на этом сильно заморачиваться.
По поводу схемы мне едут мосфеты.
Если на мосфетах то придется что-то типа этого городить: https://yadi.sk/i/gKCXBpA03EEM2N
Насчет инерции. Не только нагреватель надо учитвыать, надо всю систему брать. 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 есть.
Запуталли меня тут с миганием - не миганием лампочек, так при таком способе регулирования обязательно должно мигать, т.к. мощность мы регулируем не отрезанием части полуволны, а всей полуволны, т.е за секунду у нас 100 полуволн, нужно пропустить 50 процентов мощности - пропускаем 50 полуволн, это все равно что диод последовательно с лампочкой включить, уже заметно что мигает, если только 1% то 1 полуволну в секунду - раз в секунду и будет мигать. вот тут популярно написано: https://habrahabr.ru/post/254719/
и действтвительно схему можно еще более упростить, а управление сделать прерываниями по таймеру.
Сам же и запутал своим детектором, человек теперь ищет у китайцев "делитель на ноль" чтобы плавно светило. А я говорю - вот он готовый плавный самостоятельный диммер. В него надо писать по шине I2C нужный уровень, а можно и читать. Ну или при помощи ШИМ обычного и ничего не мигает. Но меня не слушают. Хотя каждый же сам как хочет...
Вот сделал заготовку для автопереворота яиц по принципу китайского, только они даже за одну пластмассу больше тысячи просят, тут себестоимость без учета собственного труда - ноль, все из остатков после ремонта. https://youtu.be/VQ0mPMOu_wo
Хочешь совет хороший по поводу профиля?
Хочешь совет хороший по поводу профиля?
От тебя любой совет, я думаю, хороший , думаешь оцинковка будет вредно действовать? тогда покрашу.
вот и платки сделали.
Совет - делай лотки из сетки оцинкованной. Профиль нифига не продувается. Тем более корыто такое.
В печатной плате незначительная ошибочка, у МОС3021 землю завел на 3-ю ногу, вместо 2-й. т.к 3-я не задействована просто соединяем ее со второй.
Лучше бы исходник с Layout дал или в чем ты там рисуешь. По фотке же не видно половину дорожек. Все в тумане. Думаешь кто-то будет по фотке плату повторять и еще потом ошибку исправлять?