Pic Lab, PIC16, Experiment #17, The clock with a thermometer

After I had enough time playing with a thermal sensor DS18b20 and the RTC DS1307 I decided to bundle them together into a single device. Another reason was the fact that the cheap Chinese clock called a day and let its electronic soul leave the nice enclosure. I considered this as an opportunity to put my stuff inside of it.

That is what I got in the end:

+1 reason is that I had a free sample of the “port expander” PCA9539, I mentioned this IC in experiment #13.

So, the first thing I want to describe is an indication system. I built it based on two 7-segment indicators (the red one is for the clock and the blue one for the temperature). The blue one was too bright, so I had to increase the resistor value to lower the brightness, since I was to lazy to add PWM here as well at the moment of time.

The schematic for the indication system is shown below:

The PCB:

After that, the main pcb has been assembled, where I placed the DS1307 clock and the thermal sensor DS18b20.

The schematic:

and the mainboard pcb:

The code:

#include <stdio.h>
#include <htc.h>
#define _XTAL_FREQ 4000000
#include "usart.h"               //функции для работы уарта
#include "softi2c.h"             //функции для работы i2c
 
#define timeh1 RB7  //3
#define timeh2 RB6  //4
#define timem1 RB4
#define timem2 RB5
 
#define tempd1 RB3
#define tempd2 RB2
#define tempd3 RB1
 
#define STATE TRISA2
#define PIN RA2
 
#define set_min RA3
#define set_hr RA4
#define setup RB0
 
__CONFIG(LVPDIS & WDTDIS & MCLREN & UNPROTECT & HS);
 
 unsigned char temphour = 0;         //hours
 unsigned char tempmin = 0;          //minutes
 
 char temperature;                  //temp
 unsigned char temp_drob = 0;       
 unsigned char sign;                
 
 volatile unsigned char button = 0;
 volatile unsigned char flag = 0;
 
const unsigned char tempdigit[11]={    
 0b10110111,   //ноль
 0b10000001,   //один
 0b00111101,   //два
 0b10101101,   //три
 0b10001011,   //четыре
 0b10101110,   //пять
 0b10111110,   //шесть
 0b10000101,   //семь
 0b10111111,   //восемь
 0b10101111,    //девять
 0b00001000
};
 
const unsigned char tempdigitvspoint[10]={  //temp values with dot
 0b11110111,   //ноль
 0b11000001,   //один
 0b01111101,   //два
 0b11101101,   //три
 0b11001011,   //четыре
 0b11101110,   //пять
 0b11111110,   //шесть
 0b11000101,   //семь
 0b11111111,   //восемь
 0b11101111    //девять
};
 
const unsigned char timedigit[10]={            //time values
 0b11110101,   //ноль
 0b00100100,   //один
 0b10111001,   //два
 0b10101101,   //три
 0b01101100,   //четыре
 0b11001101,   //пять
 0b11011101,  //шесть
 0b10100100,   //семь
 0b11111101,   //восемь
 0b11101101    //девять
};
 
const unsigned char timedigitvspoint[10]={       //time values with dot
 0b11110111,   //ноль
 0b00100110,   //один
 0b10111011,   //два
 0b10101111,   //три
 0b01101110,   //четыре
 0b11001111,   //пять
 0b11011111,  //шесть
 0b10100110,   //семь
 0b11111111,   //восемь
 0b11101111    //девять
};
 
/* functions calling */
static bit INIT(void);
void TX(unsigned char cmd);
unsigned char RX();
void get_temp();
unsigned char BCDconv (unsigned char source);
unsigned char DCBconv (unsigned char source);
void SetMin(unsigned char minutes);
unsigned char ReadMin();
void SetHour(unsigned char hours);
unsigned char ReadHour();
void SetSeconds(unsigned char seconds);
unsigned char ReadSeconds();
void ShowTime();
void SetupTime();
void InitIO(void);
void Display(unsigned char time, unsigned char temperaturet);
void Displaypoint(unsigned char time, unsigned char temperaturet);
void Displaypointminus(unsigned char time, unsigned char temperaturet);
void DispAll(unsigned char hour, unsigned char min, unsigned char temperaturet);
 
void main(void){
 unsigned char input;
 unsigned char i=0;
 
 CMCON = 0x07;
 
 TRISB = 0x00;
 TRISB0 = 1;
 TRISA3 = 1;
 TRISA4 = 1;
 get_temp();                 //getting temp values for the power on

 
 InitIO();              //port io expander
 
 /* setup timer and refresh period */
 
 T1CKPS1 = 1;
 T1CKPS0 = 1; // prescaler = 8
 
 T1OSCEN = 0; //no intosc
 TMR1CS = 0; // Fosc/4
 GIE = 1;   // global interrupt
 PEIE = 1;  // periferal interrups
 TMR1IE = 1; // interrupt on TMR1 overflow
 TMR1ON = 1; // enabling the timer
 
 TMR1H = 0b10110000; TMR1L = 0x00;  //init timer value 65024
 INTE = 0;
 
 temphour = ReadHour();
 tempmin = ReadMin();
 //get_temp();
 
 for(;;){
 
 DispAll(temphour, tempmin , temperature);         //display everything
 
 /* data refresh setup */
 if (flag == 20) {
 temphour = ReadHour();
 tempmin = ReadMin();
 i++;
 flag = 0;
 }
 if (i == 100) { TMR1IE = 0;
 get_temp();
 i = 0;
 TMR1IE = 1; }
 
 /* button pressing handler */
 
 if (!set_hr) {
 TMR1IE = 0;
 __delay_ms(100);
 if (!set_hr) {
 
 if (temphour<24) {
 temphour++;
 SetHour(temphour);
 } else {
 temphour = 1;
 SetHour(temphour);
 }
 
 }
 TMR1IE = 1;
 }
 if (!set_min) {
 TMR1IE = 0;
 __delay_ms(100);
 if (!set_min) {
 if (tempmin<60) {
 tempmin++;
 SetMin(tempmin);
 } else {
 tempmin = 1;
 SetMin(tempmin);
 }
 
 }
 TMR1IE = 1;
 }
 
 if (!setup) {
 TMR1IE = 0;
 __delay_ms(100);
 if (!setup) {
 SetSeconds(0);
 
 }
 TMR1IE = 1;
 }
 
/*
 /* uart menu */
 
 input = getch();
 
 switch (input) {
 case 49 : ShowTime();
 break;
 case 50 : SetupTime();
 break;
 case 51 : get_temp();
 ShowTime();
 break;
 }
 if (input == 49) {     SetupTime();}
*/
 
 }
 
}
 
interrupt isr() {               //interrupts handler
 
if (TMR1IF) {
flag++;
TMR1H = 0b10110000; TMR1L = 0x00;
TMR1IF = 0;  
}
 
}
 
/*  1-wire functions */
static bit INIT(void){
static bit b;
STATE = 1;
STATE = 0;
__delay_us(500);
STATE = 1;
__delay_us(65);
b = PIN;
__delay_us(450);
 
return b;
 
}
 
void TX(unsigned char cmd){
unsigned char temp = 0;
unsigned char i = 0;
temp = cmd;
for (i=0;i<8;i++) {
 if (temp&0x01) {
 STATE = 0;
 __delay_us(5);
 STATE = 1;
 __delay_us(70);
 } else {
 STATE = 0;
 __delay_us(70);
 STATE = 1;
 __delay_us(5);
 
 }
 temp >>= 1;
 }
 
}
 
unsigned char RX() {
unsigned char d = 0;
unsigned char i = 0;
for (i=0;i<8;i++){
 STATE = 0;
 __delay_us(6);
 STATE = 1;
 __delay_us(4);
 d>>=1;
 if (PIN == 1) d |= 0x80;
 //printf("\r\n %d", d);
 __delay_us(60);
 
 }
 
return d;
 
}
 
/* getting the temp value */
void get_temp() {
static bit init;
unsigned char temp1;
unsigned char temp2;
init = INIT();
if (!init) {
TX(0xCC);
TX(0x44);
__delay_ms(150);
__delay_ms(150);
__delay_ms(150);
__delay_ms(150);
__delay_ms(150);
} else printf("bug");
init = INIT();
if (!init) {
TX(0xCC);
TX(0xBE);
 
temp1 = RX();
temp2 = RX();
 
}
temp_drob = temp1 & 0b00001111;    
temp_drob = ((temp_drob*6)+2)/10;              
temp1 >>= 4;
sign = temp2 & 0x80;
temp2 <<= 4;
temp2 &= 0b01110000;
temp2 |= temp1;
 
if (sign) { temperature = 127-temp2;
 temp_drob = 10 - temp_drob;
 }   else temperature = temp2;
 
}
 
/* clock functions */
 
unsigned char BCDconv (unsigned char source) {
 unsigned char temp_min=0;
 unsigned char temp_maj=0;
 temp_min = source&15;
 temp_maj = source >> 4;
 //printf("\r\n minor - %x", temp_min);
 //printf("\r\n major - %x", temp_maj);
 temp_maj *= 10;
 //printf("\r\n major - %x", temp_maj);
 
 return temp_maj+temp_min;
}
 
unsigned char DCBconv (unsigned char source) {
 unsigned char temp_min=0;
 unsigned char temp_maj=0;
 temp_maj = source/10 ;
 temp_min = source - temp_maj*10;
 temp_maj <<= 4;
 
 return temp_maj+temp_min;
 
}
 
void SetMin(unsigned char minutes) {        //write minutes value
 i2c_start();
 i2c_tx(0b11010000);
 i2c_tx(0x01);
 i2c_tx(DCBconv(minutes));
 i2c_stop();
}
 
unsigned char ReadMin() {
 unsigned char temp = 0;
 i2c_start();            //read minutes
 i2c_tx(0b11010000);
 i2c_tx(0x01);
 i2c_start();
 i2c_tx(0b11010001);
 temp = i2c_rx(0);
 i2c_stop();
 
 return BCDconv(temp);
}
 
void SetHour(unsigned char hours) {        //hour writing
 i2c_start();
 i2c_tx(0b11010000);
 i2c_tx(0x02);
 i2c_tx(DCBconv(hours));
 i2c_stop();
}
 
unsigned char ReadHour() {
 unsigned char temp = 0;
 unsigned char temp2 = 0;
 i2c_start();            //read hours
 i2c_tx(0b11010000);
 i2c_tx(0x02);
 i2c_start();
 i2c_tx(0b11010001);
 temp = i2c_rx(0);
 i2c_stop();

 
 return BCDconv(temp);
}
 
void SetSeconds(unsigned char seconds) {        //write seconds
 i2c_start();
 i2c_tx(0b11010000);
 i2c_tx(0x00);
 i2c_tx(DCBconv(seconds));
 i2c_stop();
}
 
unsigned char ReadSeconds() {
 unsigned char temp = 0;
 i2c_start();            //read seconds
 i2c_tx(0b11010000);
 i2c_tx(0x00);
 i2c_start();
 i2c_tx(0b11010001);
 temp = i2c_rx(0);
 i2c_stop();
 
 return BCDconv(temp);
}
 
/*  USART functions */
void ShowTime() {
 printf("\fTime - %d :", ReadHour());
 printf(" %d :", ReadMin());
 printf(" %d ", ReadSeconds());
 
 printf("\r\ntemperatura -- ");
 if (sign) printf("-"); else printf("+");
 printf("%d", temperature);
 printf(".%d", temp_drob);
 
 printf("\r\n*********************");
 
 printf("\r\n Menu");
 printf("\r\n 1 - Reload time");
 printf("\r\n 2 - Setup time");
 printf("\r\n 3 - Reload temp");
 
}
 
void SetupTime() {
 unsigned char state = 1;
 unsigned char temp_min = 0;
 unsigned char temp_maj = 0;
 unsigned char temp = 0;
 
 while(state){
 printf("\fEnter hours - ");
 temp_maj = getch();
 printf(" %c", temp_maj);
 temp_min = getch();
 printf("%c", temp_min);
 temp = getch();
 if (temp == 13) {
 temp_maj -= 48;
 temp_min -= 48;
 temp = temp_maj*10 + temp_min;
 if (temp < 24) {
 SetHour(temp);
 state = 0;
 }
 
 }
 }
 state = 1;
 while(state){
 printf("\fEnter minutes - ");
 temp_maj = getch();
 printf(" %c", temp_maj);
 temp_min = getch();
 printf("%c", temp_min);
 temp = getch();
 if (temp == 13) {
 temp_maj -= 48;
 temp_min -= 48;
 temp = temp_maj*10 + temp_min;
 if (temp < 61) {
 SetMin(temp);
 state = 0;
 }
 }
 }
 state = 1;
 while(state){
 printf("\fEnter seconds - ");
 temp_maj = getch();
 printf(" %c", temp_maj);
 temp_min = getch();
 printf("%c", temp_min);
 temp = getch();
 if (temp == 13) {
 temp_maj -= 48;
 temp_min -= 48;
 temp = temp_maj*10 + temp_min;
 if (temp < 61) {
 SetSeconds(temp);
 state = 0;
 }
 }
 }
 
 ShowTime();
 
}
 
/* io expander functions */
void InitIO(void) {
 i2c_start();
 i2c_tx(0b11101000);
 i2c_tx(0b00000110);
 i2c_tx(0x00);
 i2c_tx(0x00);
 i2c_stop();
}
 
void Display(unsigned char time, unsigned char temperaturet) {
 unsigned char timetemp = 0;
 unsigned char temptemp = 0;
 timetemp = time;
 temptemp = temperaturet;
 i2c_start();
 i2c_tx(0b11101000);
 i2c_tx(0b00000010);
 i2c_tx(timedigit[timetemp]);
 i2c_tx(tempdigit[temptemp]);
 i2c_stop();
 
}
 
void Displaypoint(unsigned char time, unsigned char temperaturet) {
 unsigned char timetemp = 0;
 unsigned char temptemp = 0;
 timetemp = time;
 temptemp = temperaturet;
 i2c_start();
 i2c_tx(0b11101000);
 i2c_tx(0b00000010);
 i2c_tx(timedigitvspoint[timetemp]);
 i2c_tx(tempdigitvspoint[temptemp]);
 i2c_stop();
 
}
 
void Displaypointminus(unsigned char time, unsigned char temperaturet) {
 unsigned char timetemp = 0;
 unsigned char temptemp = 0;
 timetemp = time;
 temptemp = temperaturet;
 i2c_start();
 i2c_tx(0b11101000);
 i2c_tx(0b00000010);
 i2c_tx(timedigitvspoint[timetemp]);
 i2c_tx(tempdigit[temptemp]);
 i2c_stop();
 
}
 
void DispAll(unsigned char hour, unsigned char min, unsigned char temperaturet) {
 unsigned char tim = 0;
 unsigned char tem = 0;
 unsigned char buf = 0;
 
 if (!sign) {
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 0;
 tim = hour/10; tem = temperaturet/10;
 Display(tim, tem);
 timeh1 = 1; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 1; tempd2 = 0; tempd3 = 0;
 __delay_us(500);
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 0;
 buf = tim*10;
 tim = hour - buf;
 tem = temperaturet - tem*10;
 Displaypoint(tim, tem);
 timeh1 = 0; timeh2 = 1; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 1; tempd3 = 0;
 __delay_us(500);
 
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 0;
 tim = min/10; tem = temp_drob;
 Display(tim, tem);
 timeh1 = 0; timeh2 = 0; timem1 = 1; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 1;
 __delay_us(500);
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 0;
 buf = tim*10;
 tim = min-buf;
 Display(tim, tem);
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 1; tempd1 = 0; tempd2 = 0; tempd3 = 1;
 __delay_us(500);
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 0;
 __delay_us(500);
 }  else
 {
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 0;
 tim = hour/10; tem = 10;
 Display(tim, tem);
 timeh1 = 1; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 1; tempd2 = 0; tempd3 = 0;
 __delay_ms(1);
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 0;
 buf = tim*10;
 tim = hour - buf;
 tem = temperaturet/10;
 Displaypointminus(tim, tem);
 timeh1 = 0; timeh2 = 1; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 1; tempd3 = 0;
 __delay_ms(1);
 
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 0;
 tim = min/10; tem = temperaturet - tem*10;
 Display(tim, tem);
 timeh1 = 0; timeh2 = 0; timem1 = 1; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 1;
 __delay_ms(1);
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 0;
 buf = tim*10;
 tim = min-buf;
 Display(tim, tem);
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 1; tempd1 = 0; tempd2 = 0; tempd3 = 1;
 __delay_ms(1);
 timeh1 = 0; timeh2 = 0; timem1 = 0; timem2 = 0; tempd1 = 0; tempd2 = 0; tempd3 = 0;
 __delay_ms(1);
 }
}

The video with the clock working:

The sources and the PCB are on my git repo 

Leave a Reply

Your email address will not be published.