Using an Arduino Uno, a waterproof digital temperature sensor and a 13mm 7-segment display to measure the temperature of your Christmassy drink (e.g hot chocolate or mulled wine).

Burning your tongue on a hot chocolate is a common problem that happens all the time. With this system, you’ll be able to tell if your Christmas drink is too hot or too cold without having to actually drink it!

What you’ll need:

  • Arduino Uno
  • DS18B20 waterproof digital temperature sensor (something like this)
  • seven 10 kiloohm (kΩ) resistors
  • one 4.7 kiloohm resistor
  • common anode 13mm 7-segment display
  • 10 kiloohm potentiometer

Part 1: 7-segment display

Firstly we’re going to need to connect the 7-segment display to the Arduino.

There are two different types of 7-segment displays: common anode and common cathode. In this blog we’re going to use a common anode display. This means that 5V is given to the common pin and if another pin is connected to ground (0V) the corresponding segment will light up. Here’s a diagram:

Image result for common anode 7 segment display diagram
[Image source: Getmicros]

When an Arduino output pin is set to LOW it goes to 0V, and hence acts as a ground pin. This means we can turn a segment on by setting a pin to LOW and turn it off by setting a pin to HIGH.

Now we need to start wiring up the display. Follow this wiring diagram:

7-segment to Arduno

As you can see, we need one resistor for each LED in the display. However, we aren’t bothering to connect the decimal point. Also, there is a potentiometer between the common anode and 5V. This is to allow us to control the brightness of the display.

Now we need to test the display. We can write a program to display all the digits from 0-9. Open up the Arduino IDE and start programming!


int ledA = 10;
int ledB = 9;
int ledC = 6;
int ledD = 7;
int ledE = 8;
int ledF = 11;
int ledG = 12;

Firstly we need to define which pin each segment is connected to. On 7-segment displays, each segment is called a letter from A to G.


int segmentValues[10][7] = {
  {0,0,0,0,0,0,1},
  {1,0,0,1,1,1,1},
  {0,0,1,0,0,1,0},
  {0,0,0,0,1,1,0},
  {1,0,0,1,1,0,0},
  {0,1,0,0,1,0,0},
  {0,1,0,0,0,0,0},
  {0,0,0,1,1,1,1},
  {0,0,0,0,0,0,0},
  {0,0,0,1,1,0,0}
};

Next, we create a nested array. This stores which segments need to be on to store a particular digit. For example, the first item is the digit 0. Each number is the value for a segment, from A to G. Notice that 0 means on (LOW) and 1 means off (HIGH).


void setup() {
  pinMode(ledA, OUTPUT);
  pinMode(ledB, OUTPUT);
  pinMode(ledC, OUTPUT);
  pinMode(ledD, OUTPUT);
  pinMode(ledE, OUTPUT);
  pinMode(ledF, OUTPUT);
  pinMode(ledG, OUTPUT);
}

In the setup code, we define all the pins as outputs.


void loop() {
 for (int digit=0; digit<10; digit++) {
  digitalWrite(ledA, segmentValues[digit][0]);
  digitalWrite(ledB, segmentValues[digit][1]);
  digitalWrite(ledC, segmentValues[digit][2]);
  digitalWrite(ledD, segmentValues[digit][3]);
  digitalWrite(ledE, segmentValues[digit][4]);
  digitalWrite(ledF, segmentValues[digit][5]);
  digitalWrite(ledG, segmentValues[digit][6]);
  delay(500);
  }
}

In the main program we have a for loop. It counts up one digit at a time from 0 to 9. Each pin is set to a value in the segmentValues array for that digit. This means that the display should count from 0 to 9 and start again. Here’s all the code:

int ledA = 10;
int ledB = 9;
int ledC = 6;
int ledD = 7;
int ledE = 8;
int ledF = 11;
int ledG = 12;

int segmentValues[10][7] = {
  {0,0,0,0,0,0,1},
  {1,0,0,1,1,1,1},
  {0,0,1,0,0,1,0},
  {0,0,0,0,1,1,0},
  {1,0,0,1,1,0,0},
  {0,1,0,0,1,0,0},
  {0,1,0,0,0,0,0},
  {0,0,0,1,1,1,1},
  {0,0,0,0,0,0,0},
  {0,0,0,1,1,0,0}
};

void setup() {
  pinMode(ledA, OUTPUT);
  pinMode(ledB, OUTPUT);
  pinMode(ledC, OUTPUT);
  pinMode(ledD, OUTPUT);
  pinMode(ledE, OUTPUT);
  pinMode(ledF, OUTPUT);
  pinMode(ledG, OUTPUT);

}

void loop() {
 for (int digit=0; digit<10; digit++) {
  digitalWrite(ledA, segmentValues[digit][0]);
  digitalWrite(ledB, segmentValues[digit][1]);
  digitalWrite(ledC, segmentValues[digit][2]);
  digitalWrite(ledD, segmentValues[digit][3]);
  digitalWrite(ledE, segmentValues[digit][4]);
  digitalWrite(ledF, segmentValues[digit][5]);
  digitalWrite(ledG, segmentValues[digit][6]);
  delay(500);
  }
}

If you find that a particular segment isn't lighting up, check that the cable connecting its pin to the arduino isn't loose and that the resistor is pushed in to the breadboard far enough. Now that the display is working, it's time to connect the sensor!

Part 2: Temperature sensor

The sensor has three pins: ground, data and power. It uses a communication protocol called the 1-wire interface to communicate with a microcontroller over only one wire. Here’s another diagram which shows how it should be connected to the arduino alongside the display:

7 segment temperature

As you can see, the black wire at the end of the cable leading to the waterproof enclosure should be connected to the Arduino’s ground pin. The red wire should be connected to 5V and the yellow wire should be connected to pin 3. Notice that there is a 4.7kΩ pull-up resistor between 5V and the data wire. I couldn’t get the wires to stay in the breadboard so I used crocodile clips to connect them to jumper cables. Now we need to test the sensor!

Before we can start using the sensor, we need to install two libraries: OneWire in order to use the 1-wire interface protocol and DallasTemperature to communicate with the DS18B20.

Firstly, download OneWire as a zip file here. Extract it to the Arduino libraries folder (For me it was C:\Program Files (x86)\Arduino\libraries). Once it has finished, rename the new folder to ‘OneWire’ instead of ‘OneWire-master’.

Secondly, download DallasTemperature as a zip file from here. Extract it to the Arduino libraries folder. Rename the new folder from ‘Arduino-Temperature-Control-Library-master’ to ‘DallasTemperature’. Once you’ve reopened your Arduino IDE we can start!


#include <OneWire.h>
#include <DallasTemperature.h>

OneWire oneWire(3);
DallasTemperature sensor(&oneWire);

Firstly we include the two libraries in the program so that we can use them. Next we create a 1-wire bus on pin 3. Then we create a DallasTemperature object to communicate with the sensor over the 1-wire bus.


void setup() {
  Serial.begin(9600);
  sensor.begin();

}

In the setup code we start serial over USB at baud 9600 and start the communication with the sensor.


void loop() {
  sensor.requestTemperatures();
  delay(100);
  Serial.print("Temperature = ");
  Serial.println(sensor.getTempCByIndex(0));
  delay(900);

}

Here we request that every sensor on the 1-wire bus sends the temperature to the Arduino (which in this case is only one sensor). We then print ‘Temperature = ‘ over serial followed by the temperature the Arduino received from sensor 0 (the only one) in degrees Celsius. Here’s all the code together:


#include <OneWire.h>
#include <DallasTemperature.h>

OneWire oneWire(3);
DallasTemperature sensor(&oneWire);
void setup() {
  Serial.begin(9600);
  sensor.begin();

}

void loop() {
  sensor.requestTemperatures();
  delay(100);
  Serial.print("Temperature = ");
  Serial.println(sensor.getTempCByIndex(0));
  delay(900);

}

Now you can run the program. You should find that every second, the Arduino sends a serial message (you can see it in the serial monitor) with the temperature. If you’re getting a temperature of -127 make sure that the wires of the sensor aren’t touching.

Now that everything is connected and working, we can write the main program to display the temperature!

Part 3: Displaying the temperature


#include <OneWire.h>
#include <DallasTemperature.h>

OneWire oneWire(3);
DallasTemperature sensor(&oneWire);

int ledA = 10;
int ledB = 9;
int ledC = 6;
int ledD = 7;
int ledE = 8;
int ledF = 11;
int ledG = 12;

Firstly, we include the libraries we need for the sensor, create a 1-wire interface and a sensor object to communicate with the sensor. Then we create variables to store which pin is connected to which segment of the 7-segment display.


int segmentValues[10][7] = {
  {0,0,0,0,0,0,1},
  {1,0,0,1,1,1,1},
  {0,0,1,0,0,1,0},
  {0,0,0,0,1,1,0},
  {1,0,0,1,1,0,0},
  {0,1,0,0,1,0,0},
  {0,1,0,0,0,0,0},
  {0,0,0,1,1,1,1},
  {0,0,0,0,0,0,0},
  {0,0,0,1,1,0,0}
};

Then we create the nested array to store which segments need to be on to display each digit, as we did before.


void setup() {
  sensor.begin();

  pinMode(ledA, OUTPUT);
  pinMode(ledB, OUTPUT);
  pinMode(ledC, OUTPUT);
  pinMode(ledD, OUTPUT);
  pinMode(ledE, OUTPUT);
  pinMode(ledF, OUTPUT);
  pinMode(ledG, OUTPUT);
  digitalWrite(ledA, HIGH);
  digitalWrite(ledB, HIGH);
  digitalWrite(ledC, HIGH);
  digitalWrite(ledD, HIGH);
  digitalWrite(ledE, HIGH);
  digitalWrite(ledF, HIGH);
  digitalWrite(ledG, HIGH);
}

In the setup code we start the library to communicate with the sensor. Then we configure each pin connected to the display as an output pin and set them all to HIGH, so all segments are off.


void loop() {
  sensor.requestTemperatures();
  delay(100);
  float temperature = sensor.getTempCByIndex(0);
  temperature = round(temperature);

In the looping code, we request the temperature from the sensor and store it as a float in a variable named ‘temperature’. Then we round it to the nearest whole number.


  if (temperature = 100) {
    digitalWrite(ledA, LOW);
    digitalWrite(ledF, LOW);
    digitalWrite(ledG, LOW);
    digitalWrite(ledE, LOW);
    digitalWrite(ledD, LOW);
    delay(500);
    digitalWrite(ledA, HIGH);
    digitalWrite(ledF, HIGH);
    digitalWrite(ledG, HIGH);
    digitalWrite(ledE, HIGH);
    digitalWrite(ledD, HIGH);

If the temperature is below -100°C or above 100°C we assume something has gone wrong – the wires of the sensor are probably touching. In this case, we display ‘E’ for error.


  } else {
    if (temperature < 0) {
      digitalWrite(ledG, LOW);
      delay(500);
      digitalWrite(ledG, HIGH);
      temperature = temperature * -1;
    }

If the temperature is negative (below 0) we display the negative sign ('-') and then convert it to positive to display it. For example, if the temperature was -12 we would display '-' and then times it by -1 to get 12 to be displayed next.

int firstDigit = static_cast( trunc(temperature/10) );
int secondDigit = static_cast( temperature – (firstDigit*10) );

After displaying or not displaying the negative sign we find the first digit and the second digit of the number. To find the first digit we:

  1. Divide by 10 (e.g 56 / 10 = 5.6)
  2. Use trunc()to cut off decimal points (e.g 5.6 → 5.0)
  3. Use static_cast to convert to an integer (e.g 5.0 → 5)
  4. Now we have the first digit (e.g 56 → 5)

To find the second digit we:

  1. Subtract by the first digit times 10 (e.g 56.0 – (5*10) = 6.0)
  2. Convert to an integer (e.g 6.0 → 6)

    digitalWrite(ledA, segmentValues[firstDigit][0]);
    digitalWrite(ledB, segmentValues[firstDigit][1]);
    digitalWrite(ledC, segmentValues[firstDigit][2]);
    digitalWrite(ledD, segmentValues[firstDigit][3]);
    digitalWrite(ledE, segmentValues[firstDigit][4]);
    digitalWrite(ledF, segmentValues[firstDigit][5]);
    digitalWrite(ledG, segmentValues[firstDigit][6]);
    delay(500);

We then display the first digit for half a second in the same way as we did when testing the display.


    digitalWrite(ledA, segmentValues[secondDigit][0]);
    digitalWrite(ledB, segmentValues[secondDigit][1]);
    digitalWrite(ledC, segmentValues[secondDigit][2]);
    digitalWrite(ledD, segmentValues[secondDigit][3]);
    digitalWrite(ledE, segmentValues[secondDigit][4]);
    digitalWrite(ledF, segmentValues[secondDigit][5]);
    digitalWrite(ledG, segmentValues[secondDigit][6]);
    delay(500);

After displaying the first digit, we display the second digit for half a second.


    digitalWrite(ledA, HIGH);
    digitalWrite(ledB, HIGH);
    digitalWrite(ledC, HIGH);
    digitalWrite(ledD, HIGH);
    digitalWrite(ledE, HIGH);
    digitalWrite(ledF, HIGH);
    digitalWrite(ledG, HIGH);
    delay(900);
  }
}

Finally we turn all the segments off. Here’s all the code together:


#include &lt;OneWire.h&gt;
#include &lt;DallasTemperature.h&gt;
<span data-mce-type="bookmark" id="mce_SELREST_start" data-mce-style="overflow:hidden;line-height:0" style="overflow:hidden;line-height:0;">&#65279;</span>
OneWire oneWire(3);
DallasTemperature sensor(&amp;oneWire);

int ledA = 10;
int ledB = 9;
int ledC = 6;
int ledD = 7;
int ledE = 8;
int ledF = 11;
int ledG = 12;

int segmentValues[10][7] = {
  {0,0,0,0,0,0,1},
  {1,0,0,1,1,1,1},
  {0,0,1,0,0,1,0},
  {0,0,0,0,1,1,0},
  {1,0,0,1,1,0,0},
  {0,1,0,0,1,0,0},
  {0,1,0,0,0,0,0},
  {0,0,0,1,1,1,1},
  {0,0,0,0,0,0,0},
  {0,0,0,1,1,0,0}
};

void setup() {
  sensor.begin();

  pinMode(ledA, OUTPUT);
  pinMode(ledB, OUTPUT);
  pinMode(ledC, OUTPUT);
  pinMode(ledD, OUTPUT);
  pinMode(ledE, OUTPUT);
  pinMode(ledF, OUTPUT);
  pinMode(ledG, OUTPUT);
  digitalWrite(ledA, HIGH);
  digitalWrite(ledB, HIGH);
  digitalWrite(ledC, HIGH);
  digitalWrite(ledD, HIGH);
  digitalWrite(ledE, HIGH);
  digitalWrite(ledF, HIGH);
  digitalWrite(ledG, HIGH);
}

void loop() {
  sensor.requestTemperatures();
  delay(100);
  float temperature = sensor.getTempCByIndex(0);
  temperature = round(temperature);
  if (temperature = 100) {
    digitalWrite(ledA, LOW);
    digitalWrite(ledF, LOW);
    digitalWrite(ledG, LOW);
    digitalWrite(ledE, LOW);
    digitalWrite(ledD, LOW);
    delay(500);
    digitalWrite(ledA, HIGH);
    digitalWrite(ledF, HIGH);
    digitalWrite(ledG, HIGH);
    digitalWrite(ledE, HIGH);
    digitalWrite(ledD, HIGH);
  } else {
    if (temperature &lt; 0) {
      digitalWrite(ledG, LOW);
      delay(500);
      digitalWrite(ledG, HIGH);
      temperature = temperature * -1;
    }
    int firstDigit = static_cast( trunc(temperature/10) );
    int secondDigit = static_cast( temperature - (firstDigit*10) );
    digitalWrite(ledA, segmentValues[firstDigit][0]);
    digitalWrite(ledB, segmentValues[firstDigit][1]);
    digitalWrite(ledC, segmentValues[firstDigit][2]);
    digitalWrite(ledD, segmentValues[firstDigit][3]);
    digitalWrite(ledE, segmentValues[firstDigit][4]);
    digitalWrite(ledF, segmentValues[firstDigit][5]);
    digitalWrite(ledG, segmentValues[firstDigit][6]);
    delay(500);
    digitalWrite(ledA, segmentValues[secondDigit][0]);
    digitalWrite(ledB, segmentValues[secondDigit][1]);
    digitalWrite(ledC, segmentValues[secondDigit][2]);
    digitalWrite(ledD, segmentValues[secondDigit][3]);
    digitalWrite(ledE, segmentValues[secondDigit][4]);
    digitalWrite(ledF, segmentValues[secondDigit][5]);
    digitalWrite(ledG, segmentValues[secondDigit][6]);
    delay(500);
    digitalWrite(ledA, HIGH);
    digitalWrite(ledB, HIGH);
    digitalWrite(ledC, HIGH);
    digitalWrite(ledD, HIGH);
    digitalWrite(ledE, HIGH);
    digitalWrite(ledF, HIGH);
    digitalWrite(ledG, HIGH);
    delay(900);
  }
}

When you upload the sketch to your Arduino, you should see the temperature displayed on the display! If you just get an 'E', make sure that the wires of the sensor aren't touching each other. Try measuring the temperature of your festive drink!

Merry Christmas!

ArduinoGIF