Physical Uno and Wokwi give different results for a simple test

Today I ran a simple "test of concept" both with a physical Uno and by simulation at Wokwi - and got different results. I used two different Unos. Could anyone please explain why?

The test is very simple: Run Blinky (with delays) and interrupt it with a LOW input at pin2. An interrupt is indicated by an LED at pin6. The LED stays on until a reset occurs.

At Wokwi, everything works as expected. Blinky is paused whenever and as long as the interrupt button is pressed. The interrupt indicator remains lit until a reset.

With an actual Uno however, the interrupt indicator lights up and stays lit but Blinky keeps on blinking merrily even while the interrupt button is being pressed, although at about twice the normal frequency. Changing the blink frequency proportionally changes the frequency during an interrupt.

void Interrupt ()
{
if (digitalRead(2) == LOW)
digitalWrite(6, HIGH);
}

void setup ()
{
pinMode(2, INPUT);		//With 10k to Vcc
pinMode(6, OUTPUT);
pinMode(13, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), Interrupt, LOW);
}

void loop ()
{
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500);
}

Thanks for the explanation and the quick reply.
This is not something I'm going to put to actual use 'as is'. The interrupt source will be a sensor and the main sequence will be something other than Blinky.

It's possible that there will be sustained and/or multiple interrupt inputs. Only the leading edge of the first interrupt signal should be recognized and all subsequent conditions must be ignored.

I'm very very new to anything to do with programming and am much more experienced in general electronics. So I came up with an idea to block all but the first leading edge with hardware, using parts that cost a total of literally one US cent. It works. The unexpected result I posted was before the blocking circuit was included.

My intention is just the opposite. The interrupt must go unnoticed except for the indicator light. A few microseconds of delay is fine.

I am not sure this is wrong, but if anything from the interrupted code ran, would it not be one instruction in the sssembled code, not one line of source code?

One line of source code, as we have seen, can pack quite a bit of computing into a few characters.

I will try to remember to bring this to the attention of the wokwi ppl. As I understand it, they run the code through the same too chain and then execute the results on an emulation of the AVR hardware.

That said, the few flaws that do crop all seem to be around really weedy issues down near the metal.

a7

I dropped an issue at the GitHub site for wokwi.

a7

Ah, yes. My ignorance is showing again. I'd read about FALLING but it didn't come up in my mind. I tried it in another small project some time ago but couldn't get it working. CHANGE worked though, as it does now.

Is a different syntax needed for FALLING?

Still doesn't work for me. That is, it doesn't turn the indicator on as LOW and CHANGE do.

Examine your button wiring. Is the pin really tied high? Does the pin really go low when the button is pressed? Are you just opening the circuit on button press? I do not see a drawing.

If you use attachInterrupt(digitalPinToInterrupt(2), Interrupt, FALLING); you do not have to test in the ISR for LOW; you can straight away set the pin.

Further, before your setup() is executed, your pin 2 is a floating input and can pick up noise from the environment. Therefore the interrupt flag in the EIFR register can aready be set before you attach the interrupt and it fires immediately after you attach.

Below code only switches the builtin LED on when the button is pressed.

void Interrupt()
{
  //if (digitalRead(2) == LOW)
  digitalWrite(13, HIGH);
}

void setup()
{
  Serial.begin(115200);
  pinMode(2, INPUT_PULLUP);  //With 10k to Vcc
  pinMode(6, OUTPUT);
  digitalWrite(13, LOW);
  pinMode(13, OUTPUT);

  // clear pending interrupts on pin 2 and 3
  EIFR = 0x03;
  attachInterrupt(digitalPinToInterrupt(2), Interrupt, FALLING);
}

void loop()
{
}

Note the use of INPUT_PULLUP. If you have an external pull-up, this is not necessary.

PS
The better way to clear is EIFR |= 0x01; to only clear the pending interrupt on pin 2.

I understand and appreciate your concern. Please don't take this the wrong way but I do have well over 50 years of experience designing, building and enhancing electronics stuff in medical, consumer, industrial and communications fields. I don't think there's much chance that I got the wiring wrong.

Here's a screenshot of the setup at Wokwi, identical to that with my physical Uno


:

That makes 1x10^6 and 1 times I have heard that.

Until you get the hang of the four-leg hobby buttons, use diagonal pins to ensure N.O. when not pressed.

I've been using 4-legged tactile switches for decades. I use them in my own designs and have replaced them in commercial products. I also tested the contacts.

Try changing this:

to pinMode(2, INPUT_PULLUP); //With internal pullup to Vcc - No external 10k

If attachInterrupt(digitalPinToInterrupt(2), Interrupt, FALLING); doesn't trigger the ISR then you have other problems which are worthy of investigation.

I did that and it immediately triggered; I did not use an external pull-up). I had to clear the flag for it to work; see post #12.

From this post of the OP the button works so what is the actual problem?

What happens when the button is NOT pressed?

OK. Thanks. I've now looked more carefully. I was more interested in the failure to trigger which the OP claimed, not the false trigger which you have explained.

The OP appeared to say that he got no response with the "FALLING" interrupt and that cannot (or should not) be hence my interest.
I guess the problem is this that the ISR triggers on FALLING even before that statement if (digitalRead(2) == LOW) can be true, hence it is ignored because of the way the OP has structured the ISR.

Initially, it was a difference in behaviour between a simulated and a real Uno.

My thoughts also but somewhere the problem shifted to something else.

Wokwi is much slower than the UNO so the Interrupt will look different.

Indeed. It appears to be a timing issue as explained. The "LOW" interrupt triggers continuously. If the code in the ISR is slow it uses up all the resources so the loop() gets stuck. Clearly the real Uno has some spare capacity to service the loop().

I'm sorry you took it that way. I said in my opening post that I'm very very new to anything to do with programming and kept saying later on how ignorant I am.

In mentioning my experience in electronics, I started with "Please don't take this the wrong way......". What followed was intended as a way of saying that it's unlikely that I made some beginner's mistake with the wiring. I'm more fastidious than most people in checking and re-checking such things. My attempt to clarify that point earned a somewhat disparaging response.