dennisj, i think the following is the core functionality you need. I have not run the code so it may need some work but I hope it gets you going in the right direction. Because you are not actually frequency counting its perhaps best start another thread with a more descriptive name - something like: pulse counting using hardware timers
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
#if defined(__AVR_ATmega1280__)
#define TCCRnA TCCR5A
#define TCCRnB TCCR5B
#define TCNTn TCNT5
#define TIFRn TIFR5
#define TOVn TOV5
#else
#define TCCRnA TCCR1A
#define TCCRnB TCCR1B
#define TCNTn TCNT1
#define TIFRn TIFR1
#define TOVn TOV1
#endif
// call this to start the counter
void counterStart() {
// hardware counter setup ( refer atmega168.pdf chapter 16-bit counter1)
TCCRnA=0; // reset timer/countern control register A
TCCRnB=0; // reset timer/countern control register A
TCNTn=0; // counter value = 0
// set timer/counter1 hardware as counter , counts events on pin Tn ( arduino pin 5 on 168, pin 47 on Mega )
// normal mode, wgm10 .. wgm13 = 0
sbi (TCCRnB ,CS10); // External clock source on Tn pin. Clock on rising edge.
sbi (TCCRnB ,CS11);
sbi (TCCRnB ,CS12);
TCCRnB = TCCRnB | 7; // Counter Clock source = pin Tn , start counting now
}
// call this to get the current count
unsigned int getCount(){
unsigned int count;
TCCRnB = TCCRnB & ~7; // Gate Off / Counter Tn stopped
count = TCNTn;
TCCRnB = TCCRnB | 7; //re start counting
return count;
}
sbi is a macro to set a bit in a register. It has two parameters, the register to be set (sfr) and the bit position (bit). Your posted code does use these correctly
i'm trying to try out the example for this but it never gets passed:
while (FreqCounter::f_ready == 0)
I confirmed this with debug code. Perhaps it's not finding the library? I dropped the library folder into arduino-0014/hardware/libraries, deleted the .o file like someone else suggested.
I'm using a Freeduino v1.22, Arduino-14. Here's the current code:
#include "FreqCounter.h"
void setup() {
Serial.begin(57600); // connect to the serial port
Serial.println("Frequency Counter");
}
long int frq;
void loop() {
FreqCounter::f_comp= 8; // Set compensation to 12
FreqCounter::start(100); // Start counting with gatetime of 100ms
while (FreqCounter::f_ready == 0){ // wait until counter ready
Serial.println("waiting for freqcounter");
Serial.println(FreqCounter::f_ready);
}
frq=FreqCounter::f_freq; // read result
Serial.println(frq); // print result
delay(20);
}
Matt, the code you posted compiles without problem for me. What error message did you get? Are you sure you have a the FreqCounter.cpp and .h files in a folder called FreqCounter that is alongside all the other Arduino libraries.
i'm not sure what went wrong. i couldn't get the code from the site to work, but i did get the code from reply 15 to work, with one modification. It sets up a handful of variables differently for ATmega1280 vs. ATmega168, while I'm using a ATmega328. I couldn't find the right way to test for the 328, so I just assumed that if it's not 1280 or 168, it's prolly 328, and the setup is prolly similar to 168, so I modified the lines starting on line 47 to say:
// 16 bit timer defines added by mem to enable redifining the timer used
#if defined(__AVR_ATmega1280__)
#define TCCRnA TCCR5A
#define TCCRnB TCCR5B
#define TCNTn TCNT5
#define TIFRn TIFR5
#define TOVn TOV5
#elif defined (__AVR_ATmega168__)
#define TCCRnA TCCR1A
#define TCCRnB TCCR1B
#define TCNTn TCNT1
#define TIFRn TIFR1
#define TOVn TOV1
#else //this will catch any other case, including ATmega 328. May cause problems on other chips.
#define TCCRnA TCCR1A
#define TCCRnB TCCR1B
#define TCNTn TCNT1
#define TIFRn TIFR1
#define TOVn TOV1
#endif
Matt, good to hear you have it working. Because the 168 and 328 have the same timer registers, you could have used the simpler conditional check posted in reply #20
Hi,
i want to measure two frequency with a single ATmega328, but i find that this library control only the pin 5, as input of the frequency.
Can i resolve in some way?
That library uses hardware timing that is fixed to pin 5 and can't be changed. Perhaps if you say what you want to do, the frequency range you expect and the accuracy you need then some other solutions (such as using pulseIn) may work for you.
I want to read a RPM and speed sensor of a bike.
The RPM signal go from 33 to 400hz, more or less...
The Speed signal from 8,75 to 1750hz.
The accuracy is't not a problem.
I write this:
/*
* Speed and Gear LED display
* an Andbad project for Arduino board.
*/
int ledPin = 13 //LED pin to count RPM TEST TEST TEST TEST TEST
int RPMpin = 2; //RPM wire connect to pin 2
int SPEEDpin = 3; //SPEED wire connect to pin 3
volatile byte RPMduration;
volatile byte SPEEDduration;
unsigned int rpm;
unsigned int speed;
unsigned long timeold;
void RPMcount()
{
RPMduration = pulseIn(RPMpin, HIGH)
detachInterrupt(0);
}
void SPEEDcount()
{
SPEEDduration = pulseIn(SPEEDpin, HIGH)
detachInterrupt(1);
}
void setup()
{
//Interrupt 0 is digital pin 2, so that is where the RPM wire is connected
//Interrupt 1 is digital pin 3, so that is where the Speed wire is connected
//Triggers on FALLING (change from HIGH to LOW)
attachInterrupt(0, RPMcount, FALLING);
attachInterrupt(1, SPEEDduration = pulseIn(RPMpin, HIGH), FALLING);
RPMduration = 0;
SPEEDduration = 0;
rpm = 0;
speed = 0;
pinMode(ledPin, OUTPUT);
pinMode(RPMpin, INPUT);
pinMode(SPEEDpin, INPUT);
}
void loop()
{
//Update RPM and Speed 8 time per second
delay(125);
rpm = 60/RPMduration;
speed = 525/60*SPEEDduration;
for (int i=0, i=(rpm/1000), i++)
{
digitalWrite(ledPin, HIGH); // set the LED on
delay(1000); // wait for a second
digitalWrite(ledPin, LOW); // set the LED off
delay(1000)
}
delay(2000);
for (int i=0, i=(speed/10), i++)
{
digitalWrite(ledPin, HIGH); // set the LED on
delay(1000); // wait for a second
digitalWrite(ledPin, LOW); // set the LED off
delay(1000)
}
//Restart the interrupt processing
attachInterrupt(0, RPMcount, FALLING);
attachInterrupt(1, SPEEDcount, FALLING);
}
how can i made to wait a LOW signal and then to launch the pulseIn in HIGH mode?
pulseIn does that for you.
This from the pulseIn reference page:
"For example, if value is HIGH, pulseIn() waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW and stops timing"
Try it without interrupts with the calls to pulseIn in loop.
Yes, I've read this page. But if I call the pulseIn when the signal is HIGH?
The time that's return it's the time from i call the function to the signal go LOW or pulseIn waits that the signal goes LOW, then goes HIGH (and start to count) and finally go LOW (stop the count)?