Skip to content
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

gpio.trig interrupt cb slow to start executing, have ~1300us overhead #1478

Closed
danlu01 opened this issue Aug 27, 2016 · 6 comments
Closed

gpio.trig interrupt cb slow to start executing, have ~1300us overhead #1478

danlu01 opened this issue Aug 27, 2016 · 6 comments
Labels

Comments

@danlu01
Copy link

danlu01 commented Aug 27, 2016

Expected behavior

From interrupt pin edge detection to executing the callback function should not exceed 200us. Using arduino mega to send a high pulse of 500us follow by a low pulse of 500us, expect to detect pulse width of ~500us.

Actual behavior

Once an interrupt pin edge is detected, gpio.trig interrupt callback takes too long before start executing CB function. It takes about ~1300us before it start executing the CB function. Any pulse width less than 1300us is reported as 1300us. Even with pulse width of 1us, ESP8266 can detect it but takes too long excuting CB function.

Test code

Below code uses pin 1 (GPIO5) to detect raising and falling edge and report the duration of the high and low pulse.

  node.setcpufreq(node.CPU160MHZ)

  pin=1
  pulse1 = tmr.now()
  function pin1cb(level)
    pulse2 = tmr.now()
    print( level, pulse2 - pulse1 )
    pulse1 = pulse2
    gpio.trig(pin, "both")
  end
  gpio.trig(pin, "down", pin1cb)

NodeMCU version

NodeMCU version 1.5.4.1

Hardware

ESP8266-ESP12 and use arduino mega to send square waves to ESP8266 GPIO5.

Arduino code:

void setup() {
  // put your setup code here, to run once:
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  digitalWrite(10,LOW);
  digitalWrite(11,LOW);
}
void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(10,HIGH);
  digitalWrite(11,HIGH);
  delayMicroseconds(500);
  digitalWrite(10,LOW);
  digitalWrite(11,LOW);
  delayMicroseconds(500);
}
@jmattsson
Copy link
Member

I'm not sure much, if anything, can be done to improve this significantly. The gpio ISR already schedules the trigger callback at the earliest possible opportunity. Interpreting Lua is not a quick thing. @devsaurus you're probably the one who's done the most timing intensive things; do you have any thought here?

@luismfonseca
Copy link
Contributor

Maybe a native implementation for something like Arduino PulseIn would serve your use case?

Unless your use case has variable pulse width delays. That would be something like the inverse of gpio.serout(). A gpio.serin(sampleTimeout) (?) that would give a pin initial state and a list of delays between state changes detected.

At any rate, I think it would be valuable to have a gpio.pulsein function. I can have a stab at this if others agree.

@marcelstoer
Copy link
Member

At any rate, I think it would be valuable to have a gpio.pulsein function.

Consider what's been discussed and implemented in #1017 before you go ahead.

@luismfonseca
Copy link
Contributor

Good point.

The solution there is more in line with a serin and not with a pulsein. Also, I'm more inclined to say that the pulsein method should be part of the gpio module.

@devsaurus
Copy link
Member

The pcm module uses hw_timer to send out samples at up to 16 k/s rate. Accuracy is good enough to reconstruct the audio signal, although I needed to stay at the "standard prio" interrupt. Having the ISR on NMI crashed the system once in a while - whether for hogging the CPU too long or for hitting unprotected SDK functions I don't know. Expect the upper limit somewhere in this ball park.

The ISR-to-Lua ratio is 1024:1. The overall system is stable and responsive when a callback is triggered every ~1000 interrupts to perform heavy-duty stuff like SPIFFS access or network buffer handling. All this leaves enough head room for housekeeping in wifi stack etc. #1085 (comment).
In contrast to @danlu01's concern, this streaming example is critical regarding averaged performance and not start-to-finish latency as with gpio.trig(). For this I also don't have detailed figures.

But I could imagine that it's feasible to capture GPIO(s) continuously with ~10 ksamples/s rate, save that in a buffer and process the data post-mortem with Lua. Though you will most likely always face significant latency to react on the GPIOs with control flow.

@stale
Copy link

stale bot commented Jun 7, 2019

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

@stale stale bot added the stale label Jun 7, 2019
@stale stale bot closed this as completed Jun 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants