Ищу исполнителя по написанию скетча по автоматизации перепелятника
- Войдите на сайт для отправки комментариев
Сб, 01/12/2012 - 22:05
Доброго времени суток!
Нужно написать скетч для управления температурой и светом перепелятника. Задание ниже, схема тоже.
Задание на программирование Arduino UNO.
- Программирование в среде Arduino 1.0.1.
- Библиотеки для LCD (2х16 + 6 кнопок), 1-Wire, DS1307 под Arduino 1.0.1 прилагаются и протестированы. Если есть возможность - русифицировать дисплей. Прилагается аналогичный пример библиотеки.
- Крайне желательно комментировать все строки кода, чтобы отладку можно было выполнить самостоятельно.
- Схема диммера взята отсюда http://www.compcar.ru/forum/showthread.php?t=8396 там же есть скетч.
- Силовая часть для управления подсветкой будет нарисована позже, когда появится ясность с мощностью нагрузки (LED – лента), поэтому достаточно обычного ШИМа на пине 3, изменяемого по датчику освещенности.
- Подключение будет выполняться согласно прилагаемой схемы.
- В перспективе к пинам 0,1 планируется подключение реле управления двигателем, контроль положения планируется отслеживать аналоговым входом (по концевикам).
- Вариант отображения информации на дисплее ниже
http://s019.radikal.ru/i609/1212/50/426b0b8f3a1c.jpg
Здесь первые 5 символов – текущее время
Символы 7,8,9 – день недели
Символы 15,16 (первой строки ) показывают день программы для брудера (1-29) – см. алгоритм ниже.
Во второй строке выводится температура с двух датчиков температуры 18B20
1. С кнопок требуется реализовать:
· Установку времени, дня недели.
· Установку дня программы брудера (1-29).
· Отключение сигнала тревоги.
· Смену режима подсветки (авто) – по датчику освещенности или (ручн.).
Алгоритм
Брудер (для птенцов).
Включить лампу на треть мощности (50 Вт).
1. День 1-7:
1.1. Проверить температуру.
1.2. Если t выходит за рамки значений (35-37С), отрегулировать диммированием (±5% мощности).
1.3. Пауза 5 мин.
1.4. Перейти к п. 1.1.
1.5. Если t<33 или > 37.5, подать звуковой сигнал.
2. День 8-14:
2.1. Проверить температуру.
2.2. Если t выходит за рамки значений (30-32С), отрегулировать диммированием (±5% мощности).
2.3. Пауза 10 мин.
2.4. Перейти к п. 2.1.
2.5. Если t<28 или > 34, подать звуковой сигнал.
3. День 15-21:
3.1. Проверить температуру.
3.2. Если t выходит за рамки значений (25-27С), отрегулировать диммированием (±5% мощности).
3.3. Пауза 15 мин.
3.4. Перейти к п. 3.1.
3.5. Если t<21 или > 27.5, подать звуковой сигнал.
4. День 22-28:
4.1. Проверить температуру.
4.2. Если t < 20 С, включить лампу на 10%, если t>22 C, выключить лампу.
4.3. Пауза 30 мин.
4.4. Перейти к п. 4.1.
4.5. Если t<19, подать звуковой сигнал.
5. День 29.
5.1. Выключить лампу.
Перепелятник.
1. Освещение.
1.1. Время 08.00-01.00
1.1.1. Проверить освещенность с помощью фоторезистора.
1.1.2. Включить светодиодную линейку на определенную мощность, в зависимости от показаний фоторезистора.
1.1.3. Пауза 10 мин
1.1.4. Перейти к п. 1.1.1.
1.2. Время 01.00-08.00
1.2.1. Выключить свет.
2. Кормушка.
1.1. Время 12.00. Провернуть сервопривод на определенное количество градусов.
1.2. Время 00.00. Провернуть сервопривод на определенное количество градусов.
схема http://narod.ru/disk/64204547001.b50fe044b6efcac2b11ab5ca41d2d954/%D1%81%D1%85%D0%B5%D0%BC%D0%B0.pdf.html
скайп: maksimkstovo1985
забыл написать где искать, подредактировал.
Хочу поблагодарить Максима за великолепно решенную задачу. После месячного сотрудничесва схема была значительно переработана, а в алгоритм внесено множество изменений и улучшений. Возможно, позже, опишу проект, если кому-то это интересно, а пока схема и фото готового девайса (точнее не совсем еще готового). К оптимизации особо не стремился, поэтому в схеме появились две ардуины, но все работает как часы (и часы тоже работают )).
Красота!
Осталось тока скетч выложить и поверю, что "в Новый год чудеса случаются! " :))
Где фото живых птиц, прошедших через это устройство? :)
Ну коль Новый год еще не прошел, выкладываю код, возможно кому-то пригодится
001
#include "Setup.h"
002
#include "Temp.h"
003
#include "Display.h"
004
#include "Keybord.h"
005
006
#include <LiquidCrystal.h>
007
#include <Wire.h>
008
#include <DS1307.h>
009
#include <EEPROM.h>
010
#include <OneWire.h>
011
#include <Servo.h>
012
013
014
SYMBOLS
015
WEEK
016
DS18B20
017
018
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
019
OneWire ds(3);
020
Servo myservo;
021
022
int
modes_temp[4] = {
023
week_1, week_2, week_3, week_4};
024
char
hour = 12, minute = 0, day_of_week = 0, day = 0, setting = 0, lcd_mode = 0;
025
bool
light_avto = 1, new_temp = 0, settings = 0, colon = 0, feed = 0;
026
bool
bruder_work = EEPROM.read(0);
027
int
lighting = 110, L = 0, dimming = 0;
028
char
char_zero[] =
" "
;
029
unsigned
long
blink_time, feed_time_out;
030
031
032
void
setup
()
033
{
034
Serial
.begin(9600);
035
036
myservo.attach(12);
037
pinMode(2, 1);
038
pinMode(13, 1);
039
pinMode(11, 1);
040
Symbols_init();
041
lcd.begin(16, 2);
042
lcd.clear();
043
RTC_update();
044
Update_lcd();
045
}
046
047
void
loop
()
048
{
049
byte
key = Keybord();
050
051
Temp_update();
052
Regulator();
053
Dimming();
054
Beeper(key);
055
056
Colon();
057
Lighting();
058
Feed();
059
060
if
(settings)
061
Settings(key);
062
else
063
Work(key);
064
065
}
066
067
void
Settings(
char
key)
068
{
069
070
static
char
setting;
071
072
if
(key == SELECT)
073
{
074
settings = 0;
075
setting = 0;
076
RTC.stop();
077
RTC.
set
(DS1307_MTH, 4);
078
RTC.
set
(DS1307_HR, hour);
079
RTC.
set
(DS1307_MIN, minute);
080
RTC.
set
(DS1307_DOW, day_of_week);
081
if
(bruder_work) RTC.
set
(DS1307_DATE, day);
082
RTC.start();
083
EEPROM.write(0, bruder_work);
084
}
085
086
switch
(setting)
087
{
088
case
0:
089
To_chars(day);
090
Blink(char_zero, 14, 0);
091
if
(key == UP || key == DOWN)
092
{
093
if
(key == UP) day++;
094
if
(key == DOWN) day--;
095
if
(day == 29) day = 0;
096
if
(day == -1) day = 28;
097
if
(day == 0) bruder_work = 0;
098
else
bruder_work = 1;
099
}
100
break
;
101
102
case
1:
103
Blink(week[day_of_week], 6, 0);
104
if
(key == UP || key == DOWN)
105
{
106
if
(key == UP) day_of_week++;
107
if
(key == DOWN) day_of_week--;
108
if
(day_of_week == 8) day_of_week = 1;
109
if
(day_of_week == 0) day_of_week = 7;
110
}
111
break
;
112
113
case
2:
114
To_chars(minute);
115
Blink(char_zero, 3, 0);
116
if
(key == UP || key == DOWN)
117
{
118
if
(key == UP) minute++;
119
if
(key == DOWN) minute--;
120
if
(minute == 60) minute = 0;
121
if
(minute == -1) minute = 59;
122
}
123
break
;
124
125
case
3:
126
To_chars(hour);
127
Blink(char_zero, 0, 0);
128
if
(key == UP || key == DOWN)
129
{
130
if
(key == UP) hour++;
131
if
(key == DOWN) hour--;
132
if
(hour == 24) hour = 0;
133
if
(hour == -1) hour = 23;
134
}
135
break
;
136
}
137
138
if
(key)
139
{
140
if
(key == LEFT) setting++;
141
if
(key == RIGHT) setting--;
142
if
(setting == 4) setting = 0;
143
if
(setting == -1) setting = 3;
144
145
Update_lcd();
146
147
if
(key == UP || key == DOWN)
148
blink_time = millis() + 500;
149
else
150
blink_time = millis();
151
}
152
153
}
154
155
void
Work(
char
key)
156
{
157
static
unsigned
long
time_out;
158
static
unsigned
long
time_update;
159
static
bool
out
;
160
static
bool
out_show;
161
162
if
(key == SELECT)
163
{
164
if
(out_show)
165
out_show = 0;
166
else
167
{
168
settings = 1;
169
RTC_update();
170
}
171
lcd_mode = 0;
172
Update_lcd();
173
}
174
175
176
177
if
(key == UP || key == DOWN)
178
{
179
if
(key == UP) lcd_mode++;
180
if
(key == DOWN) lcd_mode--;
181
if
(lcd_mode == 4) lcd_mode = 0;
182
if
(lcd_mode == -1)lcd_mode = 3;
183
Update_lcd();
184
185
if
(lcd_mode)
186
{
187
time_out = millis() + time_show*1000L;
188
out_show = 1;
189
}
190
else
191
out_show = 0;
192
}
193
194
if
(key == RIGHT || key == LEFT)
195
{
196
if
(!out_show)
197
{
198
if
(
out
)
199
{
200
if
(key == RIGHT) lighting += 10;
201
if
(lighting > 110) lighting = 0;
202
if
(key == LEFT) lighting -= 10;
203
if
(lighting < -10) lighting = 100;
204
if
(lighting > 100) lighting = 110;
205
if
(lighting < 0) lighting = -10;
206
if
(lighting < 0 || lighting > 100)
207
light_avto = 1;
208
else
209
light_avto = 0;
210
}
211
lcd.setCursor(6, 0);
212
lcd.print(
"CBET:"
);
213
if
(light_avto)
214
lcd.print(
"ABTO "
);
215
else
216
{
217
lcd.print(lighting);
218
lcd.print(
"%"
);
219
lcd.print(
" "
);
220
}
221
time_out = millis() + 1000;
222
out
= 1;
223
}
224
else
if
(lcd_mode == 3) Feed_start();
225
}
226
227
if
(millis() > time_out &&
out
|| millis() > time_out && out_show)
228
{
229
lcd_mode = 0;
230
Update_lcd();
231
out
= 0;
232
out_show = 0;
233
}
234
235
if
(millis() > time_update && !
out
)
236
{
237
RTC_update();
238
Update_lcd();
239
time_update = millis() + disp_upd;
240
}
241
242
}
243
244
245
void
Regulator()
246
{
247
if
(new_temp)
248
{
249
if
(bruder_work)
250
{
251
if
(temp[0]) dimming = PID_control(modes_temp[(day-1)/7], temp[0]);
252
}
253
else
dimming = 0;
254
new_temp = 0;
255
}
256
}
257
258
259
byte
PID_control(
int
settemp,
int
currenttemp)
260
{
261
static
int
last_error;
262
static
long
I;
263
int
P = settemp - currenttemp;
264
long
D = (((settemp - currenttemp) - last_error) * 1000 / (
long
)Tt);
265
last_error = settemp - currenttemp;
266
long
PID = Kp*P + Ki*I + Kd*D;
267
PID = constrain(PID, 0, 254);
268
if
(PID > 0 && PID < 254) I = I + ((settemp - currenttemp) * (
long
)Tt) / 1000;
269
return
PID;
270
}
271
272
273
void
Temp_update()
274
{
275
static
unsigned
long
temp_upd;
276
if
(millis() > temp_upd)
277
{
278
static
bool
convert_read;
279
if
(!convert_read)
280
{
281
ds.reset();
282
ds.write(0xCC);
283
ds.write(0x44, 1);
284
convert_read = 1;
285
temp_upd = millis() + 1000;
286
}
287
else
288
{
289
for
(
byte
i = 0; i < 2; i++)
290
{
291
ds.reset();
292
ds.select(addr[i]);
293
ds.write(0xBE);
294
byte
data[2];
295
for
(
byte
j = 0; j < 2; j++) data[j] = ds.read();
296
unsigned
int
raw = (data[1] << 8) | data[0];
297
temp[i] = ((
float
)raw/16.0)*10;
298
temp[i] = constrain(temp[i], 0, 500);
299
}
300
convert_read = 0;
301
temp_upd = millis() + 1500;
302
new_temp = 1;
303
}
304
}
305
}
306
307
308
void
Lighting()
309
{
310
static
unsigned
long
time_upd;
311
if
(millis() > time_upd)
312
{
313
if
(light_avto)
314
{
315
if
(hour >= HOUR_ON && hour < HOUR_OFF)
316
L = 0;
317
else
318
L = map(ADC_read(1), MIN_L, MAX_L, MAX_P, MIN_P);
319
}
320
else
321
L = map(lighting, 0, 100, MIN_P, MAX_P);
322
L = constrain(L, MIN_P, MAX_P);
323
analogWrite(11, L);
324
time_upd = millis() + 200;
325
}
326
}
327
328
329
void
Dimming()
330
{
331
dimming = constrain(dimming, 0, 254);
332
static
int
prev_dimming;
333
if
(dimming != prev_dimming)
334
{
335
Serial
.write(dimming);
336
prev_dimming = dimming;
337
}
338
}
339
340
341
void
RTC_update()
342
{
343
static
unsigned
long
rtc_up_time;
344
if
(millis() > rtc_up_time)
345
{
346
hour = RTC.
get
(DS1307_HR, 1);
347
minute = RTC.
get
(DS1307_MIN, 0);
348
day_of_week = RTC.
get
(DS1307_DOW, 0);
349
if
(bruder_work) day = RTC.
get
(DS1307_DATE, 0);
350
if
(day > 28) day = 0;
351
if
(day == 0) bruder_work = 0;
352
if
(day == 0 && EEPROM.read(0)) EEPROM.write(0, bruder_work);
353
rtc_up_time = millis() + 10000;
354
}
355
}
356
357
358
void
To_chars(
byte
num)
359
{
360
if
(num < 10)
361
{
362
char_zero[0] =
'0'
;
363
char_zero[1] = num +
'0'
;
364
}
365
else
366
{
367
char_zero[0] = num/10 +
'0'
;
368
char_zero[1] = num%10 +
'0'
;
369
}
370
char_zero[3] = 0;
371
}
372
373
void
Blink(
char
*s,
byte
num_sym,
byte
num_str)
374
{
375
if
(millis() > blink_time)
376
{
377
lcd.setCursor(num_sym, num_str);
378
static
bool
blink;
379
blink = !blink;
380
if
(blink)
381
lcd.print(s);
382
else
383
lcd.print(
" "
);
384
blink_time = millis() + 300;
385
}
386
}
387
388
void
Colon()
389
{
390
391
static
unsigned
long
colon_time;
392
if
(millis() > colon_time)
393
{
394
colon = !colon;
395
lcd.setCursor(2, 0);
396
if
(colon)
397
lcd.print(
":"
);
398
else
399
lcd.print(
" "
);
400
colon_time = millis() + 500;
401
}
402
}
403
404
void
Update_lcd()
405
{
406
lcd.setCursor(0, 0);
407
To_chars(hour);
408
lcd.print(char_zero);
409
410
lcd.setCursor(2, 0);
411
if
(colon)
412
lcd.print(
":"
);
413
else
414
lcd.print(
" "
);
415
416
lcd.setCursor(3, 0);
417
To_chars(minute);
418
lcd.print(char_zero);
419
lcd.print(
" "
);
420
421
switch
(lcd_mode)
422
{
423
case
0:
424
lcd.setCursor(6, 0);
425
lcd.print(week[day_of_week]);
426
lcd.print(
" "
);
427
lcd.setCursor(9, 0);
428
lcd.print(
"\2EH\4-"
);
429
lcd.setCursor(14, 0);
430
To_chars(day);
431
lcd.print(char_zero);
432
break
;
433
434
case
1:
435
lcd.setCursor(6, 0);
436
lcd.print(
"TE\3\7O:"
);
437
lcd.print(map(dimming, 0, 254, 0, 100));
438
lcd.print(
"%"
);
439
lcd.print(
" "
);
440
break
;
441
442
case
2:
443
lcd.setCursor(6, 0);
444
lcd.print(
"CBET:"
);
445
lcd.print(map(L, MIN_P, MAX_P, 0, 100));
446
lcd.print(
"%"
);
447
lcd.print(
" "
);
448
break
;
449
450
case
3:
451
lcd.setCursor(6, 0);
452
if
(feed) lcd.print(
"KOPM: \2A "
);
453
else
lcd.print(
"KOPM: HET "
);
454
break
;
455
}
456
457
lcd.setCursor(0, 1);
458
lcd.print(
'\6'
);
459
Temp_print(temp[0]);
460
lcd.setCursor(9, 1);
461
lcd.print(
'\0'
);
462
Temp_print(temp[1]);
463
}
464
465
void
Temp_print(
int
t)
466
{
467
char
char_temp[] =
" "
;
468
char_temp[0] = t/100 +
'0'
;
469
char_temp[1] = (t/10)%10 +
'0'
;
470
char_temp[2] =
'.'
;
471
char_temp[3] = t%10 +
'0'
;
472
lcd.print(char_temp);
473
lcd.print(
"\1C"
);
474
475
}
476
477
void
Symbols_init()
478
{
479
lcd.createChar(1, gradus);
480
lcd.createChar(2, DD);
481
lcd.createChar(3, PP);
482
lcd.createChar(4, MIA);
483
lcd.createChar(5, CH);
484
lcd.createChar(6, chicken);
485
lcd.createChar(7, LL);
486
lcd.createChar(0, adult);
487
}
488
489
byte
ADC_read(
byte
ADC_pin)
490
{
491
ADMUX = ADC_pin;
// ADC pin
492
ADMUX |= 1<<REFS0;
// Set ADC reference to AVCC
493
ADMUX |= 1<<ADLAR;
// 8 bit reading
494
ADCSRA |= 1<<ADEN;
495
ADCSRA |= 1<<ADSC;
496
while
(!(ADCSRA & (1<<ADIF)));
497
ADCSRA |= 1<<ADIF;
498
byte
result = ADCH;
499
ADMUX = 0;
500
ADCSRB &= ~(1<<ADLAR);
// 10 bit reading
501
return
result;
502
}
503
504
byte
Keybord()
505
{
506
static
unsigned
long
key_time;
507
if
(millis() < key_time)
return
0;
508
509
static
byte
key_prev;
510
if
(ADC_read(0) > 200)
511
{
512
key_prev = 0;
513
return
0;
514
}
515
516
byte
key = 0;
517
byte
push[] =
518
{
519
0, 0, 0, 0, 0
520
};
521
522
for
(
byte
i = 0; i < 5; i++)
523
{
524
byte
a = ADC_read(0);
// 0 НИЧЕГО
525
if
(a == 0) push[i] = 1;
// 1 ВПРАВО
526
else
if
(a < 50) push[i] = 2;
// 2 ВВЕРХ
527
else
if
(a < 100) push[i] = 3;
// 3 ВНИЗ
528
else
if
(a < 150) push[i] = 4;
// 4 ВЛЕВО
529
else
if
(a < 200) push[i] = 5;
// 5 ВЫБОР
530
else
push[i] = 0;
531
delay(5);
532
}
533
if
(push[0] == push[1] && push[1] == push[2] && push[2] == push[3] && push[3] == push[4]) key = push[0];
534
535
if
(key == key_prev)
return
0;
536
537
key_prev = key;
538
key_time = millis() + 50;
539
return
key;
540
}
541
542
void
Beeper(
byte
&key)
543
{
544
static
bool
beep;
545
static
unsigned
long
beep_off_time;
546
547
if
(bruder_work)
548
{
549
static
byte
mode_prev;
550
if
(mode_prev != (day-1)/7)
551
{
552
beep_off_time = millis() + off_time*1000L;
553
mode_prev = (day-1)/7;
554
}
555
556
static
bool
flag;
557
if
(millis() > beep_off_time)
558
{
559
if
(temp[0] > modes_temp[(day-1)/7]+temp_beep || temp[0] < modes_temp[(day-1)/7]-temp_beep)
560
{
561
if
(!flag)
562
{
563
beep = 1;
564
flag = 1;
565
}
566
}
567
else
568
{
569
if
(flag)
570
{
571
beep = 0;
572
flag = 0;
573
}
574
}
575
}
576
577
}
578
else
beep_off_time = millis() + off_time*1000L;
579
580
if
(key && beep)
581
{
582
beep = 0;
583
key = 0;
584
}
585
586
Beep(beep);
587
}
588
589
void
Beep(
bool
beep)
590
{
591
static
byte
time;
592
static
unsigned
long
time_out;
593
if
(beep)
594
{
595
if
(millis() > time_out)
596
{
597
digitalWrite(13, !digitalRead(13));
598
time_out = millis() + 250;
599
time++;
600
if
(time > 5)
601
{
602
time = 0;
603
time_out = millis() + 1250;
604
}
605
}
606
}
607
else
608
{
609
digitalWrite(13, 0);
610
time = 0;
611
}
612
}
613
614
615
void
Feed_start()
616
{
617
feed = 1;
618
myservo.write(pos_feed_en);
619
digitalWrite(2, 1);
620
feed_time_out = millis() + feed_time;
621
Update_lcd();
622
}
623
624
void
Feed()
625
{
626
static
bool
started;
627
if
(hour == feed_hour_1 || hour == feed_hour_2)
628
{
629
if
(!started)
630
{
631
Feed_start();
632
started = 1;
633
}
634
}
635
else
started = 0;
636
637
if
(feed)
638
if
(millis() > feed_time_out)
639
{
640
feed = 0;
641
myservo.write(pos_feed_dis);
642
digitalWrite(2, 0);
643
Update_lcd();
644
}
645
}
Птицы через это устройство еще не прошли, но уже готовятся ). Вот тоже живая, но выращенная "вручную" без устройства ).
Большой респект !!!
Бум разбираться! Дуину взял месяц назад, и одна из причин была как раз - для возможной автоматизации подсобного своего хозяйства.
Успехов Вам sergsap в инновационном птицеводстве =) ! И с праздниками!
Спасибо, Вас тоже с праздниками. Сам недавно узнал о дуине, купил гору железа на ебее, вот первый пилотный проектик, весьма полезный ). Программить самостоятельно тяжеловато, ибо не умею ), а вот паяльник раньше часто в руках держал, тут сложностей не вижу. Что касается автоматизации птицеводства, то это интересная тема, т.к. перепела очень забавные птички и любят порядок во всем - свет, климат. Если что не так, сразу убивать друг друга начинают ну или самоликвидироваться. Поэтому интересно усовершенствовать их быт ). Хотя, признаюсь, хобби птицеводства не мое лично, но вот приходится погружаться в тонкости ).
PS забыл сказать, что скетч не полный и в схеме есть косяк, когла ее причесывал, шину I2C через резисторы случайно на землю повесил. В общем, документация не полная пока )
sergsap , можно поподробнее по схеме ?
зачем вторая дуина прежде всего, она управляет яркостью ламп ?
То есть вопрос - почему одной дуиной обойтись было нельзя
Вторая дуина появилась в результате того, что в ходе отладки устройства вылез небольшой баг - при подключении библиотеки 1-Wire иногда (хаотически) лампа вспыхивала. Небольшой анализ показал подозрения на конфликт библиотеки с внутренним прерыванием, с которым работает диммер. Первым решением было взять готовый диммер с управлением 1-10В и рулить им из ардуины, но поиск таких устройств навел на мысль, что они дороже дуины Nano. Также maksim предложил взять маленький атмелчик и сделать на нем диммер, но для меня это был очередной круг итераций и изысканий, а тут вроде как все готово, вот и остановились на дуине. К тому же, если не ошибаюсь, то библиотеке Servo нужен тот же таймер, что и диммеру, поэтому это тоже оправдывает вторую дуину. Ну и резерв IO не будет лишним для возможного развития проекта. С одной уной резерва просто нет
Такой способ диммирования "кушает" очень много ресурсов МК - одно внешнее прерывание и один таймер. Но основная проблема в том что возник конфликт с библиотекой OneWire.h потому как она при опросе датчиков отключает прерывания и лампа начинает помигивать, если же убрать из OneWire.h отключение прерываний, то температура с датчиков читалась через раз. Было предложено отказаться именно от токого способа диммирования, но так как готового подходящего варианта не нашли, а времени на разработку чего-то другого не было, то было решено просто вынести диммер в отдельную дуину и оставить все как есть.
Теоретически можно было бы попробывать синхронизировать опрос датчиков с работой диммера, но неизвестно был бы положительный результат.
Эх, не успел чуток добавить вопрос к #10
Sergsap, а девайс под названием "кормушка" - воплощение Ваших рук или заводского изготовления? Что-то я пока не встречал таких ни в жизни ни в инете, если не брать кадры ютюба про американские кормушки для домашних питомцев =/
Кормушка пока вынашивается в голове ). Будет определенно рукотворного производтства. Коль управление реализовали, осталось дело за малым. Малый пока думает ).
... Малый пока думает ).
Понятно, спасибо )))
а о датчиках DHT не думали? там и влажность есть, возможно перепелам это тоже важно, Я вот ковыряюсь тоже с DS18B20, ну тормозят они по черному, про запрет прерывания тоже видел, они на максимальном разрешении делают delay(750) при запрете прерываний, насколко я помню.
Плюс ко всему электростатикой от шарканья ногами сажаю эти датчики на показание -0 , и никакого решения кроме как перезагружать контроллер по питанию пока не нашел. Понятно что их нужно изолилировать, но с DHT проблем помойму меньше, если их не очень много.
DHT11 на всякий пожарный тоже были закуплены, но так и остались лежать в запасе. Мне не понравилась их точность 2С по температуре и 5% по влажности. Про проблемы DS18B20 даже и не слышал, а вот раньше с ними сталкивался и плохого ничего сказать не могу. Сейчас у меня на дисплее температура отображается с точностью до десятых градуса и весьма удобно наблюдать за ее изменениями, а также процессом термостатирования.
Была мысль до кучи повесить DHT11 и смотреть за влажностью, но рулить влажностью нечем, поэтому и нужды вроде как нет. Как и нет информации о потребности птичек к определенной влажности ).
Была мысль до кучи повесить DHT11 и смотреть за влажностью, но рулить влажностью нечем,
Как это "нечем"? Микрокомпрессор с пульверизатором - и будет Вам руль для добавления влажности. Уменьшение - только вентиляцией, хотя, в теории, можно было бы и пельтье приспособить на конденсацию влаги.
Сейчас модно применять ультразвуковые увлажнители. Вот интересно насколько сложно такой ультразвуковой излучатель найти и прикрутить к Arduino. Еще есть так называемая "мойка воздуха" когда на барабан закреплен пористый материал, а нижняя часть погружена в жидкость. Барабан мееедлено крутится, губка намокает, затем несколько испаряется, заодно улавливая пыль, а затем по завершению круга погружается в жидкость и смывает пыль. Еще верхнюючасть желательно обдувать вентилятором, чтобы усиливать испарение. Хотя наверно для перепелятника актуально обратное - осушитель
Еще есть так называемая "мойка воздуха" когда на барабан закреплен пористый материал, а нижняя часть погружена в жидкость. Барабан мееедлено крутится, губка намокает, затем несколько испаряется, заодно улавливая пыль, а затем по завершению круга погружается в жидкость и смывает пыль.
Нету там пористого материала. :) Ребристые пластиковые диски, по 6 штук с каждой стороны. Раз в месяц приходится разбирать и мыть не только поддон, но и поверхность дисков со щеткой, т.к. собирать-то оно собирает, а вот со смывом всей грязи в поддон - не ахти.
Как это не чем"? Микрокомпрессор с пульверизатором - и будет Вам руль для добавления влажности. Уменьшение - только вентиляцией, хотя, в теории, можно было бы и пельтье приспособить на конденсацию влаги.
Вот этого больше всего и боялся, что придется еще и общеобменную вентиляцию городить, а надо то было покормить, да посветить )).
А просто увлажнитель ИМХО не вариант, будет локально влажность высаживаться, потом мох пойдет расти, за ним тоже уход понадобится )
а такая схема вам не подойдет?
Нет, не подойдет, это всего лишь позиционный регулятор на реле.