Introduction
This project describes how to read temperature from a DS1820 sensor with a PIC16F628A microcontroller and display the temperature value in a multiplexed 4-digit seven segment display. The temperature will be displayed in both Centigrade and Fahrenheit units switching back and forth. The temperature resolution is 1 degree in both the units. Out of 4-digits, the most significant three digits will display numeric temperature values from 00 to 125. The most significant digit will show '-' for negative temperatures, and the least significant digit will display C or F.
On my PIC16F628A board, connect D1 to RA2, D2 to RA1, D3 to RA0, and D4 to RA3. DS1820 data will be read at RA4 port. The seven segments a-g will be driven by RB0-RB6.
Software
/* Project name:
Seven-segment display digital thermometer
* Copyright:
(c) Rajendra Bhatt, 2010.
MCU: PIC16F628A
Oscillator: XT, 4.0 MHz
*/
// Temperature digits
unsigned short i, DD0=0x3f, DD1=0x3f,DD2=0x3f, CF_Flag=0xff, CF=0x3f, N_Flag;
// CF_Flag = 0: F, 1: C
// Variable to store temperature register value
unsigned temp_value=0, temp_whole;
unsigned int temp_fraction=0;
float temp_F;
//-------------- Function to Return mask for common cathode 7-seg. display
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
case 10 : return 0x40; // Symbol '-'
case 11 : return 0x39; // Symbol C
case 12 : return 0x71; // Symbol F
case 13 : return 0x00; // Blank
} //case end
}
void display_temp(short DD0, short DD1, short DD2, short CF) {
for (i = 0; i<=200; i++) {
PORTB = DD0;
RA0_bit = 1; // Select Ones Digit
RA1_bit = 0;
RA2_bit = 0;
RA3_bit = 0;
delay_ms(5);
PORTB = DD1;
RA0_bit = 0;
RA1_bit = 1; // Select Tens Digit
RA2_bit = 0;
RA3_bit = 0;
delay_ms(5);
PORTB = DD2;
RA0_bit = 0;
RA1_bit = 0;
RA2_bit = 1; // Select +/- Digit
RA3_bit = 0;
delay_ms(5);
PORTB = CF;
RA0_bit = 0;
RA1_bit = 0;
RA2_bit = 0 ;
RA3_bit = 1; // Select CF Digit
delay_ms(5);
}
return;
}
void main() {
CMCON |= 7; // Disable Comparators
TRISB = 0x00; // Set PORTB direction to be output
PORTB = 0x00; // Turn OFF LEDs on PORTB
TRISA0_bit = 0; // RA.0 to RA3 Output
TRISA1_bit = 0;
TRISA2_bit = 0;
TRISA3_bit = 0;
//--- main loop
do {
N_Flag = 0; // Reset Temp Flag
//--- perform temperature reading
Ow_Reset(&PORTA, 4); // Onewire reset signal
Ow_Write(&PORTA, 4, 0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTA, 4, 0x44); // Issue command CONVERT_T
display_temp(DD0, DD1, DD2,CF) ;
Ow_Reset(&PORTA, 4);
Ow_Write(&PORTA, 4, 0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTA, 4, 0xBE); // Issue command READ_SCRATCHPAD
// Next Read Temperature
// Read Byte 0 from Scratchpad
temp_value = Ow_Read(&PORTA, 4);
// Then read Byte 1 from Scratchpad and shift 8 bit left and add the Byte 0
temp_value = (Ow_Read(&PORTA, 4) << 8) + temp_value;
if (temp_value & 0x8000) {
temp_value = ~temp_value + 1;
N_Flag = 1; // Temp is -ive
}
if (temp_value & 0x0001) temp_value += 1; // 0.5 round to 1
temp_value = temp_value >> 1 ;
if (CF_Flag == 0) {
if (N_Flag ==1) {
temp_F = (32.0-9.0*temp_value/5.0)*10 + 6;
if (temp_F < 0){
N_Flag=1;
temp_value = abs(temp_value);
}
else N_Flag = 0;
}
else temp_F = (9.0*temp_value/5.0+32.0)*10 + 6; //If decimal is greater or equal
// to 0.5, add 0.5
temp_value = temp_F/10;
CF = 12;
}
if (CF_Flag == 0xff) CF = 11;
DD0 = temp_value%10; // Extract Ones Digit
DD0 = mask(DD0);
DD1 = (temp_value/10)%10; // Extract Tens Digit
DD1 = mask(DD1);
DD2 = temp_value/100; // Extract Hundred digit
CF = mask(CF);
if (N_Flag == 1) DD2=10;
else if (DD2 == 0) DD2 = 13 ;
DD2 = mask(DD2) ;
PORTB=0x00;
CF_Flag =~CF_Flag;
} while (1);
}
Output Pictures
This project describes how to read temperature from a DS1820 sensor with a PIC16F628A microcontroller and display the temperature value in a multiplexed 4-digit seven segment display. The temperature will be displayed in both Centigrade and Fahrenheit units switching back and forth. The temperature resolution is 1 degree in both the units. Out of 4-digits, the most significant three digits will display numeric temperature values from 00 to 125. The most significant digit will show '-' for negative temperatures, and the least significant digit will display C or F.
On my PIC16F628A board, connect D1 to RA2, D2 to RA1, D3 to RA0, and D4 to RA3. DS1820 data will be read at RA4 port. The seven segments a-g will be driven by RB0-RB6.
Software
/* Project name:
Seven-segment display digital thermometer
* Copyright:
(c) Rajendra Bhatt, 2010.
MCU: PIC16F628A
Oscillator: XT, 4.0 MHz
*/
// Temperature digits
unsigned short i, DD0=0x3f, DD1=0x3f,DD2=0x3f, CF_Flag=0xff, CF=0x3f, N_Flag;
// CF_Flag = 0: F, 1: C
// Variable to store temperature register value
unsigned temp_value=0, temp_whole;
unsigned int temp_fraction=0;
float temp_F;
//-------------- Function to Return mask for common cathode 7-seg. display
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
case 10 : return 0x40; // Symbol '-'
case 11 : return 0x39; // Symbol C
case 12 : return 0x71; // Symbol F
case 13 : return 0x00; // Blank
} //case end
}
void display_temp(short DD0, short DD1, short DD2, short CF) {
for (i = 0; i<=200; i++) {
PORTB = DD0;
RA0_bit = 1; // Select Ones Digit
RA1_bit = 0;
RA2_bit = 0;
RA3_bit = 0;
delay_ms(5);
PORTB = DD1;
RA0_bit = 0;
RA1_bit = 1; // Select Tens Digit
RA2_bit = 0;
RA3_bit = 0;
delay_ms(5);
PORTB = DD2;
RA0_bit = 0;
RA1_bit = 0;
RA2_bit = 1; // Select +/- Digit
RA3_bit = 0;
delay_ms(5);
PORTB = CF;
RA0_bit = 0;
RA1_bit = 0;
RA2_bit = 0 ;
RA3_bit = 1; // Select CF Digit
delay_ms(5);
}
return;
}
void main() {
CMCON |= 7; // Disable Comparators
TRISB = 0x00; // Set PORTB direction to be output
PORTB = 0x00; // Turn OFF LEDs on PORTB
TRISA0_bit = 0; // RA.0 to RA3 Output
TRISA1_bit = 0;
TRISA2_bit = 0;
TRISA3_bit = 0;
//--- main loop
do {
N_Flag = 0; // Reset Temp Flag
//--- perform temperature reading
Ow_Reset(&PORTA, 4); // Onewire reset signal
Ow_Write(&PORTA, 4, 0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTA, 4, 0x44); // Issue command CONVERT_T
display_temp(DD0, DD1, DD2,CF) ;
Ow_Reset(&PORTA, 4);
Ow_Write(&PORTA, 4, 0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTA, 4, 0xBE); // Issue command READ_SCRATCHPAD
// Next Read Temperature
// Read Byte 0 from Scratchpad
temp_value = Ow_Read(&PORTA, 4);
// Then read Byte 1 from Scratchpad and shift 8 bit left and add the Byte 0
temp_value = (Ow_Read(&PORTA, 4) << 8) + temp_value;
if (temp_value & 0x8000) {
temp_value = ~temp_value + 1;
N_Flag = 1; // Temp is -ive
}
if (temp_value & 0x0001) temp_value += 1; // 0.5 round to 1
temp_value = temp_value >> 1 ;
if (CF_Flag == 0) {
if (N_Flag ==1) {
temp_F = (32.0-9.0*temp_value/5.0)*10 + 6;
if (temp_F < 0){
N_Flag=1;
temp_value = abs(temp_value);
}
else N_Flag = 0;
}
else temp_F = (9.0*temp_value/5.0+32.0)*10 + 6; //If decimal is greater or equal
// to 0.5, add 0.5
temp_value = temp_F/10;
CF = 12;
}
if (CF_Flag == 0xff) CF = 11;
DD0 = temp_value%10; // Extract Ones Digit
DD0 = mask(DD0);
DD1 = (temp_value/10)%10; // Extract Tens Digit
DD1 = mask(DD1);
DD2 = temp_value/100; // Extract Hundred digit
CF = mask(CF);
if (N_Flag == 1) DD2=10;
else if (DD2 == 0) DD2 = 13 ;
DD2 = mask(DD2) ;
PORTB=0x00;
CF_Flag =~CF_Flag;
} while (1);
}
Output Pictures
No comments:
Post a Comment