Serial triggered interrupt handler/ editing HardwareSerial in core

Hi all,

So a little project backrground; I'm building a sensor which uses the arduino nano. It provides data to an application on my PC over serial. My sensor has two modes of operation and I would like to be able to toggle between them with a serial message triggered by my external application in a sort of closed loop system.

I guess the obvious answer for the arduino to register this message and switch modes would be using a SerialEvent. However, my thinking (could be wrong), is that this isn't ideal because one of the two modes is intended to be high bandwidth, so ideally I don't want to be jumping out of the main loop after every iteration to check the input buffer. And also I suppose I would have to have an if statement or switch/case sort of setup in main loop, which would presumably also lower the frequency...?

I have a read that it's possible to adapt the core code, specifically HardwareSerial.cpp so that instead of putting incoming bytes in the input buffer the interrupt handler can do something else. If I can set this up so that it switches the mode upon the interrupt I'm thinking I could essentially have the two modes operating and synchronously receive a signal from my pc to switch between them thus not compromising speed at all.

Is this feasible? I'm imagining there may be a problem in that the interrupt routine wouldn't be just a quick operation and it would need to looping continuously, I would then also need to be able to get out of the routine upon another signal from the PC...

Does anybody have any advice on the best way to go about this sort of thing?

Best,

Nick

if(Serial.available()){ is not slow. I've never timed it, but I expect it's under a microsecond. Just use it like it's supposed to be used.

I don’t want to be jumping out of the main loop after every iteration to check the input buffer.

Yes you do. But you do this in loop, so there’s no “jumping out of the main loop”.

Writing Arduino sketches is more like this:

balancing plates.jpg

The things you need to do are like the plates. loop keeps all your plates spinning. It takes a little time to walk down the line, and the time spent on each plate may vary a little, but they all get “serviced”. There is no OS on the Arduino to keep things running in “the background”, so it has to keep checking each thing it has to do.

As you do more advanced projects, you may run into a case where loop doesn’t get to one of the tasks soon enough (i.e., a plate drops). For example, using delay or a while loop keeps your sketch stuck on one of the tasks. Lots of libraries do this. :stuck_out_tongue: Plates be droppin’!

Another mistake is printing too much stuff. At 9600, each character takes about 1ms to transmit. Serial has an output buffer that can hold on to 64 characters. When you print something < 64 chars, the first one starts getting transmitted and the rest are saved in the output buffer. Then it returns from Serial.print to do the next thing in your program. About 1ms later, while loop is spinning those other plates, a transmit interrupt occurs. That “guy”, the MCU, hops over to the output buffer and starts sending the 2nd character, a very quick process. Then he goes back to whatever he was doing in loop. Plates keep spinning.

However, if the output buffer already has 64 characters in it from previous prints, Serial.print has to wait for some of the characters to be sent before it can put the new characters in the output buffer. Essentially, it will delay for 1ms/char. Plates be droppin’!

The same thing can happen with a library call (or your code). If the library stays in a while loop, waiting for something to happen, it doesn’t return quickly so you can see if a command came in on the serial port.

Take a look at the General Design topics on the Useful Links page.

HTH!
/dev

Ah thanks for the advice. All very useful information. I think my curiosity sort of got the better of me and I was kind of just interested to see how to use the input buffer interrupt in HardwareSerial to asynchronous stuff. It seems that in loop checking of the input buffer is going to be good enough for what i need to do.

Cheers,