Skip to content

interrupts on slow edges #1229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
404-baitnotfound opened this issue Mar 17, 2018 · 9 comments
Closed

interrupts on slow edges #1229

404-baitnotfound opened this issue Mar 17, 2018 · 9 comments
Labels
Status: Stale Issue is stale stage (outdated/stuck)

Comments

@404-baitnotfound
Copy link

404-baitnotfound commented Mar 17, 2018

Description:

Hey I would like to use interrupts on buttons. However if I put a cap for debouncing the slow rising/falling edge triggers between 15/25 events with 100nF / 10K. Bigger Caps only increase the number of events. No cap results in a bouncy signal.
Also it seems that Falling/Rising edge does not work on slow edges.

If the dectection is depending on the rise/fall time than I don't see a reliable way of implementing anything with interrupts.

Sketch:

#include <Arduino.h>

const byte interruptPin = 27;
volatile int interruptCounter = 0;
int numberOfInterrupts = 0;
 
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
 
void IRAM_ATTR handleInterrupt() {
  
    portENTER_CRITICAL_ISR(&mux);
      interruptCounter++;
    portEXIT_CRITICAL_ISR(&mux);

  
}
 
void setup() {
 
  Serial.begin(115200);
  Serial.println("Monitoring interrupts: ");
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
}
 
void loop() {
 
  if(interruptCounter>0){
 
      portENTER_CRITICAL(&mux);
      interruptCounter--;
      portEXIT_CRITICAL(&mux);
 
      numberOfInterrupts++;
      Serial.print("An interrupt has occurred. Total: ");
      Serial.println(numberOfInterrupts);
  }
  delay(50);
}
@LuisVSa
Copy link

LuisVSa commented Mar 19, 2018

Hello,
I would use no cap. On the first interrupt, it's service would be to detach interrupt on the pin and set a one shoot timer. Then the service to the timer alarm would be the service to the button.

Regards, Luis

@404-baitnotfound
Copy link
Author

404-baitnotfound commented Mar 25, 2018

So after a long fight with my esp32 I gave up on the idea of using interrupts with an Encoder. The stability is just not there.
The idea with the oneShootTimer does not work. Because when the Timer is up the signal is either High again therefor no edge. Or the signal is unstable and I end up detecting multiple edges.


And btw. attachInterrupt with LOW attribute does not work at all...... Someone should look into this.
(Note writing LOW as attribute will turn off interrupts. #4 sould do it but does not work)

@JacoFourie
Copy link

I have a rotary encode and a water flow meter working fine. I have wifi stuff running on one CPU and the encode and sensor stuff on the other one. All is working 100% so var.

@JacoFourie
Copy link

This test code has a water flow meter and a water pressure sensor.

const byte interruptPin = 4;
int statusLed = 18 , sensorPin = 39;


volatile byte pulseCount;  
float calibrationFactor = 1;
float flowRate;
float pressure_bar;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
unsigned long oldTime;
 
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
 
void IRAM_ATTR handleInterrupt() {
  portENTER_CRITICAL_ISR(&mux);
  pulseCount++;
  portEXIT_CRITICAL_ISR(&mux);
}
 
void setup() {
 
  Serial.begin(115200);
  Serial.println("Monitoring interrupts: ");
  pinMode(interruptPin, INPUT_PULLUP);
  pinMode(statusLed, OUTPUT);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;
  
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
 
}
 
void loop() {
 

  if((millis() - oldTime) > 1000)    // Only process counters once per second
  {         
    digitalWrite(statusLed, HIGH); 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(interruptPin);          
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;        
    oldTime = millis();      
    flowMilliLitres = (flowRate / 60) * 1000;
    
    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;      
    unsigned int frac;
    
    // Print the flow rate for this second in litres / minute 
    frac = (flowRate - int(flowRate)) * 10;        
    pulseCount = 0;

    int sensorVal = analogRead(sensorPin);
    pressure_bar = mymap(sensorVal , 0 , 4095 , 0.0 , 12.0);

    if(pressure_bar < 0.7){
          pressure_bar = 0;
       }
            
    // Enable the interrupt again
    attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING); 
    digitalWrite(statusLed, LOW);    
  }

  Serial.print("Water Used : ");
  Serial.print(String(totalMilliLitres / 1000.));
  Serial.print(" Flow Rate : ");
  Serial.print(flowRate);
  Serial.print(" Pressure Bar : ");
  Serial.println(pressure_bar);
  

  delay(10);
  
}

float  mymap(double x, double in_min, double in_max, double out_min, double out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

I have another one using the Encoder as input device. I can pick up click, double click, click and hold as well as the rotation.

@JacoFourie
Copy link

I am using this encoder library.
soligen2010/encoder#10

@JacoFourie
Copy link

And I am using timer interrupts to make the encoder work.

#1141

@404-baitnotfound
Copy link
Author

In my aplication a debouncetime of 1000ms ist not possible. According to my oszi the shortest Puls time is between 1-2ms and the longest mybe 200ms. I use a debouncetime of 400us. Also I added a noise counter. So even if there is no 400us LOW Intervall the value can bei set. Using 1ms timer-interrupts would not work, and using 100-200us Timer Intervall would be unrealistic

@stale
Copy link

stale bot commented Aug 1, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Status: Stale Issue is stale stage (outdated/stuck) label Aug 1, 2019
@stale
Copy link

stale bot commented Aug 15, 2019

This stale issue has been automatically closed. Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Stale Issue is stale stage (outdated/stuck)
Projects
None yet
Development

No branches or pull requests

3 participants