This is not a question for beginners.

I am implementing a functional interface to an asynchronous serial device connected to the Serial1 port on a mega.

To ensure clarity, I want to implement a series of functions thus:

    {param} CallInterface({param1},{param2},...) {
        ....{await Response or timeout}....
        return Response;

Obviously, when "awaiting Response" we are blocking the operational thread and have to allow an additional thread processor access in order to retrieve and parse the response.

On a multithreaded platform, this would be trivial to implement using semaphores and other multi-threading techniques, but on Arduino,AVR the solution is possibly less obvious, or not.

So, the question is, what is the best and most effective way to implement a pattern such as this on the Arduino platform?

  • Obviously, when "awaiting Response" we are blocking the operational thread ... actually, that is not obvious ... you could use non-blocking code – jsotola Jul 27 at 4:08
  • 1
    It's hard to tell what's the “best and most effective” without knowing the exact requirements of your project. I once faced a similar situation when I needed my code to be non-blocking. I then added a “callback” parameter to CallInterface, to which the response is to be delivered, and an update() method to the object implementing the interface, in order for it to catch the response and deliver it to the callback. – Edgar Bonet Jul 27 at 6:12
  • @jsotola can you please follow this up with an example of a non-blocking code pattern That would work on the Arduino platform? – Mark Jul 27 at 6:45
  • @EdgarBonet Thanks Edgar, yes this is a similar model to Async Javascript / Node. Initial impressions are that I would need to implement a callback array in the receiver code to capture any and all potential requests for this data that need to be fulfilled when and if the response arrives. The only issue I foresee with this is that there is no "linkage" between the request and response other than the fact that the response happens soon after the request. – Mark Jul 27 at 6:54
  • There is no way of linking a specific request with a specific response other than to block requests until all pending requests are fulfilled, or a timeout occurs. – Mark Jul 27 at 6:54

The typical way I handle this kind of thing is to have one "master" function that controls everything using a finite state machine in a non-blocking way.

That function could contain all the logic to do things, or it could be simpler and just handle the basic communication and then pass details on to a callback function that is specified in the action function call.

So the flow could be:

  1. You call a function that just sets up things:
  • It stores details of the request to be made
  • It records the address of a "callback" function
  1. You execute your "run" function repeatedly from loop()
  • It sends the command to the target
  • It receives and parses the response storing it internally somewhere
  • When the response is complete it executes the callback function passing it the response

Not all of 2 would happen each iteration of loop(), so write it in a non-blocking way (using .available() etc) and only call the callback when everything is complete.

So in that way you can set up a chain of things to happen:

  1. You submit request 1 with callback A.
  2. Callback A submits request 2 with callback B.
  3. Callback B submits request 3 with callback C.

... etc ...

As an example this is how a modem control could look:

Modem.command("AT+CREG?", testRegistration);
>>> send         AT+CREG?
<<< store        +CREG: 0,2
<<< store
<<< identify     OK
--- Execute testRegistration(true, "+CREG: 0,2\n\n");

Or maybe if it goes wrong:

Modem.command("AT+CROG?", testRegistration); // Oops, made a typo...
>>> send         AT+CROG?
<<< identify     ERR
--- Execute testRegistration(false, "");
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.