Sunday, January 25, 2009

3D Electronics Design

I just found a new thing to play with, 3D Electronics Design. I have seen some great 3D images of electronics component design for sometimes but I couldn't figure how they were made. Below image is one of my favorite. Please see for more images.

I have been playing with Eagle3D for sometimes. However, I cannot manipulate my design interactively and cannot export models to render in other 3D renderers. Just today, I found that blueroomelectronics's designs were made with Google SketchUp. So, I downloaded and installed it. The software is very easy to use. But, there is no electronics component library. However, there are some components available for you to download from google 3D warehouse. If you want anything that not available in the google 3D warehouse, you have to make it by yourself.
Below is my first try on making a PIC16F887 with TQFP-44 package.

SketchUp PCB Electronics component
I hope that I will come up with complete 3D designs of my clock projects. It's very fun to do these things.

Things to do

There are requests from readers as the following:
1. Complete project of the GPS clock
2. Adding calendar to my Digital Clock
3. Full function DS1307 Clock

And my own to do list:
4. FM Radio
5. Nixie Clock
6. Chronograph (stop watch)
7. Digital clock with 7-segment multiplexing using PIC16F627a or PIC16F628 + DS1307 + DS18S20 (Clock+Thermometer)
8. Digital clock + radio + thermometer (PIC16F887 + DS1307 + DS18S20 + Radio chip)
9. Complete led dot matrix clock
10.16x16 Led Dot matrix display

Wednesday, January 21, 2009

2-digit BCD to decimal conversion

Now, I'm working on the full feature clock using DS1307. In the clock, I use many BCD to decimal (bcd2dec) and decimal to BCD conversions for reading and setting time of the DS1307 RTC. MikroC provides buit-in functions for these conversions but the functions consume modest amount of MCU memory space. I have came up with simple functions that consume less memory for doing 2-digit BCD to decimal and the reverse conversions.

2-digit BCD to Decimal conversion function:
unsigned short myBcd2Dec(unsigned short bcd){
return ((bcd >> 4)*10+(bcd & 0x0F));

Example: myBcd2Dec(01000101) = 45

2-digit Decimal to BCD conversion function:
unsigned short myDec2Bcd(unsigned short dec){
return (((dec/10)<<4)(dec%10));

Example: myDec2Bcd(45) = 01000101

Sunday, January 11, 2009

Square Wave output from DS1307

For the clock that uses DS1307 RTC chip, I want a blinking led for indication of second. So, I have placed a resistor and an LED to pin 7 (SQW/OUT) of the DS1307 like below schematic:
Schematic for Square Wave Output DS1307

With this configuration (hardware+software), the LED was blinking at 1 time/second but the blink pattern was not my expectation. The LED is Off when the clock is updated and it is On at 0.5 second later. Quoted from the Control Register section of the DS1307's Datasheet:

With the square wave output set to 1Hz, the clock registers update on the falling edge of the square wave.

I want the reverse pattern (the LED is On when the time is updated and it is Off at 0.5 second later). So, I will add an invert logic before the LED like:
Invert logic at the output of DS1307
I have a plan to use this square wave output of the DS1307 for generating an interrupt to instruct the MCU to read time from the DS1307 and I will keep in mind that "The clock is updated at the falling edge of the square wave". The complete clock will be posted here later.

Monday, January 5, 2009

A Simple Clock using DS1307 + PIC16F877A

Even I have posted about "DS1307 + PIC16F877A", I didn't have chance to make a real prototype of the clock. I have done only on the simulation software. Today, I have received a comment about that post. ah_bear followed my code and schematic on that post but the clock didn't work. This is because the code on that post is for reading time from DS1307 so there must be some values in the DS1307 before you can read. The solution is simple. Just place setting time codes before reading codes.

This time, I have made a real prototype to confirm that it's working. There is no setting buttons. If you want to make a real usable clock you have to implement the button interfaces (I may make one and post it here). The photo of my working prototype is featured below. Please check out my flikr at for more photos.
A simple clock using DS1307 and PIC16F877A
The schematic of the clock is very simple. Please note that the schematic does not show power supply to the PIC16F877A and the DS1307, you have to connect them by youself. If you are new to PIC/LCD interface please see MikroC "Hello World!" LCD example .
Schematic of a simple clock using DS1307 and PIC16F877A

The source code:
//Sample code for
//DS1307 RTC Interfacing with PIC16F877A
//Coded by
//Compiler: mikroC 8.0.0
//Use with your own risk

unsigned short read_ds1307(unsigned short address );
void write_ds1307(unsigned short address,unsigned short w_data);
unsigned short sec;
unsigned short minute;
unsigned short hour;
unsigned short day;
unsigned short date;
unsigned short month;
unsigned short year;
unsigned short data;
char time[9];
char ddate[11];

unsigned char BCD2UpperCh(unsigned char bcd);
unsigned char BCD2LowerCh(unsigned char bcd);

void main(){

I2C_Init(100000); //DS1307 I2C is running at 100KHz
PORTB = 0;
TRISB = 0// Configure PORTB as output
Lcd_Init(&PORTB); // Initialize LCD connected to PORTB
Lcd_Cmd(Lcd_CLEAR); // Clear display
Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off

//Set Time
write_ds1307(0,0x80); //Reset second to 0 sec. and stop Oscillator
write_ds1307(1,0x10); //write min 27
write_ds1307(2,0x01); //write hour 14
write_ds1307(3,0x02); //write day of week 2:Monday
write_ds1307(4,0x05); // write date 17
write_ds1307(5,0x01); // write month 6 June
write_ds1307(6,0x09); // write year 8 --> 2008
write_ds1307(7,0x10); //SQWE output at 1 Hz
write_ds1307(0,0x00); //Reset second to 0 sec. and start Oscillator

sec=read_ds1307(0); // read second
minute=read_ds1307(1); // read minute
hour=read_ds1307(2); // read hour
day=read_ds1307(3); // read day
date=read_ds1307(4); // read date
month=read_ds1307(5); // read month
year=read_ds1307(6); // read year

time[0] = BCD2UpperCh(hour);
time[1] = BCD2LowerCh(hour);
time[2] = ':';
time[3] = BCD2UpperCh(minute);
time[4] = BCD2LowerCh(minute);
time[5] = ':';
time[6] = BCD2UpperCh(sec);
time[7] = BCD2LowerCh(sec);
time[8] = '\0';

ddate[0] = BCD2UpperCh(date);
ddate[1] = BCD2LowerCh(date);
ddate[2] ='/';
ddate[3] = BCD2UpperCh(month);
ddate[4] = BCD2LowerCh(month);
ddate[5] ='/';
ddate[6] = '2';
ddate[7] = '0';
ddate[8] = BCD2UpperCh(year);
ddate[9] = BCD2LowerCh(year);
ddate[10] = '\0';


unsigned short read_ds1307(unsigned short address)
I2C_Wr(0xd0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
I2C_Wr(0xd1); //0x68 followed by 1 --> 0xD1

unsigned char BCD2UpperCh(unsigned char bcd)
return ((bcd >> 4) + '0');

unsigned char BCD2LowerCh(unsigned char bcd)
return ((bcd & 0x0F) + '0');
void write_ds1307(unsigned short address,unsigned short w_data)
I2C_Start(); // issue I2C start signal
//address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
I2C_Wr(0xD0); // send byte via I2C (device address + W)
I2C_Wr(address); // send byte (address of DS1307 location)
I2C_Wr(w_data); // send data (data to be written)
I2C_Stop(); // issue I2C stop signal