Problem regarding 7 segment display

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
Hello, I want to build a soldering station using Arduino. The soldering station works, but the code probably has a mistake and the display does not update as expected. When I rotate the pot, then the display (7 segment 3 digit) shows the value read from the pot, but the display does not update as the soldering iron is heating up.
Please have a look at the code and tell me what you think ?

Soldering station:
#include <PID_v2.h>
#include <max6675.h>

int thermoDO = 12;
int thermoCS = 10;
int thermoCLK = 13;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);

//protection
int relay_pin = A5;

//This array contains what segments need to be turned on to display numbers 0-9
byte const digits[] = {
  B00111111, B00000110, B01011011, B01001111, B01100110, B01101101, B01111101, B00000111, B01111111, B01101111
};

int digit_common_pins[] = {A2, A3, A4}; //Common pins for the triple 7-Segment LED display
int max_digits = 3;
int current_digit = max_digits - 1;

unsigned long updaterate = 1000; //Change how fast the display updates. No lower than 500
unsigned long lastupdate;

int temperature = 0;

//Define Variables we'll be connecting to
double Setpoint, Input, Output;
double heaterTemp;

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

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);

void setup()
{
  DDRD = B11111111;  // sets Arduino pins 0 to 7 as outputs
  for (int y = 0; y < max_digits; y++)
  {
    pinMode(digit_common_pins[y], OUTPUT);
  }
  //We do not want to drive the soldering iron at 100% because it may burn, so we set it to about 85% (220/255)
  myPID.SetOutputLimits(0, 220);
  myPID.SetMode(AUTOMATIC);
  lastupdate = millis();
  Setpoint = 0;
  pinMode(relay_pin, OUTPUT);
  digitalWrite(relay_pin, LOW);
  delay(1000);
  digitalWrite(relay_pin, HIGH);
}

void loop() {
  //  Read temperature
  heaterTemp = thermocouple.readCelsius();
  Input = (0.779828 * heaterTemp) - 10.3427;
  //Display temperature
  if (isnan(heaterTemp) or Input >= 432) // No TC Connection OR over-temperature
  {
    while (true) {
      digitalWrite(relay_pin, LOW);
      digitalWrite(11, LOW);
      PORTD = B00000000;
    }
  }
  if (millis() - lastupdate > updaterate) {
    lastupdate = millis();
    temperature = Input;
  }
  //Read setpoint and transform it into degrees celsius(minimum 150, maximum 350)
  double newSetpoint = analogRead(1);
  newSetpoint = map(newSetpoint, 0, 1023, 150, 400);
  //Display setpoint
  if (abs(newSetpoint - Setpoint) > 3) {
    Setpoint = newSetpoint;
    temperature = newSetpoint;
    lastupdate = millis();
  }

  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();
  //Drive the output
  analogWrite(11, Output);
  //Display the temperature
  if (temperature < 50){
    show(50);
  }
  else
  {
    show(temperature);
  }
      
}

void show(int value) {
  int digits_array[] = {};
  boolean empty_most_significant = true;
  for (int z = max_digits - 1; z >= 0; z--) //Cycle through each digit
  {
    digits_array[z] = value / pow(10, z); //We now take each digit from the number
    if (digits_array[z] != 0 ) empty_most_significant = false; //Do not display leading zeros
    value = value - digits_array[z] * pow(10, z);
    if (z == current_digit)
    {
      if (!empty_most_significant || z == 0) { //Check to see that we do not have leading zeros and display the current digit
        PORTD = digits[digits_array[z]]; //Remove ~ for common cathode
      }
      else
      {
        PORTD = B00000000;
      }
      digitalWrite(digit_common_pins[z], HIGH);//Change to LOW for common cathode
    } else {
      digitalWrite(digit_common_pins[z], LOW);//Change to HIGH for common cathode
    }

  }
  current_digit--;
  if (current_digit < 0)
  {
    current_digit = max_digits; //Start over
  }
}
 

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
LE: by modifying the loop() like this, it seems to work. Is it correct ? Does the Arduino correctly reading the MAX6675, at correct time intervals ??
C:
void loop() {

  if (millis() - lastupdate > updaterate) {
    lastupdate = millis();
    //  Read temperature
    heaterTemp = thermocouple.readCelsius();
    Input = (0.779828 * heaterTemp) - 10.3427;
    //Display temperature
    if (isnan(heaterTemp) or Input >= 432) // No TC Connection OR over-temperature
    {
      while (true) {
        digitalWrite(relay_pin, LOW);
        digitalWrite(11, LOW);
        PORTD = B00000000;
      }
    }
    temperature = Input;
  }
  //Read setpoint and transform it into degrees celsius(minimum 150, maximum 350)
  double newSetpoint = analogRead(A1);
  newSetpoint = map(newSetpoint, 0, 1023, 150, 400);
  //Display setpoint
  if (abs(newSetpoint - Setpoint) > 3) {
    Setpoint = newSetpoint;
    temperature = newSetpoint;
    lastupdate = millis();
  }

  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();
  //Drive the output
  analogWrite(11, Output);
  //Display the temperature
  if (temperature < 50) {
    show(50);
  }
  else
  {
    show(temperature);
  }

}
 
Last edited:

KeithWalker

Joined Jul 10, 2017
3,063
It is quite difficult and very time consuming to try to de-bug someone else's program, because we can't run it to see what is really going on. I suggest that you try to de-bug the program using the serial monitor.
Work your way through the loop a bit at a time, adding serial.print statements to display the values of the relevant variables. Put a delay (1 second?) at the end of the loop so you have time to read the results. Every time you sample the variables, record them, then stop the program. Comment out the serial.print lines and add more at the next operational part of the program. When you review the results, you can see exactly what the program is really doing, and you will have a good indication of where it is going astray.
 

AlbertHall

Joined Jun 4, 2014
12,345

eetech00

Joined Jun 8, 2013
3,858
See, even Arduino agree with me that improvement was needed. This version of the IDE is free but you will also need a JTAG interface which, as far as I know, is not free.
And all this only covers those boards with a JTAG interface.
The TS wasn’t specific about which boards.
Both are reasonable suggestions.

you can use serial print statements, but they are a pita to manage.
 

KeithWalker

Joined Jul 10, 2017
3,063
My main objection to Arduino is that it is very hard to debug a problem.
For instance there is no option to single step through the program and view the variables as you go.
You actually can if after each set of variables has been printed, you use "while" to wait for a prompt that you input from the keyboard.
 

SamR

Joined Mar 19, 2019
5,031
Or you can stop the scrolling in the serial monitor in order to see what is going on. Writing code for the serial monitor may not be the "best" solution but it is what you have to work with in the Arduino IDE.
 

AlbertHall

Joined Jun 4, 2014
12,345
Microchip MPLAB-X has, for instance:
Stop the program when a particular value is written to a particular variable.
Run the program in a simulator with no hardware needed and time any part of the program with simulated external inputs.
 

Thread Starter

mike_the_begginer

Joined Dec 7, 2019
132
After searching on different forums, I found the problem: the MAX6675 module needs to be read at a minimum 250mS interval. In the initial code, the program was reading more frequently than 250mS. I modified the program as shown below, and it works:


Soldering Station:
#include <PID_v2.h>
#include <max6675.h>

//MAX6675 module data pins
int thermoDO = 12;
int thermoCS = 10;
int thermoCLK = 13;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);

//Protection pins
int relay_pin = A2;
//int led_pin = 8;

//This array contains what segments need to be turned on to display numbers 0-9
byte const digits[] = {
  B00111111, B00000110, B01011011, B01001111, B01100110, B01101101, B01111101, B00000111, B01111111, B01101111
};

int digit_common_pins[] = {A3, A4, A5}; //Common pins for the triple 7-Segment LED display
int max_digits = 3;
int current_digit = max_digits - 1;

unsigned long updaterate = 700; //Change how fast the display updates. No lower than 500
unsigned long lastupdate, lastupdate_max;

int temperature = 0;

//Define Variables we'll be connecting to
double Setpoint, Input, Output;
double heaterTemp;

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

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);

void setup()
{
  DDRD = B11111111;  // sets Arduino pins 0 to 7 as outputs
  for (int y = 0; y < max_digits; y++)
  {
    pinMode(digit_common_pins[y], OUTPUT);
  }
  //We do not want to drive the soldering iron at 100% because it may burn, so we set it to about 85% (220/255)
  myPID.SetOutputLimits(0, 220);
  myPID.SetMode(AUTOMATIC);
  lastupdate = millis();
  lastupdate_max = millis();
  Setpoint = 0;
  //pinMode(led_pin, OUTPUT);
  pinMode(relay_pin, OUTPUT);
  //digitalWrite(led_pin, LOW);
  digitalWrite(relay_pin, LOW);
  delay(1000);
  digitalWrite(relay_pin, HIGH); // turns on the relay to let the current flow to the soldering iron heater
}

void loop() {
  if (millis() - lastupdate_max > 250){
    lastupdate_max = millis();
    //  Read temperature
    heaterTemp = thermocouple.readCelsius();
    Input = (0.779828 * heaterTemp) - 10.3427; //estimate the temperature of the iron's tip, by reading the temperature of the iron's heater
    //Display error
    if (isnan(heaterTemp) or Input >= 432) // No TC Connection OR over-temperature
    {
      while (true) {
        digitalWrite(relay_pin, LOW);//cuts off the power to the soldering iron
        digitalWrite(11, LOW);//turns off the PID output
        PORTD = B00000000; // Turns off the entire display
        //digitalWrite(led_pin, HIGH);
      }
    }
  }
  //Display temperature
  if (millis() - lastupdate > updaterate) {
    lastupdate = millis();
    temperature = Input;
  }
  //Read setpoint and transform it into degrees celsius(minimum 150, maximum 400)
  double newSetpoint = analogRead(A1);
  newSetpoint = map(newSetpoint, 0, 1023, 150, 400);
  //Display setpoint
  if (abs(newSetpoint - Setpoint) > 3) {
    Setpoint = newSetpoint;
    temperature = newSetpoint;
    lastupdate = millis();
  }

  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(); // compute the pid output
  //Drive the output
  analogWrite(11, Output);
  //Display the temperature
  if (temperature < 50) {
    show(50); //display 50 if the estimated temperature is below 50C
  }
  else
  {
    show(temperature); //display the temperature
  }

}

void show(int value) {
  int digits_array[] = {};
  boolean empty_most_significant = true;
  for (int z = max_digits - 1; z >= 0; z--) //Cycle through each digit
  {
    digits_array[z] = value / pow(10, z); //We now take each digit from the number
    if (digits_array[z] != 0 ) empty_most_significant = false; //Do not display leading zeros
    value = value - digits_array[z] * pow(10, z);
    if (z == current_digit)
    {
      if (!empty_most_significant || z == 0) { //Check to see that we do not have leading zeros and display the current digit
        PORTD = digits[digits_array[z]]; //Remove ~ for common cathode
      }
      else
      {
        PORTD = B00000000;
      }
      digitalWrite(digit_common_pins[z], HIGH);//Change to LOW for common cathode
    } else {
      digitalWrite(digit_common_pins[z], LOW);//Change to HIGH for common cathode
    }

  }
  current_digit--;
  if (current_digit < 0)
  {
    current_digit = max_digits; //Start over
  }
}
 
Top