ArduWir
Вы хотите отреагировать на этот пост ? Создайте аккаунт всего в несколько кликов или войдите на форум.

ПИ регулятор отопления

Перейти вниз

Чего нехватает?

ПИ регулятор отопления Vote_lcap0%ПИ регулятор отопления Vote_rcap 0% 
[ 0 ]
ПИ регулятор отопления Vote_lcap0%ПИ регулятор отопления Vote_rcap 0% 
[ 0 ]
ПИ регулятор отопления Vote_lcap0%ПИ регулятор отопления Vote_rcap 0% 
[ 0 ]
ПИ регулятор отопления Vote_lcap0%ПИ регулятор отопления Vote_rcap 0% 
[ 0 ]
 
Всего проголосовало : 0
 
 
Опрос закрыт

ПИ регулятор отопления Empty ПИ регулятор отопления

Сообщение  Admin Ср 23 Мар 2016 - 14:01

ПИ регулятор отопления Img_20151207_125633
Представляю ПИ терморегулятор на микроконтроллере ATMega8. Прошивка написана в среде Ардуино и залита через Arduino ISP. В качестве датчика температуры использован NTC терморезистор на 10кОм при 20 градусах цельсия. Регулятор имеет релейный выход, выбор реле осуществляеться по необходимой мощности нагревателя. Регулятор можно использовать как с электроконвекторами так и с другими нагревательными приборами. Регулятор может выдавать мощность с точностью до 1% (в связи с тем что выход релейный а продолжительность минимального управляющего воздействия 500мс минимальная мощность ограничена 4%-2сек.). По сути организован медленный ШИМ с периодом 500мс.
Небольшая особенность представленной схемы в том что питание на терморезистор подаеться только в момент измерения, что помогает избежать саморазогрев терморезистора. На схеме не указан LCD но из скетча должно быть понятно к каким выводам он подключен.
ПИ регулятор отопления Termistor
Код:


        //кнопки А0, реле 13,12 подсветка 10
        #include <LiquidCrystal.h>
        #define key_in analogRead(0)//вход аналоговых кнопок
        #define T_Sensor_OFF digitalWrite(16,LOW)//отключить термистор
        #define T_Sensor_ON digitalWrite(16,HIGH)//включить термистор
        #define HI_OFF digitalWrite(13,LOW)//отключить реле HI
        #define HI_ON digitalWrite(13,HIGH)//включить реле HI
        //#define LO_OFF digitalWrite(12,LOW)//отключить реле LO
        //#define LO_ON digitalWrite(12,HIGH)//включить реле LO
        #define n_f 10.0//температура по умолчанию
        #define p_s 50//частота обновления экрана
        #define t_pwm 600//период ШИМ
        #define t_time 1000//период опроса температуры
        //для ПИ регулятора
        float p,i;
        LiquidCrystal lcd(7,6,5,4,3,2);
        long time;//интервал замера температуры
        long lcd_time;//интервал отрисовки экрана
        long on_time;//для периода ШИМ
        int zad=0;
        int k_b[]={
        512,683,768};//аналоговые кнопки SET + -
        float temp=0.0;//текущее значение температуры
        float pre_temp=0.0;//предыдущее значение температуры
        int w=0;
        float ust=n_f;//termostate
        int c=0;//пройденые циклы мощности
        float addr[25][2] = {
        {
        0,32.0
        }
        ,
        {
        5,25.5
        }
        ,
        {
        10,20.0
        }
        ,
        {
        15,15.7
        }
        ,
        {
        20,12.62
        }
        ,
        {
        25,10.0
        }
        ,
        {
        30,8.24
        }
        ,
        {
        35,6.63
        }
        ,
        {
        40,5.41
        }
        ,
        {
        45,4.41
        }
        ,
        {
        50,3.62
        }
        ,
        {
        55,2.99
        }
        ,
        {
        60,2.48
        }
        ,
        {
        65,2.08
        }
        ,
        {
        70,1.75
        }
        ,
        {
        75,1.47
        }
        ,
        {
        80,1.258
        }
        ,
        {
        85,1.063
        }
        ,
        {
        90,0.905
        }
        ,
        {
        95,0.776
        }
        ,
        {
        100,0.669
        }
        ,
        {
        105,0.581
        }
        ,
        {
        110,0.505
        }
        ,
        {
        115,0.442
        }
        ,
        {
        120,0.387
        }
        ,
        };
        byte cel[] =
        {
        0b01000,
        0b10100,
        0b01000,
        0b00111,
        0b01000,
        0b01000,
        0b00111
        };
        void setup(){
        // Serial.begin(9600);
        pinMode(13,OUTPUT);//реле HI
        // pinMode(12,OUTPUT);//реле LO
        pinMode(16,OUTPUT);//питание термистора
        T_Sensor_OFF;
        HI_OFF;//отключить реле HI
        // LO_OFF;//отключить реле LO
        lcd.begin(16, 2);
        analogWrite(10,250);//подсветка
        time = millis();
        lcd_time = time;
        on_time = time;
        lcd.createChar(1, cel);
        }
        void loop(){
        key();//опрос кнопок
        if (time>millis()){//защита от переполнения
        time=millis();
        lcd_time=time;
        on_time=time;
        }
        //---------------чтение температуры---------------
        if ((millis()-time)>=t_time){
        time=millis();
        temp=getTemp();
        temp=(pre_temp*0.2)+(temp*0.8);//фильтр
        // w=abs((ust-temp)*(pre_temp-temp));//время выхода на уставку
        pre_temp=temp;
        PIctl();//расчет мощности
        }
        //-------------------вывод на экран----------------
        if ((millis()-lcd_time)>=p_s){//вывод на экран
        lcd_time=millis();
        Screen_print();
        }
        //---------------------управление мощностью--------------------------
        //выдаем мощность
        if (millis()>3000){
        if((millis()-on_time)>=t_pwm){//период ШИМ
        on_time=millis();
        if(c<zad){
        HI_ON;
        }
        else{
        if (zad != 100){
        HI_OFF;
        }
        }
        c=c+1;
        if(c==100){
        c=0;
        //PIctl();
        }
        }
        }
        }
        void PIctl()
{
    if(temp>(ust-0.5)&&temp<(ust+0.5))//зона нечувствительности +-0,5C
  {
    zad=i;
  }
  else
  {
  float e;
  e=(ust-temp);
  // расчет выходной мощности:
  p=130.0*e;//130 коффициент пропорциональности
  if (p<0.0)
  {
    p=0.0;//ограничение P
  }
  i=(i+(e*0.014));//0.7
  if (i>100.0)
  {
    i=100.0;//ограничение I
  }
    if (i<-100.0)
  {
    i=-100.0;//ограничение I
  }
  //расчет выходной мощности
  zad=p+i;
  }
  //ограничение управляющего сигнала
  //для исключения частого переключения реле
  //если твердотельное реле, можно не ограничивать
  if (zad<4){
    zad=0;
  }
  if (zad>96){
    zad=100;
  }
//корректировка при отклонении температуры более чем на +-2С
//для быстрого выхода на уставку
  if (temp<(ust-2.0))//если темп < уст на 2С
  {
    zad=100;//то мощность 100%
    i=0;
  }
  if (temp>(ust+2.0))//если темп > уст на 2С
  {
    zad=0;//то мощность 0%
    i=0;
  }
}
        //----------------опрос клавиш-------------------------------
        void key(){
        int x;
        x = key_in;
        if (x>k_b[0]-5 && x<k_b[0]+5){//МЕНЮ
        UP_butt();
        key_m(0);
        }
        if (x>k_b[1]-5 && x<k_b[1]+5){// +
        UP_butt();
        key_m(1);
        }
        if (x>k_b[2]-5 && x<k_b[2]+5){// -
        UP_butt();
        key_m(2);
        }
        }
        //---------------проверка отпускания кнопки-----------------
        void UP_butt(){
        while (key_in<1010){//ждем отпускания кнопки
        }
        }
        //------------------замер температуры----------------------
        double getTemp()
        {
        T_Sensor_ON;
        delay(10);//задержка при подаче питания терморезистора
        int t;
        t=0;
        for (int i=0; i <= 15; i++){
        //for (int i=0; i <= 4; i++){
        t = t + analogRead(1);
        }
        // T_Sensor_OFF;
        t=t/4;
        //t=t/5;
        float R;
        R=getR(t);
        int i=0;
        while (addr[i][1] >R)
        {
        i++;
        }
        double result;
        result=(R-addr[i][1])*(addr[i-1][0]-addr[i][0])/(addr[i-1][1]-addr[i][1])+addr[i][0];
        return result;
        }
        float getR(float V)
        {
        float result;
        result=-10*V/(V-4096);
        //result=-10*V/(V-1024);
        T_Sensor_OFF;
        return result;
        }
        //-----------------обработка кнопок-------------------------
        void key_m(int x){
        // lcd.clear();
        switch (x){
        case 0://menu
        ust=10;
        break;
        case 1://кнопка +
        ust++;
        if (ust>35){
        ust=35;
        }
        break;
        case 2://кнопка -
        ust--;
        if (ust<5){
        ust=5;
        }
        break;
        }
        }
        int oversempling(){
        T_Sensor_ON;
        delay(10);//задержка при подаче питания терморезистора
        int o;
        o=0;
        for (int i=0; i <= 15; i++){//оверсемплинг до 4096
        //for (int i=0; i <= 4; i++){
        o = o + analogRead(1);
        }
        T_Sensor_OFF;
        o=o/4;
        //t=t/5;
        return o;
        }
        void Screen_print()
        {
        byte a=0;
        byte b=0;
        tempPrint(temp,0,0);
        tempPrint(ust,0,1);
        lcd.setCursor(6, 0);
        lcd.print(zad);
        lcd.print("% ");
        varPrint(i,"I ",6,1);
        // lcd.print("I ");
        lcd.setCursor(12, 0);
        lcd.print(c);
        lcd.print("m ");
        a=digitalRead(13);
        b=digitalRead(12);
        if (a==1 && b==0){
        lcd.setCursor(12, 1);
        lcd.print("HI ");
        }
        if (a==0 && b==1){
        lcd.setCursor(12, 1);
        lcd.print("LO ");
        }
        if (a==0 && b==0){
        lcd.setCursor(12, 1);
        lcd.print("OFF");
        }
        }
        //-------------вывод температуры----------------------------
        void tempPrint(double t, int x, int y){
        lcd.setCursor(x, y);
        lcd.print(t);
        lcd.setCursor(x+4, y);
        lcd.print(char(1));//вывод градусов
        }
        //---------------вывод переменной-------------------------
        void varPrint (double v, char* t, int x, int y){
        lcd.setCursor(x, y);
        lcd.print(v);
        lcd.print(t);
        }


Admin
Admin

Сообщения : 21
Дата регистрации : 2012-12-11

https://allduino.forum2x2.ru

Вернуться к началу Перейти вниз

Вернуться к началу


 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения