Author Topic: Connecting MAX6675 and 3 digit 7 segment display to Arduino Nano (or Uno)  (Read 419 times)

0 Members and 1 Guest are viewing this topic.

Offline mike_mike

  • Frequent Contributor
  • **
  • Posts: 729
  • Country: ro
Hi! I am working at a project, which will be a soldering station, and it will use a 3 digit 7 segment display instead of LCD display as I used previously.
I wanted to ask what library and what code should I write for the 3 digit 7 segment display in order to not interfere with the MAX6675 module ?
The schematic with the connections from Arduino to the display (but using only 3 digits) is attached.




 

Online ledtester

  • Super Contributor
  • ***
  • Posts: 1697
  • Country: us
My guess is that your problem is that the Arduino only has 14 GPIO pins and you're already using 12 of them for your 3-digit display not leaving enough for the max6675.

Common solutions are:

- use a shift register for the segment drivers - this will free up several GPIOs:

https://create.arduino.cc/projecthub/meljr/7-segment-led-displays-102-using-a-shift-register-6b6976

- use a MAX7219 module or chip to drive the LED digit display (just search for max7219 + arduino)

 

Offline mike_mike

  • Frequent Contributor
  • **
  • Posts: 729
  • Country: ro
Tried this code. It works. Please have a look and tell me what you think ? (especially with the loop() function) ?
The code didn't worked until I introduced the reading of the thermocouple (MAX6675) into the if (millis() - lastupdate > updaterate).
Is the Arduino correctly reading the MAX6675, at correct time intervals ?

Code: [Select]
#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;
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[] = {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 = 700; //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(led_pin, OUTPUT);
  pinMode(relay_pin, OUTPUT);
  digitalWrite(led_pin, LOW);
  digitalWrite(relay_pin, LOW);
  delay(1000);
  digitalWrite(relay_pin, HIGH);
}

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;
        digitalWrite(led_pin, HIGH);
      }
    }
    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);
  }

}

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
  }
}
« Last Edit: March 21, 2021, 11:15:10 am by mike_mike »
 

Offline mike_mike

  • Frequent Contributor
  • **
  • Posts: 729
  • Country: ro
I found the problem. I will write the solution here, probably it will be useful to someone.
The max6675 module needs to be read at a minimum interval of 250mS. Please have a look at this code, were is a comment that explains the mentioned time interval: https://github.com/adafruit/MAX6675-library/blob/master/examples/serialthermocouple/serialthermocouple.ino

Then I modified the code as shown below:
Code: [Select]
#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
  }
}


I tested the code and it seems to work good...
« Last Edit: March 23, 2021, 11:06:21 am by mike_mike »
 
The following users thanked this post: ledtester


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf