Ищу исполнителя по написанию скетча по автоматизации перепелятника

sergsap
Offline
Зарегистрирован: 01.12.2012

Доброго времени суток!

Нужно написать скетч для управления температурой и светом перепелятника. Задание ниже, схема тоже.

 

Задание на программирование Arduino UNO.

  1. Программирование в среде Arduino 1.0.1.
  2. Библиотеки для LCD (2х16 + 6 кнопок), 1-Wire, DS1307 под Arduino 1.0.1 прилагаются и протестированы. Если есть возможность - русифицировать дисплей. Прилагается аналогичный пример библиотеки.
  3. Крайне желательно комментировать все строки кода, чтобы отладку можно было выполнить самостоятельно.
  4. Схема диммера взята отсюда http://www.compcar.ru/forum/showthread.php?t=8396 там же есть скетч.
  5. Силовая часть для управления подсветкой будет нарисована позже, когда появится ясность с мощностью нагрузки (LED – лента), поэтому достаточно обычного ШИМа на пине 3, изменяемого по датчику освещенности.
  6. Подключение будет выполняться согласно прилагаемой схемы.
  7. В перспективе к пинам 0,1 планируется подключение реле управления двигателем, контроль положения планируется отслеживать аналоговым входом (по концевикам).
  8. Вариант отображения информации на дисплее ниже

\"\\"\\"\"

 

sergsap
Offline
Зарегистрирован: 01.12.2012

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

maksim
Offline
Зарегистрирован: 12.02.2012
скайп: maksimkstovo1985

 

maksim
Offline
Зарегистрирован: 12.02.2012

забыл написать где искать, подредактировал.

sergsap
Offline
Зарегистрирован: 01.12.2012

Хочу поблагодарить Максима за великолепно решенную задачу. После месячного сотрудничесва схема была значительно переработана, а в алгоритм внесено множество изменений и улучшений. Возможно, позже, опишу проект, если кому-то это интересно, а пока схема и фото готового девайса (точнее не совсем еще готового). К оптимизации особо не стремился, поэтому в схеме появились две ардуины, но все работает как часы (и часы тоже работают )).

 

klinsky
Offline
Зарегистрирован: 16.11.2012

Красота!

Осталось тока скетч выложить и поверю, что "в Новый год чудеса случаются! " :))

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

Где фото живых птиц, прошедших через это устройство? :)

sergsap
Offline
Зарегистрирован: 01.12.2012

Ну коль Новый год еще не прошел, выкладываю код, возможно кому-то пригодится

#include "Setup.h"
#include "Temp.h"
#include "Display.h"
#include "Keybord.h"

#include <LiquidCrystal.h>
#include <Wire.h>
#include <DS1307.h>
#include <EEPROM.h>
#include <OneWire.h>
#include <Servo.h> 


SYMBOLS
WEEK
DS18B20

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
OneWire  ds(3);
Servo myservo; 

int modes_temp[4] = {
  week_1, week_2, week_3, week_4};
char hour = 12, minute = 0, day_of_week = 0, day = 0, setting = 0, lcd_mode = 0;
bool light_avto = 1, new_temp = 0, settings = 0, colon = 0, feed = 0;
bool bruder_work = EEPROM.read(0);
int lighting = 110, L = 0, dimming = 0;
char char_zero[] = "   ";
unsigned long blink_time, feed_time_out;


void setup() 
{
  Serial.begin(9600);

  myservo.attach(12);
  pinMode(2, 1);
  pinMode(13, 1);
  pinMode(11, 1);
  Symbols_init();
  lcd.begin(16, 2);
  lcd.clear();
  RTC_update();  
  Update_lcd();
}

void loop() 
{
  byte key = Keybord();

  Temp_update();  
  Regulator();
  Dimming();
  Beeper(key);

  Colon();
  Lighting();
  Feed();

  if(settings)
    Settings(key);
  else
    Work(key);

}

void Settings(char key)
{

  static char setting; 

  if(key == SELECT) 
  {
    settings = 0;
    setting = 0;
    RTC.stop();
    RTC.set(DS1307_MTH, 4);
    RTC.set(DS1307_HR, hour);
    RTC.set(DS1307_MIN, minute);
    RTC.set(DS1307_DOW, day_of_week);
    if(bruder_work) RTC.set(DS1307_DATE, day);
    RTC.start();
    EEPROM.write(0, bruder_work);
  }

  switch(setting)
  {
  case 0:    
    To_chars(day);
    Blink(char_zero, 14, 0);
    if(key == UP || key == DOWN)
    {       
      if(key == UP) day++;
      if(key == DOWN) day--;
      if(day == 29) day = 0;
      if(day == -1) day = 28;
      if(day == 0) bruder_work = 0;
      else bruder_work = 1;
    } 
    break;

  case 1:
    Blink(week[day_of_week], 6, 0);
    if(key == UP || key == DOWN)
    {       
      if(key == UP) day_of_week++;
      if(key == DOWN) day_of_week--;
      if(day_of_week == 8) day_of_week = 1;
      if(day_of_week == 0) day_of_week = 7;
    } 
    break;

  case 2:
    To_chars(minute);
    Blink(char_zero, 3, 0);
    if(key == UP || key == DOWN)
    {       
      if(key == UP) minute++;
      if(key == DOWN) minute--;
      if(minute == 60) minute = 0;
      if(minute == -1) minute = 59;
    } 
    break;

  case 3:
    To_chars(hour);
    Blink(char_zero, 0, 0);
    if(key == UP || key == DOWN)
    {       
      if(key == UP) hour++;
      if(key == DOWN) hour--;
      if(hour == 24) hour = 0;
      if(hour == -1) hour = 23;
    } 
    break;
  }

  if(key)
  {       
    if(key == LEFT) setting++;
    if(key == RIGHT) setting--;
    if(setting == 4) setting = 0;
    if(setting == -1) setting = 3;

    Update_lcd();

    if(key == UP || key == DOWN)
      blink_time = millis() + 500;
    else
      blink_time = millis();
  }

}

void Work(char key)
{
  static unsigned long time_out;
  static unsigned long time_update;
  static bool out;
  static bool out_show;

  if(key == SELECT)
  {
    if(out_show)
      out_show = 0;
    else
    {      
      settings = 1;
      RTC_update(); 
    }
    lcd_mode = 0;
    Update_lcd();
  }



  if(key == UP || key == DOWN)
  { 
    if(key == UP)   lcd_mode++;  
    if(key == DOWN) lcd_mode--;
    if(lcd_mode == 4) lcd_mode = 0;
    if(lcd_mode == -1)lcd_mode = 3;
    Update_lcd();

    if(lcd_mode)
    {
      time_out = millis() + time_show*1000L;
      out_show = 1;
    }
    else
      out_show = 0;
  } 

  if(key == RIGHT || key == LEFT)
  {
    if(!out_show)
    {
      if(out)
      {
        if(key == RIGHT) lighting += 10;
        if(lighting > 110) lighting = 0;
        if(key == LEFT) lighting -= 10;
        if(lighting < -10) lighting = 100;
        if(lighting > 100) lighting = 110;
        if(lighting < 0) lighting = -10;
        if(lighting < 0 || lighting > 100) 
          light_avto = 1;
        else
          light_avto = 0;
      }
      lcd.setCursor(6, 0);
      lcd.print("CBET:");
      if(light_avto) 
        lcd.print("ABTO ");
      else
      {
        lcd.print(lighting);
        lcd.print("%");
        lcd.print("   ");
      }
      time_out = millis() + 1000;
      out = 1;
    }
    else if(lcd_mode == 3) Feed_start();
  } 

  if(millis() > time_out && out || millis() > time_out && out_show)
  {
    lcd_mode = 0;
    Update_lcd();
    out = 0;
    out_show = 0;
  }

  if(millis() > time_update && !out)
  {
    RTC_update();
    Update_lcd();
    time_update = millis() + disp_upd;
  }

}


void Regulator()
{
  if(new_temp)
  {   
    if(bruder_work) 
    {
      if(temp[0]) dimming = PID_control(modes_temp[(day-1)/7], temp[0]); 
    }
    else dimming = 0; 
    new_temp = 0;
  }
}


byte PID_control(int settemp, int currenttemp)
{
  static int last_error;
  static long I;
  int P = settemp - currenttemp;
  long D = (((settemp - currenttemp) - last_error) * 1000 / (long)Tt); 
  last_error = settemp - currenttemp;
  long PID = Kp*P + Ki*I + Kd*D;
  PID = constrain(PID, 0, 254);
  if(PID > 0 && PID < 254) I = I + ((settemp - currenttemp) * (long)Tt) / 1000;
  return PID;
}


void Temp_update()
{
  static unsigned long temp_upd;
  if(millis() > temp_upd)
  {
    static bool convert_read;
    if(!convert_read)
    {
      ds.reset();
      ds.write(0xCC);   
      ds.write(0x44, 1);
      convert_read = 1;
      temp_upd = millis() + 1000;
    }
    else
    {
      for(byte i = 0; i < 2; i++)
      {
        ds.reset();
        ds.select(addr[i]);    
        ds.write(0xBE);
        byte data[2];  
        for(byte j = 0; j < 2; j++) data[j] = ds.read();
        unsigned int raw = (data[1] << 8) | data[0];
        temp[i] = ((float)raw/16.0)*10;
        temp[i] = constrain(temp[i], 0, 500);
      }
      convert_read = 0;
      temp_upd = millis() + 1500;
      new_temp = 1;
    }
  }
}


void Lighting()
{
  static unsigned long time_upd;
  if(millis() > time_upd)
  {
    if(light_avto)
    {
      if(hour >= HOUR_ON && hour < HOUR_OFF)
        L = 0;
      else
        L = map(ADC_read(1), MIN_L, MAX_L, MAX_P, MIN_P);                 
    }
    else
      L = map(lighting, 0, 100, MIN_P, MAX_P);
    L = constrain(L, MIN_P, MAX_P);
    analogWrite(11, L);
    time_upd = millis() + 200;
  }
}


void Dimming()
{
  dimming = constrain(dimming, 0, 254);
  static int prev_dimming;
  if(dimming != prev_dimming)
  {
    Serial.write(dimming);  
    prev_dimming = dimming;
  }
}


void RTC_update()
{
  static unsigned long rtc_up_time;
  if(millis() > rtc_up_time)
  {
    hour = RTC.get(DS1307_HR, 1);
    minute = RTC.get(DS1307_MIN, 0);
    day_of_week = RTC.get(DS1307_DOW, 0);
    if(bruder_work) day = RTC.get(DS1307_DATE, 0);
    if(day > 28) day = 0; 
    if(day == 0) bruder_work = 0;
    if(day == 0 && EEPROM.read(0)) EEPROM.write(0, bruder_work);
    rtc_up_time = millis() + 10000;
  }
}


void To_chars(byte num)
{ 
  if(num < 10) 
  {
    char_zero[0] = '0';
    char_zero[1] = num + '0';
  }
  else
  {
    char_zero[0] = num/10 + '0';
    char_zero[1] = num%10 + '0';   
  }
  char_zero[3] = 0;
}

void Blink(char *s, byte num_sym, byte num_str)
{ 
  if(millis() > blink_time)
  {
    lcd.setCursor(num_sym, num_str);
    static bool blink;
    blink = !blink;
    if(blink)
      lcd.print(s);
    else
      lcd.print("  ");
    blink_time = millis() + 300;
  }
}

void Colon()
{

  static unsigned long colon_time;
  if(millis() > colon_time)
  {
    colon = !colon;
    lcd.setCursor(2, 0);    
    if(colon)
      lcd.print(":");
    else
      lcd.print(" ");
    colon_time = millis() + 500;
  }
}

void Update_lcd()
{
  lcd.setCursor(0, 0);   
  To_chars(hour);
  lcd.print(char_zero);

  lcd.setCursor(2, 0);    
  if(colon)
    lcd.print(":");
  else
    lcd.print(" ");

  lcd.setCursor(3, 0);
  To_chars(minute);
  lcd.print(char_zero);
  lcd.print(" ");

  switch(lcd_mode)
  {
  case 0:
    lcd.setCursor(6, 0);
    lcd.print(week[day_of_week]);
    lcd.print(" ");
    lcd.setCursor(9, 0);
    lcd.print("\2EH\4-"); 
    lcd.setCursor(14, 0);
    To_chars(day);
    lcd.print(char_zero); 
    break;

  case 1:
    lcd.setCursor(6, 0);
    lcd.print("TE\3\7O:");
    lcd.print(map(dimming, 0, 254, 0, 100));
    lcd.print("%");
    lcd.print("  ");
    break;

  case 2:
    lcd.setCursor(6, 0);
    lcd.print("CBET:");
    lcd.print(map(L, MIN_P, MAX_P, 0, 100));
    lcd.print("%");
    lcd.print("   ");
    break;

  case 3:
    lcd.setCursor(6, 0);
    if(feed) lcd.print("KOPM: \2A  ");
    else lcd.print("KOPM: HET ");    
    break;
  }

  lcd.setCursor(0, 1);
  lcd.print('\6');
  Temp_print(temp[0]);
  lcd.setCursor(9, 1);
  lcd.print('\0');
  Temp_print(temp[1]);
}

void Temp_print(int t)
{
  char char_temp[] = "    ";
  char_temp[0] = t/100 + '0';
  char_temp[1] = (t/10)%10 + '0';
  char_temp[2] = '.';
  char_temp[3] = t%10 + '0';
  lcd.print(char_temp);
  lcd.print("\1C");

}

void Symbols_init()
{
  lcd.createChar(1, gradus);
  lcd.createChar(2, DD);
  lcd.createChar(3, PP);
  lcd.createChar(4, MIA);
  lcd.createChar(5, CH);
  lcd.createChar(6, chicken);
  lcd.createChar(7, LL);
  lcd.createChar(0, adult);
}

byte ADC_read(byte ADC_pin)
{
  ADMUX = ADC_pin; // ADC pin
  ADMUX |= 1<<REFS0; // Set ADC reference to AVCC
  ADMUX |= 1<<ADLAR; // 8 bit reading  
  ADCSRA |= 1<<ADEN;
  ADCSRA |= 1<<ADSC;
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA |= 1<<ADIF; 
  byte result = ADCH;
  ADMUX = 0;
  ADCSRB &= ~(1<<ADLAR); // 10 bit reading
  return result;
}

byte Keybord()
{ 
  static unsigned long key_time;
  if(millis() < key_time) return 0; 

  static byte key_prev;
  if(ADC_read(0) > 200) 
  {
    key_prev = 0;
    return 0;
  }

  byte key = 0;
  byte push[] = 
  {
    0, 0, 0, 0, 0
  };

  for(byte i = 0; i < 5; i++)
  {
    byte a = ADC_read(0);         // 0 НИЧЕГО
    if(a == 0) push[i] = 1;       // 1 ВПРАВО
    else if(a < 50) push[i] = 2;  // 2 ВВЕРХ
    else if(a < 100) push[i] = 3; // 3 ВНИЗ
    else if(a < 150) push[i] = 4; // 4 ВЛЕВО
    else if(a < 200) push[i] = 5; // 5 ВЫБОР
    else push[i] = 0; 
    delay(5);
  } 
  if(push[0] == push[1] && push[1] == push[2] && push[2] == push[3] && push[3] == push[4]) key = push[0];  

  if(key == key_prev) return 0;

  key_prev = key;
  key_time = millis() + 50;
  return key;
}

void Beeper(byte &key)
{
  static bool beep;
  static unsigned long beep_off_time;

  if(bruder_work)
  { 
    static byte mode_prev;
    if(mode_prev != (day-1)/7)
    {
      beep_off_time = millis() + off_time*1000L;
      mode_prev = (day-1)/7;
    }

    static bool flag;
    if(millis() > beep_off_time)
    {  
      if(temp[0] > modes_temp[(day-1)/7]+temp_beep || temp[0] < modes_temp[(day-1)/7]-temp_beep) 
      {       
        if(!flag)
        {  
          beep = 1;
          flag = 1;
        }      
      }
      else 
      {        
        if(flag)
        {
          beep = 0;
          flag = 0;
        }        
      }
    }

  }
  else beep_off_time = millis() + off_time*1000L;

  if(key && beep) 
  {
    beep = 0;
    key = 0;
  }

  Beep(beep);
}

void Beep(bool beep)
{
  static byte time;
  static unsigned long time_out;
  if(beep)
  {   
    if(millis() > time_out)
    {
      digitalWrite(13, !digitalRead(13));
      time_out = millis() + 250;
      time++;
      if(time > 5) 
      {
        time = 0;
        time_out = millis() + 1250;
      }
    }
  }
  else 
  {
    digitalWrite(13, 0);
    time = 0;
  }
}


void Feed_start()
{
  feed = 1;
  myservo.write(pos_feed_en); 
  digitalWrite(2, 1);
  feed_time_out = millis() + feed_time;
  Update_lcd();
}

void Feed()
{
  static bool started;
  if(hour == feed_hour_1 || hour == feed_hour_2)
  {
    if(!started)
    {
      Feed_start();
      started = 1;
    }
  }
  else started = 0;
  
    if(feed) 
      if(millis() > feed_time_out) 
      {
        feed = 0;
        myservo.write(pos_feed_dis); 
        digitalWrite(2, 0);
        Update_lcd();
      }
}

Птицы через это устройство еще не прошли, но уже готовятся ). Вот тоже живая, но выращенная "вручную" без устройства ).

klinsky
Offline
Зарегистрирован: 16.11.2012

Большой респект !!!

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

Успехов Вам sergsap в инновационном птицеводстве =) ! И с праздниками!

sergsap
Offline
Зарегистрирован: 01.12.2012

Спасибо, Вас тоже с праздниками. Сам недавно узнал о дуине, купил гору железа на ебее, вот первый пилотный проектик, весьма полезный ). Программить самостоятельно тяжеловато, ибо не умею ), а вот паяльник раньше часто в руках держал, тут сложностей не вижу. Что касается автоматизации птицеводства, то это интересная тема, т.к. перепела очень забавные птички и любят порядок во всем - свет, климат. Если что не так, сразу убивать друг друга начинают ну или самоликвидироваться. Поэтому интересно усовершенствовать их быт ). Хотя, признаюсь, хобби птицеводства не мое лично, но вот приходится погружаться в тонкости ).

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

Borland
Offline
Зарегистрирован: 17.05.2012

sergsap , можно поподробнее по схеме ?

зачем вторая дуина прежде всего, она управляет яркостью ламп ?

То есть вопрос - почему одной дуиной обойтись было нельзя

sergsap
Offline
Зарегистрирован: 01.12.2012

Вторая дуина появилась в результате того, что в ходе отладки устройства вылез небольшой баг - при подключении библиотеки 1-Wire иногда (хаотически) лампа вспыхивала. Небольшой анализ показал подозрения на конфликт библиотеки с внутренним прерыванием, с которым работает диммер. Первым решением было взять готовый диммер с управлением 1-10В и рулить им из ардуины, но поиск таких устройств навел на мысль, что они дороже дуины Nano. Также maksim предложил взять маленький атмелчик и сделать на нем диммер, но для меня это был очередной круг итераций и изысканий, а тут вроде как все готово, вот и остановились на дуине. К тому же, если не ошибаюсь, то библиотеке Servo нужен тот же таймер, что и диммеру, поэтому это тоже оправдывает вторую дуину. Ну и резерв IO не будет лишним для возможного развития проекта. С одной уной резерва просто нет

maksim
Offline
Зарегистрирован: 12.02.2012

Такой способ диммирования "кушает" очень много ресурсов МК - одно внешнее прерывание и один таймер. Но основная проблема в том что возник конфликт с библиотекой OneWire.h потому как она при опросе датчиков отключает прерывания и лампа начинает помигивать, если же убрать из OneWire.h отключение прерываний, то температура с датчиков читалась через раз. Было предложено отказаться именно от токого способа диммирования, но так как готового подходящего варианта не нашли, а времени на разработку чего-то другого не было, то было решено просто вынести диммер в отдельную дуину и оставить все как есть.

Теоретически можно было бы попробывать синхронизировать опрос датчиков с работой диммера, но неизвестно был бы положительный результат.

klinsky
Offline
Зарегистрирован: 16.11.2012

Эх, не успел чуток добавить вопрос к #10

Sergsap, а девайс под названием "кормушка" - воплощение Ваших рук или заводского изготовления? Что-то я пока не встречал таких ни в жизни ни в инете, если не брать кадры  ютюба про американские кормушки для домашних питомцев =/

sergsap
Offline
Зарегистрирован: 01.12.2012

Кормушка пока вынашивается в голове ). Будет определенно рукотворного производтства. Коль управление реализовали, осталось дело за малым. Малый пока думает ). 

klinsky
Offline
Зарегистрирован: 16.11.2012

sergsap пишет:

... Малый пока думает ). 

Понятно, спасибо )))

Borland
Offline
Зарегистрирован: 17.05.2012

а о датчиках DHT не думали? там и влажность есть, возможно перепелам это тоже важно, Я вот ковыряюсь тоже с  DS18B20, ну тормозят они по черному, про запрет прерывания тоже видел, они на максимальном разрешении делают delay(750) при запрете прерываний, насколко я помню.

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

 

sergsap
Offline
Зарегистрирован: 01.12.2012

DHT11 на всякий пожарный тоже были закуплены, но так и остались лежать в запасе. Мне не понравилась их точность 2С по температуре и 5% по влажности. Про проблемы DS18B20 даже и не слышал, а вот раньше с ними сталкивался и плохого ничего сказать не могу. Сейчас у меня на дисплее температура отображается с точностью до десятых градуса и весьма удобно наблюдать за ее изменениями, а также процессом термостатирования.

Была мысль до кучи повесить DHT11 и смотреть за влажностью, но рулить влажностью нечем, поэтому и нужды вроде как нет. Как и нет информации о потребности птичек к определенной влажности ).

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

sergsap пишет:

Была мысль до кучи повесить DHT11 и смотреть за влажностью, но рулить влажностью нечем,

Как это "нечем"? Микрокомпрессор с пульверизатором - и будет Вам руль для добавления влажности. Уменьшение - только вентиляцией, хотя, в теории, можно было бы и пельтье приспособить на конденсацию влаги.

Zapek@n
Offline
Зарегистрирован: 16.02.2012

Сейчас модно применять ультразвуковые увлажнители. Вот интересно насколько сложно такой ультразвуковой излучатель найти и прикрутить к Arduino. Еще есть так называемая "мойка воздуха" когда на барабан закреплен пористый материал, а нижняя часть погружена в жидкость. Барабан мееедлено крутится, губка намокает, затем несколько испаряется, заодно улавливая пыль, а затем по завершению круга погружается в жидкость и смывает пыль. Еще верхнюючасть желательно обдувать вентилятором, чтобы усиливать испарение. Хотя наверно для перепелятника актуально обратное - осушитель

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

Zapek@n пишет:

Еще есть так называемая "мойка воздуха" когда на барабан закреплен пористый материал, а нижняя часть погружена в жидкость. Барабан мееедлено крутится, губка намокает, затем несколько испаряется, заодно улавливая пыль, а затем по завершению круга погружается в жидкость и смывает пыль.

Нету там пористого материала. :) Ребристые пластиковые диски, по 6 штук с каждой стороны. Раз в месяц приходится разбирать и мыть не только поддон, но и поверхность дисков со щеткой, т.к. собирать-то оно собирает, а вот со смывом всей грязи в поддон - не ахти.

sergsap
Offline
Зарегистрирован: 01.12.2012

Andrey_Y_Ostanovsky пишет:

Как это не чем"? Микрокомпрессор с пульверизатором - и будет Вам руль для добавления влажности. Уменьшение - только вентиляцией, хотя, в теории, можно было бы и пельтье приспособить на конденсацию влаги.

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

А просто увлажнитель ИМХО не вариант, будет локально влажность высаживаться, потом мох пойдет расти, за ним тоже уход понадобится )

vworld
vworld аватар
Offline
Зарегистрирован: 26.09.2011

а такая схема вам не подойдет?

maksim
Offline
Зарегистрирован: 12.02.2012

Нет, не подойдет, это всего лишь позиционный регулятор на реле.