Pages: [1]   Go Down
Author Topic: Multiplexing a 7 segment display while checking a MAX31855 thermocouple chip  (Read 657 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

HI,

I am trying to multiplex a 7 segment 3 digit common cathode display while checking a MAX31855 thermocouple chip. I can accomplish this with the hardware I have and the code I have. The problem is that it seems to take about 100 ms to make a full thermocouple chip reading. While that's happening my LED display shuts off. It's only a blink but 100 ms is very noticeable to the human eye. I was wondering if there is a way to write the code, or I guess wire the hardware different, so that there is no break in my LED display, or at least its not noticeable to the human eye.

To be clear, I am not trying to have the thermocouple reading output on my display, so dont worry that the code is not accomplishing that. The thermocouple reading in the code below actually serves no purpose, but it will later. For now, I just need to be able to read my thermocouple chip without causing a noticeable blink on the 7 segment display.

The desired temp stuff in the code is just using an analog pin to read potentiometer and then making a number out of it. Then I send that number to the 7 segment to be displayed.

Right now the 7 segment 3 digit display is directly wired to 11 output pins on my arduino mega2560, with only resistors between the output pins and the display pins. I am using an Adafruit breakout board with a MAX31855 chip. It has a Vin and GND pin, a ChipSelect pin a Clock pin and a MISO pin.

Again, thankfully the display works and the thermocouple works, I just want to get rid of the blink on the display when the microcontroller reads the thermocouple chip.

The code is a bit messy because I have been trying all sorts of things and moving bits around, but it should be right.

Thanks a bunch in advance to anyone and everyone who helps.
 
Code:
/ ***** INCLUDES *****
#include "Adafruit_MAX31855.h"

int thermoDO = 3;
int thermoCS = 4;
int thermoCLK = 5;

// Initiates digital reading of Potentiometer
int Reading = analogRead(A0);

// Digit Pin Association
int digit1 = 9;
int digit2 = 10;
int digit3 = 11;

// Segment Pin Associations
int segA = 2;
int segB = 55;
int segC = 56;
int segD = 57;
int segE = 6;
int segF = 7;
int segG = 8;

// Calling other variables into play
int hundreds = 0;
int tens = 0;
int ones = 0;

long TCTempMillis = 0;

long TCTempInterval = 100;

Adafruit_MAX31855 thermocouple(thermoCLK, thermoCS, thermoDO);

// Calling Pin Outputs and Serial
void setup(){
  Serial.begin(9600);
 
  pinMode(digit1, OUTPUT);
  pinMode(digit2, OUTPUT);
  pinMode(digit3, OUTPUT);
 
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);
}

// The loop multiplexing the temperature
void loop() {
  // Allows for correct reading on DesiredTemp read out
  float DesiredTemp;
 
  int Reading = analogRead(A0);
 
  // Setting the Desired Temp based off the Potentiometer
  DesiredTemp = Reading/1023.0;
  DesiredTemp = (DesiredTemp * 50.0) + 0.0;
  //Serial.println(DesiredTemp);
 
  hundreds = int(DesiredTemp/100);
  //Serial.println(hundreds);
 
  tens = int(DesiredTemp/10);
  tens = tens - (int(tens/10)*10);
 
  ones = DesiredTemp - (int(DesiredTemp/10)*10);
 
  // Thermocouple initiation
  unsigned long currentMillis = millis();
 
  if (currentMillis - TCTempMillis > TCTempInterval){
    TCTempMillis = currentMillis;
    // HOT End Thermocouple Readout
    double c = thermocouple.readFarenheit();
    if (isnan(c)) {
      Serial.println("Something wrong with thermocouple!");
    } else {
      Serial.print("HOT Temp = ");
      Serial.print(thermocouple.readFarenheit());
      Serial.println(" F");
   }
  }
 
  digitalWrite(digit1, HIGH);
  digitalWrite(digit2, HIGH);
  digitalWrite(digit3, HIGH);
 
  digitalWrite(digit1, LOW);
  numMultiplex(hundreds);
  delay(5);
  digitalWrite(digit1, HIGH);
 
  digitalWrite(digit2, LOW);
  numMultiplex(tens);
  delay(5);
  digitalWrite(digit2, HIGH);
 
  digitalWrite(digit3, LOW);
  numMultiplex(ones);
  delay(5);
  digitalWrite(digit3, HIGH);
}

void numMultiplex(int x){
   switch(x){
     case 1: one(); break;
     case 2: two(); break;
     case 3: three(); break;
     case 4: four(); break;
     case 5: five(); break;
     case 6: six(); break;
     case 7: seven(); break;
     case 8: eight(); break;
     case 9: nine(); break;
     default: zero(); break;
   }
}

void clearLEDs()
{   
  digitalWrite(  2, LOW); // A
  digitalWrite(  55, LOW); // B
  digitalWrite(  56, LOW); // C
  digitalWrite(  57, LOW); // D
  digitalWrite(  6, LOW); // E
  digitalWrite(  7, LOW); // F
  digitalWrite(  8, LOW); // G
}

void zero(){
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, HIGH);
  digitalWrite(segE, HIGH);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, LOW);
}
   
void one() {
  digitalWrite(segA, LOW);
  digitalWrite(segB, HIGH);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, LOW);
  digitalWrite(segE, LOW);
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
}
 
void two() {
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
  digitalWrite(segC, LOW);
  digitalWrite(segD, HIGH);
  digitalWrite(segE, HIGH);
  digitalWrite(segF, LOW);
  digitalWrite(segG, HIGH);
}
 
void three() {
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, HIGH);
  digitalWrite(segE, LOW);
  digitalWrite(segF, LOW);
  digitalWrite(segG, HIGH);
}
 
void four() {
  digitalWrite(segA, LOW);
  digitalWrite(segB, HIGH);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, LOW);
  digitalWrite(segE, LOW);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, HIGH);
}
 
void five() {
  digitalWrite(segA, HIGH);
  digitalWrite(segB, LOW);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, HIGH);
  digitalWrite(segE, LOW);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, HIGH);
}
 
void six() {
  digitalWrite(segA, HIGH);
  digitalWrite(segB, LOW);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, HIGH);
  digitalWrite(segE, HIGH);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, HIGH);
}
 
void seven(){
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, LOW);
  digitalWrite(segE, LOW);
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);
}
 
void eight() {
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, HIGH);
  digitalWrite(segE, HIGH);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, HIGH);
}
 
void nine() {
digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, LOW);
  digitalWrite(segE, LOW);
  digitalWrite(segF, HIGH);
  digitalWrite(segG, HIGH);
}
Logged

West Yorkshire, UK
Offline Offline
Edison Member
*
Karma: 44
Posts: 1377
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi E_HVC,

One thing I noticed immediately reading your code is that you are calling thermocouple.readFarenheit() twice. You might be able to reduce the flicker a little by fixing that. You assign the returned value to the variable "c", but then you don't use "c" when you print the result to Serial output.

If that doesn't help much, the question will then become this: does that Adafruit library disable interrupts? If not, you could rewrite your code to update your display using a timer interrupt.

EDIT: just had a quick look at the Adafruit library code and it doesn't seem to disable interrupts. It uses 1 millisecond delays, around 35 per reading, so your 100ms is probably the result of the double read. If using timed interrupts, it will be important to keep the interrupt code fast to avoid interfering with the thermocouple library. This library sounds suitable.

Paul
« Last Edit: February 21, 2014, 08:24:56 am by PaulRB » Logged

NSW Australia
Offline Offline
Faraday Member
**
Karma: 87
Posts: 3545
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Has it occurred to you that it is not the thermocouple reading that is taking the time, but the serial printing?

9600 baud is about one character per millisecond.

Without interleave, you cannot multiplex and print at the same time.

Other problems - you do a whole multiplex on each pass through the loop - you might be better - if you must print - to perform one step of the multiplex on each loop.  Even better, do one step of the printing on each loop.  ( Load the text to print into an array.)

Code:
  digitalWrite(digit1, HIGH);
  digitalWrite(digit2, HIGH);
  digitalWrite(digit3, HIGH);
Should be in setup(), not loop().

Digit codes are butt-ugly - should be (one single, progmem) array which is executed by reading in a loop.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the responses, they were helpful in pointing things out I didn't see before.

Paul__B, I dont think its the problem of printing. One of the first things I tried was getting rid of the prints and it still made the LED display blink. You are most likely right, setting the code for an array would probably make things much faster. My background is not in coding so it will take me sometime to learn about arrays and try to set my code up with one, but I will try.

PaulRB is right about the multiple millisecond delays in the library. every time the micro controller is called to read the thermocouple chip, it is taking around 70 milliseconds. I have been looking at the library and seeing if there is a way to get that to be shorter. Another person has written a faster library https://github.com/fickleview/MAX31855_DEG_C_lib but I cant get his code to work for me. 

I am seeing only two options but I could be looking at this close minded.

First option is to figure a way out get the micro controller to read the thermocouple chip within a millisecond or 2 or less. If I could accomplish that, I would be able to have it go in between the multiplexing and the human eye would not be able to detect any flicker.

The second option is to us the timed interrupts that PaulRB was talking about rather than the multiple 1 ms delays for the thermocouple. Then I could have the multiplexing of the LEDs going on during each timed interrupt, rather than stopping the whole set of code. for that to work I would have to speed up my multiplexing quite a bit, probably using an array like Paul__B mentioned. (and I'm sure there are other unforeseen problems I will stumble across with that method).

Oh I guess a third option is to just have a second micro controller chip, but it seems like there is a way to do this with only one chip.

Let me know if you guys see any other options and if you have suggestions as to how to implement those to options I laid out, if you think they are a good idea, of course.

Again my background is in mechanical engineering, not computer or electrical engineering, so sorry for the messy code and if what I am say is none sense.
Logged

West Yorkshire, UK
Offline Offline
Edison Member
*
Karma: 44
Posts: 1377
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

every time the micro controller is called to read the thermocouple chip, it is taking around 70 milliseconds. I have been looking at the library and seeing if there is a way to get that to be shorter.

You can cut that delay in half - see my earlier suggestion.

First option is to figure a way out get the micro controller to read the thermocouple chip within a millisecond or 2 or less.

Not an option. The time taken is determined by the thermocouple chip and you can't change that. The best you could do is write code or find a library that uses interrupt-driven code to read the thermocouple.

I think your two best options are:
1. Write code or find a library to read the thermocouple chip using timed interrupts
2. Write code or find a library to multiplex the displays using timed interrupts

Either solution means that the main() loop can carry out one task while the other task is going on in the background (i.e. in interrupt routines).

I'm sure there is a library for driving 7-seg displays using interrupts & timers, it was discussed on a thread a couple of weeks ago...

EDIT: It was this: Seven Seg Library. But its not timer/interrupt driven, so no good for fixing your flicker problem. Recommend you go with the timer library I mentioned in my earlier post.
« Last Edit: February 23, 2014, 05:55:05 am by PaulRB » Logged

Pages: [1]   Go Up
Jump to: