• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Arduino nano PID control

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

Last edited:

Latest threads

EE World Online Articles

Loading
Top