Interrupt for measuring time

Hello guys,

I have tried to find something suitable but I had no luck so far that's why I approach you since you are my last hope :D

I have got an electrical engine and I want to measure the frequency with which it runs. My rotational meter creates a rectangle current. I want to count how often there is a rise in the current and I want to measure the time between two flanks.

But I have no idea how the overall structure looks like. Can you please help me?

You can use an interrupt triggered when the pin goes from low to high (voltage) and then, measure time.

unsigned long lastTime;
unsigned long Period;

void setup()
{
  attachInterrupt(0, measureFrec, RISING);  // Arduino Pin 2
}

void measureFrec()
{
  unsigned long time;
  
  time = millis();  // Beware overflow!!
  Period = time - lastTime;
  lastTime = time;
}

What sort of frequency are we talking about?
An interrupt may not be necessary.

Hi,
That code sample isn’t going to work for all sorts of reasons, you can read about most of them here (yes I know its an incomplete sample) -

The post relates to a slightly different requirement, but can be adapted to your needs, it also includes information on these two topics which are frequently overlooked and will cause your project to fail if not addressed -

Check out -

  1. Volatile Shared Variables
  2. Variable Access

Duane B

rcarduino.blogspot.com

Maybe you can use pulseIn(pin, state);

byte pin = 2; //or whatever pin you're using
unsigned long high2low = pulseIn(pin, HIGH); //microseconds from when pin 2 turns HIGH to when it turns LOW
unsigned long low2high = pulseIn(pin, LOW); //microseconds from when pin 2 turns LOW to when it turns HIGH

Caution: pulseIn delays you're code, and will time out in 1 second if no signal is received. You can adjust the timeout by doing: pulseIn(pin, state, timeout); timeout is in microseconds.

This is a little something I put together when I wanted to play with a frequency counter.
I measure the period and converts that to a frequency. If it period is relatively short, it increases the number of periods measured to average the measurements.
The output is to a cheap 16x2 LCD display.

// The LCD is usually interfaced via 16 pins which are labelled as shown below:
                         //Connections to Arduino
                         //  LCD                                                 Connection
                         //  1. GND - Ground                                     GND
                         //  2. VDD - 3 - 5V                                     5V
                         //  3. VO  - Contrast                                   (Tap off a 5K - 10K pot across VCC and Ground)
#define LCD_RS       12  //  4. RS  - Register Select - 0=Command / 1=Character  Arduino Pin as defined
                         //  5. RW  - Read/Write - 0=Write or 1=Read             GND
#define LCD_ENABLE   11  //  6. E   - Enable - Enable data transmit              Arduino Pin as defined
                         //  7. DB0 - Data Bit 0                                 N/A
                         //  8. DB1 - Data Bit 1                                 N/A
                         //  9. DB2 - Data Bit 2                                 N/A
                         // 10. DB3 - Data Bit 3                                 N/A
#define LCD_DB4       4  // 11. DB4 - Data Bit 4 - used in 4 bit operation       Arduino Pin as defined
#define LCD_DB5       6  // 12. DB5 - Data Bit 5 - used in 4 bit operation       Arduino Pin as defined
#define LCD_DB6       7  // 13. DB6 - Data Bit 6 - used in 4 bit operation       Arduino Pin as defined
#define LCD_DB7       8  // 14. DB7 - Data Bit 7 - used in 4 bit operation       Arduino Pin as defined
#define LCD_Backlight 9  // 15. BL1 - Backlight +                                Emitter of 2N3904, Collector to VCC, Base to D9 via 10K resistor
                         // 16. BL2 - Backlight -                                GND

//   I2C
//   A4 - Data  (SDA)
//   A5 - Clock (SCL)

#include <Wire.h>
#include <Time.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_DB4, LCD_DB5, LCD_DB6, LCD_DB7);

#define SAMPLE_SIZE  1
static  uint16_t iSample_Size = SAMPLE_SIZE;
volatile uint32_t iSample;
volatile char bSamplesCtl = -1; // -1= Stop, not taking samples  0=Start taking samples  1=Sample are ready


void setup () {
  Wire.begin();

  lcd.begin(16, 2); lcd.clear();
  pinMode(LCD_Backlight, OUTPUT); analogWrite(LCD_Backlight, 128); // Set the brightness of the backlight using PWM

  pinMode(2, INPUT_PULLUP);
  attachInterrupt(0, Pin2_ISR, FALLING);

  bSamplesCtl = 0; // Start taking timing samples
}

void loop() {
  delay(500);
  lcd.setCursor(0, 0);

  if (bSamplesCtl != 1) { // Sampling not complete
    lcd.print('*');
  } else {                // we have a set of samples
    uint32_t iFreq;
    if (iSample_Size <= 4000) {
      iFreq = (1000000L * iSample_Size) / iSample;
    } else {
      iFreq = 1000000L / (iSample / iSample_Size);
    }
    lcd.print(iFreq); lcd.print("Hz ");
    lcd.print(iSample);
    lcd.print(" ");
    lcd.print(iSample_Size);
    if (iSample < 1000) { // Less than one millisecond worth of samples
      iSample_Size *= 2; // double the samples
      if (iSample_Size > 4000) iSample_Size = 4000;
    }
    bSamplesCtl = 0; // Take another samples
  }
}

void Pin2_ISR()
{
  static uint32_t iPrev = 0;
  static uint16_t iSampleCnt = 0;
  uint32_t iTemp = micros();

  if (bSamplesCtl == -1) return; // -1= Stop, not taking samples
  if (bSamplesCtl == 1)  return; //  1= Sample ready for use.
                                 //  0= Taking samples
  if (iSampleCnt == 0)
    iPrev = iTemp;

  iSampleCnt++;
  if (iSampleCnt > iSample_Size) { // Sampling complete
    iSample = iTemp-iPrev;        // Save results
    iPrev = 0; iSampleCnt = 0;    // Clean-up ready for next use.
    bSamplesCtl = 1;              // 1= Sample is ready for use.
  }
}