-
Notifications
You must be signed in to change notification settings - Fork 10
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
Interrupt related compilation issue with UNO R4 Minima #28
Comments
Hello, and thanks for creating this issue. Please provide the following information:
Could you please also share the complete error message you're receiving? |
All files (library & board files) and Arduino IDE are the latest available versions. I will check and list the exact versions later today and attach the compilation error messages as requested. |
Version information:
Error messages: exit status 1 Compilation error: exit status 1` |
Thank you. At the top of the header, try adding the line: #define NOT_AN_INTERRUPT -1 |
I tried by adding the line to the RC_Receiver example which resulted into different error messages as before. I then realized that you probably meant Servoinput.h file and tried that as well. This resulted into the same errors as adding the line to the sketch. Here's the error listing: exit status 1 Compilation error: exit status 1` So it seems that the problem lies somewhere deeper. |
The library won't compile on Arduino platforms that do not define the `NOT_AN_INTERRUPT` macro. This macro is used by the library to evaluate whether a pin is supported for interrupts. The previous fix (e7e5845) defines this macro if it's missing, with the assumption that all pins on the platform support interrupts. That didn't solve the issue with the renesas platform (#28) however, as the `digitalPinToInterrupt()` function is a passthrough and not a compile-time constant. That fails the `static_assert()` check. Instead, this patch adds a bypass. If `NOT_AN_INTERRUPT` is not defined, all code that uses the `digitalPinToInterrupt()` function and the `NOT_AN_INTERRUPT` flag is disabled. There won't be any compile-time or run-time checks for whether the pin is supported or not, but there's nothing we can do about that if the platform doesn't support the feature.
It looks to be an issue with inconsistencies between the Arduino cores. The renesas core does not implement the I've pushed a patch to a new branch entitled "renesas" with a workaround. The examples compile on my machine, but I do not have an Uno R4 on hand to test. Please give the branch a test and report back. |
I tested quickly with the "Calibration" example since it needs only one input pin. It compiles, uploads and runs OK but does not seem to detect the servo signal. It keeps printing "Waiting for servo signal...". I will build a better cable to use with a servo tester tomorrow and verify but my current connection should work as well. Servo tester powers up from +5 V and GND pins on UNO R4 and signal wire is connected with a test hook to D2. Thus the connection is the same as you show in your article but uses a servo tester instead of an RX. Could I add some lines to the code to help finding if interrupts are actually generated? Meanwhile, I'll try the standard pulsein to make sure my setup works otherwise. |
Unless the driver is sending a signal out of spec, the Here's two things to try to narrow down the issue. First, try with everything defined in the void setup() {
Serial.begin(115200);
ServoInputPin<2> servo;
while(true) {
float angle = servo.getAngle(); // get angle of servo (0 - 180)
Serial.println(angle);
}
}
void loop() {} Second, try using a helper function to call the ISR: ServoInputPin<2> servo;
void helperISR() {
servo.isr();
}
void setup() {
Serial.begin(115200);
attachInterrupt(digitalPinToInterrupt(2), helperISR, CHANGE);
}
void loop() {
float angle = servo.getAngle(); // get angle of servo (0 - 180)
Serial.println(angle);
} |
Thanks for these! Both of these test codes work. ISR is firing and I get data from 0 to 180 degrees when I adjust the servo tester between the extremes. However, the readings are quite noisy, angle accuracy seems to be roughly +/-5 %. I know for sure that the servo tester outputs very clean pulse with 1 us accuracy and low jitter. I verified it with an oscilloscope. I don't know if the noise is a problem at this point since the idea was to see if interrupts are being generated or not. |
Thanks for following up. If both of those codes work it confirms that it's an issue with the class constructor attaching the interrupt. I'm not sure whether that's because of a static initialization order issue or because the chip's interrupt support doesn't spool up until Re: noise, are you saying accuracy is +/-5% of the dialed angle, or that the reported angle jitters +/-5% when the driver's angle is supposedly constant? Please try recording the output using if(servo.available()) {
Serial.println(servo.getPulseRaw());
} If you have access to a scope and the means to do so, please attach images of the waveform when connected in situ to the Arduino. |
The reported angle jitters by roughly +/- 5 % of full scale when the angle (pulse width) is kept constant. In other words the jitter is about +/- 9 degrees regardless of what the servo tester setting is. Sorry that my statement was a bit unclear. I'll continue testing tomorrow, hopefully. I have a small electronics lab at home so taking scope images is no problem at all. |
OK, I did a quick test already. I added the new code to the loop of the 2nd test code and commented the servo.getAngle related lines out. The raw measurement is much much better for some reason. When "middle point" is selected from the servo tester, it outputs exactly 1520 us pulse which is what Futaba RC systems do. The new code measures it quite well: I can verify the pulse width and shape soon with my oscilloscope. The measurement noise seems to be just +/-3 us (varies a bit more than is visible in this plot) with a +2 us offset. The offset error is either caused by the inaccurate clock of the MCU since it uses its internal oscillator or pulse shape or both. |
Interesting. Try using the original code, but with the if(servo.available()) {
float angle = servo.getAngle(); // get angle of servo (0 - 180)
Serial.println(angle);
} |
This approach works better and with the available() block the angle output reports 93.2 deg - 94.5 deg. I observed this over a longer period and there's definitely variation due to the temperature correction that adjusts the internal oscillator of the MCU. It looks like now angle reporting is in line with the getPulseRaw() reporting in the previous test. BTW, here's an oscilloscope image of the servo tester output in middle position. Persistence is 10 s here and no jitter to be seen: |
I forgot to mention one detail that might help in troubleshooting:
is installed, it is difficult to get another sketch uploaded. Double tapping reset button seems to be the only remedy. To me this sounds like the interrupt is firing at least partially randomly and even removing the servo signal does not help. |
Do you have the same issues uploading if you remove the |
No, if that line is commented out, another sketch can be uploaded normally without messing with the reset button. I just tried that once but the behavior was quite consistent earlier. I had to do some research to find out the fix... |
It sounds to me like the library is functioning properly, and the cause of the jitter is from the serial implementation blocking or otherwise delaying the interrupt from firing. It might be prudent to add the Other than that, is the library working properly? I can merge the |
I tend to agree - even though I have very little or no coding skills, I do know the hardware side and how interrupts function. Based on the results with I will go on and try to create the simple LED control system for F3P model airplanes that I was originally planning to do. The servo pulse decoding part does not have to be super fancy so the standard Arduino |
This was causing issues on certain platforms where the platform's interrupt attachment system was not set up or available when the object was constructed in global scope (see #28). Instead, the user must attach() the object themselves before they can read signals. The library examples have been updated accordingly.
I've pushed some changes to a "v2" branch which should hopefully solve the interrupt issue. The new version of the library requires a call to |
I tested this v2 branch with two of the examples: BasicAngle and Calibration. The library works OK but with Uno R4 the examples need the additional GetAngle example change:
|
That sounds about right, given the current assumption that it's an issue with const unsigned long Center = 1520;
const unsigned long Window = 50;
const int AlertPin = 3; // or whatever pin is easy
void loop() {
const unsigned long raw = servo.getPulseRaw();
if(raw <= (Center - Window/2) || raw >= (Center + Window/2)) {
digitalWrite(AlertPin, HIGH);
digitalWrite(AlertPin, LOW);
}
} Scope the For what it's worth, I took a peek into the 'renesas' core and the interrupt request table is set up in |
Thanks, I'll test that during the weekend (or even earlier) and report back. It's pretty clear to me what that code does. |
I tested the "AlertPin" approach with this code:
It took me a while to figure out that the pin must be defined as OUTPUT first but once I added that, the code works and AlertPin stops changing state when the pulse width is inside the Window. Thus nothing in this code causes jitter in the measurement. When pulse width is outside the Window, the pin changes state all the time very rapidly. I added 1 ms delay to be able to see the signals properly in this case. |
If that's the case, the issue must either be in the I'm hesitant to add the I also haven't experienced the jittering issue on any of the other platforms I've tested, which leads me to believe it's a fault with the R4 core implementation. Otherwise, it sounds like the library is working as well as can be expected on the Uno R4. It now compiles without error and the ISR attaches as designed. I'm going to merge the v2 branch, push a release, and close this issue. Thank you for all of your help and feedback! |
Resolved by #30. |
Thank you very much for the efforts. I agree with your reasoning. It wouldn't make sense to add the Would it be possible to report this behavior to the R4 core team as a bug? |
Yes, you can create an issue on the Arduino renesas core: https://github.com/arduino/ArduinoCore-renesas Although for their benefit it would be better if you could create a minimally reproducible example that does not involve the library. Perhaps an interrupt function that records the value of const int pin = 2;
volatile unsigned long m;
unsigned long last;
void isr() {
// record time on rising edge
if(digitalRead(pin) == HIGH) m = micros();
}
void setup() {
Serial.begin(115200);
pinMode(pin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(pin), ISR, CHANGE);
}
void loop() {
const unsigned long x = m;
Serial.println(x - last);
last = x;
} Completely untested, but that's the gist. |
When trying to compile code that uses ServoInput library - one of the examples for instance - the compilation fails with multiple error reports related to a missing interrupt capability. This happens even though the HW has interrupt capable pins D2 and D3 just like the earlier UNO versions.
The issue is easily reproduced by just selecting a code example accompanied with this library and compiling first with Arduino UNO selected. the switch to Arduino UNO R4 to see compilation fail.
This may be related to a similar issue found with ESP32. It could also have something to to with the interrupt handling of Renesas RA4 MCU.
The text was updated successfully, but these errors were encountered: