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