Friday, September 12, 2008

PIC CLOCK FINAL VERSION

As promised in the earlier post, here comes the photos and a video of the PIC CLOCK using the DS1307. The features of the clock are;

1. Displaying the Time, date, month and year
2. Displaying the Temperature
3. Display Time, Date & Month and Temperature Alternatively
4. Battery backup
5. Display illumination reduced at night (From 10pm to 6am)
6. Highly accurate. (DS1307 RTC and temperature compensated crystal DS32kHz)

The following video shows how the clock is in action. It displays Time, date and temperature alternatively. All the parameters (hour, minute, second, date, month, year etc.) can be set by selecting the appropriate mode and increment buttons. Display blinks when entered into the change mode. There are modes to display Time, Seconds, Date , Year and Temperature continuously. Everything is fixed inside a floppy disk box. I'm gonna wrap it with something to hide the internals, may be with a dark sticker.




Some pictures of the clock in different angles;






















Parts List

PIC16F628A microcontroller
DS1307 Real Time Clock IC
DS32kHZ Crystal
MAX7219/21 Display Driver
DS18S20 Temperature Sensor
4 Seven Segment LED Displays
2 AA Battery Holder (3v)
7805 5v regulator
9v ac power pack
IC holders, wire, vero board and lots of patience 


Code snippets I used for the project;

Defining the SPI & I2C connection in PORTB. Display driver MAX7221 uses SPI while DS1307 RTC uses I2C.

void InitMain() {
Soft_Spi_Config(&PORTB, 4, 5, 3);
Soft_I2C_Config(&PORTB, 0, 1);

}//~


Initializing the RTC.

void ds1307_init(){
char seconds=0;

Soft_I2C_Start();
Soft_I2C_Write(0xD0); // WR to RTC
Soft_I2C_Write(0x00); // REG 0
Soft_I2C_Start();
Soft_I2C_Write(0xD1); // RD from RTC
seconds = Bcd2Dec(Soft_I2C_Read(1)& 0x7F); // Read current "seconds" in DS1307
Soft_I2C_Stop();


Delay_us(3);

Soft_I2C_Start();
Soft_I2C_Write(0xD0); // WR to RTC
Soft_I2C_Write(0x00); // REG 0

Soft_I2C_Write(Dec2Bcd(seconds)); // Start oscillator with current "seconds value
Soft_I2C_Start();
Soft_I2C_Write(0xD0); // WR to RTC
Soft_I2C_Write(0x07); // Control Register
Soft_I2C_Write(0x80); // Disable squarewave output pin
Soft_I2C_Stop();
}//~end of function


Initialize MAX7221

void max7219_init1() {
PORTA &= 0xFD; // SELECT MAX
Soft_SPI_write(0x09); // BCD mode for digit decoding
Soft_SPI_write(0xFF);
PORTA |= 2; // DESELECT MAX

PORTA &= 0xFD; // SELECT MAX
Soft_SPI_write(0x0A);
Soft_SPI_write(0x03); // Segment luminosity intensity
PORTA |= 2; // DESELECT MAX

PORTA &= 0xFD; // SELECT MAX
Soft_SPI_write(0x0B);
Soft_SPI_write(0x03); // Display refresh
PORTA |= 2; // DESELECT MAX

PORTA &= 0xFD; // SELECT MAX
Soft_SPI_write(0x0C);
Soft_SPI_write(0x01); // Turn on the display
PORTA |= 2; // DESELECT MAX

PORTA &= 0xFD; // SELECT MAX
Soft_SPI_write(0x00);
Soft_SPI_write(0xFF); // No test
PORTA |= 2; // DESELECT MAX
}


Display the values using MAX7221

void Write_7219(int x, int y) {

PORTA &= 0xFD;
Soft_SPI_write(x); // send i to max7219 (digit place)
Soft_SPI_write(y);

PORTA |=2;

}


Reading & writing to the RTC

unsigned short read_ds1307(unsigned short address)
{
Soft_I2C_Start();
Soft_I2C_Write(0xd0);
Soft_I2C_Write(address);
Soft_I2C_Start();
Soft_I2C_Write(0xd1);
data=BCD2DEC(Soft_I2C_Read(0));
Soft_I2C_Stop();
return(data);
}

void Write_DS1307(unsigned short Address, unsigned short _Data) {

Soft_I2C_Start(); // start a serial transfer
Soft_I2C_Write(0xD0); // which device, 1101000 = DS1307, + direction bit (R=1,W=0)
// thus 11010000 = 0xD0 ie write to DS1307
// need to tell the DS1307 which address is to be written to
Soft_I2C_Write(Address); // send the address to be written to the DS1307
Soft_I2C_Write(_Data); // send actual data to be written into Address on the DS1307
Soft_I2C_Stop(); // finished serial transfer (and release the I2C bus)
}


Read Temperature (DS18S20) & Display

void Read_temp()
{
ow_reset(&PORTB,2); // onewire reset signal
ow_write(&PORTB,2,0xCC); // issue command to DS1820
ow_write(&PORTB,2,0x44) ;

delay_us(120);

ow_reset(&PORTB,2);
ow_write(&PORTB,2,0xCC); // issue command to DS1820
ow_write(&PORTB,2,0xBE);

delay_ms(500);

j1 = ow_read(&PORTB,2); // get result
_Decimal = j1 & 0x01 ;
j1 = j1 >> 1 ;

}

void display_temp()
{
Read_temp();
j = j1%10;
j = j+0x80;
Write_7219(2,j);
j = j1/10 ;
Write_7219(1,j);

if (_decimal==0)
Write_7219(3,0x00);
else
Write_7219(3,0x05);

Write_7219(4,0x0F);



}


To display time, date and to edit the parameters, I wrote separate modules using the above basic building blocks. If somebody needs the schematic and the complete source / hex, drop me an email or leave a comment with the email address. I used Mikroelektronika forum (http://www.mikroe.com/forum/) heavily and almost all the above coding segments are taken from the forum. Therefore, full credit goes to all the people who contributed to the forum.