Interrupts rarely firing [SOLVED]

Hi,

I’m using a Photon with the SparkFun Weather Shield. Currently I’m trying to read the anemometer using interrupts by incrementing a counter every time the interrupt occurs. However, it seems like the interrupt occurs very rarely, if ever (but it does happen some times, so something must work).

Of course, I’m a complete newbie with regards to C, interrupts, edges etc :wink:

Here’s my code:

long lastWrite;
unsigned long millisBetweenWrites = 10000;
int volatile rotations;

int ANEMOMETER_PIN = D3;

void rotation() {
  rotations += 1;
  Serial.println("Rotation!");
}

void setup() {
  Serial.begin(9600);
  attachInterrupt(ANEMOMETER_PIN, rotation, FALLING);
  lastWrite = millis();
  rotations = 0;
}

void loop() {
  long currentTime = millis();
  if ((currentTime - lastWrite) > millisBetweenWrites) {
    int result = (int) rotations;
    Serial.print("Save ");
    Serial.println(result);
    if (Spark.variable("rotations", &result, INT)==false) {
      Serial.println("Could not save :-(");
    }
    rotations = 0;
    lastWrite = currentTime;
  }
}

When I attach my serial console and give the anemometer a little spin (tens of rotations) I get perhaps one or two indications that the rotation() function is called.

I’ve tried all three kinds of interrupt modes (yes, I’m that blank).

Any ideas?

Where is this device from and how did you hook up to the Sparkfun weather shield?

First of - how have you got the anemometer wired to your Photon?

I must admit that I’ve lost track with the background behaviour of attachInterrupt() over the last firmware releases, but a save bet should be to set your interrupt pin as pinMode(ANEMOMETER_PIN, INPUT_PULLUP) to detect falling edges.

I’d also not Serial.print() inside an ISR.

This part has to be changed too

void loop()
{
    ...
    if (Spark.variable("rotations", &result, INT)==false) {
      Serial.println("Could not save :-(");
    }
    ...
}

This is not how Spark.variables() work.

You’ll have to use a global variable and hook it up to the Spark.variable() in setup().
Then whenever you change the global variable the Spark.variable() will reflect this.

To test your anemometer, don’t wire up anything else to avoid any side effects from other devices.

For the ISR try this one

void rotation() {
  rotations++;
  digitalWrite(D7, !digitalRead(D7));
}

And do pinMode(D7, OUTPUT); in setup().
This way you’ll get immediate optical feedback if your ISR gets triggered.


But as Kenneth asked, not knowing your actual device does not help giving exact advice.
(e.g. if it privides definet HIGH and LOW states, pull-resistors won’t be required).

1 Like

^^^ not to be overlooked in @ScruffR's comments ^^^

I bought the device from a local hardware dealer as spare parts to a weather station. I’m 99% sure it’s the same as this one: https://www.sparkfun.com/products/8942

The pinMode did the trick. Now I’m able to read rotations from the device. Even though a quick test indicates I get twice as many rotations - I’ll have to look into this.

I removed the call to Serial.println from the ISR. Any insight on why this isn’t a good idea?

About the Spark.variable - I obviously didn’t read the docs properly :slight_smile:

1 Like

Serial uses interrupts which may conflict with your ISR.

If you want to observe/debug over serial monitor, you can do that in your loop() function:

void loop()
{
  static int lastRotations = 0;
  if (rotations != lastRotations)
  {
    Serial.println(rotations);
    lastRotations = rotations;
  }
  // your other stuff
}
2 Likes