dmadison / ServoInput

Interrupt-driven servo decoder library for Arduino
GNU Lesser General Public License v3.0
22 stars 10 forks source link

Will this work with current ESP32? #19

Closed KnightDeluxe12 closed 7 months ago

KnightDeluxe12 commented 2 years ago

I'm wondering if this library is also applicable for esp32? because i broke my nano and i only have esp32 as a spare for a rc car project thanks

dmadison commented 2 years ago

It should, although I've never tested it myself.

bisak commented 2 years ago

@dmadison Unfortunately I cannot get any of the examples to work. Always stuck at Waiting for servo signals.... Whereas I'm certain connections are OK because I'm able to get some output via a simple pulseIn(). How could we go about debugging this?

dmadison commented 2 years ago

What board are you using?

If you skip the available() check and call getPulseRaw(), do you get any values?

If not then it's likely an interrupt issue of some sort. The first thing I would test is that the interrupt routine is being triggered without the library. Something like:

volatile bool triggered = false;

void ICACHE_RAM_ATTR isr() {
    triggered = true;
}

attachInterrupt(pin, isr, CHANGE);
while(true) {
    if(triggered) {
        triggered = false;
        Serial.print("T ");
        Serial.println(micros());
    }
}

If that works, expand it to call the public isr() function of the template class from within your own ISR. If that works then it's likely to be an issue with the automatic ISR setup, otherwise it may be an issue with the timestamp functions.

clowrey commented 1 year ago

Thanks for this awesome library!! I am also trying to use this on ESP32 and it only returns 0 for getPulseRaw() or getAngle()when I have only one ServoInputPin<2> servo2;

If I put two input pins: ServoInputPin<2> servo2; ServoInputPin<5> servo5;

It goes into a boot loop with gpio_install_isr_service(449): GPIO isr service already installed which was the first error I encountered before removing one of those and just getting 0 as the data returned. I need two pins to work eventually.

So then I found this issue in the tracker and tried out your great debugging example!

And the interrupt test did work! it is showing me the micros since startup!! yay!

So then I added servo.isr(); to the interrupt handler and it works!

Then I tried to add two servo pin interrupts and two calls etc and it now has two inputs working!!! :) Again thanks for this awesome code!

const byte servoPin0 = 2;
const byte servoPin1 = 5;

#define SERVOINPUT_NO_INTERRUPTS 
#include <ServoInput.h>
ServoInputPin<servoPin0> servo0;
ServoInputPin<servoPin1> servo1;

void ICACHE_RAM_ATTR servoISR0() {
  servo0.isr();
}

void ICACHE_RAM_ATTR servoISR1() {
  servo1.isr();
}

void setup() {
  Serial.begin(115200);
  attachInterrupt(servoPin0, servoISR0, CHANGE);
  attachInterrupt(servoPin1, servoISR1, CHANGE);
}

void loop() {
  float angleServo0 = servo0.getAngle();  // get angle of servo (0 - 180)
  float angleServo1 = servo1.getAngle();  // get angle of servo (0 - 180)

  Serial.print(F("Servo0: "));
  Serial.println(angleServo0);

  Serial.print(F("Servo1: "));
  Serial.println(angleServo1);
}
dmadison commented 1 year ago

Thank you for the feedback! That confirms my suspicions that it's an issue with the automatic interrupt attachment.

If you have some time to follow up: could you test whether you encounter the same error if you define the objects within setup() rather than globally? Using your code from above:

const byte servoPin0 = 2;
const byte servoPin1 = 5;

#include <ServoInput.h>

void setup() {
  Serial.begin(115200);
  ServoInputPin<servoPin0> servo0;
  ServoInputPin<servoPin1> servo1;

  while(true) {
    float angleServo0 = servo0.getAngle();  // get angle of servo (0 - 180)
    float angleServo1 = servo1.getAngle();  // get angle of servo (0 - 180)

    Serial.print(F("Servo0: "));
    Serial.println(angleServo0);

    Serial.print(F("Servo1: "));
    Serial.println(angleServo1);
  }
}

void loop() {}  // intentionally empty

If that works then it would appear to be a static initialization order error, i.e. that the interrupt matrix isn't set up before we try to attach the interrupts. If that doesn't work then there's likely an issue getting the ESP to accept the reinterpret_cast trick we're doing with the template.

SkylarTheGrey commented 7 months ago

I was able to get @clowrey pass-through ISR to work. Can also confirm that on an ESP-WROOM-32 that your code with the declaration in setup() does work, though of course its then not usable in other functions.

dmadison commented 7 months ago

Thank you everyone who has responded with information about this issue. Hopefully this should be fixed with the latest release and the changes from PR #30. The interrupt handler must now be attached by the user, which avoids the automatic attachment pitfalls present in the ESP32 core.

Please test the 2.0.0 release, and feel free to reopen this issue if anyone still has problems.