1 2 3 4 5 6 7 8 9 10 10/10 9,84оценок: 31

Ракетный котел - 2

Тема в разделе "Котлы, горелки, котельное об-е своими руками", создана пользователем Perelesnik, 19.07.17.

Статус темы:
Закрыта.
  1. Royal257
    Регистрация:
    24.10.16
    Сообщения:
    75
    Благодарности:
    30

    Royal257

    Живу здесь

    Royal257

    Живу здесь

    Регистрация:
    24.10.16
    Сообщения:
    75
    Благодарности:
    30
    Адрес:
    Россия, Ярославль
    @Perelesnik, надеюсь эту зиму котел так же хорошо отработал, не доставляя проблем, что даже писать было не чего :).

    Как там планы с комплектами труб? Керамическая мастерская все еще существует?
     
  2. Perelesnik
    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616

    Perelesnik

    Живу здесь

    Perelesnik

    Живу здесь

    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616
    Адрес:
    Черкассы
    Добра! Я пока весь в авиационных делах. Поэтому сюда заглядываю очень редко. По керамике будем что-то решать к лету. Материал (глина, шамот и так далее) есть, формы есть, по обжигу, думаю, тоже решим.
    Пока ничего никому не обещаю, список заказов не собираю.
    Когда начнется "движение", сообщу здесь.
    Тогда и составлю план действий по керамике.

    Не писал сюда, так как уже всё написал, добавить больше и нечего по сути.
     
  3. alarin
    Регистрация:
    29.07.16
    Сообщения:
    8.662
    Благодарности:
    3.751

    alarin

    Живу здесь

    alarin

    Живу здесь

    Регистрация:
    29.07.16
    Сообщения:
    8.662
    Благодарности:
    3.751
    Адрес:
    Казахстан, Алма-Ата
    Керамическая мастерская жива в Алма-Ате. По кладочному раствору и клею открылась в Москве.
     
  4. Royal257
    Регистрация:
    24.10.16
    Сообщения:
    75
    Благодарности:
    30

    Royal257

    Живу здесь

    Royal257

    Живу здесь

    Регистрация:
    24.10.16
    Сообщения:
    75
    Благодарности:
    30
    Адрес:
    Россия, Ярославль
    Про Алма-Ату я помню :), этот вариант тоже прорабатывается.
    Сделать подобный котел конечно хочется, но пока возник вопрос целесообразности водяного отопления для нас. Наброски сделаны и взята пауза, заодно и по керамике что то решится.

    Вот что надо сделать в этом сезоне, так это в бане печь новую сложить.
     
  5. Perelesnik
    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616

    Perelesnik

    Живу здесь

    Perelesnik

    Живу здесь

    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616
    Адрес:
    Черкассы
    Всем добра и тепла!

    Мало кто такое делает, а я сделаю :)

    В общем, вот все коды контроллера в финальном релизе:

    Главный контроллер:

    Код:
    #define INTERVAL_GET_DATA 1000  // интервала измерений, мс
    #define DS18B20PIN 23           // пин подключения контакта DATA
    #include <OneWire.h>
    
    #include "U8glib.h"
    #include <TimerOne.h>
    #include <Button.h>
    #include <EEPROM.h>
    
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    
    #include <SdFat.h>
    //#include <PID_v1.h>
    
    OneWire ds(DS18B20PIN); // подключаем "далласы"
    
    int speakerPin = 5;  // выход на динамик
    
    float spid; // готовый угол поворота сервы с ПИД регуляятора
    int rizerdiff; // динамическая разница температуры в райзере
    int rizerdiffflag; // флаг замера температуры райзера для динамики
    float riserpretemp; // Предыдущая температура в райзере
    float tempdeficite; // недостающие градусы по воде
    
    int Primsec; // счетчик секунд для динамики пераметров вычисления первички
    
    float     D_forv_water ;
    float     P_forv_water ;
    float     D_riser ;
    float     P_riser ;
    float     D_bunker ;
    float     P_bunker ;
    float     preservoprim;
    float     D_preservoprim;
    float     P_preservoprim;
    float     workservoprim;
    float     servoprim_speed = 0.25;
    byte  Tflag;
    
    unsigned long millis_int1 = 0; // переменная для таймера "далласов"
    float temp; // данные с какого-то "далласа", котрый сейчас читаем
    float pretemp; // предыдущее значение, считанное с "далласов"
    float rew_water = 0;  // обратка
    float forv_water = 0;  // подача
    float temp_water = 0; // временная установка для переходного режима
    float pre_forv_water = 0; // предыдущее занчение подачи
    
    // выводы для подключения SD модуля (софтверный SPI)
    const uint8_t SOFT_MISO_PIN = 12;
    const uint8_t SOFT_MOSI_PIN = 11;
    const uint8_t SOFT_SCK_PIN  = 13;
    
    const uint8_t SD_CHIP_SELECT_PIN = 9;
    const uint8_t RF_CHIP_SELECT_PIN = 7;
    
    byte inSD; // флаг наличия карточки SD
    
    // SdFat software SPI template
    SdFatSoftSpi<SOFT_MISO_PIN, SOFT_MOSI_PIN, SOFT_SCK_PIN> sd;
    
    // Test file.
    SdFile file;
    char fnm[30]; // создаем имя файла
    int filenum; // порядковый номер файла
    
    #define Butt 2 // пин кнопки
    
    RF24 radio(RF_CHIP_SELECT_PIN, 8); // CE, CSN
    
    const byte address1[6] = "00001"; // адреса "труб" дл радио
    const uint64_t pipe01 = 0xF0F1F2F3F4LL;
    const uint64_t pipe02 = 0xF0F1F2F3F1LL;
    
    
    Button encoderA (3, 4); // сигнал A
    Button encoderB (4, 4); //  сигнал B
    
    int pos = 0; // пооложение энкодера
    byte settherm = 60; // установка температуры воды
    byte presetthermradio; // установка температуры, полученная через радио
    byte presettherm = 60; // установка температуры в главном контроллере
    bool buttflag = LOW; // перебираем положение кнопки
    bool thermmenuflag = LOW;
    int menu = 0; // входим в меню по такту кнопки
    int submenu = 0;
    int prepos = 0; // предыдущее положение
    int L = 0; // положение по вертикали на главном экране
    int LCDledPin = 44;    // Подключение подсветки дисплея
    byte LCDled = 80;  // значение подсветки
    bool LCDflag = LOW; // флаг изменения значения подсветки
    byte preLCDled = 120; // предыдущее занчение подсветки
    int preposLED = 0; // обнудяем энкодер для считывания значения подсветки
    byte id = 1; // символ устройства для радио
    
    int counter = 0; // счетчик для тайминга событий
    int counterwrite = 0; // счетчик тайминга записи на карточку
    
    float riser; // температура райзера
    float bunker; // температура бункера
    
    float temperature;
    
    byte servoprim = 11; // угол сервы первички
    byte servosec = 22; // угол сервы вторички
    
    long worktime; // счетчик времени горения
    unsigned long currentTime; // таймер загрузки
    
    unsigned long presentTime;
    unsigned long preMillisRadioWrite;
    long RadioWriteOFF = 900; // время приема радио
    long RadioWriteON = 100; // время передачи радио
    
    U8GLIB_ST7920_128X64 u8g(38, 40, 42, U8G_PIN_NONE); //иннициализация дисплея
    
    // иконки для дисплея:
    static unsigned char u8g_sd_bits[] = {0xFC, 0x03, 0xAA, 0x02, 0xA9, 0x02, 0x01, 0x02, 0x01, 0x02, 0x69, 0x02, 0xA5, 0x02, 0xA9, 0x02, 0x65, 0x02, 0x01, 0x02, 0xFF, 0x03, 0x00, 0x00};
    static unsigned char u8g_rize_bits[] = {0x00, 0x00, 0x38, 0x00, 0x44, 0x08, 0x44, 0x14, 0x44, 0x22, 0x44, 0x08, 0x44, 0x14, 0x54, 0x22, 0x54, 0x08, 0x92, 0x14, 0xBA, 0x22, 0x92, 0x08, 0x44, 0x14, 0x38, 0x22, 0x00, 0x00, 0x00, 0x00};
    static unsigned char u8g_foll_bits[] = {0x00, 0x00, 0x78, 0x00, 0x84, 0x00, 0x84, 0x44, 0x84, 0x28, 0x84, 0x10, 0x84, 0x44, 0x84, 0x28, 0x84, 0x10, 0x84, 0x44, 0x02, 0x29, 0x32, 0x11, 0x32, 0x45, 0x84, 0x28, 0x78, 0x10, 0x00, 0x00};
    static unsigned char u8g_fire_bits[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xE8, 0x0B, 0x78, 0x0F, 0x78, 0x1E, 0xDC, 0x1C, 0x9C, 0x18, 0x0C, 0x18, 0x08, 0x08, 0x10, 0x04, 0x00, 0x00};
    static unsigned char u8g_snow_bits[] = {0x00, 0x00, 0xFE, 0x0F, 0xFE, 0x0F, 0x0E, 0x0E, 0xAE, 0x0E, 0x06, 0x0C, 0x56, 0x0D, 0x06, 0x0C, 0xAE, 0x0E, 0x0E, 0x0E, 0xFE, 0x0F, 0xFE, 0x0F, 0x00, 0x00, 0x00, 0x00};
    
    void Button() {
    
      if (digitalRead(Butt) == LOW) { //проверка нажатия на кнопку
        if (buttflag == LOW) {
          delay (400);
          menu++;
          tone(speakerPin, 800, 200);
        
    
          if (menu >= 3) {
            menu = 0;
            L = 0;
            EEPROM.write(0, settherm);
            EEPROM.write(1, LCDled);
    
          }
          if (menu == 1) {
            pos = 0;
            L = 0;
          }
        }
      
        buttflag = HIGH;
    
    
      }
      if (digitalRead(Butt) == HIGH && buttflag == HIGH) { //проверка нажатия на кнопку
        buttflag = LOW;
      }
    
    }
    
    // обработчик прерывания 250 мкс
    void timerInterrupt() {
      encoderA.filterAvarage(); // вызов метода фильтрации
      encoderB.filterAvarage(); // вызов метода фильтрации
      if ( encoderA.flagClick == true ) {
        encoderA.flagClick = false;
        if ( encoderB.flagPress == true) {
          // против часовой стрелки
          pos++;
          tone(speakerPin, 1200, 100);
    
          if (menu == 0 && pos < 0) {
            pos = 0;
          }
    
    
        }
        else {
          // по часовой стрелке
          pos--;
          tone(speakerPin, 1400, 100);
    
    
        }
      }
    }
    
    // рисуем меню
    void menudraw(void) {
      u8g.drawBox(0, submenu * 12 , 5, 10);
      u8g.drawHLine(0, submenu * 12 + 10 , 120);
      u8g.setFont(u8g_font_7x14Br);
      u8g.setPrintPos(10, 10);
      u8g.print("Back");
      u8g.setPrintPos(10, 22);
      u8g.print("Start");
      u8g.setPrintPos(10, 34);
      u8g.print("Set Therm");
      u8g.setPrintPos(10, 46);
      u8g.print("Brightness %");
      u8g.setPrintPos(98, 46);
      u8g.print(map (LCDled, 0, 255, 0, 100));
    
      if (thermmenuflag == LOW) {
        u8g.setPrintPos(98, 34);
        u8g.print(settherm);
        u8g.setPrintPos(62, 22);
        u8g.print(worktime / 60 / 60);
        u8g.setPrintPos(75, 22);
        u8g.print(":");
        u8g.setPrintPos(80, 22);
        u8g.print((worktime / 60) % 60);
        u8g.setPrintPos(93, 22);
        u8g.print(":");
        u8g.setPrintPos(98, 22);
        u8g.print(worktime % 60);
      }
      if (menu == 1) {
        submenu = pos;
        if (submenu >= 4) {
          pos = 0;
        }
        if (submenu < 0) {
          pos = 0;
        }
      }
    
      if (submenu == 0 && menu == 2) {
        menu = 0;
        submenu = 1;
      }
      if (submenu == 1 && menu == 2) {
        menu = 0;
        currentTime = millis();
        filenum = EEPROM.read(2);
        filenum++;
        EEPROM.write(2, filenum);
        sprintf(fnm, "%02d.log", filenum);
        pos = 1;
      }
      if (pos == 2 && menu == 2 && thermmenuflag == LOW && LCDflag == LOW) {
        prepos = pos;
        presettherm = settherm;
        thermmenuflag = HIGH;
      }
    
      if (thermmenuflag == HIGH && LCDflag == LOW) {
        u8g.drawFrame(78, 6, 45, 28);
        u8g.drawFrame(77, 5, 47, 30);
        u8g.setFont(u8g_font_gdb20n);
        u8g.setPrintPos(84, 30);
        u8g.print(settherm);
        settherm = presettherm + pos - prepos;
        if (settherm >= 100 || settherm < 40) {
          prepos = pos;
        }
    
      }
    
      if (menu != 2) {
        thermmenuflag = LOW;
        LCDflag = LOW;
      }
    
      if (pos == 3 && menu == 2 && LCDflag == LOW && thermmenuflag == LOW) {
        preposLED = pos;
        preLCDled = LCDled;
        LCDflag = HIGH;
      }
    
      if (LCDflag == HIGH && thermmenuflag == LOW) {
        u8g.drawBox (120, submenu * 12 , 5, 11);
        LCDled = preLCDled + ((pos - preposLED) * 2.55);
        if (LCDled >= 255 || LCDled < 0) {
          preposLED = pos;
        }
    
    
      }
    }
    
    void workdraw(void) {
      u8g.setFont(u8g_font_7x14Br);
      u8g.setPrintPos(77, 12);
      u8g.print(worktime / 60 / 60);
      u8g.setPrintPos(90, 12);
      u8g.print(":");
      u8g.setPrintPos(95, 12);
      u8g.print((worktime / 60) % 60);
      u8g.setPrintPos(108, 12);
      u8g.print(":");
      u8g.setPrintPos(113, 12);
      u8g.print(worktime % 60);
      u8g.drawFrame(74, 0, 54, 14);
      u8g.drawFrame(0, 0, 34, 38);
      u8g.drawLine(35, 0, 72, 0);
      u8g.drawLine(35, 0, 35, 37);
      u8g.drawLine(72, 0, 72, 15);
      u8g.drawLine(72, 15, 127, 15);
      u8g.drawLine(35, 37, 79, 37);
      u8g.drawLine(79, 37, 79, 51);
      u8g.drawLine(79, 51, 127, 51);
      u8g.drawLine(127, 15, 127, 51);
    
      u8g.setPrintPos(4, 12);
      u8g.print("Set:");
      u8g.setPrintPos(37, 12);
      u8g.print("Water");
      u8g.setFont(u8g_font_gdb20n);
      u8g.setPrintPos(1, 36);
      u8g.print(settherm);
      u8g.setPrintPos(38, 36);
      u8g.print(forv_water);
      u8g.setFont(u8g_font_7x14Br);
      u8g.setPrintPos(86, 49);
      u8g.print(rew_water);
    
      if (rew_water >= 1) {
        u8g.drawBox(81, 50 - (int(forv_water) - int(rew_water)) / 2, 4, (int(forv_water) - int(rew_water)) / 2);
        u8g.drawBox(122, 50 - (int(forv_water) - int(rew_water)) / 2, 4, (int(forv_water) - int(rew_water)) / 2);
      }
    
      if (riser - bunker >= 20 || riser >= 450) {
        u8g.drawXBM(78, 50, 15, 15, u8g_fire_bits);
      }
      else {
        u8g.drawXBM(78, 52, 13, 14, u8g_snow_bits);
      }
    
      if (inSD == HIGH) {
        u8g.drawXBM(118, 53, 11, 12, u8g_sd_bits);
      }
      else {
    
        u8g.print("  ");
      }
    
      if (pre_forv_water <= forv_water) {
        u8g.drawXBM(111, 18, 16, 16, u8g_rize_bits);
      }
      else {
        u8g.drawXBM(111, 18, 16, 16, u8g_foll_bits);
      }
    
      u8g.drawFrame(0, 39, 78, 25);
    
      u8g.setFont(u8g_font_5x7r);
      u8g.setPrintPos(2, 49);
      u8g.print("Bunker");
      u8g.setPrintPos(2, 60);
      u8g.print("Riser");
    
      u8g.setPrintPos(92, 64);
      u8g.print(temperature);
    
      u8g.setFont(u8g_font_7x14Br);
      u8g.setPrintPos(35, 51);
      u8g.print(bunker);
      u8g.setPrintPos(28, 62);
      u8g.print(riser);
    
    
    }
    
    float get_data_ds18b20()  { // функция дляя работы с "далласами"
      byte i;
      byte present = 0;
      byte data[12];
      byte addr[8];
      int Temp;
      float fTemp = 0.0;
    
      if ( !ds.search(addr)) {
        ds.reset_search();
      }
    
      ds.reset();
      ds.select(addr);
      ds.write(0x44, 1);
      present = ds.reset();
      ds.select(addr);
      ds.write(0xBE);
    
      for ( i = 0; i < 3; i++) {
        data[i] = ds.read();
      }
      Temp = ((data[1] << 8) + data[0]);
    
      fTemp = 1.0 * Temp / 16 + (float(Temp % 16)) * 1.0 / 16;
      return fTemp;
    }
    
    void ServoPrim () {
    
    
         if (Tflag > 0) {
          if ( D_forv_water != 0 && spid - D_forv_water >= 2 && spid - D_forv_water < 180 ) {
            spid = spid - (D_forv_water*2);
          }
          if ( D_riser != 0 && spid - D_riser >= 2 && spid - D_riser < 180 ) {
            spid = spid - D_riser;
          }
          if ( D_bunker != 0 && spid - D_bunker >= 2 && spid - D_bunker < 180 ) {
            spid = spid - D_bunker;
          }
    
    
          if (settherm - forv_water >= 5) {
            if (forv_water - temp_water >= 1 ) {
              temp_water = forv_water + 2;
            }
            if (temp_water - forv_water >= 3 ) {
              temp_water = forv_water + 2;
            }
          }
          else {
            temp_water = settherm;
          }
    
          tempdeficite = temp_water - forv_water;
    
          if ( spid + tempdeficite > 2 && spid + tempdeficite < 180 ) {
            spid = spid + tempdeficite;
          }
    
          if (riser > 500 && spid - (map (riser, 500, 1100, 2, 180) / constrain (tempdeficite, 1, 5)) >= 2) {
            preservoprim = spid - (map (riser, 500, 1100, 2, 180) / constrain (tempdeficite, 1, 5));
          }
          else {
            preservoprim = spid;
          }
      
        if ( settherm - forv_water <= 0.2 ) {
          spid = 2;
          preservoprim = 2;
        }
    
        D_preservoprim = P_preservoprim - preservoprim;
      
      
        if ((worktime > 2400 && riser >= 450 && riser <= 800) || riser >= 500){
        workservoprim = P_preservoprim - D_preservoprim * servoprim_speed;
        }
    
        if (worktime < 2400 && riser < 500 && forv_water < 90){
          workservoprim = P_preservoprim - (P_preservoprim - 180) * servoprim_speed;
        }
      
        if (riser < 450  && forv_water < 90){
          workservoprim = P_preservoprim - (P_preservoprim - 180) * servoprim_speed;
        }
    
        if (riser > 800 || forv_water > 95){
          workservoprim = P_preservoprim - (P_preservoprim - 1) * servoprim_speed;
        }
    
        servoprim = byte(constrain (workservoprim, 0, 180));
        //Serial.print (D_forv_water);
        //Serial.print ("  ");
        //Serial.println (servoprim);
    
        P_preservoprim = workservoprim;
    
        Tflag = 0;
      }
    
    }
    
    
    void ServoSec () {
    
      if (riserpretemp < riser)
      {
        rizerdiff = rizerdiff + (riser - riserpretemp);
      }
      if (riserpretemp > riser)
      {
        rizerdiff = rizerdiff - (riserpretemp - riser);
      }
    
      rizerdiff = constrain (rizerdiff, 2, 180);
    
      if (riser <= 450) {
        servosec = 2;
      }
      if (riser > 450 && riser <= 500) {
        servosec = (map ( rizerdiff, 2, 180, 5, 180) + map ( riser, 450, 500, 5, 80)) / 2;
      }
      if (riser > 500 && riser <= 600) {
        servosec = (map ( rizerdiff, 2, 180, 60, 180) + map ( riser, 500, 600, 60, 120)) / 2;
      }
      if (riser > 600 && riser <= 800) {
        servosec = (map ( rizerdiff, 2, 180, 100, 180) + map ( riser, 600, 800, 100, 160)) / 2;
      }
      if (riser > 800) {
        servosec = (map ( rizerdiff, 2, 180, 160, 180) + map ( riser, 800, 1020, 160, 180)) / 2;
      }
      servosec = constrain (servosec, 0, 180);
    }
    
    void setup() {
    
      Serial.begin (9600);
    
      radio.begin();
      radio.setChannel(9); // канал (0-127)
      radio.setDataRate(RF24_1MBPS);
      radio.setPALevel(RF24_PA_MAX);
      radio.openWritingPipe(address1);
      radio.openReadingPipe(1, pipe01); // открываем трубу с индитификатором "pipe01"
      radio.openReadingPipe(2, pipe02); // открываем трубу с индитификатором "pipe02"
    
    
      pinMode (2, INPUT);
      pinMode(LCDledPin, OUTPUT);
      attachInterrupt(0, Button, CHANGE); //прерывание по изменению пина №2(для Arduino UNO)
      Timer1.initialize(250); // инициализация таймера 1, период 250 мкс
      Timer1.attachInterrupt(timerInterrupt, 250); // задаем обработчик прерываний
    
      pinMode(SD_CHIP_SELECT_PIN, OUTPUT);
      pinMode(RF_CHIP_SELECT_PIN, OUTPUT);
    
      analogWrite(LCDledPin, LCDled);
    
      if (EEPROM.read(0) >= 100 || EEPROM.read(0) <= 40) {
        settherm = 60;
      }
      else {
        settherm = EEPROM.read(0);
      }
    
      LCDled = EEPROM.read(1);
    
      u8g.firstPage();
      do {
        workdraw();
      } while ( u8g.nextPage() );
      sd.begin(SD_CHIP_SELECT_PIN, SPI_HALF_SPEED);
      filenum = EEPROM.read(2);
      sprintf(fnm, "%02d.log", filenum);
    
      pinMode(speakerPin, OUTPUT);
    }
    
    void loop()
    {
      uint8_t pipeNum = 0;
      float temp = get_data_ds18b20();
    
    
      if (millis() - millis_int1 >= INTERVAL_GET_DATA) {
        if (temp < 100) {
          if (pretemp - temp >= 1) {
            rew_water = temp;
          }
    
          if (temp - pretemp >= 1) {
            pre_forv_water = forv_water;
            forv_water = temp;
          }
    
    
          pretemp = temp;
        }
    
        Primsec ++;
        millis_int1 = millis();
      }
    
      presentTime = millis();
      worktime = (presentTime - currentTime) / 1000; // таймер времени горения закладки топлива
      analogWrite(LCDledPin, LCDled);
    
      if (menu >= 1) {
        u8g.firstPage();
        do {
          menudraw();
        } while ( u8g.nextPage() );
      }
    
      if (menu == 0) {
        u8g.firstPage();
        do {
          workdraw();
        } while ( u8g.nextPage() );
    
        if (pos < 0) {
          pos = 0;
        }
    
    
        struct Datamain {
          byte id;
          long worktime;
          float riser;
          float bunker;
          int  settherm;
          float forv_water;
          float rew_water;
          byte servoprim;
          byte servosec;
        } text;
    
        struct LowDevice {
          byte id;
          int settherm;
          float riser;
          float bunker;
        } text1;
    
        struct HomeDevice {
          byte id;
          float temperature;
          int setthermfromhome;
        } text2;
    
        if (text2.setthermfromhome > 40 && text2.setthermfromhome < 80) {
          settherm = text2.setthermfromhome;
          EEPROM.write(0, settherm);
        }
    
    
        text.id = id;
        text.worktime = worktime;
        text.riser = riser;
        text.bunker = bunker;
        text.settherm = settherm;
        text.forv_water = forv_water;
        text.rew_water = rew_water;
        text.servoprim = servoprim;
        text.servosec = servosec;
    
        if (Primsec >= 5) {
          D_forv_water = forv_water - P_forv_water;
          P_forv_water = forv_water;
          D_riser = riser - P_riser;
          P_riser = riser;
          D_bunker = bunker - P_bunker;
          P_bunker = bunker;
          Tflag = 1;
          Primsec = 0;
        }
    
        ServoPrim (); // вычисляем угол первички
    
    
        if (presentTime - preMillisRadioWrite >= RadioWriteOFF) {
    
          digitalWrite(SD_CHIP_SELECT_PIN, HIGH);
          digitalWrite(RF_CHIP_SELECT_PIN, LOW);
          radio.stopListening();
    
          radio.write(&text, sizeof(text));
        }
    
        if (presentTime - preMillisRadioWrite >= RadioWriteOFF + RadioWriteON) {
    
    
          radio.startListening();
          if (radio.available(&pipeNum)) {
            if (pipeNum == 1) {
              radio.read(&text1, sizeof(text1));
              riser = text1.riser;
              bunker = text1.bunker;
            }
            if (pipeNum == 2) {
              radio.read(&text2, sizeof(text2));
              temperature = text2.temperature;
            }
    
          }
          preMillisRadioWrite = presentTime;
          counter++;
        }
    
    
    
        if (counter >= 2) {
          counterwrite++;
          rizerdiffflag++;
          digitalWrite(RF_CHIP_SELECT_PIN, HIGH);
          digitalWrite(SD_CHIP_SELECT_PIN, LOW);
    
          if (counterwrite >= 30) {
    
            file.open(fnm, FILE_WRITE);
    
            if (worktime / 60 / 60 < 10) {
              file.print ("0");
            }
            file.print (worktime / 60 / 60);
            file.print (":");
            if (worktime / 60 % 60 < 10) {
              file.print ("0");
            }
            file.print ((worktime / 60) % 60);
            file.print (":");
            if (worktime % 60 < 10) {
              file.print ("0");
            }
            file.print (worktime % 60);
    
            file.print("  ;  ");
            file.print(riser);
    
            file.print("  ;  ");
            if (bunker > 0 && bunker < 1030) {
              file.print(bunker);
            }
            else {
              file.print("0");
            }
    
            file.print("  ;  ");
            file.print(settherm);
    
            file.print("  ;  ");
            file.print(forv_water);
    
            file.print("  ;  ");
            if (rew_water < 100 && rew_water > 0) {
              file.print(rew_water);
            }
            else {
              file.print("0");
            }
    
            file.print("  ;  ");
            file.print(servoprim);
    
            file.print("  ;  ");
            file.print(servosec);
    
            file.print("  ;  ");
            file.println(temperature);
    
            file.close();
            counterwrite = 0;
          }
    
          file.open(fnm, FILE_READ);
    
          if (file.read() >= 0) {
            inSD = HIGH;
          }
          else {
            inSD = LOW;
            sd.begin(SD_CHIP_SELECT_PIN, SPI_HALF_SPEED);
            file.close();
            file.open(fnm, FILE_WRITE);
    
            if (worktime / 60 / 60 < 10) {
              file.print ("0");
            }
            file.print (worktime / 60 / 60);
            file.print (":");
            if (worktime / 60 % 60 < 10) {
              file.print ("0");
            }
            file.print ((worktime / 60) % 60);
            file.print (":");
            if (worktime % 60 < 10) {
              file.print ("0");
            }
            file.println (worktime % 60);
            file.close();
          }
          file.close();
    
          counter = 0;
        }
      }
      if (rizerdiffflag >= 10) { // вычисляем раз в 2х10 = 20 секунд
        riserpretemp = riser;
        rizerdiffflag = 0;
        ServoSec (); // вычисляем угол вторички
      }
    }
    
    
    
     
  6. Perelesnik
    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616

    Perelesnik

    Живу здесь

    Perelesnik

    Живу здесь

    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616
    Адрес:
    Черкассы
    "Нижний" контроллер (сервы и термопары):

    Код:
    #include "max6675.h"
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    #include <Servo.h>
    
    
    RF24 radio(7, 8); // CE, CSN
    
    Servo servo1;
    Servo servo2;
    
    const byte address1[6] = "00001";
    const uint64_t pipe01 = 0xF0F1F2F3F4LL;
    byte id = 2;
    long worktime;
    float riser;
    float bunker;
    //int settherm ;
    float forv_water;
    float rew_water;
    byte servoprim;
    byte servosec;
    
    
    unsigned long presentTime;
    unsigned long preMillisRadioWrite;
    long RadioWriteOFF = 700;
    long RadioWriteON = 300;
    
    int thermoDO1 = 2;  //он же SO
    int thermoDO2 = 3;  //он же SO
    int thermoCS = 5;
    int thermoCLK = 6;  //он же SCK
    
    MAX6675 thermocouple1(thermoCLK, thermoCS, thermoDO1);// это организовываем подключение термопар
    MAX6675 thermocouple2(thermoCLK, thermoCS, thermoDO2);
    
    byte presint1 = 200;
    byte presint2 = 200;
    byte angle1;
    byte angle2;
    byte dev1;
    byte dev2;
    byte flag1;
    byte flag2;
    unsigned long previousMillis = 0;
    unsigned long currentMillis = 0;
    unsigned long previousMillis2 = 0;
    unsigned long currentMillis2 = 0;
    int servoworktime = 2000;
    
    void setup() {
      Serial.begin(9600);
      radio.begin();
      radio.setChannel(89); // канал (0-127)
      radio.setDataRate(RF24_1MBPS);
      radio.setPALevel(RF24_PA_MIN);
      radio.openWritingPipe(pipe01);
      radio.openReadingPipe(1, address1);
    
    
    
      delay(500);
    }
    void loop() {
    
      presentTime = millis();
    
      struct Datamain {
        byte id;
        long worktime;
        float riser;
        float bunker;
        int  settherm;
        float forv_water;
        float rew_water;
        byte servoprim;
        byte servosec;
    
      } text;
    
      struct LowDevice {
        byte id;
        int settherm;
        float riser;
        float bunker;
      } text1;
    
    
    
      text1.id = id;
      //text1.settherm = settherm;
      text1.riser = riser;
      text1.bunker = bunker;
    
      if (presentTime - preMillisRadioWrite >= RadioWriteOFF) {
        radio.stopListening();
    
        radio.write(&text1, sizeof(text1));
        riser = thermocouple1.readCelsius();
        bunker = thermocouple2.readCelsius();
      }
    
      if (presentTime - preMillisRadioWrite >= RadioWriteOFF + RadioWriteON) {
    
        radio.startListening();
    
        if (radio.available()) {
    
          radio.read(&text, sizeof(text));
          angle1 = map(text.servoprim, 0, 180, 0, 160);
          angle2 = map(text.servosec, 0, 180, 0, 160);
        }
        preMillisRadioWrite = presentTime;
      }
    
      if (presint1 >= angle1) {
        dev1 = (presint1 - angle1);
      }
      if (presint1 < angle1) {
        dev1 = (angle1 - presint1);
      }
      if (presint2 >= angle2) {
        dev2 = (presint2 - angle2);
      }
      if (presint2 < angle2) {
        dev2 = (angle2 - presint2);
      }
    
      if (dev1 > 3)
      {
        Serial.print (dev1);
        Serial.print (" f  ");
        Serial.print (angle1);
        Serial.print (" f  ");
        Serial.println (presint1);
        flag1 = 1;
        previousMillis = millis();
        presint1 = angle1;
      }
    
      if (flag1 == 1)
      {
    
        servo1.attach(10);
    
        servo1.write(angle1);
        currentMillis = millis();
    
        if (currentMillis - previousMillis > servoworktime)
        {
    
          flag1 = 0;
          servo1.detach();
        }
    
      }
    
    
      if (dev2 > 3)
      {
        Serial.print (dev2);
        Serial.print (" s  ");
        Serial.print (angle2);
        Serial.print (" s  ");
        Serial.println (presint2);
        flag2 = 1;
        previousMillis2 = millis();
        presint2 = angle2;
      }
    
      if (flag2 == 1)
      {
        servo2.attach(9);
        servo2.write(180 - angle2);
        currentMillis2 = millis();
    
        if (currentMillis2 - previousMillis2 > servoworktime)
        {
    
          flag2 = 0;
          servo2.detach();
        }
    
      }
    }
    
     
  7. Perelesnik
    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616

    Perelesnik

    Живу здесь

    Perelesnik

    Живу здесь

    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616
    Адрес:
    Черкассы
    "Домашний" контроллер:

    Код:
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    #include <Adafruit_SSD1306.h>
    #include <OneWire.h>
    #include <string.h>
    #include <EEPROM.h>
    
    RF24 radio(7, 8); // CE, CSN
    
    #define POWER_MODE  0 // режим питания, 0 - внешнее, 1 - паразитное
    OneWire sensDs (4);  // датчик подключен к выводу 4
    
    #define OLED_RESET 4
    Adafruit_SSD1306 display(OLED_RESET);
    
    const byte address1[6] = "00001";
    const uint64_t pipe02 = 0xF0F1F2F3F1LL;
    
    unsigned long presentTime;
    unsigned long preMillisRadioWrite;
    int Serialwritecount;
    long RadioWriteOFF = 900; // время приема радио
    long RadioWriteON = 100; // время передачи радио
    
    byte id = 3;
    float tadj = 3.19; // оффсет комнатной температуры
    
    char incomingBytes[7];
    int greenPin = 6;
    int yelloPin = 5;
    int soundPin = 9;
    byte bufData[9];  // буфер данных ds18b20
    float temperature;  // измеренная температура ds18b20
    
    int alarm = 520; // частота звука тревоги
    int alarmtemp1 = 450; // тревога по температуре в райзере
    int alarmtemp2 = 300; // тревога по температуре в бункере
    int normtemp = 500; // приемлемая температура райзера
    int hightemp = 700; // высокая температура райзера
    int extratemp = 900; // повышенная температура райзера
    int loadtemp = 420; // температура бункера для загрузки
    int loadrizer = 450; // температура райзера для загрузки
    int servoprimlimalarm = 160; // положение сервы первички для тревоги
    
    String Var = ""; //переменная для приема строки
    
    int loadtemps1, s5, d1;
    float s2, s3, s4, pidp, pidi, pidd;
    
    boolean comwriting = false;
    
    void setup() {
      Serial.begin(9600);
      display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
      radio.begin();
      radio.setChannel(9); // канал (0-127)
      radio.setDataRate(RF24_1MBPS);
      radio.setPALevel(RF24_PA_MIN);
    // radio.openWritingPipe(pipe02);
      radio.openReadingPipe(1, address1);
    
      loadtemp = EEPROM.read(1) + 350;
    radio.startListening();
    
    
      display.clearDisplay();
      display.display();
      pinMode(greenPin, OUTPUT);
      pinMode(yelloPin, OUTPUT);
      pinMode(soundPin, OUTPUT);
      tone (soundPin, 440, 200);
      digitalWrite(yelloPin, HIGH);
      delay(500);
      digitalWrite(yelloPin, LOW);
      digitalWrite(greenPin, HIGH);
    }
    
    void loop() {
    
      if (Serial.available() > 0)  {
        comwriting = true;
        Var = Var + (char)(Serial.read());
    
        String T1, T2, T3, T4, T5, D1;
        T1 = Var.substring(Var.indexOf("T1") + 2, Var.indexOf("1T")); //копируем часть строки от начального до конечного тега
        T2 = Var.substring(Var.indexOf("T2") + 2, Var.indexOf("2T"));
        T3 = Var.substring(Var.indexOf("T3") + 2, Var.indexOf("3T"));
        T4 = Var.substring(Var.indexOf("T4") + 2, Var.indexOf("4T"));
        T5 = Var.substring(Var.indexOf("T5") + 2, Var.indexOf("5T"));
        D1 = Var.substring(Var.indexOf("D1") + 2, Var.indexOf("1D"));
    
        loadtemps1 = T1.toInt();
        s2 = T2.toFloat();
        s3 = T3.toFloat();
        s4 = T4.toFloat();
        s5 = T5.toInt();
        d1 = D1.toInt();   
      }
    
      else {
        Var = "";
        Serial.flush();
        comwriting = false;
       
      }
    
      if (loadtemps1 >= 400 && loadtemp != loadtemps1) {
        loadtemp = loadtemps1;
        EEPROM.write(1, loadtemp - 350);
      }
    
      if (s2 > 0 && s2 < 5) {
        pidp = s2;
      }
    
      if (s3 > 0 && s3 < 5) {
        pidi = s3;
      }
    
      if (s4 > 0 && s4 < 5) {
        pidd = s4;
      }
    
      presentTime = millis();
    
      sensDs.reset();  // сброс шины
      sensDs.write(0xCC, POWER_MODE); // пропуск ROM
      sensDs.write(0x44, POWER_MODE); // инициализация измерения
    
    
    
      struct HomeDevice {
        byte id;
        float temperature;
        int setthermfromhome;
      } text2;
    
      text2.id = id;
      text2.temperature = temperature;
      if (d1 > 40) {
        text2.setthermfromhome = d1;
      }
      else {
        text2.setthermfromhome = 0;
      }
    
       struct Datamain {
        byte id;
        long worktime;
        float riser;
        float bunker;
        int  settherm;
        float forv_water;
        float rew_water;
        byte servoprim;
        byte servosec;
    
      } text;
    
       if (d1 == text.settherm){
        d1 = 0;
      }
    
    //  if (presentTime - preMillisRadioWrite >= RadioWriteOFF) {
    
    //    radio.stopListening();
    
    //    radio.write(&text2, sizeof(text2));
    //  }
    
      if (presentTime - preMillisRadioWrite >= RadioWriteOFF + RadioWriteON) {
    
    
    //   radio.startListening();
        if (radio.available()) {
    
          radio.read(&text, sizeof(text));
    
        }
        preMillisRadioWrite = presentTime;
        Serialwritecount ++;
    
        if (Serialwritecount >= 5 && comwriting == false) { // Выводим данные в порт раз в 5 секунд
    
          Serial.print(text.id);
          Serial.print("; ");
    
          Serial.print(text2.temperature);
          Serial.print("; ");
    
          if (text.worktime / 60 / 60 < 10) {
            Serial.print ("0");
          }
          Serial.print (text.worktime / 60 / 60);
          Serial.print (":");
          if (text.worktime / 60 % 60 < 10) {
            Serial.print ("0");
          }
          Serial.print ((text.worktime / 60) % 60);
          Serial.print (":");
          if (text.worktime % 60 < 10) {
            Serial.print ("0");
          }
          Serial.print (text.worktime % 60);
    
          Serial.print("; ");
          Serial.print(text.riser);
    
          Serial.print("; ");
          if (text.bunker > 0 && text.bunker < 1030) {
            Serial.print(text.bunker);
          }
          else {
            Serial.print("0");
          }
    
          Serial.print("; ");
          Serial.print(text.settherm);
    
          Serial.print("; ");
          Serial.print(text.forv_water);
    
          Serial.print("; ");
          if (text.rew_water < 100 && text.rew_water > 0) {
            Serial.print(text.rew_water);
          }
          else {
            Serial.print("0");
          }
    
          Serial.print("; ");
          Serial.print(text.servoprim);
    
          Serial.print("; ");
          Serial.print(text.servosec);
    
    
          Serial.print("; ");
          Serial.print(loadtemp);
    
          Serial.print("; ");
          Serial.print(pidp, 3);
    
          Serial.print("; ");
          Serial.print(pidi, 3);
    
          Serial.print("; ");
          Serial.println(pidd, 3);
    
    
    
    
    
          Serialwritecount = 0;
        }
    
        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(0, 0);
        display.println("R:");
        display.setCursor(15, 0);
        display.println(text.riser);
        display.setCursor(70, 0);
        display.println (text.worktime / 60 / 60);
        display.setCursor(85, 0);
        display.println (":");
        display.setCursor(90, 0);
        display.println ((text.worktime / 60) % 60);
        display.setCursor(110, 0);
        display.println (":");
        display.setCursor(115, 0);
        display.println (text.worktime % 60);
    
        display.setCursor(61, 25);
        display.println ("1:");
        display.setCursor(74, 25);
        display.println (text.servoprim);
    
        display.setCursor(0, 12);
        display.println("B:");
        display.setCursor(15, 12);
        display.println(text.bunker);
        display.setCursor(70, 12);
        display.println("F:");
        display.setCursor(85, 12);
        display.println(text.forv_water);
        display.setCursor(0, 25);
        display.println("S:");
        display.setCursor(15, 25);
        display.println(text.settherm);
       
    
    
        display.setCursor(32, 23);
        display.println(text2.temperature, 1);
        display.drawRect (30, 21, 28, 11, 1);
        display.drawLine (0, 22, 30, 22, 1);
        display.drawLine (58, 22, 128, 22, 1);
        display.drawLine (66, 0, 66, 22, 1);
        display.drawLine (93, 22, 93, 33, 1);
    
        display.setCursor(97, 25);
        display.println("2:");
        display.setCursor(110, 25);
        display.println(text.servosec);
        display.display();
        display.clearDisplay();
      }
    
      sensDs.reset();  // сброс шины
      sensDs.write(0xCC, POWER_MODE); // пропуск ROM
      sensDs.write(0xBE, POWER_MODE); // команда чтения памяти датчика
      sensDs.read_bytes(bufData, 9);  // чтение памяти датчика, 9 байтов
    
      if ( OneWire::crc8(bufData, 8) == bufData[8] ) {
    
        temperature =  (float)((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.0625 + 0.03125 - tadj;
      }
      if (text.bunker > 50 && text.bunker < alarmtemp2 && text.riser < alarmtemp1 && text.worktime > 2400 && text.servoprim > servoprimlimalarm )
    
      {
        digitalWrite(yelloPin, HIGH);
        tone(soundPin, alarm);
        delay (400);
        digitalWrite(yelloPin, LOW);
        noTone(soundPin);
        delay (100);
      }
    
      if (text.riser > normtemp)
      {
        analogWrite(greenPin, 200);
      }
      else
      {
        digitalWrite(greenPin, LOW);
      }
    
      if (text.riser > hightemp)
      {
        analogWrite(yelloPin, 200);
      }
      else
      {
        digitalWrite(yelloPin, LOW);
      }
    
      if (text.bunker > 50 && text.riser < loadrizer && text.bunker < loadtemp && text.worktime > 1200 && text.servoprim > servoprimlimalarm)
    
      {
        digitalWrite(greenPin, HIGH);
        delay(200);
        digitalWrite(yelloPin, HIGH);
        delay(200);
        digitalWrite(greenPin, LOW);
        delay(200);
        digitalWrite(yelloPin, LOW);
        delay(200);
    
      }
    
    }
    
     
  8. Perelesnik
    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616

    Perelesnik

    Живу здесь

    Perelesnik

    Живу здесь

    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616
    Адрес:
    Черкассы
    Мои рабочие эскизы по соединениям элементов.
    Иероглифы авторские, но расшифровке должны поддаваться.

    Главный контроллер:
    IMG_20190508_193711[1].jpg

    Нижний контроллер:
    IMG_20190508_193732[1].jpg

    Домашний контроллер:
    IMG_20190508_193803[1].jpg

    Цифры в квадратиках - номера выводов Ардуинок.
     
  9. alarin
    Регистрация:
    29.07.16
    Сообщения:
    8.662
    Благодарности:
    3.751

    alarin

    Живу здесь

    alarin

    Живу здесь

    Регистрация:
    29.07.16
    Сообщения:
    8.662
    Благодарности:
    3.751
    Адрес:
    Казахстан, Алма-Ата
    Я только приступаю к сему таинству, так сказать одушевлению котла:)]. Спасибо, за выложенный код, хотя конструкция котла несколько другая, и другие элементы автоматизации, сам алгоритм тот же, но несколько расширенный, поскольку появились новые свойства и более расширенные возможности управления.
    В ОЕМ версии твоего ГК (горизонтального участка) введена возможность управления сечением ГО. Ну и сам узел спроектирован под применение сборной керамики...
    ...Верхняя деталь, заменяющая нержавейку в маске ГК
    DSC02923.JPG ну и т. д...
     
  10. Lapotnik
    Регистрация:
    23.08.15
    Сообщения:
    25
    Благодарности:
    4

    Lapotnik

    Участник

    Lapotnik

    Участник

    Регистрация:
    23.08.15
    Сообщения:
    25
    Благодарности:
    4
    Спасибо огроменное, Руслан!
     
  11. Perelesnik
    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616

    Perelesnik

    Живу здесь

    Perelesnik

    Живу здесь

    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616
    Адрес:
    Черкассы
    Добра всем!
    Собственно, обещал, что дам знать, когда могу приступить к керамике, то сообщаю, что уже можно начинать думать в этом направлении.
    Погода устанавливается благоприятная.
    Вопрос только в том, соберется ли работы на одну загрузку печи для обжига, или не соберется. Соберется - будем делать, не соберется - то и смысла нет начинать. Потому никому ничего не обещал в течение этой зимы и весны, и списков не составлял, чтобы никого зря не обнадеживать.
    Если на этот сезон не соберется, то вопрос отложим уже на следующий год. Ну или вообще эту тему керамическую закрою.
    В общем, нужно сейчас определиться, начинать процесс или не начинать.
     
  12. StarykovMih
    Регистрация:
    13.11.12
    Сообщения:
    522
    Благодарности:
    176

    StarykovMih

    Живу здесь

    StarykovMih

    Живу здесь

    Регистрация:
    13.11.12
    Сообщения:
    522
    Благодарности:
    176
    Адрес:
    Киев
    А ссылочку можно?
     
  13. StarykovMih
    Регистрация:
    13.11.12
    Сообщения:
    522
    Благодарности:
    176

    StarykovMih

    Живу здесь

    StarykovMih

    Живу здесь

    Регистрация:
    13.11.12
    Сообщения:
    522
    Благодарности:
    176
    Адрес:
    Киев
    ... или хотя бы модель.
    Заранее спасибо.
     
  14. Perelesnik
    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616

    Perelesnik

    Живу здесь

    Perelesnik

    Живу здесь

    Регистрация:
    01.02.13
    Сообщения:
    991
    Благодарности:
    4.616
    Адрес:
    Черкассы
    @StarykovMih, судя по картинке и цене, то такой:
    https://arduino.ua/prod1561-shagovii-dvigatel-28byj-48-12v
    Снимок.JPG

    Всем, к кому это касается: уже набралось 5 заказов. Осталось еще столько же набрать, и будет одна загрузка печи для обжига.
    Пока никому не отвечаю в личке по данному вопросу, просто считаю... Как выяснится все полностью, и я смогу что-то обещать, отвечу всем.
     
  15. StarykovMih
    Регистрация:
    13.11.12
    Сообщения:
    522
    Благодарности:
    176

    StarykovMih

    Живу здесь

    StarykovMih

    Живу здесь

    Регистрация:
    13.11.12
    Сообщения:
    522
    Благодарности:
    176
    Адрес:
    Киев
Статус темы:
Закрыта.