Author Topic: Possible improvements? arduino frequency counter  (Read 5532 times)

0 Members and 1 Guest are viewing this topic.

Offline RerouterTopic starter

  • Super Contributor
  • ***
  • Posts: 4694
  • Country: au
  • Question Everything... Except This Statement
Possible improvements? arduino frequency counter
« on: April 27, 2013, 01:13:47 pm »
over the past few weeks while my Internets been flaky I've been working on a multipurpose little tool, though i have come across something i cant quite pin down,

while feeding in an external input driver directly off a buffer (though not quite de-bounced) I'm seeing i need to add some 14.6 milliseconds to the lcd loop time for above 2Khz signals to get the correct reading, the required delay appears to be correct all the way up to 70Khz, and i cannot quite explain it. now i have removed all the code but this one function for simplicities sake and the problem remains?

I am hoping its something glaring in my face that i am missing, and at the same time possible insight into ways to improve this little snippet, (possible directly writing to the LCD as opposed to the library?)

As for why i am using an interrupt, its as another function measures pulse time, and hope to reuse the same pin.

Code: [Select]
#include <LiquidCrystal.h>

 // Working Values
 unsigned long  duration         =  0;      // Time of last valid action for frequency patterns
 unsigned long  temp             =  0;      // Temporariy variable for holding count for frequency measurement,
 unsigned long  last             =  0;      // Used variable for holding count for frequency measurement,

 // Interrupt Values
 volatile unsigned long count    =  0;      // Volitile variable for counting pulses for frequency measurement, 
 
 // Pin Definitions
 #define       COUNT                2       // Pin 2  - Pulse counting input

 // Task Definitions
 LiquidCrystal lcd(A5, A4, A3, A2, A1, A0);                         // defines LCD pin locations
 
 /*                                               Setup                                                   */
/*IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII*/

void setup() {
 // Set Device I/O Pinmodes
  pinMode(COUNT,  INPUT);

 // Initialises LCD
  lcd.begin(16, 2);                  // LCD Setup
  lcd.noCursor();
}

/*-------------------------------------------------------------------------------------------------------*/

void loop() {
  hz();
}
 // interupt routine for pulse counting
void pulse() {
  count++;                                   // increment count for every pulse
}
 // for counting frequency
void hz() {
  count = 0;                                    // Reset count for current loop
  duration = micros();
  attachInterrupt(0, pulse, RISING);           // Set up interrupt for counting on input 2
  lcd.clear();
  lcd.setCursor(4,0);                           // set cursor to begin               
 
  while(1) {
      if (micros() - duration >=1000000 ) {     // 1 second gate time increased to correct for lcd loop
        duration = micros();                    // sets duration to current time, resetting the if statement
        temp = count;                           // sets temp to current count to avoid lcd delay variation     
        lcd.setCursor(4,0);                     // sets cursor back to start position
        lcd.print((count - last));            // prints frequency, (yet to work out why its doubled)
        lcd.print(" Hz   ");                    // prints Hz after variable and blanking spaces to avoid a full clear
        last = temp;                           // updates last to current count
       
      }
  }
  detachInterrupt(0);                           // removes the interrupt as its no longer needed
}

thanks for any help in advance,
Ryan,
 

Offline amspire

  • Super Contributor
  • ***
  • Posts: 3802
  • Country: au
Re: Possible improvements? arduino frequency counter
« Reply #1 on: April 28, 2013, 12:32:27 am »
I haven't worked through your code, but I see you are using the LiquidCrystal routine and it is bad news when you are using interrupts. Talking to a generic LCD involves a lot of rediculously long delays well into the mS region, and the Arduino code has terrible delay routines that mess up other interrupts.

I have attached a bodged version of the LiquidCrystal code that I used to solve the problem.

By the way, if you want to get the best possible accuracy for frequency measurements, the method is to measure the period of a  a seconds worth of input frequency cycles.

So if in in 1.0000126 seconds, you measure 15,678 cycles, you calculate the frequency to be 15,678/1.0000126 = 15,678.197 Hz. If you are using a 16MHz clock, then you will always get the over 7 digits resolution regardless of frequency. With the counting cycles per second, then if you measure 50Hz, you only get resolution to 1Hz which is only +/-2% resolution which is pretty lousy.

If you do not use any LCD functions at all during a measurement, you can probably use the original Arduino LCD routine and you can probably get the interrupt latency variation down to a few cycles that means you can get a 6 digit accuracy which is much more then the accuracy of the Arduino crystal oscillator.

In my case, I had real time interrupts that had to be function 100% of the time, so I had to change the LCD routine.

Richard
« Last Edit: April 28, 2013, 12:40:19 am by amspire »
 

Offline RerouterTopic starter

  • Super Contributor
  • ***
  • Posts: 4694
  • Country: au
  • Question Everything... Except This Statement
Re: Possible improvements? arduino frequency counter
« Reply #2 on: April 28, 2013, 12:56:15 am »
thank you very much amspire :) i'll give that a shot,

EDIT: works beautifully, and thank you for the odd division ration for decimal points, helps out on another part of it that i hadn't even gotten around to implementing (was only ever after 1 decimal place)


« Last Edit: April 28, 2013, 01:11:38 am by Rerouter »
 

Offline bingo600

  • Super Contributor
  • ***
  • Posts: 1989
  • Country: dk
Re: Possible improvements? arduino frequency counter
« Reply #3 on: April 28, 2013, 10:44:44 am »
Have a look here

http://www.mshopf.de/proj/avr/freq_meter.html

64bit atithmetic
http://www.mshopf.de/proj/avr/uint64_ops.html

Discussion
http://translate.google.com/translate?sl=de&tl=en&js=n&prev=_t&hl=en&ie=UTF-8&eotf=1&u=http%3A%2F%2Fwww.mikrocontroller.net%2Ftopic%2F186801

Another 64bit implementation (can be tricky if you want the linker to overlay the routines)
I just defined the assembler routines with my own name , and called those from within C , as the
overlaying was a bit messy , and drew in some other stuff. But i got it to fit in a Tiny13  :D
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=113673


/Bingo

 

Offline RerouterTopic starter

  • Super Contributor
  • ***
  • Posts: 4694
  • Country: au
  • Question Everything... Except This Statement
Re: Possible improvements? arduino frequency counter
« Reply #4 on: April 28, 2013, 11:50:04 am »
i was only ever after 25Khz max (automotive), and i have to say while i've been starting to peer my head into the registers, i'm not that keen a programmer just yet...

for now I've got that part working and successfully tested my code to 150Khz without any issues, also added a reciprocal mode based on the microseconds interrupt for sub 100Hz measurement, and moved onto some of the more boring parts of it, that becomes very task specific, (25Khz at 1Hz steps and 0-100Hz at 0.1Hz where pretty much my design requirements) but if i ever need to revamp it to do more I'll chase it up,

also to any future lurkers, using micros rather than millis removed fluctuations in my measurements, and that is why i used it in my code,
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf