The LOLex Update 7: It has a Button!

You may be wondering why I haven't been posting in awhile.  That can be explained by the fact that I started my senior year at CP SLO about a week and half ago.  I'm taking some cool classes that should greatly benefit me in my project shenanigans.  They are Intro to Mechatronics, Controls, Senior Project, Thermal Science Lab and Music Theory.  Enough about school, time for the LOLex.

Over the past 2 weeks I have been trying to get the uC to keep accurate time so that the watch will actually be useful.  Here are the various revisions I went through until I ended up where I am now.

1) The internal oscillator of the uC.  This worked alright to get the basic code working but blew as a way to keep the time.  It was fast by almost 2 minutes and 40 seconds every hour.  When I found this out I knew I had to move on to a ceramic resonator or crystal oscillator.
Mine says 4.00M
2) A ceramic resonator I pulled out of a broken stereo system that I use for parts.  At least I think it was a resonator.  I did some research and there are two types of these ceramic device, filters and resonators.  I couldn't find out if they were the same device but functioned differently based on the circuitry and application.  Anyway I used it.  It's value was 4.00Mhz so I didn't have to change my timer code at all but I did have to change the configuration bits for the PIC, from internal osc to external osc.  After testing, it preformed much much better than the internal osc.  However it still wasn't perfect.  This time it was slow about 10 seconds every 12 hours.

3) I also pulled out a 4.500 MHz and a 16.**** MHz crystal oscillator from the stereo.  Using a crystal oscillator was my next logical step.  I used the 4.500 crystal since I pulled off its loading capacitors too.  The loading capacitors help stabilize the crystal.  I had to do a little modification to the timer code because of the crystals new value.  I guess I should also mention that when I moved to the external oscillator I had to swap a couple connections since the oscillator takes up 2 pins on the uC, so I can't light up the decimal point on the display.  After testing this,  I found that it was still a little slow.  To compensate this I gradually decreased the timer compare value so that the second increment would be triggered faster.  

4) This is what I'm planning on doing.   The weekend before I left for school, a near by neighborhood had a massive block sale.  I scoured the place for super cheap digital watches.  My goal was to find on with a 32 kHz watch crystal that I could use.  Well I found one but I have yet to do anything with it.  The PIC has a input for a crystal of that size for use with the timer1 module.  I am going to use it so I can put the uC to sleep and still have the timer running and keeping track of the time.  When I press the button (which I will be covering shortly) it wakes up and displays the time then goes back to sleep.  This will greatly increase battery life, which is last the last challenge I'll need to tackle for this project to be finished.

button yeah!
I introduced a button to my uC so that they could set the time together. Since I was very limited pins I used something I saw on this site.  I connected the button to one of the output pins for the display so that it multiplexed with it. So I have to change that pin from output to input whenever I'm polling the button.  I don't know it thats the right way to do it but it seems to work.  This was also the first time in any of my projects that I have used a button so I had to learn about debouncing and everything else that goes a long with buttons.

Here how my set routine works.  First to get into set mode the button is held down for a short while.  If you just press the button then the time is displayed for like 2 seconds.  Once in set mode it sets the hours by incrementing them and then the user presses the button to stop the incrementing and set the hours.  The same is done for the minutes.  Here's my horrible code.  Again I'm always looking for suggestions on my code and whatnot. 

void set(void)
{
    char hour = 0, min = 0;
    char setCount = 0;
    
    /*Ill display SET or something when it comes into this mode 
        so that one doesn't automatically set the time*/
    for(setCount =0;setCount<500;setCount++){
        PORTB = 0b10100010;
        delay(100);
        PORTB = 0x00;
    }
    setCount = 0;
    while(hour == 0){        
        if(setCount == 100){            
            setCount = 0;
            hh++;
        }    
        if(hh == 13){
            hh = 1;
        }
        display(hh/10,hh%10,mn/10,mn%10);
        if(RA1==1){
            delay(1200);
            if(RA1==0){
                hour = 1;
            }
        }
        setCount++;
    }
    while(min==0){
        if(setCount == 100){            
            setCount = 0;
            mn++;
        }    
        if(mn == 60){
            mn = 0;
        }
        display(hh/10,hh%10,mn/10,mn%10);
        if(RA1==1){
            delay(1200);
            if(RA1==0){
                min = 1;
            }
        }
        setCount++;
    }
}
And here's the part where you enter into the set routine.


while(1)  /*run forever.  Idles if button not pressed.  if button held goes into setup*/
    {
        TRISA = 0xF2; 
        if(RA1 == 1){    //is button pressed
            hold = 1;
            counter = longCount;
            while(hold == 1){
                delay(700);  //delay 10ms
                if(RA1 == 1){  //is button still pressed    
                    counter--;    //decrease counter
                    if(counter==0){    //if zero it was a long hold
                        GIE = 0;
                        set();
                        GIE = 1;
                        hold = 0;
                    }
                }
                else if(RA1 == 0){  //button wasnt held
                    counter = 100;
                    TRISA = 0xF0;
                    while(counter != 0){
                        display(hh/10,hh%10,mn/10,mn%10);
                        counter-=1;
                    }
                    hold=0;
                }    
            }
            
        }            
    }
To make this better I am thinking about implementing something similar to this.  That should make the code somewhat nicer and less confusing.

Well I've basically been testing this version since Sunday, so 3 days and it hasn't lost/gained a minute.  The watch crystal will probably get integrated this weekend.  After that stage goes through testing I should be getting VERY close to putting everything in the case.

The LOLex Update 6: PICing My Brains Out

I still have no idea why I'm using a PIC but hey after crashing through Hi Techs FAQ and the PIC16F628's datasheet, I finally have some what of shaky grasp of programming a PIC in C.  From there I just ported my Arduino code over with this sites help for the pin outs.  I had a couple hiccups along the way.  The one that stumped me until I had my morning of bowl of oatmeal was that my interrupt routine was continuously being executed and the main block of code was never run.  Well it turned out that I had enabled the compare match interrupt before I had set the value that I wanted the interrupt generated at.  So a quick switch of those 2 lines of code solved the problem.  The other problem is pretty embarrassing, I had the power and ground wires switched so it wouldn't turn on.  Once I fixed that it turned on and worked!

Well it sort of works.  The clock is fast, so far its gained 30 sec in about 13 mins or so.  So now I have to work on that.  Lets work it right here and hopefully myself or one of my readers can help me out.  So the internal oscillator is 4MHz but internal clock is that divided by 4 so 1MHz.  Then if I prescale it by 8 that gives me 125kHz.  Now if I set my compare match value to 62500 (since timer1 is a 16bit timer it will overflow at 65536) and in my interrupt routine I increment a variable.  Then when that is incremented twice 1 second should have past so then my seconds variable can be incremented.  How does that sound? Any complainants?  I realize that the internal oscillator is not as accurate as a crystal but it should be more accurate than what I'm seeing if front of me.  I should probably get a 32.768kHz watch crystal to use for this thing but then I take up 2 pins and 2 pins in PORTA are basically input only so I wouldn't be able to fully drive my display.  Anyway here's my codez.  
#include <pic.h>

/*Use the following code for turning multiple bits on or off in a variable, according to mask.*/
#define bits_on(var,mask) var |= mask
#define bits_off(var,mask) var &= ~0 ^ mask

void printHour(char num); //I spent to much time coding in python this summer
void printMin(char num); //totally forgot about function prototypes lol
void delay(unsigned int x); 

volatile unsigned char ss = 0;
volatile unsigned char mn = 0;
volatile unsigned char hh = 1;

char digits[] = {0b00010010,//0 digits
                 0b10111110,//1
                 0b10000011,//2
                 0b10000110,//3
                 0b00101110,//4
                 0b01000110,//5
                 0b01100010,//6
                 0b00011110,//7
                 0b00000010,//8
                 0b00001110,//9
                 0b10011111};//colon

char digiCon[] = {0b0000001, //digit 1
            0b0000010, //digit 2
            0b0000100, //colon
             0b0001000, //digit 3
            0b1000000}; //digit 4

char scaler = 0; 

void interrupt isr(void){
    if(CCP1IF){
        CCP1IF = 0;
        scaler++;
        if(scaler == 2){
            scaler = 0;
            ss++;
            if(ss == 60){
                ss=0;
                mn++;
                if(mn == 60){
                    mn=0;
                    hh++;
                    if(hh == 13){
                        hh=1;
                    }
                }
            }
        }
    } 
}

void main (void)
{
    CMCON = 0x07; /*disable comparators*/

    TRISA = 0b10110000; /*config RA0-3 and RA6 as output*/
    TRISB = 0x00; /*config RB0-7 as output*/
    PORTA = 0x00; 
    PORTB = 0x00;

    INTCON = 0;
    CCP1IE = 1; /*compare interrupt enable*/

    PEIE = 1; /*peripheral interrupt enable*/
    GIE = 1; /*global interrupts enable*/

    CCPR1L = 0x24; 
    CCPR1H = 0xF4; /*Compare match value 62500*/
    CCP1CON = 0b00001011; /*Compare mode, trigger special event, CCP1IF bit set, TMR1 reset
Didn't think of it at the time but setting the match value before 
you enable the interrupt would be a smart thing to do.*/
    T1CON = 0b00110001; /*set up timer1, 1:8 prescale(1MHz -> 125kHz, start timer*/

    while(1) /*print the digits forever*/
    {
        printHour(mn);
        printMin(ss);
    }
} 

void printHour(char num)
{
    char temp = num / 10; //get tens place digit
    num = num % 10; // remove tens from number, left with ones place

    bits_on(PORTB,digits[temp]);
    bits_on(PORTA,digiCon[0]);
    delay(250);
    bits_off(PORTA,digiCon[0]);
    bits_off(PORTB,digits[temp]);

    bits_on(PORTB,digits[num]);
    bits_on(PORTA,digiCon[1]);
    delay(250);
    bits_off(PORTA,digiCon[1]);
    bits_off(PORTB,digits[num]);

    bits_on(PORTB,digits[10]);
    bits_on(PORTA,digiCon[2]);
    delay(250);
    bits_off(PORTA,digiCon[2]);
    bits_off(PORTB,digits[10]);
}

void printMin(char num)
{
    char temp = num / 10; //get tens place digit
    num = num % 10; // remove tens from number, left with ones place

    bits_on(PORTB,digits[temp]);
    bits_on(PORTA,digiCon[3]);
    delay(250);
    bits_off(PORTA,digiCon[3]);
    bits_off(PORTB,digits[temp]);

    bits_on(PORTB,digits[num]);
    bits_on(PORTA,digiCon[4]);
    delay(250);
    bits_off(PORTA,digiCon[4]);
    bits_off(PORTB,digits[num]);
}

void delay(unsigned int x)
{
    while(--x != 0)
        continue;
} 
If you have any suggestions for my code let me know.

Oh yeah I made the case opening a little bigger.  Just a bit though but everything *should* fit now.

The LOLex Update 5: Just LOL

That ^ has to fit in there ->      LOL.
Hmmm.  I probably should have made the case a little bigger or actually had put a little more time in to the design phase.  Whatever, it's ridiculous and thats why it's called the LOLex.

It's down to using only 6 pins.  That's going to change though once I switch from the 74138 demux and 74194 4 bit shift register to two 74595 8 bit serial to parallel/serial shift registers.  Using those will cut the pin count down to 3, leaving 3 open for buttons or other nifty features!!  Woot!  I'll actually be able to set the time.

Speaking of setting the time.  I found something that I want to add to version 2 of the LOLex, radio controlled time setting via the WWVB.  That's right it'll be synced with an atomic clock.  I've already started doing a little research about it.  The major thing I'll need is an antenna and receiver to receive the 60kHz signal.  I'll let the microcontroller decode the signal, which doesn't seem like a difficult thing to do.  The microcontroller's clock will still do all the time keeping but it'll be updated every 24 hours or so.  So that and an OLED screen is what I have in store for version 2.  Lets not get ahead of myself just yet, I still need to finish the first one.

Time to work more on fitting everything into the case.  But I'll leave you with this video thats full of mechanical watch Pr0n!!  It might be a future project.

UPDATE:
So instead of making a whole new post for this small thought I've just had, I'm just going to add to this one.  After mulling around with some chips, the display and the case I've come to the conclusion that it's not going to fit unless I switch to surface mount components which not something I want to do.   However there is an alternative solution, switch from the 8 pin microcontroller I was planing on using to a 16,18 or 20 pin one.  I only need 12 pins (who needs a decimal point!) to to drive the display so either would work but 18/20 pin would be better since I'd have 3/5 pins for buttons and what not.  It have to be one with an internal oscillator in order to cut down on the number of external components.  It would definitely be over kill since I wouldn't be using it to its full extent.  Oh yeah I bough a PIC16f628 when I bought my PIC12f683, just to have a PIC with more pins (Don't ask me why I went with a PIC and not an AVR like what the Arduino has, it was a spur of the moment decision along with the fact that I have a PICkit2 from something my brother gave me).   Looks like I get to use it for this now.  When I go that route I'd have a good .375 x .4 x 1.1in area for the battery and anything else.  This just proves that you should spend more time designing (not while watching Transformers) before you start buying parts. Oh well.

The LOLex Update 4: It's About to get a Little Cramped

I've made some progress on the LOLex over the past couple days.  Most of it was on the electronics portion since the case was pretty much done.  I ditched the OLED screen in favor of a cheaper solution, 4 digit 7 segment module.  The OLED screen will show up in version 2.  It took a little searching but I found one small enough to fit in the case.  With the display decided on the case was able to be finished.


It only required one modification to make the display fit.  The pocket in the upper and lower case pieces had to be widened.  After that was done, a slot so that the display was visible was cut.  That's all the machining in this update.

Since I'm not going to use a real time clock chip,  I needed a way to generate an accurate second from my microcontroller.  For my prototype, I'm just using my Arduino since its quick.  I knew that I could divide down the microcontroller's clock to get a second or some fraction of a second but I had no idea how to do that.  After some probing on the web, I came across this site.  It had exactly what I was looking for but I didn't understand what was happening.  So just like the guy I dove into the ATmega328's datasheet.  After an hour of searching, reading and referencing guy's code, I finally had a basic understanding of the 328's timers.

To help me learn I wrote some a 1 second timer in a different way than what I had just seen.  Firstly I had to set up the timer registers.
TIMSK1 = 0x02;  //enable global and timer CTC interrupt
 TCCR1A = 0x00;  // normal mode
 TCNT1 = 0x0000;  //initial value for timer
 OCR1A = 0xF424;   //timer match value
 TCCR1B = 0x0C; //start clock and prescale 
TIMSK1: Enable the CTC interrupt. In CTC or Clear timer on Compare mode the timer is cleared when the counter equals  the output compare register.
TCCR1A: Timer control register A.  You can enable some other modes and things but I just need it in normal mode.
TCCR1B: Timer control register B.  Has the bits to enable CTC mode.  Also you start and prescale the clock from this register.  I have it dividing the clock by 256.
TCNT1: The timer/counter.
OCR1A: Output compare register.  Contains the value that the timer is compared to.  When they match an interrupt is generated.

Next was the interrupt code.
ISR(TIMER1_COMPA_vect) {
  second++;
  if (second == 60){
    second = 0;
    minute++;
    if(minute == 60){
      minute = 0;
      hour++;
      if(hour==13){
         hour=1;
      }
    }
  }
}
I got super confused when I saw this in the other guys code.  I couldn't find reference to ISR function or to TIMER1_COMPA_vect in the datasheet.  I finally found it in some avr header file.   I had no idea that those even existed.  I guess that the arduino IDE and bootloader has sheltered me from the down and dirty uC programming. 

When I wrote that I didn't have the 4 digit display so I just use the 2 digits that I had already set up and displayed the seconds to make sure that it was keeping reasonably accurate time.  It ran for over half a day and didn't show any sign of lag or speeding up.

With the 4 digit display, I also got a grab bag of 7400 series logic IC's.  I was hoping for some serial shift registers in the bag but there wasn't any.  I got a wide variety of chips but the majority were 7404 inventers.  In the mix were a couple of a 74138 demultiplexers, that I made use of in my next circuit.

In my final watch circuit I'm going to need to use the smallest number of pins possible.  I used the demux to control which segments are lit up.  The 3 control pins of the demux are connected to the Arduino and the enables are tied their respective rails.  Right now I have 5 transistor switches turn on an off each digit.  On the display each digit has a common anode and all the grounds are connected to the demux.  Writing a LOW to a segment turns it on.  So if you've been counting, I've used 8 pins.  I'd like to knock that down to at most 6.  That can be accomplished be using some shift registers or another demux like in the picture (it isn't connected).

Here is the slightly confusing code, well its only confusing if you don't understand bitmath.
void lightSegs(byte num)
{
  byte temp=digits[num];
  byte bTemp;
  for(i=0;i<8;i++){
    if(!(temp & 0x01)){ //select correct segment for demux
      bTemp = bin[i];
      a0 = bTemp & 0x01;  // demux control pins
      a1 = (bTemp>>1) & 0x01;
      a2 = (bTemp>>2) & 0x01;
      digitalWrite(A0,a0);
      digitalWrite(A1,a1);
      digitalWrite(A2,a2);
      delay(.25);
    }
    temp = temp>>1;
  }
}
First a little explanation of the variables.  Digits is an array of binary numbers, where each number represents what segments are on for each number.  Bin is an array of numbers 1 thru 8 in binary.  Its used to select the correct output pin on the demux.  Ok here it goes.  There are 8 segments on 7 segment display when you include the decimal point.  So we begin with the for loop.  Next we AND the digit and a binary 1 together and if that equals zero then we turn on the segment.  That is accomplished by assigning the 3 control bits to a0,a1 and a2 variables.  Those select the correct output from the demux, which in turn sets the output to LOW, which then turns on the segment.   After that the digit value is shifted over and ANDed to see if the next segment is on or off.   

I hope that made some sense.  The major challenges that are ahead are shrinking everything,  using only 6 pins, learning how to program a PIC and powering everything.  As always comments and suggestion are welcome and greatly appreciated.

The LOLex Update 3: Just Got a Whole Lot Cooler

Okay.  I've seriously been thinking about doing the electronics for the watch myself.  It'd be a 'final project' of my summer build session since it would draw from all the areas that I dabbled in this summer.  The problem I'm facing now is the display.  I have only found a few displays that are less than 30mm wide.  The ones that I have found are OLED displays (specifically this one).  It would be insanely cool to have one of those in a watch.  I could have various clock animations and other little things to spice up the display.

I'm thinking about using a small AVR or PIC mircocontroller to control the display and clock timing.  Any suggestions are welcome.  I've also been thinking about including a hall effect sensor to serve as a switch to set the time after seeing this watch.  Hmm I guess another problem I'm bound to run into is how to power it.  Maybe a coin cell or a really small LiPo pack.  With either one I'd probably get horrible battery life it the display was on for more than seconds at a time.
Here is the top cover almost finished.  I kept track of the backlash this time and the pocket came out prefect.  From now on I'm always going to remove the backlash and reset my zero (since its totally manual) whenever I need to change directions.  I should have been doing that from the beginning but I didn't know what I was doing.
The mounting holes were drilled and countersunk, again keeping track of the backlash made them come up near perfect.  After that was done a 30 degree chamfer was cut around the cover.  A small vertical section was left to provide a spot for the vice to grip when it comes time to mill a slot for the display.
Over the next few days I'll be considering my options and make a decision on in what direction I want to proceed with this project, watch guts or custom circuit.  If I don't decide fast then this project will spill over into the school year since I only have a week and half before I start.

The LOLex Update 2: Killer Backlash

The LOLex is coming along nicely.  I finished the main body this afternoon but I haven't found a donor watch yet.  The cover piece is just going to be a piece of 1/8in Al with chamfered edges and a hole for the display.
My magical magnetic based jig worked! I broke a drill bit though.  The extra spring pins that I thought I had are eluding me, so I can't test the holes without disassembling my watch which I don't want to do.  Angling the sides went smoothly with the help of a 30 degree triangle. 
Backlash totally owned me on the pocket.  The last side is probably off by .01in.  That may seem small but its pretty noticeable IRL.  It doesn't matter that much since in the end it's going to be covered up.  All that's left is what was previously mentioned.  I'm always open to suggestions for finishing touches and whatnot.

The LOLex: More Awesome Than Your Dads Rolex

I'm finally getting over a cold I had this week, so I thought I'd celebrate by making something, more specifically a wrist watch body.  First a little background on my watch wearing habits.  I just became a regular watch wearer about 6 months ago when I started timing and keeping track of my swim workouts.  Before that I couldn't stand watches.

The basic design came from the watch I wear day to day.  It was the most creative thing I could come up with while my mind was being bored by Transformers (Megan Fox, you're not hot).  I seriously thought about building my own watch circuit but I gave that up after 5 minutes (Maybe for version 2).  So some cheapo digital watch will become the insides.   
Here's what I got done before dinner time.  I always seem to start machining right before dinner.  When my Dad came into the garage to check out what I was making, he said that I should call it the Olex, like Rolex.  Me being a totally l33t dude, decided I would call it the LOLex.  Why?  Because it's funny and this watch is going to be ridiculous.  Here's some specs.  It's 1.35 x 2 x .375 in.

There's not that much more to do, so it should be done with it tomorrow.  I have to mill out an area to hold the electronics and mill 4 more angles.  Currently I don't have a plan for closing up the hole.  There will be mounting holes for something but I don't know what that something will be.  I'll just wait to I get to that part to figure something out.
I decided to use my magical magnetic holder thingy to make my life a little easier.  I still have no idea how it works.  I mean a switch that turns a on and off a magnet and it's powered either.  So confusing.  It's probably something simple.  Anyway if you know let me know.

Well this setup lets me drill the hole for the spring pin in one side and then flip the piece over and drill the other side without changing anything.  It should work as long as I don't break my 60 gauge drill bit.

There's a rummage sale at my high school tomorrow, at which I'm hoping to find a watch that will donate its guts to the belly of the LOLex.  If I don't find one I'll check out the Goodwill or some other thrift store.

Recent Posts