So you're a Noob? Post your questions here until you graduate! Don't be shy.

User avatar
By QuickFix
#67647 I'm trying to measure the time between two interrupts.
My goal is to attach two sensors (about 30cm apart) to two separate pins, each attached to an interrupt, so that I can calculate the speed an object travels between the two sensors.

Since I'm relatively new to the ESP (and C++ programming), I'm first trying a proof of concept using a Wemos board, connected to a single 1-Button shield and a NeoPixel-shield.
For this proof of concept, I'm using the 1-button shield positions (up and down) to simulate the two sensors; in the end result this will be replaced by two sensors and two interrupts in code.

This is the code I use:
Code: Select allextern "C"{
  #include "user_interface.h"
}

#include <Adafruit_NeoPixel.h>

#define LED_PIN 4    // D2
#define SWITCH_PIN 0 // D3

boolean triggered;
char line[40];

volatile uint32 sw_up;
volatile uint32 sw_down;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(1, LED_PIN, NEO_GRB + NEO_KHZ800);

void switching() {
  if (digitalRead(SWITCH_PIN) == LOW) {
    sw_up = 0;
    sw_down = system_get_time(); // millis();
  } else {
    sw_up = system_get_time(); // millis();
  }
}

void setup() {
  sw_up = 0;
  sw_down = 0;
  triggered = false;
 
  Serial.begin(115200);
  Serial.setDebugOutput(false); 

  Serial.println("Initializing switch");
  pinMode(SWITCH_PIN, INPUT_PULLUP);

  Serial.println("Initializing interrupts");
  attachInterrupt(digitalPinToInterrupt(SWITCH_PIN), switching, CHANGE);
 
  Serial.println("Initializing NeoPixel library..."); 
  pixels.begin(); // This initializes the NeoPixel library.
  pixels.setPixelColor(0, pixels.Color(0, 0, 255));
  pixels.show(); 
}

void loop() { 
  if (sw_down > 0) {
    if (sw_up > 0) {
      Serial.println("Switch is up");
      Serial.print("Trigger time is: ");
      int time_taken = sw_up - sw_down;
      Serial.println(time_taken);
     
      pixels.setPixelColor(0, pixels.Color(0, 0, 255));
      pixels.show();
     
      sw_up = 0;
      sw_down = 0;
      triggered = false;         
    } else if (!triggered) {
      Serial.println("Switch is down");

      pixels.setPixelColor(0, pixels.Color(255, 0, 0));
      pixels.show();     
      triggered = true;
    }
  }
}
To my joy, the code compiles and works. :D

If I press the button the NeoPixel turns RED and when I release the button the NeoPixel turns GREEN.
Also the state of the button is printed correctly onto the console and when the button is depressed, the time taken between press and depress *should* be shown (time_now - time_then = time_taken).

I say *should* because all I get is some, seamingly, random numbers as a result:
Code: Select allInitializing switch
Initializing interrupts
Initializing NeoPixel library...
Switch is down
Switch is up
Trigger time is: 656218
Switch is down
Switch is up
Trigger time is: 179
Switch is down
Switch is up
Trigger time is: 39923
Switch is down
Switch is up
Trigger time is: 39900
Switch is down
Switch is up
Trigger time is: 533833
Switch is down
Switch is up
Trigger time is: 58324
Switch is down
Switch is up
Trigger time is: -22804555
I'm even getting negative results (sw_down > sw_up). :?

I've tried using millis(), micros() and other time related functions, but they all seem to return unlogical bogus times.
I remember having read once that certain time functions can't be used inside an interrupt, but I can't seem to find that information anymore. :|

Great chance I'm just making a simple programming error, but I don't see it at the moment.
Can anyone point me in the right direction?

Greetz,

Peter
User avatar
By rudy
#67648 I think your problem might be that you are catching multiple switch closures and openings, called switch bounce. There are different ways of dealing with it. Considering what you are trying to do I would take the approach of getting the first interrupt and then disable interrupts for that input until you know/think you are ready for a new cycle.

The ESP8266 is not a great candidate for capturing stuff like this. There is too much stuff that needs to execute that you don't have control over. I would rather use a dedicated CPU for this kind of task and pass that information to the ESP to do the wireless communications.
User avatar
By QuickFix
#67654 Yes, I noticed there is indeed some bounce on the switch while I was testing.
I will investigate on the proper way to debounce the circuit once I use actual IR/light sensors.

I also found this similar project on Hackaday: I will have a look at that as well.

Thanks for now. :)
User avatar
By QuickFix
#67683 Thanks @philbowles.

I already read more about the implications of bouncing contacts and interrupts, also updated the code by disabling and re-enabling interrups.
I'm also using ESP.getCycleCount now (stolen from the project I mentioned in my previous post), divided by the clock frequency for more accuracy.

But I'll get there (eventually, I hope). ;)