Arduino Nano zero crossing detection

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
I understood that there is an dead band controller. But I have implemented into my circuit a PID controller.
Should I delete the PID code and introduce the code for the dead band control ?
Or there is a more sophisticated method to combine those 2 types of controller ?
 
Last edited:

Irving

Joined Jan 30, 2016
3,887
No, the PID controller implements an element of deadband as well...

The mapping of error (lowError,highError) to (0,24) gives a deadband.
If errorLow = -15 and errorHigh = +15 then -15 maps to 0, +15 maps to 24, and errors from -0.625 to +0.625 map to 12, the centre point. By adjusting lowError & highError we can control this deadband to some extent.

As said before, the running of the iron at 50% duty cycle may not reduce power enough to maintain control at lower temperatures so we may have to be a bit cleverer... either slowing the measurement cycle down, say to 1 sec, and a count 0 - 99 or going back to bang-bang control at lower temperatures...
 

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
I modified the code like below (line 27):
C:
int lowError = -15;
int highError = 15;


void zero() {
  counter++;
  if ((counter == 24) || (counter > duty)) { //reach max count or duty cycle limit.
    digitalWrite(triac, LOW);
  }
  // else *** remove this
  if (counter >= 25) {
    counter = 0;
    digitalWrite(test, HIGH); // *** added, this will generate a pulse on test pin (5) every 250mS to prove counter incrementing...
    pottemperature = analogRead(potentiometer);
    pottemperature = map(pottemperature, 0, 1023, 150, 400);
    digitalWrite(test, LOW); // *** put test pin low
    realTemperature = thermocouple.readCelsius();
    temperature = int(0.779828 * realTemperature - 10.3427); // make temperature an integer
    if (tempError || isnan(realTemperature) || temperature >= 432) { // on error kill power & set global error flag
      digitalWrite(relay, LOW); // turn off power to iron
      tempError = true; //set error flag. can only be unset outside ISR. Once set no further action taken till unset in main loop.
    }
    else { //reading valid
      if (temperature < pottemperature) { //*** change, remove =
        digitalWrite(test1, HIGH);  // *** added, generate a pulse on test1 (D6) when pottemp >= temp
        error = pottemperature - temperature;  // don't think you need abs() here as t cannot be > pt and get here...
        error = map(error, lowError, highError, 0, 24);
        cumError += error * 250.0; //*** change - something got lost in one of my earlier edits
        rateError = (error - lastError) / 250.0; //*** change
        output = Kp * error + Ki * cumError + Kd * rateError; //output error needs to be mapped to a number between 0 and 24
        duty = map(output, lowError, highError, 0, 24); // lowError is const >= 0, highError is const for fully on.
        duty = constrain(duty, 0, 24); // keep duty between 0 and 24 (24 = 96%)
        if (duty > 0) {
          digitalWrite(triac, HIGH);  //*** change, added '>0'
        }
        lastError = error;
        digitalWrite(test1, LOW); // *** added

      }
      else {
        duty = 0;
      }//if (temperature
    }//if (tempError
  }//if(counter == 25...
}//zero
 

Irving

Joined Jan 30, 2016
3,887
Good, but you need the other edits I did in post #76 as well...

I'm off to give a tutorial (online), back in about 3h or so...
 

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
Please find attached the results for 300 C, 250 C and for 350 C when Kp was 2.5.

LE: I also tried to make a graph based on the information for 350 C temperature and Kp = 2.5.
 

Attachments

Last edited:

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
New test, with lowError = -25 and highError = +25.
Temperature is higher than previous test, even if the setpoint is the same.
Second test, with lowError = -10 and highError = +10.

Latest code used:
C:
int lowError = -10; //guessing for now.  The bigger these values the smaller the deadband either side of 0 error that constitues a 50% duty cycle
int highError = +10;

//PID constants
double Kp = 1;
double Ki = 0;
double Kd = 0;


void zero() {
  counter++;
//*** change this line below
  if (counter>duty) { //reach duty cycle limit, unless duty was 25 in which case leave on until next duty calculated later
    digitalWrite(triac, LOW);
  }

  if (counter >= 25) {
    counter = 0;
    digitalWrite(test, HIGH); //this will generate a pulse on test pin (5) every 250mS to prove counter incrementing...
    pottemperature = analogRead(potentiometer);
    pottemperature = map(pottemperature, 0, 1023, 150, 400);
    digitalWrite(test, LOW); // put test pin low
    realTemperature = thermocouple.readCelsius();
    temperature = int(0.779828 * realTemperature - 10.3427); // make temperature an integer
    if (tempError || isnan(realTemperature) || temperature >= 432) { // on error kill power & set global error flag
      digitalWrite(relay, LOW); // turn off power to iron
//*** add this line below just in case
      digitalWrite(triac, LOW);
      tempError = true; //set error flag. can only be unset outside ISR. Once set no further action taken till unset in main loop.
    }
    else { //reading valid
//***      if (temperature < pottemperature) { //*** remove this line and allow errors to be both + and -
        digitalWrite(test1, HIGH);  // *** changed, generate a pulse on test1 (D6) when reading valid
        error = pottemperature - temperature;  // *** +ve error when low = increase duty cycle, -ve error when high = decrease it
        error = map(error, lowError, highError, 0, 24);
        cumError += error * 250.0; //
        rateError = (error - lastError) / 250.0; //
        output = Kp * error + Ki * cumError + Kd * rateError; //output error needs to be mapped to a number between 0 and 24
        duty = map(output, lowError, highError, 0, 25); // *** lowError is const for fully off, highError is const for fully on. zero error maps to 50%
        duty = constrain(duty, 0, 25); // ***keep duty between 0 and 25 (25 = 100%)
//*** re-arrange & add 3 lines
        if(duty>0) {
          digitalWrite(triac, HIGH);
        } else {
          digitalWrite(triac, LOW);
        }
        lastError = error;
        digitalWrite(test1, LOW);
//*** remove 3 lines
//      }
//      else {
//        duty = 0;
//      }//if (temperature
    }//if (tempError
  } //if(counter >= 25
}// zero()
 

Attachments

Irving

Joined Jan 30, 2016
3,887
Modify this ...

Code:
char textbuf[50]; //buffer for data to send
ulong serialTime = millis(); //sending interval for data
ulong displayTime = serialTime;  //display interval for LCD
int pt; //local store for pot and iron temperatures;
int tmp;

void loop() {
  if(millis() >serialTime+PRINTRATE){ //send serial data every PRINTRATE mS
    noInterrupts(); // make sure our local copies are not corrupted while copying them over from ISR
    tmp = temperature;
    pt = pottemperature;
    interrupts();
    sprintf(textbuf, "Time: %lu, Set: %4u, Temp: %4u", millis()/100, pt, tmp);  //format the print string
    Serial.println(textbuf); //send to serial monitor, about 3mS @ 115200
    serialTime += PRINTRATE;
  }
to this...

Code:
char textbuf[100]; //buffer for data to send
ulong serialTime = millis(); //sending interval for data
ulong displayTime = serialTime;  //display interval for LCD
int pt; //local store for pot and iron temperatures;
int tmp;
double err, cErr, rErr, op;
int dty;

void loop() {
  if(millis() >serialTime+PRINTRATE){ //send serial data every PRINTRATE mS
    noInterrupts(); // make sure our local copies are not corrupted while copying them over from ISR
    tmp = temperature;
    pt = pottemperature;
    err = error;
    cErr = cumError;
    rErr = rateError;
    op = output;
    dty = duty;
    interrupts();
    sprintf(textbuf, "Time: %lu, Set: %4u, Temp: %4u", millis()/100, pt, tmp);  //format the print string
    Serial.print(textbuf);
    sprintf(textbuf, ", error: %8.2f, cumErr: %8.2f, rateErr: %8.2f, output: %8.2f, duty: %3u", err,cErr, rErr, op, dty);  
    Serial.println(textbuf); //send to serial monitor, about 3mS @ 115200
    serialTime += PRINTRATE;
  }
 

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
Please find attached what it shows on the serial monitor. I see a problem where it shows '?' instead of numbers ...
The loop() is:
C:
void loop() {
  if(millis() >serialTime+PRINTRATE){ //send serial data every PRINTRATE mS
    noInterrupts(); // make sure our local copies are not corrupted while copying them over from ISR
    tmp = temperature;
    pt = pottemperature;
    err = error;
    cErr = cumError;
    rErr = rateError;
    op = output;
    dty = duty;
    interrupts();
    sprintf(textbuf, "Time: %lu, Set: %4u, Temp: %4u", millis()/100, pt, tmp);  //format the print string
    Serial.print(textbuf);
    sprintf(textbuf, ", error: %8.2f, cumErr: %8.2f, rateErr: %8.2f, output: %8.2f, duty: %3u", err,cErr, rErr, op, dty);
    Serial.println(textbuf); //send to serial monitor, about 3mS @ 115200
    serialTime += PRINTRATE;
  }

  if (millis() > displayTime + DISPLAYRATE) { //update display every DISPLAYRATE mS
    if (!tempError) {  // if no error
      updateDisplay();
    } else // do something on error
    {
      // eg show the word error on the display
      if (!shownError) { // we've not shown error yet, so show it
        displayErrors();
        shownError = true; //set flag so don't show it again
      }
    }
    displayTime += DISPLAYRATE;
  }
}
 

Attachments

Irving

Joined Jan 30, 2016
3,887
hmmmm, try replacing %8.2f with %.9g, the numbers should have some value...

looking at the output, we can see the duty cycle is 25 while error is obviously large and reduces quickly as we get close to the required temperature, until it goes to 0 and the iron starts to cool. Then as error increases, duty increases, pulling it up. Its actually regulating quite well, with no overshoot. It will be interesting to see what happens if you try soldering something...

i'm thinking to experiment with a longer cycle time of 1sec.
 

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
I melted 60/40 solder on a 3.5x3 cm copper pad (35um thickness - I think) and the evolution of temperature is shown in the attached file (the one with 320 C temperature). It looks like the temperature is stable, but it has some variations.
Also, using .9g format is in the other file.
The '?' still appeared in the serial monitor.

C:
 sprintf(textbuf, ", error: %.9g, cumErr: %.9g, rateErr: %.9g, output: %.9g, duty: %3u", err,cErr, rErr, op, dty);
 

Attachments

Irving

Joined Jan 30, 2016
3,887
And it held the temperature within 4 degrees, I'd say that was pretty good. What do you think?


It seems to me its pretty well controlled. Its heating as fast as it can to set temperature. Without the Ki factor it can't overshoot, and Kp = 5 shows its only using ON (25), 66% (16), 33% (8) and OFF (0) setting with those settings of low & highError.

Try dialling in a small amount of Ki, say 2, and see how it changes...
 
Last edited:

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
By adding Ki = 2, then the heating up time from room temperature to 350 C increases (i would say - a lot), and there appeared a strange thing. Suddenly, when it was at 350 C, it lost the control of the heater, and it gone up to 400 C, and then I switched off the power. Also, after the iron cooled down a little, then I switched the power on again and set the temp to 250 C, but it again lost the control and it heated up to 300 C, when I switched off the power.
Edit: if I set Ki = 0 again, then the over heating problem disappear.

What do you think?
I think 4 C is good.
 

Attachments

Last edited:

Irving

Joined Jan 30, 2016
3,887
Well that proves Ki is providing an acceleration. It can't make it heat up faster, but it can overcome the slowdown as it approaches the setting. Ki probably needs to be smaller, ie 0.5 or less maybe.
 

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
This time the same over temperature happened, but the increase was a little slower I think.
Ki was 0.25. Kp was 5. lowError = 0 and highError = 15.

Edit: I was curious and I had an idea about PID library (which I mentioned previously in this topic) and I used the PID_v1 library to modify the code as shown below. Please find attached the results using Kp = 5 and Ki = 0.25. I am not 100% sure it is correct what I have done, please have a look. It looks like the temperature does not rise out of control as previous. Also, I don't know if the timing of the PID algorithm is correct.

C:
#include <PID_v1.h>

//PID constants
double Kp = 5;
double Ki = 0.25;
double Kd = 0;

PID myPID(&input, &output, &setPoint, Kp, Ki, Kd, DIRECT);

void setup() {
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(0,128);   // the values were took randomly I am not sure if those values are correct
}

void zero() {
  counter++;
  //*** change this line below
  if (counter > duty) { //reach duty cycle limit, unless duty was 25 in which case leave on until next duty calculated later
    digitalWrite(triac, LOW);
  }

  if (counter >= 25) {
    counter = 0;
    digitalWrite(test, HIGH); //this will generate a pulse on test pin (5) every 250mS to prove counter incrementing...
    pottemperature = analogRead(potentiometer);
    pottemperature = map(pottemperature, 0, 1023, 150, 400);
    setPoint = pottemperature;
    digitalWrite(test, LOW); // put test pin low
    realTemperature = thermocouple.readCelsius();
    temperature = int(0.779828 * realTemperature - 10.3427); // make temperature an integer
    input = temperature;
    if (tempError || isnan(realTemperature) || temperature >= 432) { // on error kill power & set global error flag
      digitalWrite(relay, LOW); // turn off power to iron
      //*** add this line below just in case
      digitalWrite(triac, LOW);
      tempError = true; //set error flag. can only be unset outside ISR. Once set no further action taken till unset in main loop.
    }
    else { //reading valid
      //***      if (temperature < pottemperature) { //*** remove this line and allow errors to be both + and -
      digitalWrite(test1, HIGH);  // *** changed, generate a pulse on test1 (D6) when reading valid
      error = pottemperature - temperature;  // *** +ve error when low = increase duty cycle, -ve error when high = decrease it
      myPID.Compute();
      //      error = map(error, lowError, highError, 0, 24);
      //      cumError += error * 250.0; //
      //      rateError = (error - lastError) / 250.0; //
      //      output = Kp * error + Ki * cumError + Kd * rateError; //output error needs to be mapped to a number between 0 and 24
      duty = map(output, lowError, highError, 0, 25); // *** lowError is const for fully off, highError is const for fully on. zero error maps to 50%
      duty = constrain(duty, 0, 25); // ***keep duty between 0 and 25 (25 = 100%)
      //*** re-arrange & add 3 lines
      if (duty > 0) {
        digitalWrite(triac, HIGH);
      } else {
        digitalWrite(triac, LOW);
      }
      lastError = error;
      digitalWrite(test1, LOW);
      //*** remove 3 lines
      //      }
      //      else {
      //        duty = 0;
      //      }//if (temperature
    }//if (tempError
  } //if(counter >= 25
}// zero()
 

Attachments

Last edited:

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
I was curious again and I modified again the code, using the PID constants and some code from this project on All About Circuits web site: https://www.allaboutcircuits.com/projects/do-it-yourself-soldering-station-with-an-atmega8/

I am wondering if I implemented the code correctly ? Could you please have a look at it ?
I would like to use the pid_v1 library instead of other pid calculations, if possible.
I saw a problem there, the output to triac (pin 7) is having a delay (1ms delay) from the zero crossing detector. I am wondering if this delay could be reduced ?

Please find attached the data from serial monitor and the code.
C:
#include <PID_v1.h>
#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

#define test A2
#define test1 A3

int lowError = 0; //guessing for now.  The bigger these values the smaller the deadband either side of 0 error that constitues a 50% duty cycle
int highError = 220;

float temperature, realTemperature;
int pottemperature;
int counter;
int tempError = false;  // global error flag
int shownError = false; //flag to say error shown
int duty = 0; // variable for duty cycle

//PID constants
//double Kp = 5;
//double Ki = 0.25;
//double Kd = 0;

//Define the aggressive and conservative Tuning Parameters
double aggKp = 4, aggKi = 0.2, aggKd = 1;
double consKp = 1, consKi = 0.05, consKd = 0.25;


//PID variables
unsigned long currentTime, previousTime;
double elapsedTime;
double error;
double lastError;
double input, output, setPoint;
double cumError, rateError;

PID myPID(&input, &output, &setPoint, consKp, consKi, consKd, DIRECT);


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)
*/

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

// added stuff to log temperatures on serial monitor
// change loop time management from simple delay

#define PRINTRATE 100
#define DISPLAYRATE 250

char textbuf[100]; //buffer for data to send
unsigned long serialTime = millis(); //sending interval for data
unsigned long displayTime = serialTime;  //display interval for LCD
int pt; //local store for pot and iron temperatures;
int tmp;
double err, cErr, rErr, op;
int dty;

void setup() {
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(0, 220);
  Serial.begin(115200); // or faster if your Arduino/PC can handle it...
  pinMode(test, OUTPUT);
  pinMode(test1, OUTPUT);
  lcd.createChar(0, thermometer);
  lcd.createChar(1, arrow);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("STATIE DE LIPIT");
  output = 0;
  setPoint = 0;
  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;
  input = temperature;
  //updateDisplay();
  attachInterrupt(digitalPinToInterrupt(2), zero, RISING);
}



void loop() {
  if (millis() > serialTime + PRINTRATE) { //send serial data every PRINTRATE mS
    noInterrupts(); // make sure our local copies are not corrupted while copying them over from ISR
    tmp = temperature;
    pt = pottemperature;
    err = error;
    cErr = cumError;
    rErr = rateError;
    op = output;
    dty = duty;
    interrupts();
    sprintf(textbuf, "Time: %lu, Set: %4u, Temp: %4u", millis() / 100, pt, tmp); //format the print string
    Serial.print(textbuf);
    sprintf(textbuf, ", error: %.9g, cumErr: %.9g, rateErr: %.9g, output: %.9g, duty: %3u", err, cErr, rErr, op, dty);
    Serial.println(textbuf); //send to serial monitor, about 3mS @ 115200
    serialTime += PRINTRATE;
  }

  if (millis() > displayTime + DISPLAYRATE) { //update display every DISPLAYRATE mS
    if (!tempError) {  // if no error
      updateDisplay();
    } else // do something on error
    {
      // eg show the word error on the display
      if (!shownError) { // we've not shown error yet, so show it
        displayErrors();
        shownError = true; //set flag so don't show it again
      }
    }
    displayTime += DISPLAYRATE;
  }
}

void zero() {
  counter++;
  //*** change this line below
  if (counter > duty) { //reach duty cycle limit, unless duty was 25 in which case leave on until next duty calculated later
    digitalWrite(triac, LOW);
  }

  if (counter >= 25) {
    counter = 0;
    digitalWrite(test, HIGH); //this will generate a pulse on test pin (5) every 250mS to prove counter incrementing...
    pottemperature = analogRead(potentiometer);
    pottemperature = map(pottemperature, 0, 1023, 150, 400);
    setPoint = pottemperature;
    digitalWrite(test, LOW); // put test pin low
    realTemperature = thermocouple.readCelsius();
    temperature = int(0.779828 * realTemperature - 10.3427); // make temperature an integer
    input = temperature;
    if (tempError || isnan(realTemperature) || temperature >= 432) { // on error kill power & set global error flag
      digitalWrite(relay, LOW); // turn off power to iron
      //*** add this line below just in case
      digitalWrite(triac, LOW);
      tempError = true; //set error flag. can only be unset outside ISR. Once set no further action taken till unset in main loop.
    }
    else { //reading valid
      //***      if (temperature < pottemperature) { //*** remove this line and allow errors to be both + and -
      digitalWrite(test1, HIGH);  // *** changed, generate a pulse on test1 (D6) when reading valid
      //error = pottemperature - temperature;  // *** +ve error when low = increase duty cycle, -ve error when high = decrease it

      double gap = abs(setPoint - input); //distance away from setpoint

      if (gap < 10)
      { //we're close to setpoint, use conservative tuning parameters
        myPID.SetTunings(consKp, consKi, consKd);
      }
      else
      {
        //we're far from setpoint, use aggressive tuning parameters
        myPID.SetTunings(aggKp, aggKi, aggKd);
      }

      myPID.Compute();
      //      error = map(error, lowError, highError, 0, 24);
      //      cumError += error * 250.0; //
      //      rateError = (error - lastError) / 250.0; //
      //      output = Kp * error + Ki * cumError + Kd * rateError; //output error needs to be mapped to a number between 0 and 24
      duty = map(output, lowError, highError, 0, 25); // *** lowError is const for fully off, highError is const for fully on. zero error maps to 50%
      duty = constrain(duty, 0, 25); // ***keep duty between 0 and 25 (25 = 100%)
      //*** re-arrange & add 3 lines
      if (duty > 0) {
        digitalWrite(triac, HIGH);
      } else {
        digitalWrite(triac, LOW);
      }
      lastError = error;
      digitalWrite(test1, LOW);
      //*** remove 3 lines
      //      }
      //      else {
      //        duty = 0;
      //      }//if (temperature
    }//if (tempError
  } //if(counter >= 25
}// zero()

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);
}
Also, please find attached the screenshots from the scope.
1. High to low transition of pin 7 (blue) and pin 2 signal (yellow)
DS0111.jpg



2. Low to high transition of pin 7 (blue) and pin 2 signal (yellow), there is an 1mS delay. I don't know if this is good or bad ? Last time, with the code for on/off control, it was less than 1mS.
DS0110.jpg



3. The wave form on the soldering iron heater:
DS0112.jpgDS0113.jpgDS0116.jpg



I am sorry if I was importunate when I wrote about the pid_v1 library, I was thinking that it is a good thing that I made the circuit work with that pid library...
 

Attachments

Last edited:
Top