«

»

Print this Post

$10 Frequency Counter Finished!

Wow, what a cool project start to finish. Simple, cheap, and absolutely useful! … and not to mention big green numbers which make it look more impressive than it actually is! This is my super-simple frequency counter designed to be used for amateur radio, all for about $10. It was a project I developed over the last few months and documented all along the way. It’s finished I guess, so this will probably be the last post about it! Now for some vids and pics:

Sure there’s room for improvement,but that’s the fun part! This is a solid start and it’s cheap as can be. Simply improving software would greatly improve its accuracy. This doesn’t use any time-averaging at all! If you had it average 20 readings, it’d probably be much smoother, update every second, and have a higher precision. Also, there’s ample room left in the case to build in a transmitter or receiver!
IMG_5452
There’s the finished project! It looks pretty good, considering it was built mostly out of junk box components, and everything it’s made from can be purchased cheaply online. I’m happy with it! I could improve my metal cutting, but that was the first time I ever cut a square window in aluminum so I’m still proud of myself.
IMG_5429
As you can see the enclosure is made from sheet metal bent and cut into 2 pieces. The enclosure was from RadioShack, and was $2.99! Yeah it might be cheaper online, but when you add shipping it’s pretty convenient to get it locally. My local RadioShack didn’t carry these metal ones (they have stupid plastic ones), but I found these in Orlando and after asking the workers I learned that anyone can find any product online (such as the case I used) and request that their local store order them. When they arrive, you can buy them with no extra charge!
IMG_5425Here are some of the internals after being mounted. Heck, these are ALL the internals! You can tell I could have gotten away with a case one third this size if I had one available. Oh well, it’s still cool.
IMG_5209

IMG_5222

IMG_5221
There are a few random photos of the build. It’s just a microcontroller reading (and resetting) a counter a bunch of times a second and displaying the result on the multiplexed display. That’s it! It was a lot of work, but a truly simple concept. The micro-controller is an ATMEL Atmega 16 AVR which is a little costly (around $5) but I had it on hand. I imagine you could accomplish the same thing with a far less intricate microcontroller! I’ll bet you could pull it off with an ATTiny2313, especially if you had a LCD display rather than a multiplexed LED like mine. The counter is a 74lv8154 chip, a 32-bit (dual 16-bit) counter IC at a bargain $0.50 – why when I google for home made frequency counters do I not see people using these? They daisy-chain multiple 8-bit counters! What a shortcut I stumbled upon…

Thinking of making your own? Go for it! Here are some of my other posts which describe the development of this thing (including stuff I tried that didn’t work). Everything I ordered should be stocked at mouser.com.
this post demonstrates it in action
this post shows it being used too
this post shows the first time I really got it working
this post has the SCHEMATIC for the counter!

I guess that sums it up! What a fun hack. If you have any questions feel free to contact me (link in the menu on the right), and if you make one of these of your own I’d LOVE to see it! I’ll even slap a photo of yours on my site to share with everyone. I had fun working on this project. If you’re at all into radio, I recommend you try attacking a project like this too! It’s more efficient at determining frequency than turning on a commercial radio receiver and spinning the dial until you hear your transmitter ^_^

SUPPLEMENTAL VIDEO

Upon request here’s the code! It’s nothing special, and certainly not very efficient, but it’s quite functional. If you re-create this project, I recommend writing your own code rather than flat copying mine. You’ll learn a heck of a lot more… and my code for this is really crap XD

#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h> 

#define A PC5
#define B PC0
#define C PC6
#define D PC7
#define E PC2
#define F PC4
#define G PC1
#define P PC3

char sendDigit(char row, char num, char dot){
	char val=0;
	if (num==0) {val|=(1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<F);}
	if (num==1) {val|=(1<<B)|(1<<C);}
	if (num==2) {val|=(1<<A)|(1<<B)|(1<<D)|(1<<E)|(1<<G);}
	if (num==3) {val|=(1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<G);}
	if (num==4) {val|=(1<<B)|(1<<C)|(1<<F)|(1<<G);}
	if (num==5) {val|=(1<<A)|(1<<C)|(1<<D)|(1<<F)|(1<<G);}
	if (num==6) {val|=(1<<A)|(1<<C)|(1<<D)|(1<<E)|(1<<F)|(1<<G);}
	if (num==7) {val|=(1<<A)|(1<<B)|(1<<C);}
	if (num==8) {val|=(1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<F)|(1<<G);}
	if (num==9) {val|=(1<<A)|(1<<B)|(1<<C)|(1<<F)|(1<<G);}
	if (dot==1) {val|=(1<<P);}
	PORTC=val;
	PORTD=(0b10000000>>row);
	_delay_ms(1);
}

void showNumber(unsigned long val){
	if (val==0) {return;}
	int i;
    int array[6]={10,0,0,0,0,0}; // NUMBER OF DIGITS
	int dly=10;
	i=6-1;
	while (val>0){
      array[i--]=val%10;
      val /= 10;
	}
	sendDigit(1,array[0],0);
	sendDigit(2,array[1],1);
	sendDigit(3,array[2],0);
	sendDigit(4,array[3],0);
	sendDigit(5,array[4],0);
	sendDigit(6,array[5],0);
	sendDigit(0,0,0);
}


#define byte1 PB4
#define byte2 PB3
#define byte3 PB2
#define byte4 PB1

unsigned long val=123456;
void readFreq(){
	unsigned long b4,b3,b2,b1;
	PORTB=255-(1<<byte1);b1=PINA;
	PORTB=255-(1<<byte2);b2=PINA;
	PORTB=255-(1<<byte3);b3=PINA;
	PORTB=255-(1<<byte4);b4=PINA;
	PORTB=0;PORTB=255;//RESET
	val=b1+b2*256+b3*65536+b4*16777216; // ad 'em up
	val=val/3355;
}

int cnt=0;
ISR(TIMER1_OVF_vect) 
{ 
   cnt++;
   readFreq();
}

int main(){
	DDRA=0;
	DDRB=255;
	DDRC=255;
	DDRD=255;

	TIMSK|= (1 << TOIE1); // Enable overflow interrupt 
	sei(); // Enable global interrupts 
   	TCCR1B|=(1<<CS11); // Set up timer at Fcpu/8

	while(1){showNumber(val);}
}

… and I know it’s unrelated, but:

(I watched this four times – it’s so random I love it!)

UPDATE This project was featured on a couple of my favorite sites, Hack-A-Day and Electronics-Lab!
counter_EL
counter_HAD

About the author

Scott W Harden

Scott Harden has had a lifelong passion for computer programming and electrical engineering, and recently has become interested in its relationship with biomolecular sciences. He has run a personal website since he was 15, which has changed names from HardenTechnologies.com, to KnightHacker.com, to ScottIsHot.com, to its current SWHarden.com. Scott has been in college for 10 years, with 3 more years to go. He has an AA in Biology (Valencia College), BS in Cell Biology (Union University), MS in Molecular Biology and Microbiology (University of Central Florida), and is currently in a combined DMD (doctor of dental medicine) / PhD (neuroscience) program through the collaboration of the College of Dentistry and College of Medicine (Interdisciplinary Program in Biomedical Science, IDP) at the University of Florida in Gainesville, Florida. In his spare time Scott builds small electrical devices (with an emphasis on radio frequency) and enjoys writing cross-platform open-source software.

Permanent link to this article: http://www.SWHarden.com/blog/2011-03-14-frequency-counter-finished/

16 comments

  1. herrkami

    I like it a lot but I think the battery isn’t such a good idea because those 7-segment displays need a lot of current. Awful soldering!!!

  2. Matthew

    I’m curious… why use the counter chip at all? Couldn’t you use the 16 bit counter in the ATMega16?

  3. herrkami

    I mean awfull in an awesome way.

  4. mahall

    Matthew-
    I don’t think you can use the counter of the ATMega16 at that high a frequency. The AVR counters are synchronous, so the input has to be slower than the clock speed (at the very, very least, half the speed. Probably a fair bit less). So, to get above 5-10 MHz, you need an external counter.

    I have heard that PIC chips have asynchronous counters, so that they can be used without an external counter for frequencies higher than the clock rate. Not sure how high they’ll go, though.

    -matt

  5. vitya

    Geat project! But can you tell me why you use the counter IC? The uC should be able to count on its own, right? I don’t know this particular one, I work with PICs, but I assume the Atmels also have some sort of counters built in. Thanks!

  6. vitya

    ok, you just answered my question too while I was writing it :) Thanks!

  7. scott

    I used the 9V because it was small, convenient, and on hand. Those displays are only illuminated 1 at a time (multiplexed) and it seems pretty bright to me! I don’t know about battery life, but I imagine if it’s an issue adding a DC jack wouldn’t be hard. There’s already a voltage regulator on board so there’s no extra circuitry involved to make it powered by a wall plug!

  8. Phil

    WTF? The video ^^.

  9. scott

    I enjoy randomness, and inject a little here and there on my website =o) The song from http://www.youtube.com/watch?v=kbbA9BhCTko has been in my head all day!

  10. sick

    omg what a shaking video, stop the coffee man 8o

  11. Fabian


    char sendDigit(char row, char num, char dot){
    char val=0;
    if (num==0) {val|=(1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<F);}
    if (num==1) {val|=(1<<B)|(1<<C);}
    if (num==2) {val|=(1<<A)|(1<<B)|(1<<D)|(1<<E)|(1<<G);}
    if (num==3) {val|=(1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<G);}
    if (num==4) {val|=(1<<B)|(1<<C)|(1<<F)|(1<<G);}
    if (num==5) {val|=(1<<A)|(1<<C)|(1<<D)|(1<<F)|(1<<G);}
    if (num==6) {val|=(1<<A)|(1<<C)|(1<<D)|(1<<E)|(1<<F)|(1<<G);}
    if (num==7) {val|=(1<<A)|(1<<B)|(1<<C);}
    if (num==8) {val|=(1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<F)|(1<<G);}
    if (num==9) {val|=(1<<A)|(1<<B)|(1<<C)|(1<<F)|(1<<G);}
    if (dot==1) {val|=(1<>row);
    _delay_ms(1);
    }

    OMG!!!
    you can use a structure to do this!!!!

  12. Warren

    I’ve been contemplating building a frequency counter for a few weeks. I will probably end up using a PICAXE as the controller. I considered both the sn74lv8154 from TI and the LS7031 from http://www.lsicsi.com. For the time base I am leaning towards the RDD106 from http://www.lsicsi.com because it will divide the crystal frequency by up to 6 decades. I am thinking of putting this on stripboard and using wire wrap sockets to make additional connections.

  13. omar

    #include
    #include
    #include

    #define SEGMENT_PORT PORTA
    #define SEGMENT_PIN PINA
    #define SEGMENT_DDR DDRA

    #define CA_PORT PORTB
    #define CA_PIN PINB
    #define CA_DDR DDRB

    // display data

    #define SEG_a 0×01
    #define SEG_b 0×02
    #define SEG_c 0×04
    #define SEG_d 0×08
    #define SEG_e 0×10
    #define SEG_f 0×20
    #define SEG_g 0×40
    #define SEG_dot 0×80

    volatile unsigned int val = 0;

    unsigned char digits[] = {
    (SEG_a|SEG_b|SEG_c|SEG_d|SEG_e|SEG_f), // 0
    (SEG_b|SEG_c), // 1
    (SEG_a|SEG_b|SEG_d|SEG_e|SEG_g), // 2
    (SEG_a|SEG_b|SEG_c|SEG_d|SEG_g), // 3
    (SEG_b|SEG_c|SEG_c|SEG_f|SEG_g), // 4
    (SEG_a|SEG_c|SEG_d|SEG_f|SEG_g), // 5
    (SEG_a|SEG_c|SEG_d|SEG_e|SEG_f|SEG_g), // 6
    (SEG_a|SEG_b|SEG_c), // 7
    (SEG_a|SEG_b|SEG_c|SEG_d|SEG_e|SEG_f|SEG_g), // 8
    (SEG_a|SEG_b|SEG_c|SEG_d|SEG_f|SEG_g), // 9
    };

    ISR(TIMER0_OVF_vect)
    {
    unsigned char cnt = 0;
    if ( val == 0) cnt = 1;
    static unsigned char active_digit = 0;
    //static unsigned char blink = 0;
    unsigned char digit_val[4] = {0, 0, 0, 0}; // NUMBER OF DIGITS
    unsigned int tmp;
    //extract each digit’s value
    tmp = val; // necessary to prevent modifying val variable
    while (tmp > 0)
    {
    digit_val[cnt++] = tmp % 10;
    tmp /= 10;
    }
    /*
    suppress leading zeros
    *** Old technique ***
    if (val < 10)
    active_digit = ++active_digit % 1;
    else if (val < 100)
    active_digit = ++active_digit % 2;
    else if (val 124))
    //output digit data
    CA_PORT |= (0×01 << active_digit);
    //blink++;
    };

    int main()
    {
    SEGMENT_DDR = 0xFF;
    CA_DDR = 0x0F;

    TIMSK |= (1 << TOIE0); // Enable overflow interrupt
    //TCCR0 |= (1<<CS01); // Set up timer at Fcpu/8
    TCCR0 |= (1<<CS01) | (1< 9999) val = 0;
    };
    };

  14. Mustafa

    hi

    I liked your device very much, especially your shamatic.
    Is it possible to send me the open shematic and the hexfile with adding of Bit-fuse of your device ?

    Best regards from Germany/Berlin
    Mustafa Eksi

  15. BajaMK

    where i can get the schematic

  16. Yulianto

    Good job scot…

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>