Generate interrupt with Python script


My ATmega is busy doing something while the Linux side is programmed to run a TCP socket with another device. When the socket receives a specific code, I want to generate an interrupt so that the Arduino microcontroller would stop doing what it is doing and it would serve the interrupt.

is it possible to generate an interrupt from a python script on linux side? I thought to change the state of one of the pins dedicated to the interrupt but I don't know how to do that without writing the code in the loop part and therefore keeping busy the ATmega.

It should be theoretically possible, but are you sure it's what you want? Read Nick Gammon's article on Interrupts, paying particular attention to the section titled "What interrupts are NOT."

Interrupts are used when the program needs to respond to an urgent high priority signal within a few microseconds, and in response do something very short and fast, then get out. Usually an interrupt service routine will just read/write a device register or two, and set a flag to signal the main program to do something, then return. Responding to a TCP socket does not sound like an interrupt sort of thing, it sounds more like what a Nick is describing as "doing something different."

What is the sketch going to do when this "interrupt" comes in? If it takes more than a handful of microseconds to do it, you probably don't want to be doing it in an interrupt -- you will run into problems if your interrupt service routine is to long, as it will affect serial communications, the millis()/micros() functions, and other existing interrupt based operations. And if your interrupt does what most interrupts do: set a flag that is checked by the main loop, then why not just check for the data directly in the main loop and skip the complication of an interrupt?

What is the sketch doing that takes so long that it can't poll for this event from Linux, which would be the normal way to handle a situation like this? If your main loop isn't repeating many times per second, perhaps you need to think about fixing that rather than looking at interrupts. Keep in mind that the TCP socket is relatively slow, and can take tens or hundreds of milliseconds to receive and process the incoming data. Does it make sense to go to the extra work of setting up an interrupt that can respond in less than a microsecond when the thing it reacts to has a timing uncertainty that is thousands or millions of times longer than that? It doesn't make sense to me.

If you are still sure you need an actual interrupt, there is a handshaking line between the two processors, which on the '32U4 side is connected to pin 7 of the shield connector. Set up that pin as an input with a pull-up and a pin change interrupt, then control that line on the Linux side. Some notes on doing that are here: How to access Pin 7 from Linux

But I strongly suggest you look at other ideas: unless you have a very unusual use case that you are not describing clearly, I don't think an interrupt is the right solution.

I would poll a value using bridge.get from the atmega. Id raise the flag from the linux side using bridge.put.

How fast should the atmega detect the flag?

I would poll a value using bridge.get from the atmega. Id raise the flag from the linux side using bridge.put.

I sometimes do that, depending on the data. It will work if the sketch is simply looking for a change in status. The problem with Bridge.put()/get() is that there is no way to know when a value has been written, so that if the same value is written again, it will never be noticed. Only changes in the value will be noticed. That means that if the sketch needs to know every time that a value has been written, it is necessary for the sketch to change/clear the value after reading it. The problem is that this is still not foolproof if the sketch doesn't read the value in time before it is rewritten, or if the value is written again between the time the value is read and then cleared. Bridge.put()/get() works well if it's a simple status value, and you only need to be concerned about the current value, and not anything that may have happened since the last time you looked.

If the value being communicated is more like a command or message, where every value is important and missing messages can't be tolerated (even if they are the same message as last time) then Bridge.put()/get() has some serious limitations. In that case, I prefer using the Mailbox class, which maintains a sort of queue of values, allowing the sketch to read each one in order.

However, the method I like to use the most is the Process class, with Process.runAsynchronously(). The sketch starts the Linux process, and when the process needs to send information to the sketch, it just prints it out to standard output and the sketch gets it using Process.available() and The advantage is less overhead (I think) and two-way communications. The disadvantage is that the data arrives in the same manner as a serial port, and you might not get a complete message at once, so it is necessary to buffer the data until a complete message is received, just like a serial port. Getting a mailbox message does not have that limitation.