نمایش نتایج: از 1 به 2 از 2

موضوع: کنترل pid دمای هیتر 220ولت با سنسور ds18b20

  1. #1
    Junior Member
    تاریخ عضویت
    May 2016
    نوشته ها
    22

    کنترل pid دمای هیتر 220ولت با سنسور ds18b20

    سلام
    من میخوام دمای یک هیتر 220 ولت رو به صورت pid و با سنسور ds18b20 کنترل کنم.
    توی این سایت ( https://electronoobs.com/eng_arduino_tut39.php ) ی پروژه بود ک اومده قسمت 220 رو با ی ترایاک و ی اپتو کوپلر 3020 کنترل میکنه و نقطه 0 برق 220 رو هم با ی پل دیود و ی اپتو 817 به میکرو میده.فقط قسمت خوندن دما اومده از ترموکوپل استفاده کرده ک من تو برنامه به جای ترموکوپل اومدم سنسور رو قرار دادم.مدار برابر شماتیک https://electronoobs.com/images/Ardu...tic_AC_PID.png بسته شده فقط ترموکوپل حذف و سنسور ds 18b20 قرار داده شده.بعد تصحیح کد پروژه من مدار رو بستم برای تست به ترموکوپل 3021 ولتاژ دادم و هیتر گرم شد و مطمعن شدم قسمت 220 و ترایات کاملا درسته، خروجی اپتو 817 رو هم چک کردم داره درست کار میکنه ولی پایه 3 ک حاصل برآیند همه محاسبات و اعمال فرمان به اپتو هست بدون توجه به دمای هیتر و دمای ست پوینت یک سره 100میکروثانیه روشنو خاموش میشه و هیتر اصلا گرم نمیشه.من کدها رو قرار میدم اگه ممکنه راهنمایی بفرمایید
    کد اصلی:
    کد:
    /*    Max6675 Module  ==>   Arduino
     *    CS              ==>     D10
     *    SO              ==>     D9
     *    SCK             ==>     D13
     *    Vcc             ==>     Vcc (5v)
     *    Gnd             ==>     Gnd      */
    
    //LCD config
    #include "max6675.h"
    #include <Wire.h> 
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C lcd(0x27,20,4);  //sometimes the adress is not 0x27. Change to 0x3f if it dosn't work.
    
    /*    i2c LCD Module  ==>   Arduino
     *    SCL             ==>     A5
     *    SDA             ==>     A4
     *    Vcc             ==>     Vcc (5v)
     *    Gnd             ==>     Gnd      */
    
    //Inputs and outputs
    int firing_pin = 3;
    int increase_pin = 11;
    int decrease_pin = 12;
    int zero_cross = 8;
    int thermoDO = 9;
    int thermoCS = 10;
    int thermoCLK = 13;
    
    //Start a MAX6675 communication with the selected pins
    MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
    
    
    //Variables
    int last_CH1_state = 0;
    bool zero_cross_detected = false;
    int firing_delay = 7400;
    
    //////////////////////////////////////////////////////
    int maximum_firing_delay = 7400;
    /*Later in the code you will se that the maximum delay after the zero detection
     * is 7400. Why? Well, we know that the 220V AC voltage has a frequency of around 50-60HZ so
     * the period is between 20ms and 16ms, depending on the country. We control the firing
     * delay each half period so each 10ms or 8 ms. To amke sure we wont pass thsoe 10ms, I've made tests
     * and the 7400us or 7.4ms was a good value. Measure your frequency and chande that value later */
    //////////////////////////////////////////////////////
    
    unsigned long previousMillis = 0; 
    unsigned long currentMillis = 0;
    int temp_read_Delay = 500;
    int real_temperature = 0;
    int setpoint = 100;
    bool pressed_1 = false;
    bool pressed_2 = false;
    
    //PID variables
    float PID_error = 0;
    float previous_error = 0;
    float elapsedTime, Time, timePrev;
    int PID_value = 0;
    //PID constants
    int kp = 203;   int ki= 7.2;   int kd = 1.04;
    int PID_p = 0;    int PID_i = 0;    int PID_d = 0;
    
    
    
    
    
    
    void setup() {
      //Define the pins
      pinMode (firing_pin,OUTPUT); 
      pinMode (zero_cross,INPUT); 
      pinMode (increase_pin,INPUT); 
      pinMode (decrease_pin,INPUT);   
      PCICR |= (1 << PCIE0);    //enable PCMSK0 scan                                                 
      PCMSK0 |= (1 << PCINT0);  //Set pin D8 (zero cross input) trigger an interrupt on state change.
      PCMSK0 |= (1 << PCINT3);  //Set pin D11 (increase button) trigger an interrupt on state change.
      PCMSK0 |= (1 << PCINT4);  //Set pin D12 (decrease button) trigger an interrupt on state change.    
      lcd.init();       //Start the LC communication
      lcd.backlight();  //Turn on backlight for LCD
    }
    
    
    void loop() {    
      currentMillis = millis();           //Save the value of time before the loop
       /*  We create this if so we will read the temperature and change values each "temp_read_Delay"
        *  value. Change that value above iv you want. The MAX6675 read is slow. Tha will affect the
        *  PID control. I've tried reading the temp each 100ms but it didn't work. With 500ms worked ok.*/
      if(currentMillis - previousMillis >= temp_read_Delay){
        previousMillis += temp_read_Delay;              //Increase the previous time for next loop
        real_temperature = thermocouple.readCelsius();  //get the real temperature in Celsius degrees
    
        PID_error = setpoint - real_temperature;        //Calculate the pid ERROR
        
        if(PID_error > 30)                              //integral constant will only affect errors below 30ºC             
        {PID_i = 0;}
        
        PID_p = kp * PID_error;                         //Calculate the P value
        PID_i = PID_i + (ki * PID_error);               //Calculate the I value
        timePrev = Time;                    // the previous time is stored before the actual time read
        Time = millis();                    // actual time read
        elapsedTime = (Time - timePrev) / 1000;   
        PID_d = kd*((PID_error - previous_error)/elapsedTime);  //Calculate the D value
        PID_value = PID_p + PID_i + PID_d;                      //Calculate total PID value
    
        //We define firing delay range between 0 and 7400. Read above why 7400!!!!!!!
        if(PID_value < 0)
        {      PID_value = 0;       }
        if(PID_value > 7400)
        {      PID_value = 7400;    }
        //Printe the values on the LCD
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Set: ");
        lcd.setCursor(5,0);
        lcd.print(setpoint);
        lcd.setCursor(0,1);
        lcd.print("Real temp: ");
        lcd.setCursor(11,1);
        lcd.print(real_temperature);
        previous_error = PID_error; //Remember to store the previous error.
      }
    
      //If the zero cross interruption was detected we create the 100us firing pulse  
      if (zero_cross_detected)     
        {
          delayMicroseconds(maximum_firing_delay - PID_value); //This delay controls the power
          digitalWrite(firing_pin,HIGH);
          delayMicroseconds(100);
          digitalWrite(firing_pin,LOW);
          zero_cross_detected = false;
        } 
    }
    //End of void loop
    // |
    // |
    // |
    // v
    //See the interruption vector
    
    
    
    
    
    
    
    
    
    //This is the interruption routine (pind D8(zero cross), D11(increase) and D12(decrease))
    //----------------------------------------------
    
    ISR(PCINT0_vect){
      ///////////////////////////////////////Input from optocoupler
      if(PINB & B00000001){            //We make an AND with the state register, We verify if pin D8 is HIGH???
        if(last_CH1_state == 0){       //If the last state was 0, then we have a state change...
          zero_cross_detected = true;  //We have detected a state change! We need both falling and rising edges
        }
      }
      else if(last_CH1_state == 1){    //If pin 8 is LOW and the last state was HIGH then we have a state change      
        zero_cross_detected = true;    //We haev detected a state change!  We need both falling and rising edges.
        last_CH1_state = 0;            //Store the current state into the last state for the next loop
        }
    
        if(PINB & B00100000){          //We make an AND with the state register, We verify if pin D11 is HIGH???
          if (!pressed_1)
          {
            setpoint = setpoint + 5;   //Increase the temperature by 5. Change this with your value if you want.
            delay(20);
            pressed_1 = true;
          }
        }
        else if (pressed_1)
        {
          pressed_1 = false;
        }
    
        if(PINB & B00010000){          //We make an AND with the state register, We verify if pin D12 is HIGH???
          if (!pressed_2)
          {
            setpoint = setpoint - 5;   //Decrease the temperature by 5. Change this with your value if you want.
            delay(20);
            pressed_2 = true;
          }
        }
        else if (pressed_2)
        {
          pressed_2 = false;
        }
    }
    //End of interruption vector for pins on port B: D8-D13

  2. #2
    Junior Member
    تاریخ عضویت
    May 2016
    نوشته ها
    22
    کدی ک من تغییرات دادم:
    کد:
    #include <OneWire.h>
    #include <DallasTemperature.h>
    #define ONE_WIRE_BUS 2
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    
    //Inputs and outputs
    int firing_pin = 3;
    int increase_pin = 11;
    int decrease_pin = 12;
    int zero_cross = 8;
    
    //Variables
    int last_CH1_state = 0;
    bool zero_cross_detected = false;
    int firing_delay = 7400;
    
    //////////////////////////////////////////////////////
    int maximum_firing_delay = 7400;
    /*Later in the code you will se that the maximum delay after the zero detection
     * is 7400. Why? Well, we know that the 220V AC voltage has a frequency of around 50-60HZ so
     * the period is between 20ms and 16ms, depending on the country. We control the firing
     * delay each half period so each 10ms or 8 ms. To amke sure we wont pass thsoe 10ms, I've made tests
     * and the 7400us or 7.4ms was a good value. Measure your frequency and chande that value later */
    //////////////////////////////////////////////////////
    
    unsigned long previousMillis = 0; 
    unsigned long currentMillis = 0;
    int temp_read_Delay = 500;
    int real_temperature = 0;
    int setpoint = 60;
    bool pressed_1 = false;
    bool pressed_2 = false;
    
    //PID variables
    float PID_error = 0;
    float previous_error = 0;
    float elapsedTime, Time, timePrev;
    int PID_value = 0;
    //PID constants
    int kp = 203;   int ki= 7.2;   int kd = 1.04;
    int PID_p = 0;    int PID_i = 0;    int PID_d = 0;
    
    
    
    
    
    
    void setup() {
      //Define the pins
      pinMode (firing_pin,OUTPUT); 
      pinMode (zero_cross,INPUT); 
      pinMode (increase_pin,INPUT); 
      pinMode (decrease_pin,INPUT); 
      Serial.begin (9600);
      sensors.begin();  
      PCICR |= (1 << PCIE0);    //enable PCMSK0 scan                                                 
      PCMSK0 |= (1 << PCINT0);  //Set pin D8 (zero cross input) trigger an interrupt on state change.
      PCMSK0 |= (1 << PCINT3);  //Set pin D11 (increase button) trigger an interrupt on state change.
      PCMSK0 |= (1 << PCINT4);  //Set pin D12 (decrease button) trigger an interrupt on state change.  
    }
    
    
    void loop() { 
        
      currentMillis = millis();           //Save the value of time before the loop
       /*  We create this if so we will read the temperature and change values each "temp_read_Delay"
        *  value. Change that value above iv you want. The MAX6675 read is slow. Tha will affect the
        *  PID control. I've tried reading the temp each 100ms but it didn't work. With 500ms worked ok.*/
      if(currentMillis - previousMillis >= temp_read_Delay){
        previousMillis += temp_read_Delay;              //Increase the previous time for next loop
        sensors.requestTemperatures(); 
        real_temperature = sensors.getTempCByIndex(0);  //get the real temperature in Celsius degrees
        Serial.println(real_temperature);
        Serial.println(PID_error);
        Serial.println(setpoint);
        Serial.println(maximum_firing_delay);
        PID_error = setpoint - real_temperature;        //Calculate the pid ERROR
        
        if(PID_error > 30)                              //integral constant will only affect errors below 30ºC             
        {PID_i = 0;}
        
        PID_p = kp * PID_error;                         //Calculate the P value
        PID_i = PID_i + (ki * PID_error);               //Calculate the I value
        timePrev = Time;                    // the previous time is stored before the actual time read
        Time = millis();                    // actual time read
        elapsedTime = (Time - timePrev) / 1000;   
        PID_d = kd*((PID_error - previous_error)/elapsedTime);  //Calculate the D value
        PID_value = PID_p + PID_i + PID_d;                      //Calculate total PID value
    
        //We define firing delay range between 0 and 7400. Read above why 7400!!!!!!!
        if(PID_value < 0)
        {      PID_value = 0;       }
        if(PID_value > 7400)
        {      PID_value = 7400;    }
    
        previous_error = PID_error; //Remember to store the previous error.
      }
    
      //If the zero cross interruption was detected we create the 100us firing pulse  
      if (zero_cross_detected)     
        {
          delayMicroseconds(maximum_firing_delay - PID_value); //This delay controls the power
          digitalWrite(firing_pin,HIGH);
          delayMicroseconds(100);
          digitalWrite(firing_pin,LOW);
          zero_cross_detected = false;
        } 
    }
    //End of void loop
    // |
    // |
    // |
    // v
    //See the interruption vector
    
    
    
    
    
    
    
    
    
    //This is the interruption routine (pind D8(zero cross), D11(increase) and D12(decrease))
    //----------------------------------------------
    
    ISR(PCINT0_vect){
      ///////////////////////////////////////Input from optocoupler
      if(PINB & B00000001){            //We make an AND with the state register, We verify if pin D8 is HIGH???
        if(last_CH1_state == 0){       //If the last state was 0, then we have a state change...
          zero_cross_detected = true;  //We have detected a state change! We need both falling and rising edges
        }
      }
      else if(last_CH1_state == 1){    //If pin 8 is LOW and the last state was HIGH then we have a state change      
        zero_cross_detected = true;    //We haev detected a state change!  We need both falling and rising edges.
        last_CH1_state = 0;            //Store the current state into the last state for the next loop
        }
    
        if(PINB & B00100000){          //We make an AND with the state register, We verify if pin D11 is HIGH???
          if (!pressed_1)
          {
            setpoint = setpoint + 5;   //Increase the temperature by 5. Change this with your value if you want.
            delay(20);
            pressed_1 = true;
          }
        }
        else if (pressed_1)
        {
          pressed_1 = false;
        }
    
        if(PINB & B00010000){          //We make an AND with the state register, We verify if pin D12 is HIGH???
          if (!pressed_2)
          {
            setpoint = setpoint - 5;   //Decrease the temperature by 5. Change this with your value if you want.
            delay(20);
            pressed_2 = true;
          }
        }
        else if (pressed_2)
        {
          pressed_2 = false;
        }
    }
    //End of interruption vector for pins on port B: D8-D13

مجوز های ارسال و ویرایش

  • شما نمیتوانید موضوع جدیدی ارسال کنید
  • شما امکان ارسال پاسخ را ندارید
  • شما نمیتوانید فایل پیوست کنید.
  • شما نمیتوانید پست های خود را ویرایش کنید
  •  

SEO by vBSEO