Arduino nano PID control

Status
Not open for further replies.

123mmm

Member
Hello, I have built the attached schematic and I have the attached code.
I have 2 questions:
1. How to correctly write the loop() function ?
2. And how to correctly write the zero() function ?


C:
#include <LiquidCrystal.h>
#include <SPI.h>
#include <Wire.h>
#include <max6675.h>

#define thermoDO 12
#define thermoCS 10
#define thermoCLK 13
#define potentiometer A0
#define zerocrossing 2
#define triac 7
#define relay A1

volatile float temperature, realTemperature;  // I have declared those 2 variables as VOLATILE, because of using them inside and outside ISR
int pottemperature;
int counter;
int duty = 0; // variable for duty cycle

byte thermometer[8] = //icon for termometer
{
  B00100,
  B01010,
  B01010,
  B01110,
  B01110,
  B11111,
  B11111,
  B01110
};

byte arrow[8] = //icon for arrow
{
  B11000,
  B01100,
  B00110,
  B00011,
  B00011,
  B00110,
  B01100,
  B11000
};

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);

/*  The circuit:
   LCD RS pin to digital pin 12
   LCD Enable pin to digital pin 11
   LCD D4 pin to digital pin 5
   LCD D5 pin to digital pin 4
   LCD D6 pin to digital pin 3
   LCD D7 pin to digital pin 2
   LCD R/W pin to ground
   LCD VSS pin to ground
   LCD VCC pin to 5V
   10K resistor:
   ends to +5V and ground
   wiper to LCD VO pin (pin 3)
*/

volatile int pidOut = 0;

double sensed_output, control_signal;
double setPoint;
double Kp; //proportional gain
double Ki; //integral gain
double Kd; //derivative gain
int T = 100; //sample time in milliseconds (ms)
unsigned long last_time = 0;
double total_error, last_error;
int max_control = 0;
int min_control = 240;

LiquidCrystal lcd(3, 4, 5, 6, 8, 9);

void setup() {
  lcd.createChar(0, thermometer);
  lcd.createChar(1, arrow);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("STATIE DE LIPIT");
  delay(1200);
  lcd.clear();
  pinMode(relay, OUTPUT);
  pinMode(potentiometer, INPUT);
  pinMode(zerocrossing, INPUT_PULLUP);
  pinMode(triac, OUTPUT);
  digitalWrite(triac, LOW);
  digitalWrite(relay, HIGH);
  realTemperature = thermocouple.readCelsius();
  temperature = 0.779828 * realTemperature - 10.3427;
  //updateDisplay();
  attachInterrupt(digitalPinToInterrupt(2), zero_crosss_int, RISING);
}

void loop() {  //moved the PID computations outside the ISR
  unsigned long current_time = millis(); //returns the number of milliseconds passed since the Arduino started running the program
  int delta_time = current_time - last_time; //delta time interval
  pottemperature = analogRead(potentiometer);
  pottemperature = map(pottemperature, 0, 1023, 150, 400);
  setPoint = pottemperature;
  realTemperature = thermocouple.readCelsius();
  temperature = int(0.779828 * realTemperature - 10.3427); // make temperature an integer
  sensed_output = temperature;
  updateDisplay();
  if (isnan(realTemperature) || temperature >= 432) {
    while (true) {
      displayErrors();
    }
  }

  if (delta_time >= T) {
    double error = setPoint - sensed_output;
    if (error <= 10) {
      Kp = 4, Ki = 0.2, Kd = 1;
    }
    if (error > 10) {
      Kp = 1, Ki = 0.05, Kd = 0.25;
    }
    total_error += error; //accumalates the error - integral term
    if (total_error >= max_control) total_error = max_control;
    else if (total_error <= min_control) total_error = min_control;
    double delta_error = error - last_error; //difference of error for derivative term
    control_signal = Kp * error + (Ki * T) * total_error + (Kd / T) * delta_error; //PID control compute
    if (control_signal >= max_control) control_signal = max_control;
    else if (control_signal <= min_control) control_signal = min_control;
    last_error = error;
  }
  noInterrupts();
  pidOut = int(control_signal);
  interrupts();
  last_time = current_time;
  delay(250);
}

void zero_crosss_int()
{
  int powertime = (39 * (256 - pidOut));
  delayMicroseconds(powertime);
  digitalWrite(triac, HIGH);
  delayMicroseconds(10);
  digitalWrite(triac, LOW);
}

void updateDisplay() {
  pottemperature = analogRead(potentiometer);
  pottemperature = map(pottemperature, 0, 1023, 150, 400);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.write((byte)0);
  lcd.setCursor(2, 0);
  lcd.print((int)pottemperature);
  lcd.setCursor(6, 0);
  lcd.print((char)223); //degree sign
  lcd.setCursor(7, 0);
  lcd.print("C");
  lcd.setCursor(0, 1);
  lcd.write((byte)1);
  if (temperature <= 45) {
    lcd.setCursor(2, 1);
    lcd.print("Lo");
  } else {
    lcd.setCursor(2, 1);
    lcd.print((int)temperature);
  }
  lcd.setCursor(6, 1);
  lcd.print("[");
  lcd.setCursor(7, 1);
  lcd.print((int)realTemperature);
  lcd.setCursor(10, 1);
  lcd.print("]");
  lcd.setCursor(12, 1);
  lcd.print((char)223);
  lcd.setCursor(13, 1);
  lcd.print("C");
}

void displayErrors() {
  digitalWrite(relay, LOW); // the relay will disconnect the power to the soldering iron heating element
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.write((byte)0);
  lcd.setCursor(1, 0);
  lcd.write((byte)0);
  lcd.setCursor(5, 0);
  lcd.print("ERROR!");
  lcd.setCursor(14, 0);
  lcd.write((byte)0);
  lcd.setCursor(15, 0);
  lcd.write((byte)0);
  delay(500);
}
 

Attachments

  • schematic_ss.png
    33 KB · Views: 356
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…