Терморегулирование. НУЖНА помощь

astroks
Offline
Зарегистрирован: 06.05.2012

 Доброго времени суток! Простите, что создаю новую тему, если потребуется, после удалю.
Суть проблемы вот в чем:
строится система термостабилизации на контроллере Arduino Duemilanove. Так как, не являюсь даже близко программистом, возникла проблема с написанием алгоритма, блок схемы, проверки на цикличность, графов и собственно самой программы. Язык программирования устройств Ардуино основан на C/C++. Предполагается, что система будет работать в нескольких режимах и потребуется несколько программ. Буду очень признателен, если кто нибудь окажет содействие.
Словесный алгоритм: контроллер выдает 1 (сигнал на открытие тиристоров) до тех пор, пока температура (осуществлена обратная связь термопарой, т.е. на вход контроллера поступает сигнал) не достигнет 300 градусов (допустим 0.33 с термопары), далее подается сигнал на закрытие тиристоров 0. Т.е. печка перестает нагреваться, но контроллер в течении 10 минут опрашивает термопару и при падении сигнала до 0.25 снова подает сигнал на открытие 1, далее по достижении 0.33 снова 0. Цикл в течении 10 минут, по прошествии 10 минут требуется нагреть печь до 800 градусов, т.е снова 1 (входящий с териопары 0.75) , но до достижения печкой уже 800 градусов снова 0, при падении до 0.65 - 1, данный цикл на 20 минут работы, после требуется снова подать 0.
понимаю, что большинству форумчан не составит проблем помочь мне, очень прошу откликнуться вас.

astroks
Offline
Зарегистрирован: 06.05.2012

О цене договоримся.

моя почта astroks@yandex.ru. 

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

Вам нужно подогнать рабочий диапазон температур к диапазону напряжений от 0 до 5 вольт т.е. если рабочий диапазон от 0 до 1000 градусов соответствует диапазону напряжений от 0 до 5 вольт, то вы получите точнось около одного градуса. После чего вы устанавливаете порги включения/выключеня печи воответствующие порогам нужных вам температур.

#define ON_1 250 // Порог включения печи 1 режим
#define OFF_1 330 // Порог выключения печи 1 режим
#define TIME_1 10 // Время работы 1 режим в минутах

#define ON_2 650  // Порог включения печи 2 режим
#define OFF_2 750  // Порог выключения печи 2 режим
#define TIME_2 20 // Время работы 2 режим в минутах

#define OUT 13 // Выход на теристоры
#define IN 0 // Аналоговый вход к термопаре

void setup() {
  Serial.begin(9600);
  pinMode(OUT, OUTPUT);
}

void loop() {
  if(millis() < TIME_1*60000){
    if(analogRead(IN) < ON_1){
      digitalWrite(OUT, HIGH);
    }
    else if(analogRead(IN) > OFF_1){
      digitalWrite(OUT, LOW);
    }
  }
  else if(millis() < (TIME_1*60000 + TIME_2*60000)){
    if(analogRead(IN) < ON_2){
      digitalWrite(OUT, HIGH);  
    }
    else if(analogRead(IN) > OFF_2){
      digitalWrite(OUT, LOW);
    }
  }
  else{
    digitalWrite(OUT, LOW);
  }
  
  Serial.println(analogRead(IN), DEC);
  delay(100);
}

 А в остальном все должно работать как вы описали. После завершения (в данном случае через 30 минут) печь остается отключенной пока не будет нажат ресет на дуине, после чего все начнется по новой. Так же для отладки в сериал-монитор выводится текущее значение аналогового входа (АЦП) с термопары.

astroks
Offline
Зарегистрирован: 06.05.2012

Спасибо огромное! Будем проверять работоспособность! Как мне Вас благодарить?

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

Вы сначала все подключите и проверьте, да и в этом коде нужно учитывать время нагрева, это критично? печь долго разогревается? если быстро (в пределах 1-2 минут) то это не критично, можно просто добавить по одной минутке в времени работы режимов, а вот если печь разогревается долго (от 5 минут и больше), то тогда надо переписывать. Так как быстро у вас разогревается печь?

astroks
Offline
Зарегистрирован: 06.05.2012

Печь греется долго. До 1000 градусов - 30 минут...

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

Тогда по-позже перепишу...

astroks
Offline
Зарегистрирован: 06.05.2012

Спасибо.

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

А остывает как долго? Как я понимаю, будет происходить так: положили заготовку в печь, нажали кнопку, печь нагревается до 300 градусов, 10 минут поддержикается 300 градусов, затем печь греется до 800, 20 минут держит эту температуру, затем вы вытаскиваете загатовку. Когда вы кладете в печь следующую заготовку? если сразу, то печь еще горячая или ждете пока остынет?

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

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

astroks
Offline
Зарегистрирован: 06.05.2012

Автоматическая подача образца. Скорость остывания не имеет значение.

astroks
Offline
Зарегистрирован: 06.05.2012

 Спасибо за совет. Сегодня вечером рассмотрю этот вопрос

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

Просто к примеру если подать заготовку в печь, а в ней уже 500 градусов и предполжим, что она остывает до 300 за 5 минут, то нужно при 300 градусах держать не 10 минут, а к примеру 3 минуты, что будет эквивалентно 10 мнутам при 300 градусах или же заготовка будет подаваться когда печь остынет до 300 ? Или это вообще не важно? Пусть хоть на момент подачи следующей заготовки в печи будет 800 градусов, дуина ждет пока остынет до 300, выжидает 10 минут, потом опять 800 на 20 минут?

astroks
Offline
Зарегистрирован: 06.05.2012

В тот момент когда остынет до 300. Время остывания с 800 до 300 12 минут...

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

Я так понимаю, за этим у вас следит уже какая-то автоматизация? 

astroks
Offline
Зарегистрирован: 06.05.2012

Нет, это эмперичечкие наблюдения..

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

Не совсем понимаю, вы же писали, что подается автоматически 

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

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

astroks
Offline
Зарегистрирован: 06.05.2012

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

astroks
Offline
Зарегистрирован: 06.05.2012

Каким образом будет осуществлен вывод?

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

Например: по завершению последненго режима (800гр. на 20мин.) на какой-нибудь вывод подется 1 (либо импульс определенной длины) и остается до тех пор пока температура не опустится до 300 градусов. В общем это зависит от того как у вас устроен механизм управления подачи, есть ли концевики крайних положений, у оператора кнопки или переключатели или кнопки с фиксацией и т.д. и т.п.

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

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

astroks
Offline
Зарегистрирован: 06.05.2012

Да, про концевики не в курсе, у оператора кнопки без фиксации. Вперед назад. Механизм помоему осуществлен на валу шагового двигателя. столы расположены под углом 90 град. при нажатии вперед вал вращается вперед, как только стол достигает места назначения кнопку опускают.  но ее можно переделать. система требует доработок и модернизации. как я понимаю с концевиками было бы проще написать программу? процесс завершился, столы сменились? Очень интересная идея. Если Вы сможете реализовать программную часть, то не могли бы Вы выделить этот блок отдельно? И будет ли работать программа без использования этого блока (т.е. если просто вытащить из программы кусок)? 

astroks
Offline
Зарегистрирован: 06.05.2012

 а вот про "лампочку и звонок" на данном этапе более реализуемо) и наверное даже предпочтительнее)

leshak
Offline
Зарегистрирован: 29.09.2011

 Сам, честно говоря, еще ее пробовал/разбирался.

Но если больше подходит решение "держать, по возможности, конкретную температуру", а не "диапазон", то стоит посмотреть в сторону этой библиотеки

http://arduino.cc/playground/Code/PIDLibrary

Особенно если есть возможность нагревать включать "плавно" (шимом или еще как-то).

Она как-раз и предназначена. Для "имеем желаемое состояние системы", имеем обратную связь (насколько желаемое состояние отличается от фактического), а библиотека дергает управляющий элемент таким образом что-бы свести разницу желаемого и действительного к нулю.

Что-такое PID-Регуляторы можно посомтреть тут http://ru.wikipedia.org/wiki/%D0%9F%D0%98%D0%94-%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%82%D0%BE%D1%80

Внизу есть ссылочки где более на пальцах и примерах разжеванно что это такое.

astroks
Offline
Зарегистрирован: 06.05.2012

Еще раз благодарю!)

astroks
Offline
Зарегистрирован: 06.05.2012

 Я думал здесь достаточно ПИ - регулятора.

leshak
Offline
Зарегистрирован: 29.09.2011

 > Я думал здесь достаточно ПИ - регулятора.

Очень возможно что так и есть. Тем более что ПИ - частный случай ПИД :)

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

Здесь достаточно ПД (позиционно-диференциального) регулятора, т.к. температура очечь инерционный параметр, внешних возмущений практически некаких нет, так что  ПД-регулитором можно будет удерживать температуру с точностью в +/-2 градуса от заданного. И как я понимаю не критично даже колебания +/-10 градусов, поэтому можно ипользовать даже просто позиционный регулютор, что и реализованно в коде выше.

astroks
Offline
Зарегистрирован: 06.05.2012

maksim, в тексте программы реализован П -регулятор?

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

Именно так как вы и описали алгоритм П(позиционный)-регулятор.

astroks
Offline
Зарегистрирован: 06.05.2012

 Какой должен быть алгоритм с ПД или ПИ регулютором?

leshak
Offline
Зарегистрирован: 29.09.2011

 А на это, скорее всего можете ответить только вы сами. Что дает заданную точность - то и должно быть.

99%, что Максим прав, и хватит той логики что уже есть, то есть П-регулятор. Если он справляется, то можно на этом и остановится. Печь действительно - очень инерционная штука.

ПД - если хочется повысить точность. Снизить отклонения. И при этом есть возможность "регулировать силу нагрева".

ПИ - может потребоватся если датчик температуры "шумит". И его показания хочется "сгладить".

astroks
Offline
Зарегистрирован: 06.05.2012

 Спасибо за информацию. Действительно не знал этого. Поэтому мне матмодель и нужна)

leshak
Offline
Зарегистрирован: 29.09.2011

 >Поэтому мне матмодель и нужна)

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

Да и не нужна она тут особо (если только это не научная работа). Проще поставить эксперимент. Посмотретьв  реальности с какой скоростью печь греется, с какой остывает.

Очень возможно что вся "мат.модель", в итоге, уложится в два банальных линейных уравнения. Для нагрева и остывания.

Ну может, время от времени, нужно будет калибровать, подправлять коэфициент если сильно зависит от температуры окружающей среды.

Но, опять-таки, это проще "померять".

Сделать что-то типа

 

loop(){
  Serial.print("Time:");
  Serial.print(millis());

  Serial.print(", Temp:");

  Serial.println(analogRead(IN));

  delay(10*1000);// меряем температуру каждые 10-сек.
}

Включить печь на нагрев, довести до максимма - сохранить лог в файл. Выключить печь. Ребутнуть ардуину. Дождатся остывания - сохранить лог в файл.

Потом взять эти логи, загнать в Exceль или Матлаб и построить график. Посмотреть что там происходит.

Повторить все это для печи с заготовкой (если теплоемкость печи и заготовки сравнимы). Посмотреть насколько "загрузка" влияется.

astroks
Offline
Зарегистрирован: 06.05.2012

Спасибо за совет!!! Отличный форум. Благодарю за содействие!

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

На самом деле ПД(позизионно-дифференциальный)(не путайте с пропорциональным) регулятор будет отличаться от П(позиционного) регулятора предварением т.е. тем что порог отключения будет меньше чем порог включения. И у ПД регулятора будет отсутсвовать зона нечувствительности. Например: 

сейчас у нас есть зона нечувствительности т.к. ON_1 = 250, а OFF_1 = 330 промежуток между 250 и 330 равный 80 - и есть зона нечувствительности. А если к примеру ON_1 = 320, а OFF_1 = 290 (в выше приведенном коде так делать нельзя), то:  идет у нас нагрев печи, при значении OFF_1 = 290 нагрев отключается, а температура все равно растет по инерции и достигает примерно 300 далее если тепература начинает падать, то срабатывает порог ON_1 = 320 т.к. 300 меньше 320. И тоже самое будет происходить при остывании печи - нагрев включится при 320, но температура будет по инерции падать. Т.е. програмно ПД регулятор будет отличаться от П тем, что нужно помимо порогов отслеживать и "направление" изменения температуры. И тогда Д-составляющая будет включаться "автоматически" если порог включения печи будет  больше порга отключения. 

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

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

Хотя я ошибся про зону нечувствительноси, у ПД регулятора она тоже будет. А точнее это недостаток ПД регулятора.

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

Поразмыслив получше, как мне кажется, нужно двигаться от простго к сложному и поэтому начнем с П регулятора и если он вас устроит, то лучше его и оставить.

Алгоритм следующий:

При включении дуина греет печь до 300гр. и поддерживает эту температуру, как только температура достигает заданной, загорается индикатор разрешения ввода образца, звонит звонок (1 секунду) и появляется разрешение на нажатие кнопки "старт" , по нажитию кнопки индикатор разрешения ввода тухнет, загорается индикатор 1 фазы нагрева и начинается отсчет 10 минут, по прошествии 10 минут тухнет индикатор 1 фазы, далее дуина греет печь до 800гр. и поддерживает эту температуру, как только температура достигла 800гр. начинается отсчет 20 минут и загорается индикатор 2 фазы нагрева, по прошествии 20 минут, индикатор 2 фазы тухнет, звонит звонок (1 секунду), загорается индикатор разрешения вывода образца и печь начинает остывать до 300гр.. Затем все по-новой.

// Настройки:
#define ON_1 300 // Порог включения печи 1 режим
#define TIME_1 10 // Время работы 1 режим в минутах

#define ON_2 800  // Порог включения печи 2 режим
#define TIME_2 20 // Время работы 2 режим в минутах

#define TIME_TEMP 200 // Интервал опроса термопары

// Выводы:
#define IN 0 // Аналоговый вход к термопаре
#define START 2 // Кнопка "СТАРТ"
#define OUT 13 // Выход на теристоры
#define BEGIN 12 // Индикатор разрешения ввода образца
#define END 11 // Индикатор окончания и разрешения вывода образца
#define RINGER 10  // Звонок
#define MODE_1 9 // Индикатор 1 фазы нагрева
#define MODE_2 8 // Индикатор 2 фазы нагрева

int temp, old_temp = 0;
boolean start, mode_1, mode_2, perm_start, perm_mode_2, ringer = 0;
unsigned long old_time_mode, old_time_temp = 0;

void setup() {
  Serial.begin(9600);
  pinMode(OUT, OUTPUT);
  pinMode(BEGIN, OUTPUT);
  pinMode(END, OUTPUT);
  pinMode(RINGER, OUTPUT);
  pinMode(MODE_1, OUTPUT);
  pinMode(MODE_2, OUTPUT);
  digitalWrite(START, 1);
}

void loop() {

  Temp();

  if(Perm(ON_1) && !perm_start){
    perm_start = 1;
    digitalWrite(END, 0);
    digitalWrite(BEGIN, 1);
    ringer = 0;
    Ringer();
  }
  if(perm_start){
    Button();
  }

  if(start){
    if(!mode_1){
      digitalWrite(MODE_1, 1);
      if(millis()-old_time_mode > TIME_1*60000){
        mode_1 = 1; 
        digitalWrite(MODE_1, 0);       
      }     
      Termostat(ON_1);
    }
    else if(!mode_2){
      if(Perm(ON_2) && !perm_mode_2){
        perm_mode_2 = 1;
        digitalWrite(MODE_2, 1);
        old_time_mode = millis();
      }
      if(perm_mode_2 && millis()-old_time_mode > TIME_2*60000){
        mode_2 = 1;
        start = 0;
        perm_start = 0;
        digitalWrite(MODE_2, 0);
        digitalWrite(END, 1);
        Ringer();
      }
      Termostat(ON_2);
    }
  }
  else{
    Termostat(ON_1);
  }
}

void Termostat(int on){
  if(temp < on){
    digitalWrite(OUT, 1);
  }
  else{
    digitalWrite(OUT, 0);
  }
}

void Temp(){
  if(millis()-old_time_temp > TIME_TEMP){
    temp = analogRead(IN);
    Serial.println(temp, DEC);
    old_time_temp = millis();
  }
}

void Button(){
  if(!digitalRead(START) && !start){
    delay(200);
    start = 1;
    mode_1 = 0;
    mode_2 = 0;
    perm_mode_2 = 0;
    ringer = 0;
    digitalWrite(BEGIN, 0);
    old_time_mode = millis();
  }
}



boolean Perm(int on){
  if(temp > on-3 && temp < on+3){
    return 1;
  }
  else{
    return 0;
  }
}



void Ringer(){
  if(!ringer){
    digitalWrite(RINGER, 1);
    delay(1000);
    digitalWrite(RINGER, 0);
    ringer = 1;
  }
}

 

Код пока еще "сырой", но рабочий.

astroks
Offline
Зарегистрирован: 06.05.2012

 Спасибо огромное. Будем проверять.

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

Да и еще, кнопка "СТАРТ" при нажатии должна замыкать 2 пин на землю(GND). И перекопируйте поновой код, я его подредактировал - ошибку нашел.

astroks
Offline
Зарегистрирован: 06.05.2012

Ребята, пока нет возможности проверить код, дуины уехала...(

leshak
Offline
Зарегистрирован: 29.09.2011

astroks пишет:

Ребята, пока нет возможности проверить код, дуины уехала...(

Можно запускать свои скетчи вдали от Arduino

astroks
Offline
Зарегистрирован: 06.05.2012

 Спасибо, попробую разобраться

leshak
Offline
Зарегистрирован: 29.09.2011

astroks пишет:

 Спасибо, попробую разобраться

Угу. Думая в вашем случае это будет даже удобней чем тестить на реальной печи. На схему добавляется переменный резистор имитирующий показание температурного датчика и крути его как хочешь, а не жди 30 минут пока реальная печь нагреется :)

Кстати, даже при наличии реальной ардуины, я бы тоже вначале скетч тестил с помощью светодиода и переменника, а не с помощью  реальной печи и реального нагревателя.

astroks
Offline
Зарегистрирован: 06.05.2012

Сейчас посмотрим...Думаю много времени у меня займет разобраться во всем этом)

leshak
Offline
Зарегистрирован: 29.09.2011

astroks пишет:

Сейчас посмотрим...Думаю много времени у меня займет разобраться во всем этом)

Не буду врать. Протеус "простеньким" не назовешь, взрыв мозга получить запросто, но "лучше день потерять, потом за 5-ть минут долететь". Зато если его освоить в нем есть "все". И рисовать схемы, и эмулировать, и платы разводить. Можно даже 3d рендер платы сделать, посмотреть как выглядется будет, не мешаются ли элементы друг другу размерами и и т.п.

Есть намного более дружелюбный симулятор ардуины. www.virtualbreadboard.net/  . Но его "как бы бесплатных версий" ;), пока найти не получалось  :( И бибилиотека элементов в нем победнее. 

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

Можете потестировать, но единственное что вы проверете - это работоспособность скейтча, я все это уже тестировал на макетке с 5 светодиодами и потенциометром. Что бы узнать как себя будет вести печь, а точнее какая и как в ней будет поддерживаться температура нужно проверять на реальной печи.

leshak
Offline
Зарегистрирован: 29.09.2011

maksim пишет:

Можете потестировать, но единственное что вы проверете - это работоспособность скейтча, я все это уже тестировал на макетке с 5 светодиодами и потенциометром.

Вы проверили только то что скетч соотвествует тому как вы поняли задачу. Безусловно это нужно было сделать.

Но нет 100% гарантии что вы ее поняли правильно (этой гарантии никогда не бывает). Поэтому и нужно что-бы в том числе и скетч проверил тот кто ставил задачу.

maksim пишет:

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

Само собой. Тут уж без печи - никак. Никакие симуляторы/резисторы тут не помогут. Лично я бы даже начинал именно с этого. Вначале просто сделать замеры в реальной печи, увидель как она себя ведет, как датчик это все воспринимает (он тоже не идеальный), потом воспроизвести это поведение симуляторами/резисторами отладить на них скетч, а уж потом "подключать реальную" и опять смотреть что выходит.

demon969
Offline
Зарегистрирован: 24.04.2012

Подскажите пожалуйста логический алгоритм, а еще лучше пример кода для терморегулятора для инкубатора. Температуру нужно держать примерно в диапазоне 37,8 ±0,2 ºС. Теорию по ПИД, я почитал, реализовать программно не могу. Сюда тоже заглянул http://arduino.cc/playground/Code/PIDLibrary, но языковой барьер))

leshak
Offline
Зарегистрирован: 29.09.2011

Самый "лобовой" алгоритм:

если температура меньше или равна 37.8 - включить нагреватель

если температура больше или равна 37.9 - выключать нагреватель.

во всех других случаях - ничего не делать.

 > но языковой барьер))

А тут никуда не денешься. Что-ро программить не имея возможности хотя-бы со словариком, хотя-бы смутно понять - не получится.

Не так уж много там слов. Так что при желании, прочитать можно даже не зная английский. Именно так барьер и разрушается: нужно что-то прочитать что интерестно-нужно. За дни можно начать понимать без словаря.

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

http://arduino.cc/playground/Code/PIDLibraryRelayOutputExample