Is there something like attachInterrupt() for internal interrupts?

I'm a software developer who has recently become interested in the Arduino, and now I'm trying my hand at interrupts.

A decent exercise in this area, I figured, would be to write some interrupt-driven code to handle a string of HC-SR04 ultrasonic transducers. I figure I can have each one of them attached to a ring buffer, and round-robin them in the background. Foreground code can then grab copies of the ring buffers whenever needed.

If you haven't worked with the HC-SR04 before, the deal is that you pulse its trigger pin for 10us, and then wait for a pulse from its echo pin, measure the length of that pulse, and derive distance-to-obstacle proportionally.

Since I have many transducers and only two external-interrupt pins, I figured I'd put a multiplexer between the HC-SR04s and pin 2.

So this is what I think I want to do, simplified and in pseudocode, for just one transducer, assuming that somehow we can get an interrupt to kick this all off:

Set trigger pin HIGH
Set alarm for 10us on ISR B

Set multiplexer on pin 2 to listen to correct echo pin
Set trigger pin LOW
Set watch for pin 2 to go HIGH on ISR C

Start timer
Set watch for pin 2 to go LOW on ISR D

Stop timer
Set to ignore activity on pin 2
Compute distance 0-255, apply to ring buffer
Advance pointers and whatnot to next transducer
Set alarm for whatever portion of 50ms has not yet elapsed on ISR A

I figure I can use something like this to get 20 readings per second, or 20 / n readings per second from each of n transducers. (My thinking is that pulsing more than one at once might cause crosstalk. Plus, it'd be hard.)

But to do this, I'm going to have to point Timer 2 at a succession of different ISRs--most clearly ISR A and ISR B, but I'm also planning to use it to time out the other steps if needed. That means I can't use the ISR() macro, because it's a compile-time thing.

I'm sure I can use absolute memory pointers, if I have to, to waller around with interrupt vectors, but is there an easier, prettier way to do this? Or perhaps there isn't, because nobody who really knew anything about interrupts would even think of approaching it this way?

So, you are trying to re-invent NewPing?

Perhaps looking at NewPing would provide some clues.

Never heard of NewPing. Not really trying to invent anything, just trying to get a handle on how interrupts work. In Arduino, that is--I already know how they work underneath.

Okay, found NewPing.

No, I'm not trying to reinvent it. First, it doesn't queue responses per transducer. Second, since each transducer gets its own echo pin, I'll bet dollars to doughnuts (although I haven't found the source code yet) that it polls for the response pulse, rather than having it trigger a pair of ISRs to start and then sample the timer.

And that second point means the it doesn't have to do what I'm trying to figure out how to do--that is, swap ISRs around internal interrupts like wives at a swingers' convention.

So I'm thinking it won't be a great deal of help.

Does the Arduino variation of C++ represent a function pointer as a byte pointer or a short pointer? Do you know?


Not having found what I'm looking for, until something better comes along I'm going to try this and see how it works:

void(*next_TIMER2_COMPA_isr)() = NULL;
void(*next_INT0_isr)() = NULL;

  next_TIMER2_COMPA_isr ();

ISR (INT0_isr) {
  next_INT0_isr ();

Now I can change next_TIMER2_COMPA_isr and next_INT0_isr to point to anything I want, and I've got almost the same effect as what I was looking for, except it's harder to read and uses more stack space and CPU cycles for the call and return.

Second, since each transducer gets its own echo pin, I'll bet dollars to doughnuts (although I haven't found the source code yet) that it polls for the response pulse, rather than having it trigger a pair of ISRs to start and then sample the timer.

A "library" for the Arduino consists of a header file and a source file. It may also (and does, in this case) include examples and a keywords.txt file.

It's difficult to believe that you found the NewPing library but can't find the source code to look at.

I looked at the documentation on the web page, and didn't immediately see the Download link in with all the others.

(I've never used a separate Arduino library before.)

Eventually I found it, downloaded it, looked at the source, and discovered that my surmise from the documentation had been correct: there's polling in there, and delays. (Maybe I should have written a "Yep, I was right" post, but it seemed superfluous.) NewPing doesn't do what I want to do.

But I'm plodding on.

Right now, I'm sorely missing a TDD framework. Over 180 lines of code, and not a single test to demand any of it into existence. I have an emulator partway done--the sort of thing automated tests in, say, Google Test could use to demand code, but microcontrollers are awfully complex to emulate, what with all those pieces and parts in there. Just emulating the USART took me a solid two weeks of spare time.