Tacometer signal with Arduino

Hello,

I am working on a controller for speed control. I am sensing the speed of a shaft via a tacometer and am running the tacometer output through a 4-bit counter IC and then to the arduino. The shaft spins at 200,000 [Hz] (~3300 [Hz]) which means that I need to sample the IC output roughly every 3 [ms].

Currently, the actual time per loop within my arduino code (measured using the micros() command) is roughly 13 [ms] or more, which of course is not fast enough.

Am I just limited by the Arduino here, or is there something I am missing? Thanks

You might want to edit your title to “tachometer”. The urge to make a joke about a tacometer will be unbearable.

2 Likes

Might be missing that people usually have an interrupt to count pulses for a tachometer. The code in the interrupt just adds 1 to a counter. When the sample is needed, the interrupts are stopped,the value is copied to a work counter and the interrupts enabled again.

download

6 Likes

:rofl: :joy: :sweat_smile:

haha, I guess I will have to leave the title as is now due to the jokes.

1 Like

It was my understanding that using an interrupt at this sort of sampling speed would just cause it to constantly go off.

IF it really has a problem, then you need a faster processor!

@thetranq
Would you post a sketch of your circuit per the forum guidelines? I'm not sure I understand what you want to do. 3ms should be plenty of time.

Agreed... something is fishy for it to take 13mS (wonder if these are uS?) for that code to run... have to see the code... haven't looked at milli function...

The interrupt routine would be far more simple and probably react quicker.

Even with an 8mHz clock, I would think it would be plenty quick.

:smiley_cat:

@thetranq
Also, would you elaborate on exactly what 200000 Hz means? is that RPM, rev per second, what?

Sorry, that was a typo, the shaft runs at 200,000 [rpm] which is ~3300 [Hz]

//////////////////////////////////////////////// PRE-CODE ////////////////////////////////////////////////

// Initialize Variables
unsigned long preTime;
unsigned long postTime;
float f_signal_max = 1000; // max frequency of signal [Hz]
float del_t_sample = 10/f_signal_max; // required sample time [s]
float elapsedTime = 0; // initialize
int lastCount = 0; // initialize
long lastFreq = 0; // initialize
long frequency = 0; // initialize
long numCounts = 0; // intialize
static char outstr[15];
int count = 0; // initialize
int Q0 = 0; int Q1 = 0; int Q2 = 0; int Q3 = 0; // initialize

// Initialize Counter Pins
int Q0_pin = 2;
int Q1_pin = 3;
int Q2_pin = 4;
int Q3_pin = 5;

//////////////////////////////////////////////// SETUP ////////////////////////////////////////////////

void setup() {

Serial.begin(9600);

// Initial Time
postTime = micros(); // initial time [us]

// Set Pin Modes
pinMode(Q0_pin,INPUT);
pinMode(Q1_pin,INPUT);
pinMode(Q2_pin,INPUT);
pinMode(Q3_pin,INPUT);

// Initialize Count
Q0 = digitalRead(Q0_pin);
Q1 = digitalRead(Q1_pin);
Q2 = digitalRead(Q2_pin);
Q3 = digitalRead(Q3_pin);
lastCount = 1Q0 + 2Q1 + 4Q2 + 8Q3; // number of pulses

}

//////////////////////////////////////////////// LOOP ////////////////////////////////////////////////

void loop() {

// Read counter values
preTime = postTime; // record time [us]
Q0 = digitalRead(Q0_pin);
Q1 = digitalRead(Q1_pin);
Q2 = digitalRead(Q2_pin);
Q3 = digitalRead(Q3_pin);
postTime = micros(); // record time [us]

// Update Calculations
count = 1Q0 + 2Q1 + 4Q2 + 8Q3; // number of pulses
elapsedTime = (postTime - preTime)/1e6; // time since last measurement [s]
numCounts = count - lastCount; // number of pulses since last measruement
if (numCounts < 0)
{numCounts += 16;}

// Update Frequency
if (numCounts == 0)
{frequency = lastFreq;} // if no additional pulses detected
else
//{frequency = numCounts / del_t_sample;} // Measured frequency of signal [Hz]
{frequency = numCounts / elapsedTime;} // Measured frequency of signal [Hz]

// Display Values
// Serial.print(Q3);
// Serial.print(Q2);
// Serial.print(Q1);
// Serial.println(Q0);
// Serial.print(count);
// Serial.print('\n');
// Serial.print(dtostrf(elapsedTime,10, 1, outstr));

// Print Information
// Serial.print('\n');
// Serial.print("Last Count: "); Serial.println(lastCount);
// Serial.print("Current Count: "); Serial.println(count);
// Serial.print("Number of Counts: "); Serial.println(numCounts);
// Serial.print("Sample Time: "); Serial.println(dtostrf(del_t_sample,5, 4, outstr));
// Serial.print("True Elapsed Time "); Serial.println(dtostrf(elapsedTime,10, 8, outstr));
Serial.print("Frequency: "); Serial.println(frequency);

// Update Parameters
//preTime = postTime;
lastCount = count;
lastFreq = frequency;

// Delay [ms]
//delay(del_t_sample*1000);
}

I'm new so it doesn't let me upload attachments, so I copied and pasted the code. I use the micros() function to record actual elapsed time, and for faster sampling rates (increase the variable "f_signal_max") the elapsed time is much longer than what the true sampling time should be

So that's 300usec per revolution and you are scaling it through a 4-bit counter? So are you triggering your interrupt off the counter output, approximately once per 4.8msec?

You still haven't posted your schematic and the worldwide telepathy link is down due to a strike so we're operating in the dark here.

Post your code using code tags, </>, per the forum use instructions.

Edit: I see after looking through your code that you are not using interrupts at all. Also, I misunderstood how you were using the counter. You can probably time your revolutions without using the hardware counter.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.