alternatasha a site to catalog random projects

"temperature display, unfinished"

temperature sensor

It’s winter time, and I need to monitor temperature throughout my place.  I had an extra Maxim DS18B20 “One-Wire” digital temperature sensor.  This can easily be read by any arduino-type microprocessor board.  I decided to use the Seeeduino Stalker for the task.  WIth its numerous digital pins, it made sense for me to hook up a simple digital display, something I’ve been wanting to do but haven’t yet.  In one of my grab bags from Jameco, I found a 3-digit 7-segment display that I was determined to make work.  First step: find the datasheet for this device.  It took some searching, but I found that it was a Kingbright BC56-11.  The datasheet told me that it was a “common cathode” numeric display.  This meant that the LEDs were connected to the common ground, and bringing the wanted segments “HIGH” would turn them on.

Unfortunately, I guessed that the pins were layed out in a “U” from the top right to the bottom right, which was wrong!  If I had looked more closely at the datasheet, I would have seen the configuration was in the same “U” pattern but starting from the bottom left.  This is why my first attempt did not work (see top image with the display in the same direction as the board).  Below is the fixed version.  Luckily I did not have to rewire the entire thing — if you notice, the display just had to be turned upside down. I connected all three digits’ segments together to keep the total number of pins required at 11 (one for each segment +  one for each digit + one for the decimal point).

Using this post at the arduino forum as a starting point for the display and example code from arduino’s One-Wire playground, I developed the following code that tells the board to sample the temperature sensor every 15 seconds and show it on the display:

// temperature data on digital 13
#include "OneWire.h"
 
// DS18S20 Temperature chip i/o
OneWire ds(13); // on pin 0
 
// LED display on pins 1-12, except 8
int i=0;
//int degree=B0;
int degree=25;
int fheit=46;
int cels=43;
int nothing=100;
float tempC;
float tempF;
float temp;
float voltage;
int reading;
int num=11;
int digitOne;
int digitTwo;
int digitThree;
unsigned long now;
unsigned long then;
void setup() {
pinMode(1, OUTPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10,OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
// Using Serial.begin(9600) makes pin 1 stay HIGH for some reason
//Serial.begin(9600);
//Serial.println('starting...');
}
void loop()
{
now=millis();
if (now-then < 15000 || millis()<100){ // take a sample every 30 seconds
byte i;
byte present = 0;
byte data[12];
byte addr[8];
//for hex:
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
///*
///*
if ( !ds.search(addr)) {
//Serial.print("No more addresses.\n");
ds.reset_search();
return;
}
 
//Serial.print("R=");
for( i = 0; i < 8; i++) {
//Serial.print(addr[i], HEX);
//Serial.print(" ");
}
 
if ( OneWire::crc8( addr, 7) != addr[7]) {
//Serial.print("CRC is not valid!\n");
return;
}
 
if ( addr[0] == 0x10) {
//Serial.print("Device is a DS18S20 family device.\n");
}
else if ( addr[0] == 0x28) {
//Serial.print("Device is a DS18B20 family device.\n");
}
else {
//Serial.print("Device family is not recognized: 0x");
//Serial.println(addr[0],HEX);
return;
}
//*/
//*/
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
 
//delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
 
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
///*
Serial.print("P=");
Serial.print(present,HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print( OneWire::crc8( data, 8), HEX);
Serial.println();
//*/
///*
//convert hex to number?
LowByte = data[0];
HighByte = data[1];
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
 
Whole = Tc_100 / 100; // separate off the whole and fractional portions
Fract = Tc_100 % 100;
float number = Tc_100/100.0;
//Serial.println(number);
temp = number*(9.0/5.0) + 32;
//Serial.println(temp);
 
/*
if (SignBit) // If its negative
{
Serial.print("-");
}
Serial.print(Whole);
Serial.print(".");
if (Fract &lt; 10)
{
Serial.print("0");
}
Serial.print(Fract);
 
Serial.print("\n");
*/
 
float num = temp;
digitOne=int(num)/10; //so, to get digitOne you divide by 10
// a number like 49 magically becomes 4, all decimals disappear
digitTwo=(int(num) - (digitOne * 10)); //then to get digit2 (9)you multiply digitOne by 10 to get 40
// and subtract it from the original 49 to get 9
digitThree = int(((num - (digitOne*10 + digitTwo))*10))%10; //subtract from original
 
if(num<0){ //for negative numbers, display 3 dashes
digitOne=999;
digitTwo=999;
digitThree=999;
}
if(num>99){ //if over 100, display C = backwards-C
digitOne=cels;
digitTwo=111;
digitThree=222;
}
 
then=now;
}
 
//NUMERAL PINS ARE 4, 5, and 9 --- for me this was 5,10,11
// 4 LOW = FIRST NUMERAL
// 5 LOW = SECOND NUMERAL
// 9 LOW = THIRD NUMERAL
// digit1 = pins 3, 26 map to board pin #5
// digit2 = pin 19 map to 10
// digit3 = pin 18 map to 11
//FIRST NUMERAL ON THE DISPLAY
 
digitalWrite(5,LOW);
digitalWrite(10,HIGH);
digitalWrite(11,HIGH);
//map 3, 19, 18 to 5, 10, 11
//digitalWrite(5,HIGH);
//digitalWrite(10,LOW);
//digitalWrite(11,LOW);
//letterfunction (6); //testing
letterfunction (digitOne); // type 0-9 in the parenthesis or
//type (degree) for the degree symbol
// or type (nothing) for nothing
 
//NUMERAL 2
 
digitalWrite(5,HIGH);
digitalWrite(10,LOW);
digitalWrite(11,HIGH);
//digitalWrite(5,LOW);
//digitalWrite(10,HIGH);
//digitalWrite(11,LOW);
 
//letterfunction(8); //testing
letterfunction(digitTwo);
 
//decimal point, at pin #9
digitalWrite(9,HIGH);
delay(5);
digitalWrite(9,LOW);
//delay(5);
 
//NUMERAL 3
 
digitalWrite(5,HIGH);
digitalWrite(10,HIGH);
digitalWrite(11,LOW);
//digitalWrite(5,LOW);
//digitalWrite(10,LOW);
//digitalWrite(11,HIGH);
 
//letterfunction(fheit); //testing
letterfunction(digitThree);
 
} // --- a6 ---
// THIS FUNCTION HAS THE DIFFERENT NUMBERS // f4 b7
// AND THE DEGREE SYMBOL // --- g3 ---
// 25, 24, 4, 2, 1, 27, 28, 5 --&gt; abcdefg dp // e1 c12
// map to 6,7,12,2,1,4,3 ; 9 // --- d2 ---
// 21, 20, 8, 7, 6, 23, 22, 9
// 16, 15, 13, 11, 10, 17, 12, 14
void letterfunction(unsigned char var){
//make sure all low: NO! makes all digits turn on with same number
// for(i=1;i<12;i++){
// digitalWrite(i,LOW);
// }
if (var==1){
//digitalWrite(6,HIGH); //pins 6 and 2 are the leftmost vertical lines
digitalWrite(7,HIGH); //pins 5 and 6 are the rightmost vertical lines
//digitalWrite(2,HIGH);
digitalWrite(12,HIGH);
//digitalWrite(1,LOW);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
digitalWrite(7,LOW);
digitalWrite(12,LOW);
//}
}
 
else if (var==2){
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);
digitalWrite(3,HIGH);
digitalWrite(1,HIGH);
digitalWrite(2,HIGH);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(3,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
}
 
else if (var==3){
digitalWrite(12,HIGH);
digitalWrite(6,HIGH);
digitalWrite(3,HIGH);
digitalWrite(7,HIGH);
digitalWrite(2,HIGH);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(12,LOW);
digitalWrite(6,LOW);
digitalWrite(3,LOW);
digitalWrite(7,LOW);
digitalWrite(2,LOW);
}
 
else if (var==4){
digitalWrite(4,HIGH);
digitalWrite(3,HIGH);
digitalWrite(7,HIGH);
digitalWrite(12,HIGH);
 
delay(5);
//for(i=1;i<14;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(4,LOW);
digitalWrite(3,LOW);
digitalWrite(7,LOW);
digitalWrite(12,LOW);
}
 
else if (var==5){
digitalWrite(6,HIGH);
digitalWrite(4,HIGH);
digitalWrite(3,HIGH);
digitalWrite(12,HIGH);
digitalWrite(2,HIGH);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(6,LOW);
digitalWrite(4,LOW);
digitalWrite(3,LOW);
digitalWrite(12,LOW);
digitalWrite(2,LOW);
}
 
else if (var==6){
digitalWrite(6,HIGH);
digitalWrite(4,HIGH);
digitalWrite(3,HIGH);
digitalWrite(12,HIGH);
digitalWrite(2,HIGH);
digitalWrite(1,HIGH);
delay(5);
 
digitalWrite(6,LOW);
digitalWrite(4,LOW);
digitalWrite(3,LOW);
digitalWrite(12,LOW);
digitalWrite(2,LOW);
digitalWrite(1,LOW);
 
}
 
else if (var==7){
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);
digitalWrite(12,HIGH);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(12,LOW);
}
 
else if (var==8){
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);
digitalWrite(12,HIGH);
digitalWrite(2,HIGH);
digitalWrite(1,HIGH);
digitalWrite(4,HIGH);
digitalWrite(3,HIGH);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(12,LOW);
digitalWrite(2,LOW);
digitalWrite(1,LOW);
digitalWrite(4,LOW);
digitalWrite(3,LOW);
}
 
else if (var==9){
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);
digitalWrite(12,HIGH);
digitalWrite(2,HIGH);
digitalWrite(4,HIGH);
digitalWrite(3,HIGH);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(12,LOW);
digitalWrite(2,LOW);
digitalWrite(4,LOW);
digitalWrite(3,LOW);
}
 
else if (var==0){
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);
digitalWrite(12,HIGH);
digitalWrite(2,HIGH);
digitalWrite(1,HIGH);
digitalWrite(4,HIGH);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(12,LOW);
digitalWrite(2,LOW);
digitalWrite(1,LOW);
digitalWrite(4,LOW);
}
 
else if (var==degree){ //the degree symbol
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);
digitalWrite(4,HIGH);
digitalWrite(3,HIGH);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(4,LOW);
digitalWrite(3,LOW);
}
 
else if (var==fheit){ //F for fahrenheit
digitalWrite(6,HIGH);
digitalWrite(1,HIGH);
digitalWrite(4,HIGH);
digitalWrite(3,HIGH);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(6,LOW);
digitalWrite(1,LOW);
digitalWrite(4,LOW);
digitalWrite(3,LOW);
}
 
else if (var==cels){ //C for celsius
digitalWrite(6,HIGH);
digitalWrite(2,HIGH);
digitalWrite(1,HIGH);
digitalWrite(4,HIGH);
delay(5);
//for(i=1;i<12;i++){
//digitalWrite(i,LOW);
//}
digitalWrite(6,LOW);
digitalWrite(2,LOW);
digitalWrite(1,LOW);
digitalWrite(4,LOW);
}
//error, a simple dash, (negative numbers)
else if(var=999){
digitalWrite(3,HIGH);
delay(5);
digitalWrite(3,LOW);
}
//error, over 99, top &amp; bttm
else if(var=222){
digitalWrite(6,HIGH);
digitalWrite(2,HIGH);
delay(5);
digitalWrite(6,LOW);
digitalWrite(2,LOW);
}
//error, over 99 backwards C
else if(var=222){
digitalWrite(6,HIGH);
digitalWrite(7,HIGH);
digitalWrite(12,HIGH);
digitalWrite(2,HIGH);
delay(5);
digitalWrite(6,LOW);
digitalWrite(7,LOW);
digitalWrite(12,LOW);
digitalWrite(2,LOW);
}
//testing
//Serial.println('testing');
}

But the DS18B20 is so sensitive that I had to put in a smoothing function.  Basically I instantiated a few more variables, most importantly an array to hold ten temperature readings that would be averaged before being sent to the display. Then I replaced “float num=temp” and the three digits at the end of the loop with:

Code:

float nums[10];
float avg;
int index=0;
float total =0;
 
//move up numbers
nums[index] = temp;
index++;
//reset to not use memory
if(index==10){
index = 0;
}
//average nums
total = 0;
for(i=0;i<=9;i++){
total += nums[i];
}
 
avg = total/10.0; //takes 10*15sec=2.5min to stabilize
 
digitOne=int(avg)/10; //so, to get digitOne you divide by 10
// a number like 49 magically becomes 4, all decimals disappear
digitTwo=(int(avg) - (digitOne * 10)); //then to get digit2 (9)you multiply digitOne by 10 to get 40
// and subtract it from the original 49 to get 9
digitThree = int(((avg - (digitOne*10 + digitTwo))*10))%10; //subtract from original

Now the displayed temperature does not jump wildly from one reading to the next. However, the information sensed is output on the display only. The data is not logged or sent anywhere. But the Seeeduino Stalker is meant to do all those things — it has an on-board real-time clock with its own CR2032 battery backup, a micro SD card slot, and an XBee header. This part of the project, as well as adding more One-Wire devices, is still in progress. I will post a follow-up as soon as it’s finished.

Leave a Reply

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