Is an interrupt a good idea for an anemometer?

Hi I'm building a machine that is like a weather station, one of the elements is an anemometer.

The anemometer i have built uses a hall effect sensor to pick up the rotations of a wind turbine, i have coded a sketch using digitalRead to monitor the input pin changes, from HIGH to LOW and count the rotations of the turbine. However after some reading on forums to come up with the most accurate code i came across interrupts. From my basic understanding, if the hall effect sensor was to trigger an interrupt, I would not need to constantly listen to the pin input and my data would be more time accurate. However I am worried that using an interrupt would mean the program would constantly be interrupted and stop the other sensors, data logger and GSM module working efficiently. If anyone that has more experience using interrupts in larger projects and could shed a little light on this, I would be most applicative. cheers JOel

The side effects of interrupts are minimized by keeping the code in the interrupt routine minimal. Just increasing a counter would be enough for anemometer. Code would look like this

volatile uint32_t counter;

void setup()
{
  Serial.begin(115200);
  attachInterrupt(0, anemoCount, CHANGE);
}

void loop()
{
  // make a working copy of the counter while disabling interrupts
  cli();
  uint32_t cnt = counter; 
  sei();

  // work with the copy
  Serial.println(cnt);
  delay(500);
}

void anemoCount()
{
  counter++;
}

Hi Shannon,

Thank you so much that’s brilliant. It’s confirmed what i was thinking, as you say I’ll only be incrementing a variable. Thanks for the sample code, do you have any idea how to incorporate this into an Arduino library. I have a working sketch which enables pin A0 to work with interrupt however when i try to convert it to a library I struggle with the correct way to call the ISR function and use the interrupts.

the sketch i’m trying to convert is below

int x = 0;
void setup()
{
  Serial.begin(9600);
  Serial.println("Boe");
  InitialiseIO();
  InitialiseInterrupt();
}

void loop() {
  /* Nothing to do: the program jumps automatically to Interrupt Service Routine "blink"
   in case of a hardware interrupt  */
}  

void InitialiseIO(){
  pinMode(A0, INPUT);	   // Pin A0 is input to which a switch is connected
  digitalWrite(A0, HIGH);   // Configure internal pull-up resistor
  pinMode(A1, INPUT);	   // Pin A1 is input to which a switch is connected
  digitalWrite(A1, HIGH);   // Configure internal pull-up resistor
  pinMode(A2, INPUT);	   // Pin A2 is input to which a switch is connected
  digitalWrite(A2, HIGH);   // Configure internal pull-up resistor
}

void InitialiseInterrupt(){
  cli();		// switch interrupts off while messing with their settings  
  PCICR =0x02;          // Enable PCINT1 interrupt
  PCMSK1 = 0b00000111;
  sei();		// turn interrupts back on
}

ISR(PCINT1_vect) {    // Interrupt service routine. Every single PCINT8..14 (=ADC0..5) change
            // will generate an interrupt: but this will always be the same interrupt routine
 
  if (digitalRead(A0)==0)
    { 
      Serial.println("A0");
      x++;
      Serial.println(x);
    }
  if (digitalRead(A1)==0)  Serial.println("A1");
  if (digitalRead(A2)==0)  Serial.println("A2");
}

this works completely fine as a sketch and does exactly what i what, however when converting it to a library i’m confused of how to structure it correctly so that the compiler doesn’t complain.
here’s my attempt below at the library

.cpp file below

/*
  Anemometer.h - Anemometer library for Wiring - implementation
  Copyright (c) 2006 John Doe.  All right reserved.
*/

// include core Wiring API
#include "Arduino.h"

// include this library's description file
#include "Anemometer.h"

// include description files for other libraries used (if any)


// Constructor /////////////////////////////////////////////////////////////////
// Function that handles the creation and setup of instances

Anemometer::Anemometer(byte pin, unsigned int resolution) {
    _pin=pin;
    _resolution=resolution;
  

  // do whatever is required to initialize the library
  Serial.begin(9600);
  Serial.println("Initialising Anemometer Input...");
  InitialiseIO();
  InitialiseInterrupt();
}

// Public Methods //////////////////////////////////////////////////////////////
// Functions available in Wiring sketches, this library, and other libraries
int Anemometer::rot(){
    _previousMillis = millis();
    Serial.print("milliseconds gone by = ");
    Serial.println(millis());
    //while time passed is less than resolution, count rotations
    while((unsigned long)(millis() - _previousMillis) <= _resolution){
    Serial.print(_r);
    }//end while
    return _r;
    _r=0;
}


// Private Methods /////////////////////////////////////////////////////////////
// Functions only available to other functions in this library

void Anemometer::InitialiseInterrupt()
{
  cli();   // switch interrupts off while messing with their settings  
  PCICR =0x02;          // Enable PCINT1 interrupt
  PCMSK1 = 0b00000111;
  sei();    // turn interrupts back on
}

void Anemometer::InitialiseIO()
{
  pinMode(_pin, INPUT);    // Pin A0 is input to which a switch is connected
  digitalWrite(_pin, HIGH);   // Configure internal pull-up resistor
}

void Anemometer::ISR(PCINT1_vect) //***THIS DOESNT SEEM TO BE CORRECT
{    // Interrupt service routine. Every single PCINT8..14 (=ADC0..5) change
            // will generate an interrupt: but this will always be the same interrupt routine
  
 
  if (digitalRead(_pin)==0)
    { 
      Serial.println(_pin);
      r++;
    }
}

and the header file below

/*
  Anemometer - library for Robotoilet - description
  Copyright (c) 2014. Joel Cormack. All right reserved.
*/

// ensure this library description is only included once
#ifndef Anemometer_h
#define Anemometer_h

// include types & constants of Wiring core API
#include "Arduino.h"

// library interface description
class Anemometer
{
  // user-accessible "public" interface
  public:
    Anemometer (byte pin, unsigned int resolution);
    int rot();
    int _r;

  // library-accessible "private" interface
  private:
    void InitialiseInterrupt();
    void InitialiseIO();
    void Anemometer::ISR(PCINT1_vect); //***THIS DOESNT SEEM TO BE CORRECT
    byte _pin;
    int _resolution;
    int _previousMillis;
    
};

#endif

Hi Newbie, (little joke there)

Don't ever do serial I/O in interrupt context.

Hey AWOL. thanks, noted and changed. :) any ideas on how to call ISR function in a library? cheers Newbie

jowell: however when converting it to a library i'm confused of how to structure it correctly so that the compiler doesn't complain.

Sounds like a good reason not to waste time making it into a library.

...R

I don't know about that OO C++ stuff, but I wrote a pure-C library that has an ISR:

http://forum.arduino.cc/index.php?topic=198337.0

You could study the source and see if that approach will work for you.