#1 2016-02-27 16:50:00

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

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

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

Что мы имеем:

Термометр - народный DS18B20, с залитыми эпоксидным клеем контактами.

Влагомер и доп. термометр - DTH11.

Arduino ProMini в качестве мозга.

LCD 16х2 с I2C контроллером.

2-х канальное реле 5В 10А

Источник https://arduino-ua.com/prod201-2h_kanalnoe_rele_5V_10A

Блок реле с опторазвязкой.


Пищалка пьезо.

#include <PID_v1.h>
#include <Wire.h>
#include "RTClib.h"
#include <LiquidCrystal_I2C.h>
#include <EEPROM2.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <SimpleTimer.h>
#include <avr/wdt.h>
#include "DHT.h"


int del = 80;                     // переменная ожидания между выборами меню
unsigned int interval = 300;      // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)

//#define EXT_HEATING                    // ИСПОЛЬЗУЕМ ДОП.НАГРЕВАТЕЛЬ ВМЕСТО УВЛАЖНИТЕЛЯ. Если нужен увлажнитель, просто закомментируйте эту строку.
#define heater_pin 13                  // нагреватель
#define humidifer_pin 12               // увлажнитель
#define fan_pin 11                     // вентилятор
#define alarm_pin 14                   // пин аварии
#define beeper_pin 9                   //пищалка по аварии
#define turn_pin 10                    // управление поворотом
#define extend_heater_pin 8          // дополнительный нагреватель
#define button_minus_pin 2            //пин кнопки "минус"
#define button_plus_pin 3             //пин кнопки "плюс"
#define button_enter_pin 4            //пин кнопки "enter"
#define DS18B20_Pin 7                 //пин термометра
#define setSampleTime 1000            //время цикла ПИД
#define voltmeter_pin 1               //вход А1 через делитель (22к/10к) подключен к питанию модуля. Измеряет до 16В.
#define T_correction -0.0             // коррекция температуры SHT10
#define h_histeresis 5.0              // гистерезис влажности
#define DHTPIN 5     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)

boolean button_minus;
boolean button_plus;
boolean button_enter;
boolean bottomView = 0;            // флаг индикации нижней строки
float humidity;                    // Влажность
float temp1Ink;                    // Температура DS18B20
float temp2Ink;                    // Температура SHT10
float dewpoint;                    // Точка росы

unsigned int rawData;
unsigned long currentTime;            // задаем переменные для тайминга поворота
unsigned long serialTime; //this will help us know when to talk with processing
unsigned long now;
unsigned long trhMillis = 0;    // период опроса датчиков

const unsigned long TRHSTEP   = 300UL;  // Период опроса датчиков

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
RTC_DS1307 rtc;
OneWire oneWire(DS18B20_Pin);
DallasTemperature sensors(&oneWire);
DHT dht(DHTPIN, DHTTYPE);

double Setpoint, Input, Output;            //объявляем переменные для ПИД
PID myPID(&Input, &Output, &Setpoint, 10000.0, 0.5, 10.5, DIRECT); //Инициализируем ПИД-библиотеку и коэффициенты
int WindowSize = setSampleTime;                  // ширина окна терморегулятора 1 секунда.
unsigned long windowStartTime;
unsigned long alarmDelay;

//SimpleTimer timer;

/*  EEPROM1 -     tempInk (float)
    EEPROM(13) -  set_humidity (float)
    EEPROM5 -     +-alarmTemp (float)
    EEPROM9 -     fanTemp (int)
    EEPROM11 -    turnPeriod (int)         */

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

  lcd.init();          // Старт дисплея
  lcd.backlight();     // Включаем подсветку дисплея
  windowStartTime = millis();
  byte stat;
  byte error = 0;
  float tempInk;
  float set_humidity;
  float alarmTemp;
  rtc.begin();         // Старт часов
  //int fanTemp;
  //int turnPeriod;
  rtc.adjust(DateTime(__DATE__, __TIME__));
  // EEPROM_read(1, tempInk);
  // tempInk = constrain(tempInk, 36.7, 38.7);
  // EEPROM_write(1, tempInk);
  // EEPROM_read(13, set_humidity);
  // set_humidity = constrain(set_humidity, 40.0, 90.0);
  // EEPROM_write(13, set_humidity);
  // EEPROM_read(9, fanTemp);
  // fanTemp = constrain(fanTemp, 38, 39);
  // EEPROM_write(9, fanTemp);
  // EEPROM_read(5, alarmTemp);
  // alarmTemp = constrain(alarmTemp, 1.0, 4.0);
  // EEPROM_write(5, alarmTemp);
  // EEPROM_read(11, turnPeriod);
  // alarmTemp = constrain(turnPeriod, 0, 13);
  // EEPROM_write(11, turnPeriod);
  
  delay(15);
  wdt_enable (WDTO_8S); //взводим сторожевой таймер на 8 секунд.
  myPID.SetOutputLimits(0, WindowSize); //задаем лимиты ширины ПИД-импульса от 0 до 1 секунды.
  myPID.SetMode(AUTOMATIC);             //включаем ПИД-регулирование
  myPID.SetSampleTime(setSampleTime);

  pinMode(extend_heater_pin, OUTPUT);      //пин дополнительного нагревателя. Переводим в 1 чтобы не включать реле.
  digitalWrite(extend_heater_pin, LOW);
  pinMode(heater_pin, OUTPUT);
  pinMode(turn_pin, OUTPUT);      // устанавливаем выводы
  digitalWrite(turn_pin, LOW);
  pinMode(humidifer_pin, OUTPUT);
  pinMode(fan_pin, OUTPUT);
  digitalWrite(fan_pin, LOW);
  pinMode(alarm_pin, OUTPUT);
  digitalWrite(alarm_pin, HIGH);
  pinMode(button_minus_pin, INPUT_PULLUP); //подтягиваем входы кнопок к плюсу встроенными резисторами
  pinMode(button_plus_pin, INPUT_PULLUP);
  pinMode(button_enter_pin, INPUT_PULLUP);
  alarmDelay = millis();
  dht.begin();
  sensors.begin();
  sensors.setResolution(12);    // установить разрешение (точность)
  sensors.setWaitForConversion(false);  // отключить ожидание
  //timer.setInterval(3000, getSensors);
  windowStartTime = millis();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
 
  // Input = getTemp();
  unsigned long now = millis();
 {
 DateTime now = rtc.now();
 lcd.setCursor(11, 0); 
 lcd.print(now.hour(), DEC);
 lcd.print(':');
 lcd.print(now.minute(), DEC);
 }
    


  //timer.run();
  button_read();
  if (!button_enter) {
    delay(del);
    lcd.clear();
    menu();
  }
  if (!button_minus) {
    delay(del);
    lcd.clear();
    alarmDelay = millis();    // задержка аварии по нажатии кнопки Минус
  }
  if (!button_plus) {
    delay(del);
    lcd.clear();
    digitalWrite(turn_pin, !digitalRead(turn_pin));       // включаем/выключаем реле поворота по кнопке Плюс
  }
  if (!button_plus && !button_plus) {
    delay(del);
    lcd.clear();
   // bottomView = !bottomView;       // переключаем режим показа нижней строки.
  }
  //send-receive with processing if it's time
  if (millis() > serialTime)
  {
    SerialReceive();
    SerialSend();
    serialTime += 500;
  }
  getSensors();
  thermostat();
//#ifdef EXT_HEATING
  extend_heater();
//#else
  humidifer();
//#endif
  turn();
  fan();
  alarm();
  //outpuPower();
  wdt_reset();
  //unsigned long now1 = millis();
  //Serial.println(now1-now);
}

///////////////////////////////////////////////////////////////////////////////////////////////
void button_read() {//функция проверки нажатия кнопки
  button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
  button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
  button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
  if (!button_minus || !button_plus || !button_enter) beeper(50);
  wdt_reset();
}

//меню////////////////////////////////////////////////////////////////////////////////////////
void menu() {
  temp_setup();
  hum_setup();
  turn_setup();
  alarm_setup();
  vent_setup();
  //data_time_setup();
}



//устанавливаем температуру в меню///////////////////////////////////////////////////////////
void temp_setup() {
  float tempInk;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(0, 0);
  lcd.print("TEMP.INK SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }
    button_read();
    //EEPROM_write(1, 37.7);
    EEPROM_read(1, tempInk);
    if (!button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (!button_minus) {
      x = 0;
      EEPROM_write(1, tempInk + 0.1);
      if (tempInk > 40) {     //проверяем, если выше 40,
        EEPROM_write(1, 40);  //пишем в память 40
      }
      lcd.clear();
    }

    if (!button_plus) {
      x = 0;
      EEPROM_write(1, tempInk - 0.1);
      if (tempInk < 30.0) {     //проверяем, если выше 30,
        EEPROM_write(1, 30.0);  //пишем в память 30
      }
      lcd.clear();
    }
    lcd.setCursor(0, 0);
    lcd.print("TEMP.INK = ");
    lcd.print(tempInk, 1);
    lcd.setCursor(0, 1);
    lcd.print("minus NEXT plus");
    delay(del);
  }
}


//устанавливаем влажность////////////////////////////////////////////////////////////////////////
void hum_setup() {
  float set_humidity;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(0, 0);
  lcd.print("HUMIDITY SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    //EEPROM_write(13, 65.0);
    //EEPROM_read_mem(13, &set_humidity, sizeof(set_humidity));
    EEPROM_read(13, set_humidity);

    if (!button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (!button_minus) {
      x = 0;
      EEPROM_write(13, set_humidity + 0.5);
      if (set_humidity > 100) {     //проверяем, если выше 40,
        EEPROM_write(13, 100.0);  //пишем в память 40
      }
      lcd.clear();
    }

    if (!button_plus) {
      x = 0;
      EEPROM_write(13, set_humidity - 0.5);
      if (set_humidity < 20) {     //проверяем, если выше 40,
        EEPROM_write(13, 20.0);  //пишем в память 40
      }
      lcd.clear();
    }

    lcd.setCursor(0, 0);
    lcd.print("Humidity = ");
    lcd.print(set_humidity, 1);
    lcd.setCursor(0, 1);
    lcd.print("minus NEXT plus");
    delay(del);
  }

}

//устанавливаем поворот/////////////////////////////////////////////////////////////////////////
void turn_setup() {
  int turnPeriod;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(0, 0);
  lcd.print("TURN SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(11, turnPeriod);

    if (!button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (!button_minus) {
      x = 0;
      EEPROM_write(11, turnPeriod + 1);
      if (turnPeriod > 13) {     //проверяем, если выше 40,
        EEPROM_write(11, 13);  //пишем в память 40
      }
      lcd.clear();
    }

    if (!button_plus) {
      x = 0;
      EEPROM_write(11, turnPeriod - 1);
      if (turnPeriod < 0) {     //проверяем, если выше 40,
        EEPROM_write(11, 0);  //пишем в память 40
      }
      lcd.clear();
    }
    EEPROM_read(11, turnPeriod);
    lcd.setCursor(0, 0);
    lcd.print("PERIOD = ");
    lcd.print(turnPeriod);
    lcd.print(" Hour");
    lcd.setCursor(0, 1);
    lcd.print("minus NEXT plus");
    delay(del);
  }
}


//устанавливаем сигнализацию/////////////////////////////////////////////////////////////////////
void alarm_setup() {
  float alarmTemp;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(0, 0);
  lcd.print("ALARM SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    //EEPROM_write(5, 2.5);
    EEPROM_read(5, alarmTemp);

    if (!button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (!button_minus) {
      x = 0;
      EEPROM_write(5, alarmTemp + 0.1);
      if (alarmTemp > 10.0) {     //проверяем, если ниже 10,
        EEPROM_write(5, 10.0);  //пишем в память 10
      }
      lcd.clear();
    }

    if (!button_plus) {
      x = 0;
      EEPROM_write(5, alarmTemp - 0.1);
      if (alarmTemp < 1.0) {     //проверяем, если выше 40,
        EEPROM_write(5, 1.0);  //пишем в память 40
      }
      lcd.clear();
    }
    lcd.setCursor(0, 0);
    lcd.print("T.Alarm + - ");
    lcd.print(alarmTemp, 1);
    lcd.print((char)223);
    lcd.print("C");
    lcd.setCursor(0, 1);
    lcd.print("minus NEXT plus");
    delay(del);
  }
}

//устанавливаем вентиляцию/////////////////////////////////////////////////////////////////
void vent_setup() {
  int fanTemp;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(0, 0);
  lcd.print("FAN SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(9, fanTemp);

    if (!button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (!button_minus) {
      x = 0;
      EEPROM_write(9, fanTemp + 1);
      if (fanTemp > 40) {     //проверяем, если выше 40,
        EEPROM_write(9, 40);  //пишем в память 40
      }
      lcd.clear();
    }

    if (!button_plus) {
      x = 0;
      EEPROM_write(9, fanTemp - 1);
      if (fanTemp < 20) {     //проверяем, если выше 40,
        EEPROM_write(9, 20);  //пишем в память 40
      }
      lcd.clear();
    }
    lcd.setCursor(0, 0);
    lcd.print("T.Fan = ");
    lcd.print(fanTemp);
    lcd.print((char)223);
    lcd.print("C");
    lcd.setCursor(0, 1);
    lcd.print("minus NEXT plus");
    delay(del);
  }
}

/////////////////////////////////////////////////////////////////////////////////////////////////
void getSensors() {

  unsigned long curMillis = millis();          // Получаем текущее время работы
  if (curMillis - trhMillis >= TRHSTEP) {    // время для нового измерения?
    sensors.requestTemperatures();
    temp1Ink = sensors.getTempCByIndex(0);
  }

   if (curMillis - trhMillis >= TRHSTEP * 4) {    // время для нового измерения?
    temp2Ink = dht.readTemperature();
    temp2Ink = (temp2Ink + (T_correction)); // Корректируем показания текрмометра
    humidity = dht.readHumidity();
    trhMillis = curMillis;
  }
  // logData();
}


//////////////////////////////////////////////////////////////////////////////////////////////////
//void logData() {
//  Serial.print("temp1Ink = ");
//  Serial.print(temp1Ink);
//  Serial.print("temp2Ink = ");
//  Serial.print(temp2Ink);
//  Serial.print(" C, Humidity = ");
//  Serial.print(humidity);
//  Serial.print(" %, Dewpoint = ");
//  Serial.print(dewpoint);
//  Serial.println(" C");
//}



//используем терморегулятор
void thermostat() {
  now = millis();
  float tempPoint;
  float set_humidity;
  EEPROM_read_mem(1, &tempPoint, sizeof(tempPoint));
  EEPROM_read(1, tempPoint);
  EEPROM_read_mem(13, &set_humidity, sizeof(set_humidity));
  EEPROM_read(13, set_humidity);
  Setpoint = tempPoint;
  myPID.Compute();


  if (now - windowStartTime > WindowSize) { //время для перещелкивания периода окна
    windowStartTime = windowStartTime + WindowSize;
    voltmeter();                        //запускаем функцию измерения напряжения
    Input = temp1Ink;
    lcd.setCursor(0, 0);                 // устанавливаем курсор в 0-ом столбце, 0 строка (начинается с 0)
    lcd.print("T");
    lcd.print(temp1Ink, 1);              // печать температуры на дисплей
    //lcd.print((char)223);
    //lcd.print("  (");
    //lcd.print(Setpoint, 1);
    //lcd.print(")");
    lcd.setCursor(5, 0);
    lcd.print("T");
    lcd.print(temp2Ink, 1);            // печать температуры на дисплей
    //lcd.print((char)223);
    //lcd.setCursor(12, 0);
    //lcd.print(" ");
    //lcd.print(temp1Ink - temp2Ink, 1);
    //lcd.print(" ");
    //lcd.print((char)223);
    //lcd.print("  (");
    //lcd.print(Setpoint, 1);
    //lcd.print(")");
    lcd.setCursor(0, 1);                 // устанавливаем курсор в 2-ом столбце, 3 строка (начинается с 0)
    lcd.print("H");
    lcd.print(humidity, 1);           // печать влажности на дисплей
    
    
  }
  if (Output > (now - windowStartTime)) digitalWrite(heater_pin, HIGH);
  else digitalWrite(heater_pin, LOW);

}

//управляем влажностью/////////////////////////////////////////////////////////////////////////
void humidifer() {
  //float humidity;
  float set_humidity;
  //  if (curMillis - humMillis >= humStep) {
  //    humMillis = curMillis;
  //    //humidity = sht1x.readHumidity();
  //  }
  //EEPROM_read_mem(13, &set_humidity, sizeof(set_humidity));
  EEPROM_read(13, set_humidity);
  if (set_humidity > humidity) digitalWrite(humidifer_pin, HIGH); //сравниваем измеренную влажность с заданной
  lcd.setCursor(5, 1);
  lcd.print("#");//вывод инфо состояния на LCD
  if (set_humidity < humidity + h_histeresis) digitalWrite(humidifer_pin, LOW);
  lcd.setCursor(5, 1);
  lcd.print("-");//вывод инфо состояния
}

//управляем поворотом//////////////////////////////////////////////////////////////////////////
void turn() {
  int turnPeriod;                //период поворота лотков в часах
  int turnCommand;
  boolean turnFlag = 0;          // флаг поворота для случайного периода
  static unsigned long loopTime;
  EEPROM_read(11, turnPeriod);
  if (turnPeriod == 0) return;           //если нулевой период поворота, то не поворачиваем яйца.
  if (turnPeriod < 13) turnCommand = turnPeriod;
  else if (turnPeriod > 12 && turnFlag == 0) { //если произошел поворот (сброшен флаг) и значение в памяти 13, то
    turnCommand = random(1, 6);        //берем случайное значение часов 1-6
    turnFlag = 1;                     //защелкиваем флаг вычисления случайных значений до следующего поворота
  }
  currentTime = millis()/1000;
  //lcd.setCursor(6, 1);
  //lcd.print("P");
  Serial.println(currentTime);
  Serial.println(loopTime + turnCommand * 3600UL);
  if (currentTime > (loopTime + turnCommand * 3600UL)) {  // 3600000 сравниваем текущий таймер с переменной loopTime + период поворота в часах.
    digitalWrite(turn_pin, !digitalRead(turn_pin));       // включаем/выключаем реле поворота
    loopTime = currentTime;    // в loopTime записываем новое значение
    turnFlag = 0;    //сбрасываем флаг поворота
  }
  //lcd.print((loopTime - currentTime + turnCommand * 3600UL) / 60UL);
  //lcd.print(" ");
}

//управляем авариями/////////////////////////////////////////////////////////////////////////////
void alarm() {
  float tempInk = sensors.getTempCByIndex(0);
  float alarmTemp;
  float setTemp;
  EEPROM_read(5, alarmTemp);
  EEPROM_read_mem(1, &setTemp, sizeof(setTemp));
  EEPROM_read(1, setTemp);
  //lcd.setCursor(0, 3);
  //lcd.print("A");
  //lcd.print(setTemp + alarmTemp, 1);
  if ((millis() - alarmDelay) > 1800000) {
    if (tempInk > (setTemp + alarmTemp) || tempInk < (setTemp - alarmTemp)) {
      beeper(10);
      digitalWrite(alarm_pin, LOW); //если измеренная температура выше заданной на величину аварии
    }
    else digitalWrite(alarm_pin, HIGH); //то включаем аварийный сигнал.
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
void beeper(int duration) {
  tone(beeper_pin, 2000, duration);
}


//управляем вентиляторами////////////////////////////////////////////////////////////////////////////
void fan() {
  //float tempInk = sht1x.readTemperatureC();
  int fanTemp;
  EEPROM_read(9, fanTemp);
  //lcd.setCursor(6, 3);
  //lcd.print("F");
  //lcd.print(fanTemp);
  if (temp1Ink > fanTemp) digitalWrite(fan_pin, HIGH); //если измеренная температура выше заданной на величину аварии
  else digitalWrite(fan_pin, LOW); //то включаем аварийный сигнал.

}

// вольтметр/////////////////////////////////////////////////////////////////////////////////////////
void voltmeter() {
  float outputValue = 0;
  outputValue = float(analogRead(voltmeter_pin)) / 63, 9;
  //if(outputValue < 4.5) beeper(50);
  //Serial.print("Voltage = " );
  //Serial.println(outputValue);
  lcd.setCursor(6, 1);
  lcd.print("V");
  lcd.print(outputValue, 1);
}

// Печать мощности нагрвателя///////////////////////////////////////////////////////////////////////
void outpuPower() {
  //lcd.setCursor(15, 3);
  //lcd.print("W");
  //lcd.print(Output, 0);
  //lcd.print(" ");
}

void extend_heater() { // управление допnnnnnnnnnnm,.kkkолнительным нагревателем на 8 ножке через блок реле.///////////
  float tempInk = sensors.getTempCByIndex(0);
  float setTemp;
  EEPROM_read_mem(1, &setTemp, sizeof(setTemp));
  EEPROM_read(1, setTemp);
  if (tempInk < (setTemp - 3)) //{
    digitalWrite(extend_heater_pin, HIGH);
//#ifdef EXT_HEATING
    //digitalWrite(humidifer_pin, LOW);
//#endif
  //}
  else digitalWrite(extend_heater_pin, LOW);
//#ifdef EXT_HEATING
  //digitalWrite(humidifer_pin, HIGH);
//#endif
}

/********************************************
* Serial Communication functions / helpers
********************************************/


union {                // This Data structure lets
  byte asBytes[24];    // us take the byte array
  float asFloat[6];    // sent from processing and
}                      // easily convert it to a
foo;                   // float array



// getting float values from processing into the arduino
// was no small task.  the way this program does it is
// as follows:
//  * a float takes up 4 bytes.  in processing, convert
//    the array of floats we want to send, into an array
//    of bytes.
//  * send the bytes to the arduino
//  * use a data structure known as a union to convert
//    the array of bytes back into an array of floats

//  the bytes coming from the arduino follow the following
//  format:
//  0: 0=Manual, 1=Auto, else = ? error ?
//  1: 0=Direct, 1=Reverse, else = ? error ?
//  2-5: float setpoint
//  6-9: float input
//  10-13: float output
//  14-17: float P_Param
//  18-21: float I_Param
//  22-245: float D_Param

///////////////////////////////////////////////////////////////////////////////////////////////////
void SerialReceive(){
  // read the bytes sent from Processing
  int index = 0;
  byte Auto_Man = -1;
  byte Direct_Reverse = -1;
  while (Serial.available() && index < 26){
    if (index == 0) Auto_Man = Serial.read();
    else if (index == 1) Direct_Reverse = Serial.read();
    else foo.asBytes[index - 2] = Serial.read();
    index++;
  }

  // if the information we got was in the correct format,
  // read it into the system
  if (index == 26  && (Auto_Man == 0 || Auto_Man == 1) && (Direct_Reverse == 0 || Direct_Reverse == 1))
  {
    Setpoint = double(foo.asFloat[0]);
    //Input=double(foo.asFloat[1]);       // * the user has the ability to send the
    //   value of "Input"  in most cases (as
    //   in this one) this is not needed.
    if (Auto_Man == 0)                    // * only change the output if we are in
    { //   manual mode.  otherwise we'll get an
      Output = double(foo.asFloat[2]);    //   output blip, then the controller will
    }                                     //   overwrite.

    double p, i, d;                       // * read in and set the controller tunings
    p = double(foo.asFloat[3]);           //
    i = double(foo.asFloat[4]);           //
    d = double(foo.asFloat[5]);           //
    myPID.SetTunings(p, i, d);            //

    if (Auto_Man == 0) myPID.SetMode(MANUAL); // * set the controller mode
    else myPID.SetMode(AUTOMATIC);             //

    if (Direct_Reverse == 0) myPID.SetControllerDirection(DIRECT); // * set the controller Direction
    else myPID.SetControllerDirection(REVERSE);          //
  }
  Serial.flush();                         // * clear any random data from the serial buffer
}


///////////////////////////////////////////////////////////////////////////////////////////////
void SerialSend(){
  Serial.print(millis() / 1000);
  Serial.print("PID ");
  Serial.print(Setpoint);
  Serial.print(" ");
  Serial.print(Input);
  Serial.print(" ");
  Serial.print(Output);
  Serial.print(" ");
  Serial.print(myPID.GetKp());
  Serial.print(" ");
  Serial.print(myPID.GetKi());
  Serial.print(" ");
  Serial.print(myPID.GetKd());
  Serial.print(" ");
  if (myPID.GetMode() == AUTOMATIC) Serial.print("Automatic");
  else Serial.print("Manual");
  Serial.print(" ");
  if (myPID.GetDirection() == DIRECT) Serial.println("Direct");
  else Serial.println("Reverse");
}

Остання редакція Dima (2016-03-15 15:16:37)

Неактивний

#2 2016-02-27 18:45:21

alex_dol
Учасник
Зареєстрований: 2015-12-28
Повідомлень: 196

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

А с какого форума вы взяли данный материал?

Неактивний

#3 2016-02-28 13:27:31

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

alex_dol пише:

А с какого форума вы взяли данный материал?

вы с какой целью интересуетесь?

Неактивний

#4 2016-02-28 14:24:01

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Dima, а что Umka  говорит? 
попросите его переделать )

Неактивний

#5 2016-02-28 17:29:28

alex_dol
Учасник
Зареєстрований: 2015-12-28
Повідомлень: 196

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Себе делаю инкубатор, но я делаю по другому принципу - из меню будет выбираться вид птицы, все остальное инкубатор будет делать сам.
Чтоб вместо SHT10 поставить DTH11 надо менять библиотеку - у них протоколы разные.
Глянул скетч - измерения встречаются в нескольких функциях. Попросите автора, а то могут быть подводные камни.

Неактивний

#6 2016-02-29 14:48:54

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

NoName пише:

Dima, а что Umka  говорит? 
попросите его переделать )

ни че там никто не говорит форум по ходу умер

Неактивний

#7 2016-02-29 14:51:08

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Чтоб вместо SHT10 поставить DTH11 надо менять библиотеку - у них протоколы разные.
это я понял
просто не знаю в каких строках надо сменить слова, и на какие

Неактивний

#8 2016-03-01 21:16:13

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Поскольку я в теме третий год, сразу советую DHT22 (да дорого но он того стоит) датчиков DS18B20 должно быть минимум два.  Датчики ни в коем случае не заливать в эпоксидку и пр. В третьих часы ну очень желательны (да и стоят не дорого). От ШИМ отказался сразу, при испытательном прогоне. Если делать инкубатор серьезный, а самая сложная для него птица, не поверите- гусь! Сразу возникает очень сложная техническая проблема влажность 80% при 37.5С. Вентиляция, нагрев это все ерунда, решается просто. И самое главное разброс "народного" DS, для него +/- 0,2 это в порядке вещей. Готовьтесь приобрести термометр лабораторный типа ТЛ для калибровки lol . Сразу скажу программу здесь не смотрел, судить не буду. Первый инкубатор был сделан на 140 гусиных яиц (четыре лотка), переделывался 2 раза  lol . Выводной инкубатор переделывал всего один раз (уже был опыт  lol ). На подходе на 300  cool И поверьте, не все просто с DS, особенно если он стоит в "потоке" от вентилятора  big_smile . Короче подводных камней столько, что программа не главное, можно сказать последнее smile .

Неактивний

#9 2016-03-02 17:11:03

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Nefreemen пише:

Поскольку я в теме третий год, сразу советую DHT22 (да дорого но он того стоит) датчиков DS18B20 должно быть минимум два.  Датчики ни в коем случае не заливать в эпоксидку и пр. В третьих часы ну очень желательны (да и стоят не дорого). От ШИМ отказался сразу, при испытательном прогоне. Если делать инкубатор серьезный, а самая сложная для него птица, не поверите- гусь! Сразу возникает очень сложная техническая проблема влажность 80% при 37.5С. Вентиляция, нагрев это все ерунда, решается просто. И самое главное разброс "народного" DS, для него +/- 0,2 это в порядке вещей. Готовьтесь приобрести термометр лабораторный типа ТЛ для калибровки lol . Сразу скажу программу здесь не смотрел, судить не буду. Первый инкубатор был сделан на 140 гусиных яиц (четыре лотка), переделывался 2 раза  lol . Выводной инкубатор переделывал всего один раз (уже был опыт  lol ). На подходе на 300  cool И поверьте, не все просто с DS, особенно если он стоит в "потоке" от вентилятора  big_smile . Короче подводных камней столько, что программа не главное, можно сказать последнее smile .


я понимаю что вы умник философ
а на практике человеку помочь не, а?

советчиков много
ноя прошу не советы по датчику DHT22
а по DHT11
и че куда вписать а не философию разводить и пиар
мол дельный совет дал а я не хочу его
выполнять

Остання редакція Dima (2016-03-02 17:14:37)

Неактивний

#10 2016-03-02 17:16:09

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Nefreemen пише:

Поскольку я в теме третий год, сразу советую DHT22 (да дорого но он того стоит) датчиков DS18B20 должно быть минимум два.  Датчики ни в коем случае не заливать в эпоксидку и пр. В третьих часы ну очень желательны (да и стоят не дорого). От ШИМ отказался сразу, при испытательном прогоне. Если делать инкубатор серьезный, а самая сложная для него птица, не поверите- гусь! Сразу возникает очень сложная техническая проблема влажность 80% при 37.5С. Вентиляция, нагрев это все ерунда, решается просто. И самое главное разброс "народного" DS, для него +/- 0,2 это в порядке вещей. Готовьтесь приобрести термометр лабораторный типа ТЛ для калибровки lol . Сразу скажу программу здесь не смотрел, судить не буду. Первый инкубатор был сделан на 140 гусиных яиц (четыре лотка), переделывался 2 раза  lol . Выводной инкубатор переделывал всего один раз (уже был опыт  lol ). На подходе на 300  cool И поверьте, не все просто с DS, особенно если он стоит в "потоке" от вентилятора  big_smile . Короче подводных камней столько, что программа не главное, можно сказать последнее smile .

а скечь где?
благодарю за помощь
но не в тему

Остання редакція Dima (2016-03-02 17:17:40)

Неактивний

#11 2016-03-02 18:12:01

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

щас буду ругаться!
итак Дима купил по некой причине непрописанный DHT11,  и теперь все таки хочет его подключить, что б деньгу не выкидывать
бывают и повеселее варианты )

Дима, вы зря так,   Nefreemen   понаступал уже на грабли, и дал понять где Вы наступите, его софт без конструкторской документации  особо вам не поможет.

Nefreemen сколько термометров использовали?

Неактивний

#12 2016-03-02 18:35:12

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

NoName пише:

щас буду ругаться!
итак Дима купил по некой причине непрописанный DHT11,  и теперь все таки хочет его подключить, что б деньгу не выкидывать
бывают и повеселее варианты )

Дима, вы зря так,   Nefreemen   понаступал уже на грабли, и дал понять где Вы наступите, его софт без конструкторской документации  особо вам не поможет.

Nefreemen сколько термометров использовали?

вот и я о том нет бы делом помочь начинают датчики гадить

мне dth11 нужен для измерения влаги если че
а основной дс18в20
инкубатор пробный если че
размеры: ширина55   высота60 глубина28

Неактивний

#13 2016-03-02 18:44:08

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Dima, инкубатор я видел только в детстве  и то с лампочкой в углу )
но если по науке, и нет  желания разбираться   - повторите чужое,

у меня есть "ТАКОЙ КОД", что можно врагу скинуть, а я за это буду в аду гореть ) код не главное,
алгоритм превыше всего для таких проектов, любая помощь "по граблям" это здорово.
у вас есть хоть что то работающее?   или все пока на этапе прототипа?

Неактивний

#14 2016-03-02 22:11:44

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Я извиняюсь, если кто то меня неправильно понял. Я ни в коем случае не хаю программу. И поверьте пиар мне совершенно не нужен. Вы не услышали главное, любой даже самый примитивный  в "мыльнице" термостат будет выполнять свою функцию. И вопрос не в программе, будут ли  навороты типа пид, вольтметр и пр (на кой тот вольтметр на каком то аккумуляторе если 220 нет lol?). Я говорю совершенно о другом, о том что с точки зрения моего опыта  не хватает этому термостату с претензией на "умный" (читай универсальный) и я думаю что и программа написана хорошо и работает (мне даже не интересно ее смотреть) важен функционал. Вопрос для меня очевиден, и в другом, для серьезного инкубатора его мало, для "коробочки" он лишний. Делать термостат для "пенопластовой коробочки" типа "наседка" и пр. но только с "моторчиком" тогда нет вопросов...А написано: "Устройство собрано и проверено. Заказал изготовление плат в Китае, на повестке дня тестирование в реальном инкубаторе. Естественно функционал будет добавляться." Следовательно речь идет о серии. Так вот если предвидится серийное производство, я и высказал то чего не хватает этому термостату. Хотите протестировать - пожалуйста, нет вопросов, только на чем? На пенопластовой коробочке? Тогда на кой пень этой коробочке вентилятор? Зачем мерить влажность, если изменить ее проблема? Я начинал с таких вот "коробочек", и могу сказать следующее, если нужно вывести цыплята дешево и сердито, идем в магазин и покупаем "коробочку", выбрасываем кондесаторный блок питания с электронного регулятора, лепим свой и все, и не паримся ( к стати посмотрите цену на т-стат Лана и прикиньте свою, а для коробочки и цыплят его хватает, разве что "моторчика нет big_smile ). Если речь идет о "серьезном" инкубаторе где уже как минимум два лотка этажеркой и предвидится вывод водоплавающей птицы то тут два пути или делается инкубатор и ТОЛЬКО ПОСЛЕ садимся и точим "железо" и программу, или сначала делается ну очень я бы сказал "гибкий" термостат со множеством настроек типа изменения дельт температур, поправочных коэффициентов и кучей датчиков. Почему да потому что в "больших" ящиках все не так просто, нужен продув нагревательного элемента где то начиная от 220 куб.м. в час,  и этот нагреватель как и вентилятор должен быть как бы "снаружи" ( ремонтно- пригодным, не затрагивая камеру инкубатора), температуру выходящего воздуха нагревателя нужно контролировать (1 датчик smile ), температуру вверху над лотками тоже ( +1 датч. smile ). Изменение (повышение) влажности - кювета с теплой водой (ТЭН, вентилятор над кюветой) +1датчик smile + датчик уровня воды smile .(всякие ультразвуковые увлажнители не катят проверено). Ну и датчик влажности (бонус еще имеем термометр). Это только все в общих чертах, не считая технических ньюансов типа экранов на датчики DS (иначе их показания прыгают как бешенные), поворотный механизм - концевики  smile Ну наконец делаем выводы, самый простой - количество лап про мини как то маловато hmm . Я когда первый раз столкнулся с проблемами сразу поменял на Атмегу32 ( а тоже была про мини). Некоторые давай скетч lol. Да нет проблем, могу выложить только зачем? Он сам по себе не представляет ни интереса ни ценности да еще садится и писать коментарии - зря тратить время . Сделаете инкубатор  и увидите что то что подходит мне, совершенно не подходит вам...

Неактивний

#15 2016-03-03 01:52:14

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Никогда не снимал роликов. Но специально для Dima снял  lol . Задело. Извиняюсь за оговорки, типа графический экран назвал символьный и др. Адрес видео
https://youtu.be/RivhKxGiPfE

Неактивний

#16 2016-03-12 13:26:49

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

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

Неактивний

#17 2016-03-12 13:47:43

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Dima пише:
#include <PID_v1.h>
#include <Wire.h>
#include "RTClib.h"
#include <LiquidCrystal_I2C.h>
#include <EEPROM2.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <SimpleTimer.h>
#include <avr/wdt.h>
#include "DHT.h"


int del = 80;                     // переменная ожидания между выборами меню
unsigned int interval = 300;      // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)

//#define EXT_HEATING                    // ИСПОЛЬЗУЕМ ДОП.НАГРЕВАТЕЛЬ ВМЕСТО УВЛАЖНИТЕЛЯ. Если нужен увлажнитель, просто закомментируйте эту строку.
#define heater_pin 13                  // нагреватель
#define humidifer_pin 12               // увлажнитель
#define fan_pin 11                     // вентилятор
#define alarm_pin 14                   // пин аварии
#define beeper_pin 9                   //пищалка по аварии
#define turn_pin 10                    // управление поворотом
#define extend_heater_pin 8          // дополнительный нагреватель
#define button_minus_pin 2            //пин кнопки "минус"
#define button_plus_pin 3             //пин кнопки "плюс"
#define button_enter_pin 4            //пин кнопки "enter"
#define DS18B20_Pin 7                 //пин термометра
#define setSampleTime 1000            //время цикла ПИД
#define voltmeter_pin 1               //вход А1 через делитель (22к/10к) подключен к питанию модуля. Измеряет до 16В.
#define T_correction -0.0             // коррекция температуры SHT10
#define h_histeresis 5.0              // гистерезис влажности
#define DHTPIN 5     // what pin we're connected to
#define DHTTYPE DHT11   // DHT 22  (AM2302)

boolean button_minus;
boolean button_plus;
boolean button_enter;
boolean bottomView = 0;            // флаг индикации нижней строки
float humidity;                    // Влажность
float temp1Ink;                    // Температура DS18B20
float temp2Ink;                    // Температура SHT10
float dewpoint;                    // Точка росы

unsigned int rawData;
unsigned long currentTime;            // задаем переменные для тайминга поворота
unsigned long serialTime; //this will help us know when to talk with processing
unsigned long now;
unsigned long trhMillis = 0;    // период опроса датчиков

const unsigned long TRHSTEP   = 300UL;  // Период опроса датчиков

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
RTC_DS1307 rtc;
OneWire oneWire(DS18B20_Pin);
DallasTemperature sensors(&oneWire);
DHT dht(DHTPIN, DHTTYPE);

double Setpoint, Input, Output;            //объявляем переменные для ПИД
PID myPID(&Input, &Output, &Setpoint, 10000.0, 0.5, 10.5, DIRECT); //Инициализируем ПИД-библиотеку и коэффициенты
int WindowSize = setSampleTime;                  // ширина окна терморегулятора 1 секунда.
unsigned long windowStartTime;
unsigned long alarmDelay;

//SimpleTimer timer;

/*  EEPROM1 -     tempInk (float)
    EEPROM(13) -  set_humidity (float)
    EEPROM5 -     +-alarmTemp (float)
    EEPROM9 -     fanTemp (int)
    EEPROM11 -    turnPeriod (int)         */

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

  lcd.init();          // Старт дисплея
  lcd.backlight();     // Включаем подсветку дисплея
  windowStartTime = millis();
  byte stat;
  byte error = 0;
  float tempInk;
  float set_humidity;
  float alarmTemp;
  rtc.begin();         // Старт часов
  //int fanTemp;
  //int turnPeriod;
  rtc.adjust(DateTime(__DATE__, __TIME__));
  // EEPROM_read(1, tempInk);
  // tempInk = constrain(tempInk, 36.7, 38.7);
  // EEPROM_write(1, tempInk);
  // EEPROM_read(13, set_humidity);
  // set_humidity = constrain(set_humidity, 40.0, 90.0);
  // EEPROM_write(13, set_humidity);
  // EEPROM_read(9, fanTemp);
  // fanTemp = constrain(fanTemp, 38, 39);
  // EEPROM_write(9, fanTemp);
  // EEPROM_read(5, alarmTemp);
  // alarmTemp = constrain(alarmTemp, 1.0, 4.0);
  // EEPROM_write(5, alarmTemp);
  // EEPROM_read(11, turnPeriod);
  // alarmTemp = constrain(turnPeriod, 0, 13);
  // EEPROM_write(11, turnPeriod);
  
  delay(15);
  wdt_enable (WDTO_8S); //взводим сторожевой таймер на 8 секунд.
  myPID.SetOutputLimits(0, WindowSize); //задаем лимиты ширины ПИД-импульса от 0 до 1 секунды.
  myPID.SetMode(AUTOMATIC);             //включаем ПИД-регулирование
  myPID.SetSampleTime(setSampleTime);

  pinMode(extend_heater_pin, OUTPUT);      //пин дополнительного нагревателя. Переводим в 1 чтобы не включать реле.
  digitalWrite(extend_heater_pin, LOW);
  pinMode(heater_pin, OUTPUT);
  pinMode(turn_pin, OUTPUT);      // устанавливаем выводы
  digitalWrite(turn_pin, LOW);
  pinMode(humidifer_pin, OUTPUT);
  pinMode(fan_pin, OUTPUT);
  digitalWrite(fan_pin, LOW);
  pinMode(alarm_pin, OUTPUT);
  digitalWrite(alarm_pin, HIGH);
  pinMode(button_minus_pin, INPUT_PULLUP); //подтягиваем входы кнопок к плюсу встроенными резисторами
  pinMode(button_plus_pin, INPUT_PULLUP);
  pinMode(button_enter_pin, INPUT_PULLUP);
  alarmDelay = millis();
  dht.begin();
  sensors.begin();
  sensors.setResolution(12);    // установить разрешение (точность)
  sensors.setWaitForConversion(false);  // отключить ожидание
  //timer.setInterval(3000, getSensors);
  windowStartTime = millis();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
 
  // Input = getTemp();
  unsigned long now = millis();
 {
 DateTime now = rtc.now();
 lcd.setCursor(11, 0); 
 lcd.print(now.hour(), DEC);
 lcd.print(':');
 lcd.print(now.minute(), DEC);
 }
    


  //timer.run();
  button_read();
  if (!button_enter) {
    delay(del);
    lcd.clear();
    menu();
  }
  if (!button_minus) {
    delay(del);
    lcd.clear();
    alarmDelay = millis();    // задержка аварии по нажатии кнопки Минус
  }
  if (!button_plus) {
    delay(del);
    lcd.clear();
    digitalWrite(turn_pin, !digitalRead(turn_pin));       // включаем/выключаем реле поворота по кнопке Плюс
  }
  if (!button_plus && !button_plus) {
    delay(del);
    lcd.clear();
   // bottomView = !bottomView;       // переключаем режим показа нижней строки.
  }
  //send-receive with processing if it's time
  if (millis() > serialTime)
  {
    SerialReceive();
    SerialSend();
    serialTime += 500;
  }
  getSensors();
  thermostat();
//#ifdef EXT_HEATING
  extend_heater();
//#else
  humidifer();
//#endif
  turn();
  fan();
  alarm();
  //outpuPower();
  wdt_reset();
  //unsigned long now1 = millis();
  //Serial.println(now1-now);
}

///////////////////////////////////////////////////////////////////////////////////////////////
void button_read() {//функция проверки нажатия кнопки
  button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
  button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
  button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
  if (!button_minus || !button_plus || !button_enter) beeper(50);
  wdt_reset();
}

//меню////////////////////////////////////////////////////////////////////////////////////////
void menu() {
  temp_setup();
  hum_setup();
  turn_setup();
  alarm_setup();
  vent_setup();
  //data_time_setup();
}



//устанавливаем температуру в меню///////////////////////////////////////////////////////////
void temp_setup() {
  float tempInk;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(0, 0);
  lcd.print("TEMP.INK SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }
    button_read();
    //EEPROM_write(1, 37.7);
    EEPROM_read(1, tempInk);
    if (!button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (!button_minus) {
      x = 0;
      EEPROM_write(1, tempInk + 0.1);
      if (tempInk > 40) {     //проверяем, если выше 40,
        EEPROM_write(1, 40);  //пишем в память 40
      }
      lcd.clear();
    }

    if (!button_plus) {
      x = 0;
      EEPROM_write(1, tempInk - 0.1);
      if (tempInk < 30.0) {     //проверяем, если выше 30,
        EEPROM_write(1, 30.0);  //пишем в память 30
      }
      lcd.clear();
    }
    lcd.setCursor(0, 0);
    lcd.print("TEMP.INK = ");
    lcd.print(tempInk, 1);
    lcd.setCursor(0, 1);
    lcd.print("minus NEXT plus");
    delay(del);
  }
}


//устанавливаем влажность////////////////////////////////////////////////////////////////////////
void hum_setup() {
  float set_humidity;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(0, 0);
  lcd.print("HUMIDITY SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    //EEPROM_write(13, 65.0);
    //EEPROM_read_mem(13, &set_humidity, sizeof(set_humidity));
    EEPROM_read(13, set_humidity);

    if (!button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (!button_minus) {
      x = 0;
      EEPROM_write(13, set_humidity + 0.5);
      if (set_humidity > 100) {     //проверяем, если выше 40,
        EEPROM_write(13, 100.0);  //пишем в память 40
      }
      lcd.clear();
    }

    if (!button_plus) {
      x = 0;
      EEPROM_write(13, set_humidity - 0.5);
      if (set_humidity < 20) {     //проверяем, если выше 40,
        EEPROM_write(13, 20.0);  //пишем в память 40
      }
      lcd.clear();
    }

    lcd.setCursor(0, 0);
    lcd.print("Humidity = ");
    lcd.print(set_humidity, 1);
    lcd.setCursor(0, 1);
    lcd.print("minus NEXT plus");
    delay(del);
  }

}

//устанавливаем поворот/////////////////////////////////////////////////////////////////////////
void turn_setup() {
  int turnPeriod;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(0, 0);
  lcd.print("TURN SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(11, turnPeriod);

    if (!button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (!button_minus) {
      x = 0;
      EEPROM_write(11, turnPeriod + 1);
      if (turnPeriod > 13) {     //проверяем, если выше 40,
        EEPROM_write(11, 13);  //пишем в память 40
      }
      lcd.clear();
    }

    if (!button_plus) {
      x = 0;
      EEPROM_write(11, turnPeriod - 1);
      if (turnPeriod < 0) {     //проверяем, если выше 40,
        EEPROM_write(11, 0);  //пишем в память 40
      }
      lcd.clear();
    }
    EEPROM_read(11, turnPeriod);
    lcd.setCursor(0, 0);
    lcd.print("PERIOD = ");
    lcd.print(turnPeriod);
    lcd.print(" Hour");
    lcd.setCursor(0, 1);
    lcd.print("minus NEXT plus");
    delay(del);
  }
}


//устанавливаем сигнализацию/////////////////////////////////////////////////////////////////////
void alarm_setup() {
  float alarmTemp;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(0, 0);
  lcd.print("ALARM SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    //EEPROM_write(5, 2.5);
    EEPROM_read(5, alarmTemp);

    if (!button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (!button_minus) {
      x = 0;
      EEPROM_write(5, alarmTemp + 0.1);
      if (alarmTemp > 10.0) {     //проверяем, если ниже 10,
        EEPROM_write(5, 10.0);  //пишем в память 10
      }
      lcd.clear();
    }

    if (!button_plus) {
      x = 0;
      EEPROM_write(5, alarmTemp - 0.1);
      if (alarmTemp < 1.0) {     //проверяем, если выше 40,
        EEPROM_write(5, 1.0);  //пишем в память 40
      }
      lcd.clear();
    }
    lcd.setCursor(0, 0);
    lcd.print("T.Alarm + - ");
    lcd.print(alarmTemp, 1);
    lcd.print((char)223);
    lcd.print("C");
    lcd.setCursor(0, 1);
    lcd.print("minus NEXT plus");
    delay(del);
  }
}

//устанавливаем вентиляцию/////////////////////////////////////////////////////////////////
void vent_setup() {
  int fanTemp;
  lcd.clear();
  delay(del);
  button_read();
  lcd.setCursor(0, 0);
  lcd.print("FAN SETUP");
  delay(1000);
  int x = 0;
  while (1) {
    x++;
    if (x > interval) {
      break;
    }

    button_read();
    EEPROM_read(9, fanTemp);

    if (!button_enter) {
      delay(del);
      lcd.clear(); //очищаем экран
      break;
    }
    if (!button_minus) {
      x = 0;
      EEPROM_write(9, fanTemp + 1);
      if (fanTemp > 40) {     //проверяем, если выше 40,
        EEPROM_write(9, 40);  //пишем в память 40
      }
      lcd.clear();
    }

    if (!button_plus) {
      x = 0;
      EEPROM_write(9, fanTemp - 1);
      if (fanTemp < 20) {     //проверяем, если выше 40,
        EEPROM_write(9, 20);  //пишем в память 40
      }
      lcd.clear();
    }
    lcd.setCursor(0, 0);
    lcd.print("T.Fan = ");
    lcd.print(fanTemp);
    lcd.print((char)223);
    lcd.print("C");
    lcd.setCursor(0, 1);
    lcd.print("minus NEXT plus");
    delay(del);
  }
}

/////////////////////////////////////////////////////////////////////////////////////////////////
void getSensors() {

  unsigned long curMillis = millis();          // Получаем текущее время работы
  if (curMillis - trhMillis >= TRHSTEP) {    // время для нового измерения?
    sensors.requestTemperatures();
    temp1Ink = sensors.getTempCByIndex(0);
  }

   if (curMillis - trhMillis >= TRHSTEP * 4) {    // время для нового измерения?
    temp2Ink = dht.readTemperature();
//    temp2Ink = (temp2Ink + (T_correction)); // Корректируем показания текрмометра
    humidity = dht.readHumidity();
    trhMillis = curMillis;
  }
  // logData();
}


//////////////////////////////////////////////////////////////////////////////////////////////////
//void logData() {
//  Serial.print("temp1Ink = ");
//  Serial.print(temp1Ink);
//  Serial.print("temp2Ink = ");
//  Serial.print(temp2Ink);
//  Serial.print(" C, Humidity = ");
//  Serial.print(humidity);
//  Serial.print(" %, Dewpoint = ");
//  Serial.print(dewpoint);
//  Serial.println(" C");
//}



//используем терморегулятор
void thermostat() {
  now = millis();
  float tempPoint;
  float set_humidity;
  EEPROM_read_mem(1, &tempPoint, sizeof(tempPoint));
  EEPROM_read(1, tempPoint);
  EEPROM_read_mem(13, &set_humidity, sizeof(set_humidity));
  EEPROM_read(13, set_humidity);
  Setpoint = tempPoint;
  myPID.Compute();


  if (now - windowStartTime > WindowSize) { //время для перещелкивания периода окна
    windowStartTime = windowStartTime + WindowSize;
    voltmeter();                        //запускаем функцию измерения напряжения
    Input = temp1Ink;
    lcd.setCursor(0, 0);                 // устанавливаем курсор в 0-ом столбце, 0 строка (начинается с 0)
    lcd.print("T");
    lcd.print(temp1Ink, 1);              // печать температуры на дисплей
    //lcd.print((char)223);
    //lcd.print("  (");
    //lcd.print(Setpoint, 1);
    //lcd.print(")");
    lcd.setCursor(5, 0);
    lcd.print("T");
    lcd.print(temp2Ink, 1);            // печать температуры на дисплей
    //lcd.print((char)223);
    //lcd.setCursor(12, 0);
    //lcd.print(" ");
    //lcd.print(temp1Ink - temp2Ink, 1);
    //lcd.print(" ");
    //lcd.print((char)223);
    //lcd.print("  (");
    //lcd.print(Setpoint, 1);
    //lcd.print(")");
    lcd.setCursor(0, 1);                 // устанавливаем курсор в 2-ом столбце, 3 строка (начинается с 0)
    lcd.print("H");
    lcd.print(humidity, 1);           // печать влажности на дисплей
    
    
  }
  if (Output > (now - windowStartTime)) digitalWrite(heater_pin, HIGH);
  else digitalWrite(heater_pin, LOW);

}

//управляем влажностью/////////////////////////////////////////////////////////////////////////
void humidifer() {
  //float humidity;
  float set_humidity;
  //  if (curMillis - humMillis >= humStep) {
  //    humMillis = curMillis;
  //    //humidity = sht1x.readHumidity();
  //  }
  //EEPROM_read_mem(13, &set_humidity, sizeof(set_humidity));
  EEPROM_read(13, set_humidity);
  if (set_humidity > humidity) digitalWrite(humidifer_pin, HIGH); //сравниваем измеренную влажность с заданной
  lcd.setCursor(5, 1);
  lcd.print("#");//вывод инфо состояния на LCD
//  if (set_humidity < humidity + h_histeresis) digitalWrite(humidifer_pin, LOW);
  lcd.setCursor(5, 1);
  lcd.print("-");//вывод инфо состояния
}

//управляем поворотом//////////////////////////////////////////////////////////////////////////
void turn() {
  int turnPeriod;                //период поворота лотков в часах
  int turnCommand;
  boolean turnFlag = 0;          // флаг поворота для случайного периода
  static unsigned long loopTime;
  EEPROM_read(11, turnPeriod);
  if (turnPeriod == 0) return;           //если нулевой период поворота, то не поворачиваем яйца.
  if (turnPeriod < 13) turnCommand = turnPeriod;
  else if (turnPeriod > 12 && turnFlag == 0) { //если произошел поворот (сброшен флаг) и значение в памяти 13, то
    turnCommand = random(1, 6);        //берем случайное значение часов 1-6
    turnFlag = 1;                     //защелкиваем флаг вычисления случайных значений до следующего поворота
  }
  currentTime = millis()/1000;
  //lcd.setCursor(6, 1);
  //lcd.print("P");
  Serial.println(currentTime);
  Serial.println(loopTime + turnCommand * 3600UL);
  if (currentTime > (loopTime + turnCommand * 3600UL)) {  // 3600000 сравниваем текущий таймер с переменной loopTime + период поворота в часах.
    digitalWrite(turn_pin, !digitalRead(turn_pin));       // включаем/выключаем реле поворота
    loopTime = currentTime;    // в loopTime записываем новое значение
    turnFlag = 0;    //сбрасываем флаг поворота
  }
  //lcd.print((loopTime - currentTime + turnCommand * 3600UL) / 60UL);
  //lcd.print(" ");
}

//управляем авариями/////////////////////////////////////////////////////////////////////////////
void alarm() {
  float tempInk = sensors.getTempCByIndex(0);
  float alarmTemp;
  float setTemp;
  EEPROM_read(5, alarmTemp);
  EEPROM_read_mem(1, &setTemp, sizeof(setTemp));
  EEPROM_read(1, setTemp);
  //lcd.setCursor(0, 3);
  //lcd.print("A");
  //lcd.print(setTemp + alarmTemp, 1);
  if ((millis() - alarmDelay) > 1800000) {
    if (tempInk > (setTemp + alarmTemp) || tempInk < (setTemp - alarmTemp)) {
      beeper(10);
      digitalWrite(alarm_pin, LOW); //если измеренная температура выше заданной на величину аварии
    }
    else digitalWrite(alarm_pin, HIGH); //то включаем аварийный сигнал.
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
void beeper(int duration) {
  tone(beeper_pin, 2000, duration);
}


//управляем вентиляторами////////////////////////////////////////////////////////////////////////////
void fan() {
  //float tempInk = sht1x.readTemperatureC();
  int fanTemp;
  EEPROM_read(9, fanTemp);
  //lcd.setCursor(6, 3);
  //lcd.print("F");
  //lcd.print(fanTemp);
  if (temp1Ink > fanTemp) digitalWrite(fan_pin, HIGH); //если измеренная температура выше заданной на величину аварии
  else digitalWrite(fan_pin, LOW); //то включаем аварийный сигнал.

}

// вольтметр/////////////////////////////////////////////////////////////////////////////////////////
void voltmeter() {
  float outputValue = 0;
  outputValue = float(analogRead(voltmeter_pin)) / 63, 9;
  //if(outputValue < 4.5) beeper(50);
  //Serial.print("Voltage = " );
  //Serial.println(outputValue);
  lcd.setCursor(6, 1);
  lcd.print("V");
  lcd.print(outputValue, 1);
}

// Печать мощности нагрвателя///////////////////////////////////////////////////////////////////////
void outpuPower() {
  //lcd.setCursor(15, 3);
  //lcd.print("W");
  //lcd.print(Output, 0);
  //lcd.print(" ");
}

void extend_heater() { // управление допnnnnnnnnnnm,.kkkолнительным нагревателем на 8 ножке через блок реле.///////////
  float tempInk = sensors.getTempCByIndex(0);
  float setTemp;
  EEPROM_read_mem(1, &setTemp, sizeof(setTemp));
  EEPROM_read(1, setTemp);
  if (tempInk < (setTemp - 3)) //{
    digitalWrite(extend_heater_pin, HIGH);
//#ifdef EXT_HEATING
    //digitalWrite(humidifer_pin, LOW);
//#endif
  //}
  else digitalWrite(extend_heater_pin, LOW);
//#ifdef EXT_HEATING
  //digitalWrite(humidifer_pin, HIGH);
//#endif
}

/********************************************
* Serial Communication functions / helpers
********************************************/


union {                // This Data structure lets
  byte asBytes[24];    // us take the byte array
  float asFloat[6];    // sent from processing and
}                      // easily convert it to a
foo;                   // float array



// getting float values from processing into the arduino
// was no small task.  the way this program does it is
// as follows:
//  * a float takes up 4 bytes.  in processing, convert
//    the array of floats we want to send, into an array
//    of bytes.
//  * send the bytes to the arduino
//  * use a data structure known as a union to convert
//    the array of bytes back into an array of floats

//  the bytes coming from the arduino follow the following
//  format:
//  0: 0=Manual, 1=Auto, else = ? error ?
//  1: 0=Direct, 1=Reverse, else = ? error ?
//  2-5: float setpoint
//  6-9: float input
//  10-13: float output
//  14-17: float P_Param
//  18-21: float I_Param
//  22-245: float D_Param

///////////////////////////////////////////////////////////////////////////////////////////////////
void SerialReceive(){
  // read the bytes sent from Processing
  int index = 0;
  byte Auto_Man = -1;
  byte Direct_Reverse = -1;
  while (Serial.available() && index < 26){
    if (index == 0) Auto_Man = Serial.read();
    else if (index == 1) Direct_Reverse = Serial.read();
    else foo.asBytes[index - 2] = Serial.read();
    index++;
  }

  // if the information we got was in the correct format,
  // read it into the system
  if (index == 26  && (Auto_Man == 0 || Auto_Man == 1) && (Direct_Reverse == 0 || Direct_Reverse == 1))
  {
    Setpoint = double(foo.asFloat[0]);
    //Input=double(foo.asFloat[1]);       // * the user has the ability to send the
    //   value of "Input"  in most cases (as
    //   in this one) this is not needed.
    if (Auto_Man == 0)                    // * only change the output if we are in
    { //   manual mode.  otherwise we'll get an
      Output = double(foo.asFloat[2]);    //   output blip, then the controller will
    }                                     //   overwrite.

    double p, i, d;                       // * read in and set the controller tunings
    p = double(foo.asFloat[3]);           //
    i = double(foo.asFloat[4]);           //
    d = double(foo.asFloat[5]);           //
    myPID.SetTunings(p, i, d);            //

    if (Auto_Man == 0) myPID.SetMode(MANUAL); // * set the controller mode
    else myPID.SetMode(AUTOMATIC);             //

    if (Direct_Reverse == 0) myPID.SetControllerDirection(DIRECT); // * set the controller Direction
    else myPID.SetControllerDirection(REVERSE);          //
  }
  Serial.flush();                         // * clear any random data from the serial buffer
}


///////////////////////////////////////////////////////////////////////////////////////////////
void SerialSend(){
  Serial.print(millis() / 1000);
  Serial.print("PID ");
  Serial.print(Setpoint);
  Serial.print(" ");
  Serial.print(Input);
  Serial.print(" ");
  Serial.print(Output);
  Serial.print(" ");
  Serial.print(myPID.GetKp());
  Serial.print(" ");
  Serial.print(myPID.GetKi());
  Serial.print(" ");
  Serial.print(myPID.GetKd());
  Serial.print(" ");
  if (myPID.GetMode() == AUTOMATIC) Serial.print("Automatic");
  else Serial.print("Manual");
  Serial.print(" ");
  if (myPID.GetDirection() == DIRECT) Serial.println("Direct");
  else Serial.println("Reverse");
}

вот нашел новый код только не пойму почему
горит постоянно #define alarm_pin 14                   // пин аварии
и подскажите правильно ли я понял что он находится на пин А0
и вольтметр показывает ерунду почему то от пк 3,3 вольта

Неактивний

#18 2016-03-12 13:54:19

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

только хотел похвалить  кто ищет то найдет )

Search "alarm_pin" (5 hits in 1 file)
  new 1 (5 hits)
    Line 20: #define alarm_pin 14                   // пин аварии
    Line 118:   pinMode(alarm_pin, OUTPUT);
    Line 119:   digitalWrite(alarm_pin, HIGH);
    Line 615:       digitalWrite(alarm_pin, LOW); //если измеренная температура выше заданной на величину аварии
    Line 617:     else digitalWrite(alarm_pin, HIGH); //то включаем аварийный сигнал.


  if ((millis() - alarmDelay) > 1800000) {
    if (tempInk > (setTemp + alarmTemp) || tempInk < (setTemp - alarmTemp)) {
      beeper(10);
      digitalWrite(alarm_pin, LOW); //если измеренная температура выше заданной на величину аварии
    }
    else digitalWrite(alarm_pin, HIGH); //то включаем аварийный сигнал.



    Line 68:     EEPROM5 -     +-alarmTemp (float)
    Line 83:   float alarmTemp;
    Line 97:   // EEPROM_read(5, alarmTemp);
    Line 98:   // alarmTemp = constrain(alarmTemp, 1.0, 4.0);
    Line 98:   // alarmTemp = constrain(alarmTemp, 1.0, 4.0);
    Line 99:   // EEPROM_write(5, alarmTemp);
    Line 101:   // alarmTemp = constrain(turnPeriod, 0, 13);
    Line 372:   float alarmTemp;
    Line 388:     EEPROM_read(5, alarmTemp);
    Line 397:       EEPROM_write(5, alarmTemp + 0.1);
    Line 398:       if (alarmTemp > 10.0) {     //проверяем, если ниже 10,
    Line 406:       EEPROM_write(5, alarmTemp - 0.1);
    Line 407:       if (alarmTemp < 1.0) {     //проверяем, если выше 40,
    Line 414:     lcd.print(alarmTemp, 1);
    Line 604:   float alarmTemp;
    Line 606:   EEPROM_read(5, alarmTemp);
    Line 611:   //lcd.print(setTemp + alarmTemp, 1);
    Line 613:     if (tempInk > (setTemp + alarmTemp) || tempInk < (setTemp - alarmTemp)) {
    Line 613:     if (tempInk > (setTemp + alarmTemp) || tempInk < (setTemp - alarmTemp)) {


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

разработка устройств, это тоже типа работа )

Неактивний

#19 2016-03-12 18:21:58

alex_dol
Учасник
Зареєстрований: 2015-12-28
Повідомлень: 196

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Ну если простой инкубатор, то вам вполне подойдет мой скетч. Делался на быструю руку для пластмассовой коробки объемом 125 л. Все работает - проверенно. Что непонятно спрашивайте.
heater_hi в 2 раза мощнее heater_low, итого получаем 4-х ступенчатую регулировку, в результате максимальное отклонение от заданной температуры у меня не превышало 0,125 С. Увлажнитель - вентилятор дующий на емкость с водой. Автоматического переворота нет, может быть допишу на досуге. Все настройки задаются в скетче.
З.Ы. Насчет watchdogа - я не знаю будет ли ваша плата корректно обрабатывать срабатывание watchdogа, это зависит от используемого проца и бутлоадера. Я не использую бутлоадер - делаю экспорт бинарного файла, затем заливаю программатором через ISP, старт без бутлоадера. Если будете использовать бутлоадер почитайте это, если не боитесь зависания - просто закоментируйте строки касающиеся watchdogа.

#include <avr/wdt.h>
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <SimpleDHT.h>
//если много ошибок датчика DHT:
//SimpleDHT.h -> строка 98 -> delayMicroseconds(10); уменьшить значение до 9 или 8, результат delayMicroseconds(9);~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#define heater_pin_low    0   //пин нагревателя малой мощности
#define heater_pin_hi     1   //пин нагревателя большой мощности
#define DS18B20_Pin       2   //пин термометра
#define DHT11_pin         3   //пин влажности и температуры
#define beeper_pin       10   //пин подключения пищалки
#define humidity_pin     11   //пин подключения увлажнителя

#define opros          5000   //интервал опроса датчиков, 2*5=10 сек

#define set_temperature     37.53 //заданая температура в инкубаторе, C
#define set_humidity          60   //заданая влажность в инкубаторе, %
#define max_humidity        80
#define min_humidity         50
#define max_temperature   38.5
#define min_temterature    36.5
#define max_delta_temp      3  //максимальная разница между показаниями датчиков, C

float DS1820_temp;     //температурв измереная с датчика DS18B20, C
float DS1820_temp_old; //температура предыдущего измерения с датчика DS18B20, C
byte DHT11_temp;   //температура измеренная с датчика DHT11, C
byte DHT11_hum;    //влажность измеренная с датчика DHT11, %
byte DHT11_Error = 0;  //счетчик ошибок датчика DHT11
byte DS1820_Error = 0; //счетчик ошибок датчика DS1820
boolean Sensor_Error = false; //флаг ошибки датчиков
boolean StartFlag = true; //флаг начального запуска, сбрасывается когда контролируемые параметры достигнут нужных значений
byte Heater = 2; //индекс мощности нагревателя, 0-3

//для DS1820
byte addr[8];
byte data[12];

LiquidCrystal lcd(9, 8, 7, 6, 5, 4); //Создаём объект LCD-дисплея, указываем, к каким пинам Arduino подключены выводы дисплея: RS, E, DB4, DB5, DB6, DB7
OneWire ds(DS18B20_Pin);
SimpleDHT11 dht11;

void setup()
{
  wdt_disable();       //выключаем watchdog (на случай перезагрузки по watchdog)
  wdt_enable(WDTO_8S); //включаем на 8 секунд

  pinMode(heater_pin_low, OUTPUT);
  pinMode(heater_pin_hi, OUTPUT);
  pinMode(humidity_pin, OUTPUT);
  digitalWrite(heater_pin_low, LOW);
  digitalWrite(heater_pin_hi, LOW);
  digitalWrite(humidity_pin, LOW);
  if ( !ds.search(addr)) Sensor_Error = true; //датчик не найден
  if (OneWire::crc8(addr, 7) != addr[7]) Sensor_Error = true; //ошибка crc

  lcd.begin(24, 2);
  lcd.print("DS t=");
  lcd.setCursor(11, 0);
  lcd.print(">");
  lcd.print(set_temperature, 2);
  lcd.print("< H=");
  lcd.setCursor(0, 1);
  lcd.print("DHTt=");
  lcd.setCursor(8, 1);
  lcd.print("h=");
  lcd.setCursor(13, 1);
  lcd.print(">");
  lcd.print(set_humidity);
  lcd.print("< Err=");
}

void loop() //------------------------------------------------------------------------------------------
{
  wdt_reset();  //сбрасываем watchdog

  GetSensors(); //получаем значения с датчиков
  Thermostat(); //корректируем мощность нагревателя
  Alarm();      //проверка корректности параметров
  Display();    //отображение данных на дисплее

  delay(opros); //задержка 5 сек
  wdt_reset();  //сбрасываем watchdog
  if (StartFlag) tone(beeper_pin, 4000, 200); //звук раз в 10 сек пока контролируемые параметры не придут в норму
  delay(opros); //задержка 5 сек
  wdt_reset();  //сбрасываем watchdog

}

// Процедура считывания температуры и влажности с датчиков----------------------------------------------
void GetSensors()
{
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1); //запуск конвертации
  delay(1000);       // maybe 750ms is enough, maybe not
  ds.reset();
  ds.select(addr);
  ds.write(0xBE);    // Read Scratchpad
  for ( byte i = 0; i < 9; i++) data[i] = ds.read();
  DS1820_temp_old = DS1820_temp;  //запоминаем предыдущую температуру
  DS1820_temp = ((data[1] << 8) | data[0]) / 16.0; //температура, С

  if (dht11.read(DHT11_pin, &DHT11_temp, &DHT11_hum, NULL))
  {
    DHT11_Error++;
    if (DHT11_Error > 5) Sensor_Error = true;
  }
  else DHT11_Error = 0;
}

//Процедура регулирования температуры и влажности-------------------------------------------------------
void Thermostat()
{
  //прогноз нужен потому что система обладает инерцией
  DS1820_temp_old = DS1820_temp + DS1820_temp - DS1820_temp_old; //вычисляем прогноз температуры для следующего измерения
  if (DS1820_temp_old > set_temperature)
  {
    if (Heater > 0)  Heater--;//если прогноз больше установленной температуры - уменьшаем мощность нагревателя
  }
  else
  {
    if (Heater < 3)  Heater++;
  }

  DS1820_temp_old = DS1820_temp - set_temperature;
  if (DS1820_temp_old > 0.14) Heater = 0; //1 шаг измерения = 0,0625: (2 шага=0,125 < 0,14 < 3 шага=0,1875), если температура больше заданной на 2 шага - выключаем нагреватель
  if (DS1820_temp_old < -0.14) Heater = 3; //1 шаг измерения = 0,0625: (2 шага=0,125 < 0,14 < 3 шага=0,1875), если температура меньше заданной на 2 шага - включаем нагреватель

  switch (Heater) {
    case 0:
      digitalWrite(heater_pin_low, LOW);
      digitalWrite(heater_pin_hi, LOW);
      break;
    case 1:
      digitalWrite(heater_pin_low, HIGH);
      digitalWrite(heater_pin_hi, LOW);
      break;
    case 2:
      digitalWrite(heater_pin_low, LOW);
      digitalWrite(heater_pin_hi, HIGH);
      break;
    case 3:
      digitalWrite(heater_pin_low, HIGH);
      digitalWrite(heater_pin_hi, HIGH);
      break;
  }

  if (DHT11_hum > set_humidity) digitalWrite(humidity_pin, LOW);
  else digitalWrite(humidity_pin, HIGH);
}

//управляем авариями------------------------------------------------------------------------------------
void Alarm()
{
  boolean alarm_flag = false; //флаг выхода контролируемых параметров за допустимые пределы
  word delta;

  noTone(beeper_pin); //выключаем сигнал об аварии
  delta = abs(DS1820_temp - DHT11_temp); //вычисляем разницу показаний температуры с датчиков
  if ( delta > max_delta_temp ) Sensor_Error = true; //проверяем разницу между показаниями температуры с датчиков
  if (DHT11_hum > max_humidity) alarm_flag = true;        //проверяем выход контролируемых параметров за допустимые пределы
  if (DHT11_hum < min_humidity) alarm_flag = true;
  if (DS1820_temp > max_temperature) alarm_flag = true;
  if (DS1820_temp < min_temterature) alarm_flag = true;
  if (alarm_flag && StartFlag)
  {
    alarm_flag = false; //если был старт и параметры еще не вошли в норму сбрасываем флаг выхода контролируемых параметров за допустимые пределы
    Sensor_Error = false;
  }
  else StartFlag = false;                         // иначе сбрасываем флаг старта
  if (alarm_flag || Sensor_Error) tone(beeper_pin, 4000);
}

//Процедура вывода информации на дисплей----------------------------------------------------------------
void Display()
{
  lcd.setCursor(5, 0);
  lcd.print(DS1820_temp, 2);
  lcd.setCursor(21, 0);
  lcd.print(Heater);
  lcd.setCursor(5, 1);
  lcd.print(DHT11_temp);
  lcd.setCursor(10, 1);
  lcd.print(DHT11_hum);
  lcd.setCursor(22, 1);
  lcd.print(DHT11_Error);
}

Остання редакція alex_dol (2016-03-12 18:24:43)

Неактивний

#20 2016-03-12 19:11:41

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

а,как переворот лотков сделать
в вашем скетче

Неактивний

#21 2016-03-12 19:25:45

alex_dol
Учасник
Зареєстрований: 2015-12-28
Повідомлень: 196

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Проще всего использовать функцию millis() и по прошествии n-го числа миллисекунд дергать каким-то пином.

Неактивний

#22 2016-03-12 19:37:41

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

alex_dol пише:

Проще всего использовать функцию millis() и по прошествии n-го числа миллисекунд дергать каким-то пином.


у меня не получилось я использовал функцию millis()
для сервопривода он срабатывал когда ему хотелось

Неактивний

#23 2016-03-14 11:57:17

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

Вот вот, milis() будет обновляться каждый раз при перезагрузке контроллера что не есть гуд. Поэтому я и рекомендовал часики, цена вопроса на аукро от 35 грн. Dima, если по электронике мне все понятно: про мини +дшт11+ds18b20+дисплей 2004, то по в части механики (переворот) и влажности у меня вопрос как Вы это видите? Я спрашиваю потому что может я "адаптирую" свой скетч под Ваши нужды. По идее изменять не много, единственно вопрос по сигнализации аварии какие параметры включать. Да забыл, еще вопрос по нагревателю, что Вы хотите использовать лампы (что не очень хорошо), тепловой шнур (для такого объема идеальный вариант) или воздушный тэн с вентилятором?

Остання редакція Nefreemen (2016-03-14 11:59:07)

Неактивний

#24 2016-03-15 11:54:25

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

https://arduino-ua.com/prod406-Draiver_ … i_na_L298N
                    +
HP LaserJet 4ml 4L 4P Main DC Printer Motor RG5 0765 MSCM048A50 4 Pin
                    +
https://arduino-ua.com/prod166-Arduino_Nano_ATmega328
                    +
https://arduino-ua.com/prod22-Real_Time … dyl_DS1307
                    +
https://arduino-ua.com/prod201-2h_kanalnoe_rele_5V_10A
                    +
дшт11+ds18b20+дисплей 20*16 и есть 2004
вот эти вещи у меня имеются в наличии

по в части механики (переворот) и влажности у меня вопрос как Вы это видите?

с помощью шаговика или сервы переворот каждые 2-3 часа

влажность как-то не думал об этом


вопрос по нагревателю, что Вы хотите использовать лампы

да для начала лампы накал. если все получится  попробую сделать тен на 12в

если что неправильно написал поправьте пожалуйста
а вот про аварию я не совсем понимаю так как с такими вещами столкнулся в первые

Неактивний

#25 2016-03-15 12:43:29

Dima
Учасник
Зареєстрований: 2016-01-13
Повідомлень: 46

Re: ПОМОГИТЕ ПОСТАВИТЬ ТОЧКИ НАД И

alex_dol пише:

Ну если простой инкубатор, то вам вполне подойдет мой скетч. Делался на быструю руку для пластмассовой коробки объемом 125 л. Все работает - проверенно. Что непонятно спрашивайте.
heater_hi в 2 раза мощнее heater_low, итого получаем 4-х ступенчатую регулировку, в результате максимальное отклонение от заданной температуры у меня не превышало 0,125 С. Увлажнитель - вентилятор дующий на емкость с водой. Автоматического переворота нет, может быть допишу на досуге. Все настройки задаются в скетче.
З.Ы. Насчет watchdogа - я не знаю будет ли ваша плата корректно обрабатывать срабатывание watchdogа, это зависит от используемого проца и бутлоадера. Я не использую бутлоадер - делаю экспорт бинарного файла, затем заливаю программатором через ISP, старт без бутлоадера. Если будете использовать бутлоадер почитайте это, если не боитесь зависания - просто закоментируйте строки касающиеся watchdogа.

#include <avr/wdt.h>
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <SimpleDHT.h>
//если много ошибок датчика DHT:
//SimpleDHT.h -> строка 98 -> delayMicroseconds(10); уменьшить значение до 9 или 8, результат delayMicroseconds(9);~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#define heater_pin_low    0   //пин нагревателя малой мощности
#define heater_pin_hi     1   //пин нагревателя большой мощности
#define DS18B20_Pin       2   //пин термометра
#define DHT11_pin         3   //пин влажности и температуры
#define beeper_pin       10   //пин подключения пищалки
#define humidity_pin     11   //пин подключения увлажнителя

#define opros          5000   //интервал опроса датчиков, 2*5=10 сек

#define set_temperature     37.53 //заданая температура в инкубаторе, C
#define set_humidity          60   //заданая влажность в инкубаторе, %
#define max_humidity        80
#define min_humidity         50
#define max_temperature   38.5
#define min_temterature    36.5
#define max_delta_temp      3  //максимальная разница между показаниями датчиков, C

float DS1820_temp;     //температурв измереная с датчика DS18B20, C
float DS1820_temp_old; //температура предыдущего измерения с датчика DS18B20, C
byte DHT11_temp;   //температура измеренная с датчика DHT11, C
byte DHT11_hum;    //влажность измеренная с датчика DHT11, %
byte DHT11_Error = 0;  //счетчик ошибок датчика DHT11
byte DS1820_Error = 0; //счетчик ошибок датчика DS1820
boolean Sensor_Error = false; //флаг ошибки датчиков
boolean StartFlag = true; //флаг начального запуска, сбрасывается когда контролируемые параметры достигнут нужных значений
byte Heater = 2; //индекс мощности нагревателя, 0-3

//для DS1820
byte addr[8];
byte data[12];

LiquidCrystal lcd(9, 8, 7, 6, 5, 4); //Создаём объект LCD-дисплея, указываем, к каким пинам Arduino подключены выводы дисплея: RS, E, DB4, DB5, DB6, DB7
OneWire ds(DS18B20_Pin);
SimpleDHT11 dht11;

void setup()
{
  wdt_disable();       //выключаем watchdog (на случай перезагрузки по watchdog)
  wdt_enable(WDTO_8S); //включаем на 8 секунд

  pinMode(heater_pin_low, OUTPUT);
  pinMode(heater_pin_hi, OUTPUT);
  pinMode(humidity_pin, OUTPUT);
  digitalWrite(heater_pin_low, LOW);
  digitalWrite(heater_pin_hi, LOW);
  digitalWrite(humidity_pin, LOW);
  if ( !ds.search(addr)) Sensor_Error = true; //датчик не найден
  if (OneWire::crc8(addr, 7) != addr[7]) Sensor_Error = true; //ошибка crc

  lcd.begin(24, 2);
  lcd.print("DS t=");
  lcd.setCursor(11, 0);
  lcd.print(">");
  lcd.print(set_temperature, 2);
  lcd.print("< H=");
  lcd.setCursor(0, 1);
  lcd.print("DHTt=");
  lcd.setCursor(8, 1);
  lcd.print("h=");
  lcd.setCursor(13, 1);
  lcd.print(">");
  lcd.print(set_humidity);
  lcd.print("< Err=");
}

void loop() //------------------------------------------------------------------------------------------
{
  wdt_reset();  //сбрасываем watchdog

  GetSensors(); //получаем значения с датчиков
  Thermostat(); //корректируем мощность нагревателя
  Alarm();      //проверка корректности параметров
  Display();    //отображение данных на дисплее

  delay(opros); //задержка 5 сек
  wdt_reset();  //сбрасываем watchdog
  if (StartFlag) tone(beeper_pin, 4000, 200); //звук раз в 10 сек пока контролируемые параметры не придут в норму
  delay(opros); //задержка 5 сек
  wdt_reset();  //сбрасываем watchdog

}

// Процедура считывания температуры и влажности с датчиков----------------------------------------------
void GetSensors()
{
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1); //запуск конвертации
  delay(1000);       // maybe 750ms is enough, maybe not
  ds.reset();
  ds.select(addr);
  ds.write(0xBE);    // Read Scratchpad
  for ( byte i = 0; i < 9; i++) data[i] = ds.read();
  DS1820_temp_old = DS1820_temp;  //запоминаем предыдущую температуру
  DS1820_temp = ((data[1] << 8) | data[0]) / 16.0; //температура, С

  if (dht11.read(DHT11_pin, &DHT11_temp, &DHT11_hum, NULL))
  {
    DHT11_Error++;
    if (DHT11_Error > 5) Sensor_Error = true;
  }
  else DHT11_Error = 0;
}

//Процедура регулирования температуры и влажности-------------------------------------------------------
void Thermostat()
{
  //прогноз нужен потому что система обладает инерцией
  DS1820_temp_old = DS1820_temp + DS1820_temp - DS1820_temp_old; //вычисляем прогноз температуры для следующего измерения
  if (DS1820_temp_old > set_temperature)
  {
    if (Heater > 0)  Heater--;//если прогноз больше установленной температуры - уменьшаем мощность нагревателя
  }
  else
  {
    if (Heater < 3)  Heater++;
  }

  DS1820_temp_old = DS1820_temp - set_temperature;
  if (DS1820_temp_old > 0.14) Heater = 0; //1 шаг измерения = 0,0625: (2 шага=0,125 < 0,14 < 3 шага=0,1875), если температура больше заданной на 2 шага - выключаем нагреватель
  if (DS1820_temp_old < -0.14) Heater = 3; //1 шаг измерения = 0,0625: (2 шага=0,125 < 0,14 < 3 шага=0,1875), если температура меньше заданной на 2 шага - включаем нагреватель

  switch (Heater) {
    case 0:
      digitalWrite(heater_pin_low, LOW);
      digitalWrite(heater_pin_hi, LOW);
      break;
    case 1:
      digitalWrite(heater_pin_low, HIGH);
      digitalWrite(heater_pin_hi, LOW);
      break;
    case 2:
      digitalWrite(heater_pin_low, LOW);
      digitalWrite(heater_pin_hi, HIGH);
      break;
    case 3:
      digitalWrite(heater_pin_low, HIGH);
      digitalWrite(heater_pin_hi, HIGH);
      break;
  }

  if (DHT11_hum > set_humidity) digitalWrite(humidity_pin, LOW);
  else digitalWrite(humidity_pin, HIGH);
}

//управляем авариями------------------------------------------------------------------------------------
void Alarm()
{
  boolean alarm_flag = false; //флаг выхода контролируемых параметров за допустимые пределы
  word delta;

  noTone(beeper_pin); //выключаем сигнал об аварии
  delta = abs(DS1820_temp - DHT11_temp); //вычисляем разницу показаний температуры с датчиков
  if ( delta > max_delta_temp ) Sensor_Error = true; //проверяем разницу между показаниями температуры с датчиков
  if (DHT11_hum > max_humidity) alarm_flag = true;        //проверяем выход контролируемых параметров за допустимые пределы
  if (DHT11_hum < min_humidity) alarm_flag = true;
  if (DS1820_temp > max_temperature) alarm_flag = true;
  if (DS1820_temp < min_temterature) alarm_flag = true;
  if (alarm_flag && StartFlag)
  {
    alarm_flag = false; //если был старт и параметры еще не вошли в норму сбрасываем флаг выхода контролируемых параметров за допустимые пределы
    Sensor_Error = false;
  }
  else StartFlag = false;                         // иначе сбрасываем флаг старта
  if (alarm_flag || Sensor_Error) tone(beeper_pin, 4000);
}

//Процедура вывода информации на дисплей----------------------------------------------------------------
void Display()
{
  lcd.setCursor(5, 0);
  lcd.print(DS1820_temp, 2);
  lcd.setCursor(21, 0);
  lcd.print(Heater);
  lcd.setCursor(5, 1);
  lcd.print(DHT11_temp);
  lcd.setCursor(10, 1);
  lcd.print(DHT11_hum);
  lcd.setCursor(22, 1);
  lcd.print(DHT11_Error);
}

ваш код не компилируется по ходу на библиотеку жалуется
у меня версия иде 1.6.6
искал в сети не нашел точно такой библиотеки #include <SimpleDHT.h>
у меня просто #include <DHT.h>

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму