NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » Frequency Counter with LCD help

February 27, 2012
by nismotony
nismotony's Avatar

Hi guys, I'm trying to build a frequency counter that will measure 10Hz - 30kHz. I have yet to experiment with the timers and counters so this is going to be a good learning project for me. I have read the tutorial and have seen the app note from Atmel. It seems that I need to be able to use the T0 or T1 pins on the ATMEGA168. This are occupied by the nerdkits LCD though. Any suggestions? This project has really been kicking my butt, I'm an analog design engineer. Any help or code examples will be much appreciated.

Tony

February 27, 2012
by pcbolt
pcbolt's Avatar

Hi Tony -

I think the way I would approach it is to use say a 3.6v Zener diode hooked up in parallel with the input signal. Then you can use any of the input port pins (i.e. PB4 or PB5). You can use the pin change interrupts to count the number of pulses coming through (just set the interrupt to fire on rising edge only). You can set up a timer as well and after a certain number of pulse counts, divide by the time elapsed and then update the LCD with the frequency. The Zener should take a sine wave and turn it into a half-wave square pulse. Watch the Nerdkit Clock video and PS/2 keyboard video for info on interrupts.

February 28, 2012
by JKITSON
JKITSON's Avatar

pcbolt..

FYI

From the data sheets INT0 & INT1 are the only interrupts that allow triggering on rise, fall, high or low. The other interrupts will give an interrupt on any pin change, ie high to low then low to high. I would very much like to use PD2 or PD3 with trigger on rise. Trying to change the lcd library to use other pins was beyond my abilities at this time.....

Jim

February 28, 2012
by pcbolt
pcbolt's Avatar

@Jim

Interesting. For Tony's project, I guess he could just double count (rise and fall). I thought for sure there was rising/falling edge bit you could set. I don't have the sheet with me but I'll look into it. Yeah, re-writing the LCD library would be tricky...but definitely not impossible.

@Tony

I need to make a correction. The Zener diode will only clip the top of the wave. You'd need a second regular diode (in series) to chop off the lower half of the input wave.

February 28, 2012
by Rick_S
Rick_S's Avatar

Using an I2C LCD only uses two pins of the micro. Gives you much more flexibility.

Rick

February 28, 2012
by JKITSON
JKITSON's Avatar

Rick

I looked at the I2C it is very nice. My problem (I think) is that my existing program has most of the pgm space used up and not enough room left to load your I2C software. I will look again closer and see if I can go there. Thanks for the reminder again. Jim

February 28, 2012
by Rick_S
Rick_S's Avatar

I'm not too sure how much more space it uses, but it definaltely will free up pins on the micro BigGrin

February 28, 2012
by Rick_S
Rick_S's Avatar

I just looked at the folders I had for initialload and my I2C_LCD that was just initialload with the I2C_LCD display. The compiled .hex file for the original was 22KB and the I2C version was 20KB... Don't know why it would be smaller but it is?? (At least the .hex is)

February 28, 2012
by JKITSON
JKITSON's Avatar

I will go over your project with I2C again. This will really help on my TRACTOR PULL SLED MONITOR project. Jim

March 01, 2012
by nismotony
nismotony's Avatar

Thanks for the help guys. @PCbolt, thanks a lot. That is the method I am going to attempt to use. I'm still working on it, I have a working real time clock, but can not seem to make the pin change interrupt work. I've written some code to see if I can just count the pin changes on PC5 and I'm not having much luck. I'm doing something wrong for sure. Code below.

// realtimeclock1.c
// for NerdKits with ATmega168
// mrobbins@mit.edu

#define F_CPU 14745600

#include <stdio.h>
#include <stdlib.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

// PIN DEFINITIONS:

void realtimeclock_setup() {
// setup Timer0:
// CTC (Clear Timer on Compare Match mode)
// TOP set by OCR0A register
TCCR0A |= (1<<WGM01);
// clocked from CLK/1024
// which is 14745600/1024, or 14400 increments per second
TCCR0B |= (1<<CS02) | (1<<CS00);
// set TOP to 143
// because it counts 0, 1, 2, ... 142, 143, 0, 1, 2 ...
// so 0 through 143 equals 144 events
OCR0A = 143;
// enable interrupt on compare event
// (14400 / 144 = 100 per second)
 TIMSK0 |= (1<<OCIE0A);
}

volatile int32_t the_time;
volatile int32_t count;

void reader_init() {

DDRC &= ~(1<<PC5); // set PC5 as input
PORTC |= (1<<PC5); // turn on internal pull up
// For reader:
// enable pin change interrupt PCINT13
PCICR |= (1<<PCIE1);
PCMSK1 |= (1<<PCINT13);

}

SIGNAL(SIG_OUTPUT_COMPARE0A)  {
// when Timer0 gets to its Output Compare value,
// one one-hundredth of a second has elapsed (0.01 seconds).
the_time++;
 }

 ISR(PCINT1_vect){

   if (PINC & (1 << PC5)){
 count++;}
  }

 int main() {

 realtimeclock_setup();
 reader_init(); 
 lcd_init();
 FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
 lcd_home();

 sei();

 while(1) {
 lcd_home();
 fprintf_P(&lcd_stream, PSTR("%10.2f sec"), (double) the_time / 100.0);
 lcd_line_two();
 fprintf_P(&lcd_stream, PSTR("%10.2f count"), (count));

}

return 0;
}
March 01, 2012
by pcbolt
pcbolt's Avatar

Tony -

Your code looks OK. I built something similar and all the interrupts look right. I'm assuming you're triggering the pin change by just grounding PC5. You might just test the pin change interrupt by just using "count++;" inside the ISR. Also, on line 79, try changing:

fprintf_P(&lcd_stream, PSTR("%10.2f count"), (count));

to:

fprintf_P(&lcd_stream, PSTR("%d count"), (count));

Treating a signed integer as a float type may be a problem.

March 02, 2012
by nismotony
nismotony's Avatar

Yes, grounding PC5. That was the problem, the LCD related code. Thanks!!

March 02, 2012
by pcbolt
pcbolt's Avatar

Cool-

Off and running now I hope :-)

Post a Reply

Please log in to post a reply.

Did you know that Morse code is a compact way to transmit human-readable text over binary channels? Learn more...