Arduino temperature sensor box

Several months ago I’ve uploaded a video on YouTube showing my new Arduino project – reading temperature from DS18B20 sensor and showing the result on a 7-segment display. In the mean time I received several questions about schematics and source code. I finally put all peaces together so here are all details.

List of components:

  • 1x Arduino board
  • 1x Protoboard and a bunch of jumper wires
  • 4x 10k resistors
  • 4x DS18B20 temperature sensors
  • 4x 4digit 7-segment displays
  • 5x 8-bit shift register (I used four M74HC59581 and one CD74HCT4094E)

 

Arduino sketch

[java]
/*

Display temperatures from four DS18B20 sensors
on four 7 segment displays.

Detailed description can be found at http://www.mskvorc.com

Author: Marko Škvorc (marko.skvorc@gmail.com)
Last changed: 24.02.2013.

*/
#include 
#include 

// 7 Segment display
// ----------------------------------------------------------
//Pin connected to ST_CP of 74HC595
int latchPin = 7;
////Pin connected to DS of 74HC595
int dataPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 9;

byte seven_seg_digits[12] = { 
     B00101000 ,  // = 0
     B11101011 ,  // = 1
     B00110010 ,  // = 2
     B10100010 ,  // = 3
     B11100001 ,  // = 4
     B10100100 ,  // = 5
     B00100100 ,  // = 6
     B11101010 ,  // = 7
     B00100000 ,  // = 8
     B10100000 ,  // = 9
     B11110111 ,  // = -
     B11111111    // = all off
};

byte dot = B00100000;
byte digits[] = {B10000000, B01000000, B00100000, B00010000};

int nextDisplay = 1;
int numDisplay = 4;
int nextSensor = 0;
// ----------------------------------------------------------

// Temperatures
// ----------------------------------------------------------
int tempPins[4] = {2, 3, 4, 5};

int temps[4] = {0, 0, 0, 0};
int tempDigits[4][4] = {{0, 0, 0, 11}, {0, 0, 0, 11}, {0, 0, 0, 11}, {0, 0, 0, 11}};

int tempReadingStep = 0;

void OneWireReset(int Pin);
void OneWireOutByte(int Pin, byte d);
byte OneWireInByte(int Pin);
// ----------------------------------------------------------


// ----------------------------------------------------------
int delayTime = 2000;
int currentDelayTime = 0;

int sensorTime = 1000; // read temp every 1 sec

int readSensorCount = sensorTime / (delayTime / 1000);

int counter = 0;
// ----------------------------------------------------------


void setup() { 
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  for (int i = 0; i < 4; i++){
    digitalWrite(tempPins[i], LOW);
    pinMode(tempPins[i], INPUT);      // sets the digital pin as input (logic 1)
  }
}

byte isDot(){
  if (nextDisplay == 2)
    return dot;
  else
    return B0;
}

void refreshDisplay(){
    digitalWrite(latchPin, LOW);
    // shift out the bits:
    
    // turn on display
    shiftOut(dataPin, clockPin, LSBFIRST , digits[nextDisplay - 1]);
    
    // show digits
    shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[tempDigits[0][nextDisplay - 1]] - isDot());
    shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[tempDigits[1][nextDisplay - 1]] - isDot());
    shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[tempDigits[2][nextDisplay - 1]] - isDot());
    shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[tempDigits[3][nextDisplay - 1]] - isDot());

    //take the latch pin high so the LEDs will light up:
    digitalWrite(latchPin, HIGH);
    
    nextDisplay = nextDisplay + 1;
    if (nextDisplay > numDisplay){
      nextDisplay = 1;
    }
}

void loop() {
  
  refreshDisplay();

  // read sensor
  if (counter == readSensorCount){
    temps[nextSensor] = readSensor(tempPins[nextSensor], tempReadingStep);
    tempReadingStep++;
    
    if (temps[nextSensor] != 0){
      tempDigits[nextSensor][2] = (abs(temps[nextSensor]) / 100) / 10;
      tempDigits[nextSensor][1] = (abs(temps[nextSensor]) / 100) % 10;
      tempDigits[nextSensor][0] = (abs(temps[nextSensor]) % 100) / 10;

      if (temps[nextSensor] < 0){
        tempDigits[nextSensor][3] = 10;
      } else {
        tempDigits[nextSensor][3] = 11;
      }
      nextSensor++;
      if (nextSensor == 4){
        nextSensor = 0;
      }
      counter = 0;
      tempReadingStep = 0;
    }
  } else {
    counter++;
  }

  int additionalDelay = delayTime - currentDelayTime;
  delayMicroseconds(additionalDelay);

  currentDelayTime = 0;
}

int readSensor(int pin, int tempReadingStep){
  int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

  switch(tempReadingStep){
    case 1:
      OneWireReset(pin);
      break;
    case 2:
      OneWireOutByte(pin, 0xcc);
      OneWireOutByte(pin, 0x44); // perform temperature conversion, strong pullup for one sec
      break;
    case 3:
      OneWireReset(pin);
      break;
    case 4:
      OneWireOutByte(pin, 0xcc);
      OneWireOutByte(pin, 0xbe);

      LowByte = OneWireInByte(pin);
      HighByte = OneWireInByte(pin);
      TReading = (HighByte << 8) + LowByte;
      SignBit = TReading & 0x8000;  // test most sig bit
      if (SignBit) // negative
      {
        TReading = (TReading ^ 0xffff) + 1; // 2's comp
      }
      Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25
      if (SignBit){
        Tc_100 = -Tc_100;
      }
      break;
    default:
      break;
  }

  return Tc_100;
}

void OneWireOutByte(int Pin, byte d) // output byte d (least sig bit first).
{
   byte n;

   for(n=8; n!=0; n--)
   {
      if ((d & 0x01) == 1)  // test least sig bit
      {
         digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(5);
         currentDelayTime = currentDelayTime + 5;
         pinMode(Pin, INPUT);
         delayMicroseconds(60);
         currentDelayTime = currentDelayTime + 60;
      }
      else
      {
         digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(60);
         currentDelayTime = currentDelayTime + 60;
         pinMode(Pin, INPUT);
      }

      d=d>>1; // now the next bit is in the least sig bit position.
   }
   
}

byte OneWireInByte(int Pin) // read byte, least sig byte first
{
    byte d, n, b;

    for (n=0; n<8; n++)
    {
        digitalWrite(Pin, LOW);
        pinMode(Pin, OUTPUT);
        delayMicroseconds(5);
        currentDelayTime = currentDelayTime + 5;
        pinMode(Pin, INPUT);
        delayMicroseconds(5);
        currentDelayTime = currentDelayTime + 5;
        b = digitalRead(Pin);
        delayMicroseconds(50);
        currentDelayTime = currentDelayTime + 50;
        d = (d >> 1) | (b<<7); // shift d to right and insert b in most sig bit position
    }
    return(d);
}

void OneWireReset(int Pin) // reset.  Should improve to act as a presence pulse
{
     digitalWrite(Pin, LOW);
     pinMode(Pin, OUTPUT); // bring low for 500 us
     delayMicroseconds(500);
     currentDelayTime = currentDelayTime + 500;
     pinMode(Pin, INPUT);
     delayMicroseconds(500);
     currentDelayTime = currentDelayTime + 500;
}
[/java]

The final product looks like this:

7 thoughts on “Arduino temperature sensor box

  1. Great Build! Is there a possibility that you could issue this build with a single sensor and a single display? Many thanks for your efforts.

  2. It has been noticed that your build has the temperature sensors connected to the analog pins like what TM35 (and similar) use versus the digital pins that DS18B20 (and similar) use. The sketch indicated that pins 7,8 and 9 are used for the 595’s but the video points to other digital pins being used. Nice build but the video does not match this sketch. :/

    • Hi Lars. Yes, you’re correct about the pins that are used for shift registers. Thank you for pointing this out. The reason is that I made the video when I was prototyping this project and the code is from the final project 🙂 Also, about the pins for sensors, analog pins can also be used as a digital pins (but not vice-versa). I used them because all of the digital pins were used for other electronic modules.

      • Greetings Marko, You are right, the analog pins can be used for digital. A good thing to keep in mind if a project gets heavy on hardware. 🙂 The way the staging of the 4x 595’s is unique to me. It is really neat!

Leave a Reply to Marko Škvorc Cancel reply

Your email address will not be published. Required fields are marked *