logo elektroda
logo elektroda
X
logo elektroda

ESP8266(wemos d1 mini) interrupt constantly alerted without cause.

grankee 2328 33
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
  • #1 17949097
    grankee
    Level 9  
    Hello, I have a problem with an interrupt that alarms itself for no reason.
    This interrupt is handled by the encoder, it is connected to pin D4, as a knob press (spinning on pins D3 and D5). Encoder library. Everything was working fine until I included wifi operation in STA mode. After knocking out this code the problem persisted, I saw that esp was still connecting to the stored network despite knocking out the code, so I compiled the code with the wifi.mode(OFF) line and then my code again. The module stopped connecting, but still the interrupt alerts probably "every frame"(b. fast spam on serial monitor). There is no load in the interrupt, one line changing the value of a global variable of type uint8_t - that's it. Switching the interrupt to another pin makes it not work at all. I have a simple function that counts "frames" and normally it's close to 500,000 per second, but when I include encoder handling (checking every frame if there has been a state change, then ignoring the check if it hasn't been 50ms (debouncing) and rechecking the state after the noise) it drops to the console value, which is 30fps.
    I tried an external 10kilo pullup, attached a 1000uF capacitor, disconnected the encoder from the pin, no change. I even checked with the arduino, the analogue pin and the drawing board in the arduino IDE (makeshift oscilloscope) what the state of the D4 pin on the esp looks like and it is ok, when I press the encoder it drops to about 60 (about 0.29V) and when I let go the state of the pin stays at one level without even special noise at about 680(3.32V) (arduino on 5V).

    What could be the cause or what other data is needed.
    Do you have a problem with Arduino? Ask question. Visit our forum Arduino.
  • ADVERTISEMENT
  • #2 17949132
    khoam
    Level 42  
    grankee wrote:
    but further the interrupt is probably alerted "every frame"
    .
    I think this is about the watchdog? You need to stop the serial monitor when the logs appear, and paste the information about the cause of the WD here - it's usually quite helpful. At this link you have information on diagnosing the cause of a WD on the ESP8266:
    https://arduino-esp8266.readthedocs.io/en/latest/faq/a02-my-esp-crashes.html
    (there's also instructions at this link on how to install the Exception Decoder in the Arduino IDE - quite a useful tool for such cases)

    grankee wrote:
    even what other data is needed.
    .
    At least the bit of code you think is causing the problem would be useful.
  • ADVERTISEMENT
  • #3 17949613
    Slawek K.
    Level 35  
    To get rid of the wifi connection, upload "blank.bin" which you can find on the web, in your case version 4M. This will overwrite the flash area where the wifi connection data is stored. Then upload your code (the one without wifi support).
    This will solve part of your problem, the rest is written about @khoam .

    Greetings
  • #4 17949632
    sylweksylwina
    Moderator of Computers service
    You don't want to auto connect to WiFi then you have the function WiFi.setAutoConnect(false);
    In the arduino tools under Erase Flash you can choose to have it erase all flash every time you upload a sketch (as above).
    If you have long loops with lots of instructions, use yield(); or delay(0); in each iteration to avoid triggering the watchdog. You can always disable the software watchdog (not recommended) ESP.wdtDisable(); but the hardware watchdog will still work.
  • ADVERTISEMENT
  • #5 17949884
    grankee
    Level 9  
    Ok I chose to overwrite all flash memory when uploading the sketch, thanks for the hint.
    khoam wrote:
    I guess this is about the watchdog? You'll need to stop the serial monitor when the logs appear and paste the WD cause information here - it's usually quite helpful. At this link you have information on diagnosing the cause of a WD on the ESP8266:
    .
    Correct me if I'm wrong, but the watchdog is what restarts the module when it crashes or something. It then pops up a stack trace and restart log. The thing is, this doesn't happen to me. I don't have reboots. It is about an interrupt registered on pin D4, which calls itself nonstop.
    A small correction, where I wrote that the loop laughs 500,000 times per second it laughs 50,000 and where I wrote that 30 it laughs 3.
    Also, if I comment out //attachInterrupt(D4, handleKey, RISING); it goes back to its speed, but stops working and pressing the encoder and spinning it even though the spinning works on separate pins D3 and D5.
    What annoys me the most is that it all worked as expected on this code, and stopped working as soon as I attached the wifi, while it didn't start working again once I removed the wifi.
    The whole code has thousands of lines (not in the loop itself of course), I will try to paste the relevant ones:

    Code: C / C++
    Log in, to see the code
    [/code].
  • ADVERTISEMENT
  • #6 17950187
    khoam
    Level 42  
    To start with, perhaps do a simple experiment (with interrupts on D4 attached):
    Code: C / C++
    Log in, to see the code
    .
  • #7 17950467
    grankee
    Level 9  
    It didn't change anything. HandleEncoder only checks if the variable has been changed, nothing there affects the interrupt itself. moreover, in Encoder.h both functions are used multiple times so when I use them it is more likely to be overwritten anyway. Here are the contents of Encoder.h:
    Code: C / C++
    Log in, to see the code
    .

    Encoder.cpp:
    Code: C / C++
    Log in, to see the code
    .
  • #8 17950521
    khoam
    Level 42  
    If you disable the encoder functionality, does the interrupt handling from D4 run correctly?
    By completely disabling I mean no creation of the variable myEnc in your code.

    Added after 2 [hours] 47 [minutes]: .

    grankee wrote:
    Encoder library.
    .
    I have looked at the sources of this library. It looks like, in the case of the ESP8266, creating the variable myEnc assigns interrupt handling to pins D3 and D5.
  • #9 17950840
    grankee
    Level 9  
    After disabling the operation on pins D3 and D5 (turning left right) still the same. I have the impression that it happens faster. The effect of the click is to jump over the menu items visible on the OLED display, it seems to me to jump faster.
    Can the interrupts on D3 and D5 affect the interrupt on D4? I'm still confused as to why this worked before. I recall that I used to have problems with the pin control in the ESP. Sometimes it was the case that a pin worked normally, but when, for example, I started to do something on another pin, the first one stopped working. For example, when pin D1 was not in use, I could do whatever I wanted with pin D2, but when I set D1 to high, I could no longer control pin D2. Such miracles happened, to this day I don't know why, of course I don't remember the pin numbers, I gave examples. Here the problem is even stranger, because I didn't connect or disconnect anything at all, I didn't even change anything related to the pins. Nothing like this has ever happened in the arduino, only the esp freaks out.
  • #10 17950850
    khoam
    Level 42  
    Can you post a picture of this encoder or provide a link to this model?

    One more thing: there is also an LED connected to pin D4 on the board. Maybe use a different pin for the button.
    Schematic attached.
  • #11 17950867
    grankee
    Level 9  
    I tried another pin, but then it doesn't work at all. It seems to me that other pins may not support interrupts.
    Rotary Encoder Module KY-040 Arduino / PIC / PI
    I don't want to give a link, because as far as I remember forbidden.
    However, it probably doesn't matter, because even if I disconnect it from pin D4 it doesn't change anything. As I wrote above, it's not the state of the pin that affects the triggering of the interrupt. I measured with arduino + drafter from serial port the state of D4 pin with encoder disconnected and it is still high there.
  • #12 17950876
    khoam
    Level 42  
    grankee wrote:
    However, it probably doesn't matter because even if I disconnect it from pin D4 it doesn't change anything.
    .
    Disconnecting does not disable interrupt handling on this pin.

    On the wemos D1 mini, all pins with the D prefix can handle external interrupts, except for D0 - at least that is what the documentation says.

    Added after 17 [minutes]:

    Instead of
    Code: C / C++
    Log in, to see the code
    .
    type
    Code: C / C++
    Log in, to see the code
    .

    Added after 25 [minutes]:

    Also use:
    Code: C / C++
    Log in, to see the code
    .
  • #13 17951549
    grankee
    Level 9  
    Unfortunately there is still no change. Yes yes, I know that disconnecting doesn't disable the service, I just meant that it doesn't matter what encoder I have, because it's not the one causing the problem, as evidenced by the fact that when I disconnect it, nothing changes.
  • #14 17951615
    khoam
    Level 42  
    I have this trick question: at which point in the code you posted in post #5, the variable isButtonPressed is assigned the value false , if the button actually is not pressed ? I don't mean handling debouncing or assigning the value false once during the declaration of this variable.
  • #15 17951660
    grankee
    Level 9  
    Hmmm you're asking where in the code and at the same time saying you're not asking about that bit, well false is assigned right there.
    The interrupt on the pin sets the value to true, while the loop every cycle executes the HandleEncoder() function, which contains the following
    Code: C / C++
    Log in, to see the code
    .
    and it is at this point that the value false is set.
    I understand that you want to suggest that setting true/false loops through faulty code and this has the effect of spamming the functions, but two questions remain, why was it working fine before and stopped even though I didn't change this particular piece of code? The second question is why when I change the setting of this variable
    Code: C / C++
    Log in, to see the code

    to
    Code: C / C++
    Log in, to see the code
    .
    this of course on the oledo stops the menu jumping because I have removed the response of this menu to the interrupt, but the serial monitor is spamming me with the variable count at a rate of about 800/s. In this case I have cut off any effect of this variable on the interrupt behaviour. I also disconnected the encoder cable from pin D4. Now the interrupt only triggers a spam on the serial monitor. I should add that connecting pin D4 to 3.3V or ground changes nothing. For the rest, its state was tested before and no change is visible there, but just to be sure, I checked such two options.
    Of course I checked on another wemos and it works the same.
  • #16 17951668
    khoam
    Level 42  
    grankee wrote:
    then the value false is set at this point.
    .
    This is a bit too "short" a condition for assigning false variable isButtonPressed , because it will only work if the condition millis() - lastUpdateMillis > 50 is also met. What if the button is not pressed, and previously the variable isButtonPressed was set to true ? This is generally to be redesigned, and it's probably not a good idea to operate this button via interrupt. Replacing the variable isButtonPressed with a counter count in the interrupt handler will not help at all here.

    grankee wrote:
    Hmmm you are asking where in the code and at the same time you say you are not asking about this fragment,
    .
    That's why I wrote that the question was tricky ;) .
  • #17 17951733
    grankee
    Level 9  
    khoam wrote:
    Converting the isButtonPressed variable to a count in the interrupt handler will not help here at all.
    .
    It probably won't help in terms of the correctness of handling this variable, but it will help insofar as we get rid of this variable from the issue of the problem altogether. Since it is no longer involved in the interrupt, the cause of the problem was certainly not or was not the only one. Incidentally, the isButtonPressed variable is only set to true in this interrupt, when defined it is set to false.
    However, if we disconnect the variable (the change of the value of which, by the way, was not the cause of the interrupt anyway, but its effect), disconnect the encoder from the pin, connect the pin to GND, power supply or leave it unconnected (which is a dangerous option, because its state now depends on a mass of factors over which it has no control), the interrupt continues to be triggered uninvited and this is the key problem.
  • Helpful post
    #18 17951755
    khoam
    Level 42  
    grankee wrote:
    The variable isButtonPressed is only set to true in this interrupt, when defined it is set to false.
    .
    but is not set to false every time the button is already released. The 'button is pressed' condition must not apply to the indefinite elapsed time since the button was pressed.

    grankee wrote:
    If, however, we disconnect the variable (whose change of value, by the way, was not the cause of the interrupt anyway, but its effect), disconnect the encoder from the pin, short the pin to ground, power supply or leave it unconnected (which is a dangerous option, because its state now depends on a mass of factors over which it has no control), the interrupt continues to be triggered uninvited and this is the key problem.
    .
    This already looks a bit like voodoo ;) Are you sure you used digitalPinToInterrupt()? Have you tried on a pin other than D4?

    Is the handling of this button extremely critical i.e. the press response must be instantaneous? Maybe it's better to move it to loop() - then there's more control over differentiating on/off states and you have better control over bouncing.
  • #19 17951817
    grankee
    Level 9  
    khoam wrote:
    This already looks a bit like voodoo
    .
    I can usually handle things from this world :D
    khoam wrote:
    Are you sure you used digitalPinToInterrupt()?

    yes
    khoam wrote:
    Have you tried on a pin other than D4?
    .
    grankee wrote:
    Switching the interrupt to a different pin makes it not work at all.


    khoam wrote:
    Maybe it's better to move it to loop() - then there's more control over distinguishing the on/off states and you have better control over bouncing.
    .
    This was the first solution I tried in general, but there was the problem described above, i.e. the pin state reading in the program was not true. The state was still LOW or HIGH, I can't remember anymore, even though the physical pin state reading said otherwise. There was also the problem I described above, that when I started to do something on the next pin, the one that was working so far stopped working and it was impossible to either set the state or read it correctly. Operating the encoder as it is now was the only working solution, now it is no longer.
    khoam wrote:
    Is the operation of this button extremely critical i.e. the response to pressing it must be instantaneous?
    .
    It's hard to say, you know, the encoder is used to navigate through menus and change settings so it needs to be fast enough for this to happen smoothly. There are delays of a few tens of ms in the ds18b20 support in the library and I had to reprogram this to get them out, because it could be felt that sometimes turning the encoder didn't catch on. I don't remember if the clicking did either. Now the ds18 works on a similar principle to debouncing, it counts down x amount of time since the last action and executes the next one if x amount of time has passed, this way I got rid of the delay altogether.
  • Helpful post
    #20 17951854
    khoam
    Level 42  
    grankee wrote:
    this way I got rid of the delay altogether
    .
    If you don't have any delays in loop() then all the more reason to move the button handler here. I suggest using EasyButton:
    https://github.com/evert-arias/EasyButton
    The read() function from this library does not introduce any delay() either, and you can elegantly plug the button press detection into a callback. Debouncing mechanisms are already built into this library.

    Added after 1 [minute]: .

    The operation of the other encoder buttons could remain as it is, i.e. on interrupts.
  • #21 17951925
    grankee
    Level 9  
    Ok, admittedly on pin D4 it doesn't work, but I switched to pin D7 and the press works. Now there is a problem with turning left right. Twisting the encoder doesn't work as a button, it only compares the state of one pin while changing the state of the other, so ideally it would be best to register both twisting pins as buttons and compare the state of one while changing the state of the other one to determine if I'm twisting left or right, do you have any better ideas on how I can do this?

    //edit wait because it doesn't seem to work, but it works 1/1000th of the turns, I need to post where the problem is.
    //edit okay, this time the problem is in my code, because when I dry paste serial.println into every twist detection it spams nicely, so I will fight it. The encoder press problem seems to be solved for now, although I'll still leave the thread until I get the wifi up and running above and make sure it continues to work.
    The problem still remains with the D4 pin not working as it should, my easybutton didn't work on it, it doesn't detect a change in state of the pin at all. It is also impossible to read its state as it keeps showing HIGH. Interestingly, as this is the pin of the built-in LED I can tell that the state is actually changing as indicated by the LED turning on and off. Furthermore, digitalWrite is unable to change the state of the pin. Still high. of course I use the pinMode function
  • #23 17951985
    grankee
    Level 9  
    Thanks good man. I'll check later that everything works with wifi and write back.
  • #24 17952001
    Slawek K.
    Level 35  
    As I am following the substantive discussion in this thread with interest, I would be grateful for feedback as to whether it has helped. In my designs, I generally go for pins D5-D8, unless I need more then I choose additional ones from the least cumbersome.

    Best regards
  • #25 17952006
    grankee
    Level 9  
    it looks like d3 has refused to work along with d4. D5 and D7 I use for the encoder and one pin is still missing. D6 supports the ds18b20 thermometer, D1 and D2 I2C. Missing pins :( I have the PFC connected but have not been able to read the actual state of the pin, I only use what outputs. Any ideas?
  • #26 17952024
    Slawek K.
    Level 35  
    Try D11 or D12, possibly D8 for rising edge detection i.e. pin shorted to vcc, as it has pulldown.

    Greetings
  • #27 17952111
    khoam
    Level 42  
    grankee wrote:
    not working as expected on pin D4, my easybutton did not work on it
    .
    How did you define the easyButton constructor for pin D4? I already wrote in post #10 that BUILTIN_LED is connected to it for power, so puEnable must be false - the default is assumed to be true:
    Code: C / C++
    Log in, to see the code
    .
    puEnable : Use or not the internal pullup resistor. Enabled by default.
    invert : Inverts button's logic. If true, low = pressed else high = pressed.

    Added after 1 [minute]: .

    grankee wrote:
    Still high. of course I use the pinMode function
    .
    What parameter are you passing to pinMode() for D3 and D4?

    Added after 2 [minutes]:

    grankee wrote:
    d3 refused to obey
    .
    Same problem as with D4. See above. D3 also already has an external pull-up resistor to the power supply.

    Added after 1 [minute]: .

    Slawek K. wrote:
    Try D11 or D12
    .
    I would advise against these - they are connected to flash.
  • #28 17952211
    Slawek K.
    Level 35  
    Try DS18B20 rewired under D3, and fire a button on D6.

    Greetings
  • #29 17952654
    grankee
    Level 9  
    khoam wrote:
    What parameter are you passing to pinMode() for D3 and D4?
    There are two parameters for the pinMode().
    pinMode(D4,INPUT);
    INPUT_PULLUP does not work either.
    khoam wrote:
    How did you define the EasyButton constructor for pin D4?
    .
    EasyButton leftEnc(LEFT_PIN,35,false);

    Here's the thing, even when I don't use easybutton but just check the state of the pin in the loop it doesn't change. It only spits out a 1 once on power up, then silence, and I alternate shorting it to ground and vcc
    Code: C / C++
    Log in, to see the code
    .
    Slawek K. wrote:
    Try D11 or D12
    .
    are not even pulled out
    Slawek K. wrote:
    Try DS18B20 rewired under D3, and fire a button on D6.
    .
    does not work on pin d3
    khoam wrote:
    Same problem as with D4. See above. D3 also already has an external pull-up resistor to supply.
    .
    Ok, but I can't understand why this interferes with operation. After all, for example in the arduino all pins have an internal pullup built in and you can always use it, yet the pins work. I thought the pullup's job was to set the state to a specific high state so that it wouldn't be random under interference, not to put the pin out of use completely. If that was to be the case then who would bring it outside and why? Why did they work before? Why if pin D4 has a pullup then the interrupt was detected nonstop, after all the interrupt was supposed to be alerted by a rising edge, not a high state, and there was a high state there all the time.

    //edit I managed to read the state of the pins in the PFC, the problem is however that reading the state of a pin every 1 loop slows down the ESP from 37000 executions per second to 3500 or about 11 times. All unused pins do not work.
    //edit I found the interrupt pin in the PFC, and it even works, the problem is that when I short-circuit a pin to ground the OLED starts spitting out bushes for a while (it works on the same I2C bus to the PFC).
    //edit ok it seems that when I simply read the state on d5 and react to its change, the display does not swirl (earlier I tried with interrupt)

    //edit the encoder on the pfc works together with the network.

    Added after 17 [hours] 2 [minutes]: .

    Summary:
    pins D3,D4 (even though they worked before) and D0 and D8, and by the way also A0, I have not been able to get them to work. The status on them is set like this and not different and nothing can be done about it :( if anyone has any more ideas I'll turn a deaf ear.

    Encoder connected to PFC, as if anyone needs it I wrote a mini library, probably not perfect but it works. Since the topic has already been set up, maybe someone else will benefit.
    https://github.com/grankee/Encoder_pfc8574

    If you don't tighten the encoder to one side of the full stroke and reverse it, it will work as a reverse twist. I haven't had the time or need to analyse all 4 steps of the encoder to eliminate this effect, because when used normally it's ok.
  • Helpful post
    #30 17953994
    khoam
    Level 42  
    Pin D4 on the wemos d1 mini is not suitable for handling external interrupts when using the Serial.print() or Serial.println() functions in a program. These functions attempt to "light" the LED on the board (BUILTIN_LED), which is connected to pin D4, resulting in the generation of an unspecified number of interrupts due to chaotic state changes on this pin. This is a feature of this module, not the ESP8266 as such. I dusted off my wemos and confirmed this practically. So you cannot use the D4 in this board for any of the encoder outputs. Of course you can always opt out of using Serial.print() ;) .

Topic summary

The discussion revolves around an issue with the ESP8266 (Wemos D1 Mini) where an interrupt on pin D4 is triggered continuously without an apparent cause. The user initially connected an encoder to this pin, which worked until WiFi functionality was added. After removing the WiFi code, the interrupt issue persisted. Various suggestions were made, including disabling auto-connect for WiFi, using the Exception Decoder for diagnosing watchdog issues, and overwriting flash memory to clear stored WiFi credentials. It was noted that pin D4 is unsuitable for interrupts due to its connection to the onboard LED, which interferes with the interrupt handling. The user eventually switched to pin D7 for the encoder button, but faced challenges with the encoder's rotation detection. The conversation highlighted the importance of choosing appropriate pins for interrupt handling on the ESP8266 and provided insights into potential workarounds and alternative microcontroller options.
Summary generated by the language model.
ADVERTISEMENT