4-Digit 7-Segment Display

So I'm new to Arduino and C++, coming from Visual Basic.NET world. Using an Arduino UNO R3, I'm reading a temperature from a TMP36 temp sensor and displaying that temperature on a 4-Digit 7-Segment display from Adafruit (Adafruit 0.56 4-Digit 7-Segment Display w/ I2C Backpack - Green [STEMMA QT / qwiic] : ID 880 : $9.95 : Adafruit Industries, Unique & fun DIY electronics and kits). I'm using a library provided by Adafruit to send the temperature value to the display. I have it working properly meaning a reading of 77 degrees from the sensor displays "77" on the display, but I want to be able to display the temperature in either Fahrenheit ("77F") or Celsius ("25C"). I can convert the temp to either Fahrenheit or Celsius but I have yet to find a way to display the "F" to the right of the 77 ("77F") or display the "C" to the right of the 25 ("25C"). I am able to create a string that contains "77F" or "25C" but it appears that I can't send a string to the display using the library. Here's the code that I'm currently trying:

void Display_Temperature(){
  int i;
  int reading = 0;
  int TempSamples = 10;
  for(i=0; i<TempSamples; i++){
    reading = reading + analogRead(TempInput);
  }
  float TempSum = reading / TempSamples;
  TempSum = (TempSum / 1024.0) * Aref;
  float tempC = (TempSum - 0.5) * 100.0;
  float tempF = tempC * 1.8 + 32.0;
  int Temp = tempF;
  String StringOne = String(Temp);
  StringOne.concat("F");
  matrix.print(StringOne);
  //matrix.print(StringOne, HEX);
  matrix.writeDisplay();
}

Any ideas?

Any ideas?

Somewhere in the library for the display will be a table that looks-up the given digit (say 0...9) and returns the segments of the display which must be lit to display that digit.
If the table doesn't include hex digits (A...F), you can add them yourself.
If it does include hex, just send 'C' or 'F' as a single hex digit.

Please get into the habit of using code tags.

Sorry, just figured out how to use code tags. The library does include hex digits. To display "77" on the display the code would be:

matrix.print(0x77, HEX);
matrix.writeDisplay();

To display "F" on the display the code would be:

matrix.print(0xF, HEX);
matrix.writeDisplay();

I just don't know how to combine the two. I tired the following but it just ends up displaying "F";

matrix print(0x77, HEX);
matrix print(0xF, HEX);
matrix.writeDisplay();

Please provide a link to the library.

Let me try to explain further. After reading temperature from the sensor, the variable Temp contains a value of "77" (Temp = 77). Now I want to append or concat() the "F" to the right of the 77 value stored in Temp so that I get a variable containing "77F". My attempt of doing this I first convert Temp to a string (StringOne), then concat() the "F" onto the 77. The string StringOne now contains "77F". I've verified this value by sending StringOne to the Serial Monitor and sure enough is displays "77F". But for some reason the library for the display doesn't like sending a string to the display. I get an error: no matching function for call to 'Adafruit_7segment::print(String&, int). I'm assuming this is because the library doesn't support string variables.

So how can I get my integer variable Temp (which contains a value of "77") and add the "F" to the right of it so that the value "77F" can be sent to the display?

Link to the Library: GitHub - adafruit/Adafruit_LED_Backpack: Adafruit LED Backpack Library for our various LED backpacks.

Examples provided with the Library:

/*************************************************** 
  This is a library for our I2C LED Backpacks

  Designed specifically to work with the Adafruit LED 7-Segment backpacks 
  ----> http://www.adafruit.com/products/881
  ----> http://www.adafruit.com/products/880
  ----> http://www.adafruit.com/products/879
  ----> http://www.adafruit.com/products/878

  These displays use I2C to communicate, 2 pins are required to 
  interface. There are multiple selectable I2C addresses. For backpacks
  with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
  with 3 Address Select pins: 0x70 thru 0x77

  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

// Enable one of these two #includes and comment out the other.
// Conditional #include doesn't work due to Arduino IDE shenanigans.
#include <Wire.h> // Enable this line if using Arduino Uno, Mega, etc.
//#include <TinyWireM.h> // Enable this line if using Adafruit Trinket, Gemma, etc.

#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"

Adafruit_7segment matrix = Adafruit_7segment();

void setup() {
#ifndef __AVR_ATtiny85__
  Serial.begin(9600);
  Serial.println("7 Segment Backpack Test");
#endif
  matrix.begin(0x70);
}

void loop() {
  // try to print a number thats too long
  matrix.print(10000, DEC);
  matrix.writeDisplay();
  delay(500);

  // print a hex number
  matrix.print(0xBEEF, HEX);
  matrix.writeDisplay();
  delay(500);

  // print a floating point 
  matrix.print(12.34);
  matrix.writeDisplay();
  delay(500);
  
  // print with print/println
  for (uint16_t counter = 0; counter < 9999; counter++) {
    matrix.println(counter);
    matrix.writeDisplay();
    delay(10);
  }

  // method #2 - draw each digit
  uint16_t blinkcounter = 0;
  boolean drawDots = false;
  for (uint16_t counter = 0; counter < 9999; counter ++) {
    matrix.writeDigitNum(0, (counter / 1000), drawDots);
    matrix.writeDigitNum(1, (counter / 100) % 10, drawDots);
    matrix.drawColon(drawDots);
    matrix.writeDigitNum(3, (counter / 10) % 10, drawDots);
    matrix.writeDigitNum(4, counter % 10, drawDots);
   
    blinkcounter+=50;
    if (blinkcounter < 500) {
      drawDots = false;
    } else if (blinkcounter < 1000) {
      drawDots = true;
    } else {
      blinkcounter = 0;
    }
    matrix.writeDisplay();
    delay(10);
  }
}

Hopefully some of this helps.

Unless there's a "cursor" position method (I can't see the library because I'm mobile), it would be simple to convert the decimal reading to BCD (hex), shift left four places and OR in the 'F' or 'C'.

@AWOL
Smart.

Yeah, but sadly doesn't work if, like me, you work in Kelvin :wink:

Stop trying to use the numerical print function and use the method for printing individual digits at specified positions instead - e.g. display.writeDigitNum(1, 0);. You will have to roll your own 2 digit print function but it's simple and examples abound.

AWOL:
Unless there's a "cursor" position method, it would be simple to convert the decimal reading to BCD (hex), shift left four places and OR in the 'F' or 'C'.

If I understand you correctly, yes there is a "cursor" position method. I can display a single digit value on any of the 4 digits of the display: matrix.writeDigitNum(4, F); (this displays an "F" on the very right digit). I'll have to figure out how convert Decimal to BCD and how to shift left four places. I'm gonna get some sleep for now. If anyone can give examples of how to do this it would help immensely. Remember I'm new to C++. Thanks to everyone for the help so far!

Okay, after trying every way possible I could think of, I took aarg's advice and gave up trying to use the print function of the library to send values to the display.

So I came up with the following code to extract each digit out of my temperature variable and send each digit to the display separately. Then depending on the state of a digital input (HIGH or LOW) I send the 'F' or 'C' to the 4th digit. Now if my temperature is 77 degrees F the temperature on the display shows '77F' and if the temperature is 25 degrees C the temperature on the display shows '25C'. Just what I was wanting.

But, the problem I now have is the code will not show a negative number (-5C). As soon as the temperature falls below "0C" the only thing that is shown on the display is the 'C'.

Any ideas?

void Display_Temperature(){
  int i = 0;
  int x = 3;
  int Temp = 0;
  int Deg = 0;
  int TempReading = 0;
  int TempSamples = 10;
  int digitcount = 0;
  int digitnum = 0;
  int digit = 0;
  float TempSum = 0;
  float tempC = 0;
  float tempF = 0;
  for(i=0; i<TempSamples; i++){
    TempReading = TempReading + analogRead(TempInput);
  }
  TempSum = TempReading / TempSamples;
  TempSum = (TempSum / 1024.0) * Aref;
  tempC = (TempSum - 0.5) * 100.0;
  tempF = tempC * 1.8 + 32.0;
  if(digitalRead(Temp_Type) == HIGH){
    Deg = 15;
    Temp = tempF;
  }
  else{
    Deg = 12;
    Temp = tempC;
  }
  digitnum = sizeof(Temp);
  while(digitcount != digitnum){
    digit = Temp % 10;
    Temp = Temp / 10;
    if(x == 2){
      x--;
    }
    Display.writeDigitNum(x,digit);
    x--;
    digitcount++;
  }
  Display.writeDigitNum(4,Deg);
  Display.writeDisplay();
}

Any ideas?

Use Kelvin. :smiley:

Use the print method, then overwrite the last digit with 'C' using writeDigitNum().

aarg:
Use the print method, then overwrite the last digit with 'C' using writeDigitNum().

I feel like I'm going in circles. None the less, its works. Thanks.

Just in case someone runs across this same problem as I, the following code gave me the results I was looking for. In a nut shell, shift the integer left one decimal place (basically adding a 0 to the right). Check to see if the integer == 0, if so directly write 0 to the 3rd digit of the display. If the integer is not equal to 0, send the integer to the display using the print function of the library. Finally directly send the 'F' or 'C' to the 4th digit of the display.This will indicate positive and negative temperatures.

void Display_Temperature(){
  int i = 0;
  int Temp = 0;
  int Deg = 0;
  int TempReading = 0;
  int TempSamples = 10;
  float TempSum = 0;
  float tempC = 0;
  float tempF = 0;
  for(i=0; i<TempSamples; i++){
    TempReading = TempReading + analogRead(TempInput);
  }
  TempSum = TempReading / TempSamples;
  TempSum = (TempSum / 1024.0) * Aref;
  tempC = (TempSum - 0.5) * 100.0;
  tempF = tempC * 1.8 + 32.0;
  if(digitalRead(Temp_Type) == HIGH){
    Deg = 15;
    Temp = tempF;
  }
  else{
    Deg = 12;
    Temp = tempC;
  }
  Temp = Temp * 10;
  if(Temp == 0){
    Display.writeDigitNum(3,0);
  }
  else{
    Display.print(Temp);
  }
  Display.writeDigitNum(4,Deg);
  Display.writeDisplay();
}

Hopefully this helps someone.

Wouldn't that leave junk in the 1st and 2nd digit when you change from say, 101F to 0F?

101F and 0F show correctly on the display. This display consist of 5 digits (0 through 4). Digit 2 is the colon between digits 1 and 3 (88:88). The colon isn't used so you have to trap it out. Now if you have a temperature of 100 degrees or greater that is negative, the minus sign will not be displayed due to only having 4 digits usable.

dcaroth:
101F and 0F show correctly on the display.

Not if the zero is displayed immediately after the 101. You are counting on single digit numbers to print blanks to the left of the zero. If you first print 101 and then 0, the display will read, "100". If you print -1 and then 0, the display will read, "-0".