Showing posts with label Dot Matrix. Show all posts
Showing posts with label Dot Matrix. Show all posts

Tuesday, August 4, 2009

Small LED dot matrix development board

I was very busy for the past two months so this blog just didn't move. As you may know, the LED dot matrix display is my favorite device. I have designed a small development board for testing my led dot matrix related programs.
The schematic is as the following:
LED dot matrix development board Schematic

The PCB is single sided so I can make it at home. Most of the components are SMD to keep small footprint of the board. The PCB size: 58.4mm x 46mm
LED dot matrix development board PCB

Acutally, I made a PCB and installed all components but the board didn't work :p. It was working when I tested the schematic on breadboard (with through hole version of PIC16F887). I think the SMD PIC16F887 may be broken or the PCB is bad but I just don't have time to figure out the problem. I will try new PCB and PIC16F887.

Tuesday, October 14, 2008

Schematic of 8x8 Led Dot Matrix Clock using PIC16F627A

Schematic of 8x8 Led Dot Matrix Clock using PIC16F627A
The above schematic is 8x8 Led Dot Matrix clock using PIC16F627A (or PIC16F628 which is more expensive but larger memory) and a shift register 74HC595. The PIC is running with 4MHz internal oscillator so pin 15 (RA6) and 16 (RA7) are free. Therefore, the PIC16F627a can drive the 8x8 Led Drive matrix with these 2 free pins (RA6, RA7) and RB0-5, . The Timer1 (TMR1) external clock is generated by the watch crystal 32.768KHz + load capacitors 15pF and fed to RB6 and RB7. The pins are used up!. Method of setting time is similar to the 5x7 Led Dot Matrix Clock.

I have intention to make this with SMD components so the 8x8 Dot Matrix will be the biggest component. The whole clock will be just 20x20mm which is small enough to be a small pocket watch or even a wristwatch. The only problem is the power supply.

Saturday, October 11, 2008

8x8 Led Dot Matrix Clock using PIC16F627A

Led Dot Matrix Clock 8x8 Actually, I have made this long before the 5x7 led dot matrix clock. The clock utilizes a PIC16F627A and a 74HC595 to drive a small 8x8 Led Dot Matrix display (20x20mm). My dream is transforming these clocks to watches that I can ware on my wrist.

8x8 Led Dot Matrix Clock using PIC16F627A

Monday, October 6, 2008

Big 5x7 Led Dot Matrix Clock with new font

Now, I'm so crazy about led dot matrix clocks and led dot matrix watches. Just recently, I have upgraded my small 5x7 Led Dot Matrix Clock with a bigger green 5x7 led dot matrix display and a new font.
For the images below, the time 21:44:37 was displaying on the clock. The clock display is big comparing to a 44mm Panerai (PAM 4).
Big Green 5x7 Led Dot Matrix Clock
Big Green 5x7 Led Dot Matrix Clock
Big Green 5x7 Led Dot Matrix Clock

The code for the new font is showing below:

const unsigned char char2[][4]={
{0x0E,0x11,0x0E,0x00}, //0
{0x09,0x1F,0x01,0x00}, //1
{0x13,0x15,0x09,0x00}, //2
{0x11,0x15,0x0A,0x00}, //3
{0x1C,0x04,0x0F,0x00}, //4
{0x19,0x15,0x12,0x00}, //5
{0x0E,0x15,0x12,0x00}, //6
{0x13,0x14,0x18,0x00}, //7
{0x0A,0x15,0x0A,0x00}, //8
{0x09,0x15,0x0E,0x00}, //9
{0x0A,0x04,0x0A,0x00}, //Comma1
{0x04,0x0A,0x04,0x00} //Comma2
};

Sunday, September 28, 2008

Led Dot Matrix Scrolling Sign

Starting from the 5x7 led dot matrix clock, now, the Led Dot Matrix is one of my favorite topics for my projects. I have some led dot matrix projects in progress. They are all watch/clock related projects. Now, I am thinking that using led dot matrix to display only numbers is just a waste. A scrolling sign would be a nice project to utilize all of the power of led dot matrix. The above photo is a Mini Scrolling LED Sign. It's available as a kit from ElectronicKits.com. I think it's a great kit to start with. This scrolling sign has 96 different characters, and can store messages up to 80 characters long.

Friday, September 26, 2008

Source Code for one chip 5x7 led dot matrix clock

As promised, listed below is the source code in MikroC for the 5x7 Led Dot Matrix Clock. The free demo version of MikroC can compile this code without any problem. Of course, the code is just for educational purpose only and use it with your own risk. The explanation about the source code will come later.
Setting time
- Press and hold MODE button until the digits blink
- The blinking digits are the hour is being set
- Press SET button to count up the hour
- When get the right hour, press MODE button to confirm hour setting
- Now the minute digits are blinking and ready to be set
- Press SET button to count up the minute
- When get the right minute, press MODE button to confirm minute setting and the second will be set to 0 automatically
- Now, the clock is set and the clock is running

Have fun!!!

Next improvements:
1. Using DS1307 as the time base will improve the clock accuracy and backup battery is also a nice feature of the DS1307
2. Dot matrix will be scanned and updated via interrupt routine to give the PIC more free time for doing something else

== Updated on 29 Nov 2009 ===
This firmware is written for The 5x7 Dot matrix Cathode Row. If you use Anode Row you have to make change to make_dotmatrix() by inverting the output PORTB and PORTD
===========================

//One 5x7 Led Dot Matrix Clock
// PIC16F887
// I will use DS1307 as the RTC for the next improvement
// punkky@gmail.com
// 26 Sep 2008

#define MYMODE PORTA.F0
#define SET  PORTA.F1

//External OSC 32.768KHz
#define HTMR1    0x80
#define LTMR1    0x00

//Constants for 4MHz Internal Clock 
#define PAUSE_TIME 40
#define SCROLL_TIME_DELAY 60
#define HM_PAUSE_TIME  8

#define DTime 200

//Cursor Positions
#define HR_H_POS  0
#define HR_L_POS  0
#define DOT_1_POS 32
#define MIN_H_POS 12
#define MIN_L_POS 12
#define DOT_2_POS 56
#define SEC_H_POS 64
#define SEC_L_POS 72
//5x7 font
//Vertical scan ,  Little endian order
const unsigned char char2[][4]={
{0x1F,0x11,0x1F,0x00},   //0
{0x09,0x1F,0x01,0x00},
{0x17,0x15,0x1D,0x00},
{0x11,0x15,0x1F,0x00},
{0x1C,0x04,0x1F,0x00},
{0x1D,0x15,0x17,0x00},
{0x1F,0x15,0x17,0x00},
{0x10,0x10,0x1F,0x00},
{0x1F,0x15,0x1F,0x00},
{0x1D,0x15,0x1F,0x00},   //9
{0x0E,0x0E,0x0E,0x00},  //Comma1
{0x04,0x0E,0x04,0x00}   //Comma2
};

unsigned char output[8];
unsigned char data[40];
unsigned char ptr;
unsigned char base_ptr;
unsigned char result_ptr;
unsigned char pp;
unsigned char pause_cnt;
unsigned char hr_pause_cnt;
unsigned char min_pause_cnt;
unsigned short counter;
unsigned short sec_h;
unsigned short sec_l;
unsigned short min_h;
unsigned short min_l;
unsigned short hr_h;
unsigned short hr_l;
unsigned short tick;
unsigned short num;
unsigned short i;
unsigned short j;
unsigned short time[8];
unsigned short setting_time;
unsigned short change_MYMODE;
void check_bt();
void button_fn(unsigned short param1unsigned short pos1unsigned short pos2);
void make_dotmatrix();

void interrupt() { //Internal clock
    PIR1.TMR1IF = 0;          // clears TMR1IF
    TMR1H = HTMR1;  //Set only high byte
    tick  = 1;                   // increment counter
}
void update_time();
void make_time();
void fill_data();
void show_digit(unsigned short pos);
void scroll();
void pause_digit(unsigned short position,unsigned short pause_delay);

unsigned short shift_register;
void main(){
  setting_time = 0;
  change_MYMODE = 0;
  ANSEL = 0x00;    //Digital I/O for PORTA
  TRISA = 0x03;
  PORTA = 0x03;
  TRISB = 0x00;
  PORTB = 0xFF;
  TRISC = 0x0E;
  TRISD = 0x00;
  PORTD = 0x00;
  ANSELH = 0x00//Digital Input for PORTB

  OSCCON = 0x65 ; //pic16f887 : 0110 0101, Internal Osc at 4MHz for lowest power consumption

  counter = 0;
  shift_register = 0x01;
  hr_h = 1;
  hr_l = 2;
  min_h = 3;
  min_l =4;
  sec_h = 0;
  sec_l = 0;
  tick = 0;
  fill_data();
  pause_cnt =0;
  hr_pause_cnt = 0;
  min_pause_cnt = 0;
//TMR1 setup
     T1CON =  0x8F;                      // 887 TMR1 Prescaler 1:1   external clock
     INTCON = 0xC0;                    // Set GIE, PEIE
     TMR1H = 0x80;
     TMR1L = 0x00;
     Delay_ms(10); // Delay for setting up TMR1
     PIE1.TMR1IE = 1;                  // enable interupt
     tick =0;
  while(1){
   scroll();
  }

}

void show_digit(unsigned short pos){
          for(i=0;i<8;i++){
           output[i] = data[i+pos];
          }
}

void update_time(){
    if(tick){
        tick =0;
        sec_l++;
        make_time();
        fill_data();
     }
}

void make_time(){
        if(sec_l>9){
            sec_l = 0;
            sec_h++;
        }
        if(sec_h>5){
            sec_h=0;
            min_l++;
        }
        if(min_l>9){
            min_l = 0;
            if(setting_time == 0){
               min_h++;
            }
        }
        if(min_h>5){
            min_h = 0;
            if(setting_time == 0){
                hr_l++;
            }
        }
        if(hr_l>9){
            hr_l = 0;
            if(setting_time == 0){
             hr_h++;
            }
        }
        if(hr_h >2){
            hr_h = 0;
        }
        if(hr_h >=2 && hr_l>3){
           if(setting_time == 0){
              hr_h = 0;
           }
           hr_l = 0;
        }

}
void fill_data(){
        time[0] = hr_h;
        time[1] = hr_l;
        time[2] = 10;
        time[3] = min_h;
        time[4] = min_l;
        time[5] = 11;
        time[6] = sec_h;
        time[7] = sec_l;
        for(i = 0;i<8;i++){
          for(j=0;j<4;j++){
           data[j+4*i] = char2[time[i]][j];
          }
        }
}

void button_fn(unsigned short param1unsigned short pos1unsigned short pos2){
      for(;;){
        if(SET == 0){
          Delay_ms(10);
          while(SET == 0);
          Delay_ms(10);
          switch (param1){
            case 1hr_h++; break;
            case 2hr_l++; break;
            case 3min_h++;break;
            case 4min_l++;break;
          }

          make_time();
          fill_data();
          show_digit(pos1);
        }
        if(MYMODE == 0){
          Delay_ms(10);
          while(MYMODE == 0);
          Delay_ms(10);
          ifparam1 == 4){
            setting_time = 0;
            ptr = 0;
            base_ptr = 0;
          }else{
            show_digit(pos2);
          }
          break;
        }
        make_dotmatrix();
        Delay_ms(1);
      }

}
void check_bt(){
    while(MYMODE == 0){
      Delay_ms(10);
      for(i=0;i<100;i++){
        for(j=0;j<10;j++){
          make_dotmatrix();
          Delay_ms(1);
          if(MYMODE != 0){
            setting_time = 0;
            change_MYMODE = 1;
            break;
          }
        }
      }

      while(MYMODE == 0){   // Set Hr high
          setting_time = 1;
          show_digit(HR_H_POS);
          make_dotmatrix();
      }
      if(change_MYMODE){
         ptr=8;
         base_ptr = 0;
         change_MYMODE = 0;
      }
    }
    if(setting_time){
      INTCON.GIE = 0 ;        //Stop time counting

      button_fn(1HR_H_POSHR_L_POS);
      button_fn(2HR_L_POSMIN_H_POS);
      button_fn(3MIN_H_POSMIN_L_POS);
      button_fn(4MIN_L_POS0);

      //Reset timer1
      TMR1L = LTMR1;
      TMR1H = HTMR1;
      INTCON.GIE = 1 ;                        // start clock
      sec_l =0;
      sec_h =0;
      tick=0;
      make_time();
      fill_data();
   }
}

void pause_digit(unsigned short positionunsigned short pause_delay){
           if(base_ptr == position){
        if(pause_cnt<pause_delay){
            base_ptr--;
            pause_cnt++;
         }else{
            base_ptr = position+1;
            pause_cnt=0;
         }

     }

}
void scroll(){
   ptr = 0;   //start pointer
   base_ptr = 0;
   while(base_ptr<41){
      result_ptr = (base_ptr+ptr)%40;
      output[ptr] = data[result_ptr];
      ptr++;
      if(ptr == 8){
                   ptr = 0;
                   base_ptr++;
                   //Sec pause
                   
             pause_digit(25,PAUSE_TIME);
                   //Min pause
                  
                   pause_digit(13,HM_PAUSE_TIME);
                   //Hr pause
                  
                   pause_digit(1,HM_PAUSE_TIME);
                  

      }
      for(pp=0;pp<SCROLL_TIME_DELAY;pp++){
            update_time();
            make_dotmatrix();
      }

      update_time();
      check_bt();
      make_dotmatrix();
  }
}
void make_dotmatrix(){
   if(counter == 7){
        PORTB =    output[counter];   //sent font data to PORTB
        Delay_us(DTime);
        PORTB = 0x00//Turn off dots
        shift_register = 0x01;
        PORTD = ~shift_register;             //sent scan data to PORTD
        counter = 0;
   } else{
        PORTB =   output[counter];
        Delay_us(DTime);
        PORTB = 0x00//Turn off dots
        shift_register = shift_register << 1;
        PORTD = ~shift_register;
        counter++;
   }
}


Monday, September 15, 2008

Schematic of the 5x7 Led Dot Matrix Clock

Schematic of the 5x7 Led Dot Matrix Clock
The above image is the schematic of the 5x7 led dot matrix digital clock. It includes a custom made component in Eagle, small 5x7 led dot matrix. However, this schematic is also working for any size of the 5x7 led dot matrix.I will post the detail about the firmware later.
-- updated 29 Nov 2009 ---
There is an error in the schematic, the MCU in the schematic is PIC16F887 (not PIC16F877)which has an internal oscillator so you don't need the external oscillator for the MCU. But you still need the 32.768 KHz for timebase.

Sunday, August 17, 2008

5x7 Led Dot Matrix Clock using only one chip



I use a microcontroller, pic16f887, as the brain of this clock. The time displays on a small 5x7 led dot matrix in lanscape mode. The chip is running with the internal oscillator at 4.0 MHz. External frequency 32.768KHz for time base is getting from DS32KHz. The accuracy is not that impressive, ~2 sec/day.
The schematic and source code in MikroC will be posted here. Please stay tuned!!
--- Update --
Source Code is now available at 5x7 dot matrix clock code
Schematic is available at 5x7 Dot Matrix clock schematic

Wednesday, August 13, 2008

Cool Clock with HDSP-2111 Display

Cool Clock with HDSP-2111 Display
Just a picture of my clock using PIC16f877a microcontroller (the project was done before I discovered PIC16f887). The HDSP-2111 (or HDSP-211x) display is a very cool led dot matrix. The interface is very easy. The quick and dirty code (no time setting function)is here.
//PIC16f877a PIC Microcontroller, 20MHz
#define Address PORTA
#define Data PORTB
#define WR PORTC.F5
#define A3 PORTC.F4
#define RST PORTC.F3

typedef unsigned short uns8;
uns8 hour;
uns8 minute;
uns8 second;
uns8 cnt;
uns8 min_cnt;
uns8 Digit[24];
uns8 i;
uns8 j;
uns8 pause_timer;
void setup();
void Init_Display();
void set_time(uns8 hr,uns8 min,uns8 sec);
void make_time();
void show_time();
void scroll();
void interrupt() {
PIR1.TMR1IF = 0; // clears TMR1IF
TMR1H = 0x0B; //Start at 0x0BDC (to overflow at 62500)
TMR1L = 0xDC;
// TMR1 starts at 0x0BDC = 3036 to make TMR1 counts to 62500 and
// overflows in every 0.1 sec
// Math: 1/5000000*8*62500 = 0.1
// 1/5000000 : time for 20MHz crystal (internal clock will be 20/4 = 1MHz)
// 8: prescaler
// 62500: TMR1 counts to 62500
// Counting number of overflows to 10 will get 1 sec.
cnt++ ; // Increment counter
}
void main(){
setup();
set_time(17,40,0); //Set time
j=0;
pause_timer = 0;

while(1){
if(cnt > 9){ //Count to 10 for 1 sec.
cnt = 0;
make_time();
show_time();
}

for(i=0;i<8;i++){
Address = i;
Data = Digit[j+i];
WR = 0;
WR = 1;
}

j++;

if(j == 9 && pause_timer<300){
j=8;
pause_timer++;
}

if(pause_timer == 100){
pause_timer = 0;
j++;
}

if(j>15){
j=0;
}

Delay_ms(200);
}

}

void setup(){
CMCON = 0x07; //Digital port
TRISA = 0;
TRISB = 0;
TRISC = 0x01; //RC7=input
Data.F7 = 0;
T1CON = 0x31; // Prescaler 1:8
PIE1.TMR1IE = 1; // enable interupt
INTCON = 0xC0; // Set GIE, PEIE
TMR1L = 0xDC;
TMR1H = 0x0B;
Init_Display();

for(i=0;i<24;i++){
Digit[i] = ' ';
}
}

void Init_Display(){
WR = 1;
RST = 0;
Delay_ms(10);
RST = 1;
Delay_ms(10);
Data = 6; //27% Brightness
A3 = 0;
WR = 0;
WR = 1;
A3 = 1;
}

void set_time(uns8 hr, uns8 min, uns8 sec){
second=sec;
minute=min;
hour=hr;
}

void make_time(){
if(second < 59){
second = second++;
}else{

second = 0;
minute = minute++;
}

if(minute > 59) {
minute = 0;
hour = hour++;

}

if(hour > 23){
hour = 0;
}

Digit[8] = hour/10+'0';
Digit[9] = hour%10+'0';
Digit[10] = ':';
Digit[11] = minute/10 + '0';
Digit[12] = minute%10 + '0';
Digit[13] = ':';
Digit[14] = second/10 + '0';
Digit[15] = second%10 + '0';
}

void show_time(){
for(i=0;i<8;i++){
Address = i;
Data = Digit[i];
WR = 0;
WR = 1;
}
}

void scroll(){

for(j=8;j<16;j++){

for(i=0;i<8;i++){

Address = i;
Data = Digit[j+i];
WR = 0;
WR = 1;

}
Delay_ms(200);
}
}



Circuit diagram is here.

Schematic of Clock with HDSP-2111 Display