"Народный" инкубатор

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Если рассогласования между заданием и уставкой нет то и выход регулятора не изменится. Или я не так понял? Можете подробней описать или лог выхода на задание выложить, если ведёте.

П составляющая = рассогласование * коэффициент пропорциональности (если рассогласование =0 то и П =0)

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

Д составляющая тем больше чем больше разница между прошлым измеренным значением и текущим с соответствующим знаком

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Но не так немного. Рассогласование есть, нет приращения. В комнате температура 22,5 градуса. По DS измеряю. Задаю скажем 28 в термостате. Выход ПИД (П) становится 113 и стоит как вкопаный. И маленький, 0,1 задан, И и Д вообще можно на прерку в 0 сделать, пропорция должна суммироваться. Так библиотека ПИД работает. Она повышает постоянно выходной коэффициент до максимума. С прогрессией. А тут посчитали разницу, добавили ее к среднему и стоим. Нет движения вверх. Рассогласование уменьшать если (грею пальцами DS), то и выходной коэффициент уменьшается. Ну оно и понятно, прибавляется меньшее рассогласование. Да, в И есть сумма, а в П нету. 

Может надо p = (temp < ust - d_ctl) ? p_max : (temp > ust) ? p_min : p + (kP * e);

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Либу рою, там сложнее все

/*Add Proportional on Measurement, if P_ON_M is specified*/
      if(!pOnE) outputSum-= kp * dInput;

      if(outputSum > outMax) outputSum= outMax;
      else if(outputSum < outMin) outputSum= outMin;

      /*Add Proportional on Error, if P_ON_E is specified*/
	   double output;
      if(pOnE) output = kp * error;
      else output = 0;

      /*Compute Rest of PID Output*/
      output += outputSum - kd * dInput;

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Umka пишет:

Но не так немного. Рассогласование есть, нет приращения. В комнате температура 22,5 градуса. По DS измеряю. Задаю скажем 28 в термостате. Выход ПИД (П) становится 113 и стоит как вкопаный. И маленький, 0,1 задан, И и Д вообще можно на прерку в 0 сделать, пропорция должна суммироваться. Так библиотека ПИД работает. Она повышает постоянно выходной коэффициент до максимума. С прогрессией. А тут посчитали разницу, добавили ее к среднему и стоим. Нет движения вверх. Рассогласование уменьшать если (грею пальцами DS), то и выходной коэффициент уменьшается. Ну оно и понятно, прибавляется меньшее рассогласование. Да, в И есть сумма, а в П нету. 

Может надо p = (temp < ust - d_ctl) ? p_max : (temp > ust) ? p_min : p + (kP * e);

В П суммы не должно быть (П это пропорционально ошибке и ни какой информации (сумме ошибок) она в отличие от И не несет.

Увеличивайте И.

Я не могу понять почему у Вас П=113

Полность секцию ПИД с дефайнами выложте.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

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

После кИ и кД выставляем в 0

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

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Umka пишет:

Так библиотека ПИД работает. Она повышает постоянно выходной коэффициент до максимума. С прогрессией. А тут посчитали разницу, добавили ее к среднему и стоим. Нет движения вверх. Рассогласование уменьшать если (грею пальцами DS), то и выходной коэффициент уменьшается. Ну оно и понятно, прибавляется меньшее рассогласование. Да, в И есть сумма, а в П нету. 

Может надо p = (temp < ust - d_ctl) ? p_max : (temp > ust) ? p_min : p + (kP * e);

На выходе регулятора складываются П+И+Д. Постоянно приростать может только И.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Я уставки не менял, только P = 20 сделал. Да, скорее всего проблема с частотой вызова функции. 113 это выходной ПИД коэффициент при максимальном 255. Он не меняется при i=0.1, вообще не увеличивается, даже за 2 часа на столе. А если этих 113 попугаев на выходе не достаточно для нагрева? В общем смысл вроде уяснил. Либо Ki больше делать, либо чаще пересчет запускать. 1 раз в секунду слишком мало. В ПИД библиотеке по умолчанию 100мС стоит.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Вызов PIDctl(Temp, setTemp); раз в секунду.

Температура и settemp просто заданы констатами. 22.0 и 37.0 соответственно. Что-то не так опять. Будто переменная Ki сбрасывается.

 

// автономный ПИД термостат с диммером на ATtiny85
//

#include <EEPROM.h>
#include <OneWire.h>
#define DETECT 1      //Детектор ноля
#define GATE 3        //управление симистором
#define PULSE 5       //ширина управляющего импульса на симистор
#define RESISTOR 4    //Светодиод совместно с кнопкой

//расчет мощности по ПИД закону регулирования
//Параметры регулятора
#define kP 20//коэффициент пропорциональности
#define p_min 0.0//минимум П составляющей - не < 0
#define p_max 100.0//максимум П составляющей - не > 100
#define kI 0.500//коэффициент интегрирования
#define i_min 0.0//минимум И составляющей
#define i_max 30.0//максимум И составляющей
#define kd 0.5//коэффициент диференциирования
#define d_ctl 7.0//зона пропорциональности ust-d_ctl
#define out_min 0//минимальный выходной %
#define out_max 254//максимальный выходной %
#define START_CONVERT 0
#define READ_TEMP 1
#define interval 1000UL

unsigned long prevmillis = 0;
//boolean state = 0;
//boolean statePrevios = 0;
// state 1 - светодиод светится, пин=выход
// state 0 светодиод не светится, пин=вход
volatile byte Value, ocr, jj;
float Temp;
const unsigned int TRHSTEP   = 1000;  // Период опроса датчиков
unsigned long trhMillis = 0;
OneWire ds(10);

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


void loop() {
  if (millis() - prevmillis >= 1500) {
    float tempSet = 37.0;
    //float tempSet = map(analogRead(RESISTOR), 0, 1023, 20, 40);
    EEPROM.put(10, tempSet);
    prevmillis = millis();
  }
  thermostat();
}


uint8_t PIDctl(float temp, float ust) {
  uint8_t out = 0;
  static float i = 0;
  static float ed = 0;
  float e, p;
  float d;
  e = (ust - temp); //ошибка регулирования
  p = (temp < ust - d_ctl) ? p_max : (temp > ust) ? p_min : (kP * e); //П составляющая
  i = (i < i_min) ? i_min : (i > i_max) ? i_max : i + (kI * e); //И составляющая
  d = kd * (e - ed); //Д составляющая
  ed = e;
  out = (p + i + d < out_min) ? out_min : (p + i + d > out_max) ? out_max : p + i + d;
  return out;
}

int tempProcess(boolean ch) {
  int t = 0;
  if (!ch) {
    ds.reset();
    ds.write(0xCC);
    ds.write(0x44);
  }
  else {
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    t = ds.read();
    t = t | (ds.read() << 8);
    return  (t * 10) >> 4; //целое в десятых *C (214=>21,4*C)
  }
}

void thermostat() {
  unsigned long curMillis = millis();          // Получаем текущее время работы
  if (curMillis - trhMillis >= TRHSTEP) {    // время для нового измерения?
    trhMillis = curMillis;
    Temp = tempProcess(READ_TEMP);//читаем темпратуру с далласа
    Temp = (float) Temp / 10;
    Temp = 20.0;
    //Serial.println(Temp);
    tempProcess(START_CONVERT); // сразу запрос на конвертацию
    float setTemp;
    EEPROM.get(10, setTemp);
    Value = PIDctl(Temp, setTemp);
    Serial.println(Value);
    ocr = map(Value, 5, 254, 250, 30);
    //Serial.println(ocr);
  }
}

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Попробуйте вместо
i = (i < i_min) ? i_min : (i > i_max) ? i_max : i + (kI * e); //И составляющая
Это
i = (i < i_min) ? i_min : (i > i_max) ? i_max : i += (kI * e); //И составляющая

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Двойное присваивание? Попробовал. Совершенно тот же результат. Залейте код в любую Ардуинку и посмотрите в порт. 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Но у меня и так работало. Может Вам пока кД уменьшить или воопще в 0 выставить, а кП увеличивать пока куставке неприблизетесь.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Нет, тут что-то не так. При Kd = 0 тот же результат. Почему оно I не суммирует?

Andrey12
Andrey12 аватар
Offline
Зарегистрирован: 26.12.2014

Umka пишет:

void loop() {
  if (millis() - prevmillis >= 1500) {
    float tempSet = 37.0;
    //float tempSet = map(analogRead(RESISTOR), 0, 1023, 20, 40);
    EEPROM.put(10, tempSet);
    prevmillis = millis();
  }
  thermostat();
}

Немного не по теме, но строка 47 убъет EPPROM за 2 дня :-(

Если я провильно посчитал 40 вывозов в минуту, 2400 в час, 57600 в сутки. Ресурс у EEPROM 100 000 циклов записи.

 

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Нет, put пишет только изменившееся значение. 

Пруф https://www.arduino.cc/en/Reference/EEPROMPut

Note

This function uses EEPROM.update() to perform the write, so does not rewrites the value if it didn't change.

 

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Вывел i в монитор.

8.50
17.00
25.50
34.00
30.00
38.50
30.00
38.50
30.00
38.50
30.00
 
Роем дальше. 
Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Нашел #define i_max 30.0//максимум И составляющей

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Да. Можете до 255 поднять
Просто в моем случае И более 15 не поднималось в установившемся режиме и я ограничил его 30
Ещё p_max установите в 255

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Фух, ну разобрались. Спасибо. Разъясните пожалуйста смысл d_ctl 

Andrey12
Andrey12 аватар
Offline
Зарегистрирован: 26.12.2014

Umka пишет:

Нет, put пишет только изменившееся значение. 

Пруф https://www.arduino.cc/en/Reference/EEPROMPut

Note

This function uses EEPROM.update() to perform the write, so does not rewrites the value if it didn't change.

 

Спасиб, век живи век учись :-)

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Смысл EEPROM.put(); и EEPROM.get(); в том что пишется только изменение и любой тип переменных автоматически поддерживается. Надо бы и на этом сайте в разделе Программирования это дописать. Эти функции класса EEPROM относительно недавно появились.

Andrey12
Andrey12 аватар
Offline
Зарегистрирован: 26.12.2014

Umka пишет:

Смысл EEPROM.put(); и EEPROM.get(); в том что пишется только изменение и любой тип переменных автоматически поддерживается. Надо бы и на этом сайте в разделе Программирования это дописать. Эти функции класса EEPROM относительно недавно появились.

Да дело в том что сам использую, пишу структуры в EEPROM, вот про  EEPROM.update() прочитал, но как то всегда был уверен что если есть  EEPROM.update() то EEPROM.put() именно переписывает информацию без доп проверок. Спасибо за подсказку перечитал справку, понял разницу :-)

С ПИД алгоритмом то удалось разобраться я так понял?

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Да, все пошло.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Umka пишет:

Фух, ну разобрались. Спасибо. Разъясните пожалуйста смысл d_ctl 


В диапазоне между (ust-d_ctl) и ust рассчитывается регулятор, если текущая температура ниже (ust-d_ctl) то П = макс. значению, если выше ust то П = мин.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Umka пишет:

Да, все пошло.


Ну и хорошо.
Попозже немного допилю ПИД, есть некоторые мысли ещё.
И автонастройку написать хочу.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

А это реально на медленных процессах? У меня либа autotune странное выдавала.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

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

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Ок, ждем с нетерпением! Хотябы адаптивный подбор коэффициентов.

Andrey12
Andrey12 аватар
Offline
Зарегистрирован: 26.12.2014

Umka пишет:

Либо Ki больше делать, либо чаще пересчет запускать. 1 раз в секунду слишком мало. В ПИД библиотеке по умолчанию 100мС стоит.

То есть выво пересчета ПИД надо запускать чем чаще тем лучше? Период вызова 1 раз в секунду уже плохо?
Либо есть какойто рекомендованый период запуска пересчета? 

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Смотря с какого датчика параметр получать и от скорости реакции (постянной времени) всей системы зависит. DS18B20 считает температуру 750мС, то есть чаще чем почти раз в секунду новые данные не прийдут, а тепловая инерция у него куда больше, особенно в гильзе когда. А квадрик за это время упадет уже с такой стабилизацией. Тот же аналоговый LM35 может 1000 раз в секунду данные выдать, но толку от этого, если они с шумом будут и опять же тепловая инерция у него. Но тема про инкубаторы, а инкубатор за секунду свой режим не изменит. Так что пойдет. Это баржа груженая на реке. Ей рулить как катером легким не получится. 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Umka пишет:

Да, все пошло.


А можете график с П,И, уставкой и текущей одновременно выложить?
Или устава температура и выход регулятора.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Завтра, на работе железки.

AleksandrM
Offline
Зарегистрирован: 20.07.2017

MOC3040 Подходит к этому варианту?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

AleksandrM пишет:

MOC3040 Подходит к этому варианту?

Подойдет хоть реле, только управлять надобудет так называемым медленным ШИМ.

AleksandrM
Offline
Зарегистрирован: 20.07.2017

Спасибо .Я так понял что нужен оптрон без Zero contpol?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

AleksandrM пишет:

Спасибо .Я так понял что нужен оптрон без Zero contpol?

И с ним можно.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Есть диммер автономный если кому надо.

http://arduino.ru/forum/programmirovanie/attiny85-i-preryvanie?

Графики не могу сегодня сделать - кабель дома забыл.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Трогал термометр в процессе. Вроде работает. Грелку позже прицеплю и в реале испытаем.

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

С грелкой интереснее конечно будет выход на уставку посмотреть. Будем подождать.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012
Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Красиво. Но "цветомузыка" убила.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

 

Вот так с грелкой-галогенкой на столе. Не настраивал.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

 

Подвинул датчик ближе. ШИМ от 1 уже светит. 43градуса это ого!

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

А на уставке ровно держится? Колебания спадают?

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

не, не ровно. Колбасит 0,4 туда-сюда. Но на открытом воздухе это невозможно, воздух движется как хочет между лампой и датчиком. Надо в коробочку. Вот приедет на днях человек, забиру коробочку инкубаторную из сендвича. Там и погоняем тогда.

AleksandrM
Offline
Зарегистрирован: 20.07.2017

Рисую свою плату под инкубатор на платформе НАНО.

Можно ли использовать выводы А6,А7  на плате НАНО как обычные линии ввода-вывода?

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012
AleksandrM
Offline
Зарегистрирован: 20.07.2017

Спасибо.

Т-есть можно выводы А6иА7 использовать как стандартный дигитальный выход.

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Нет, только A6 можно. A7 в другом регистре. Разве трудно посчитать? А0 это 14, А6 - 19.