Does "if (radio.available)" wait for a message

If I have

void getData() 
{
  if ( radio.available() ) 
  {
      radio.read( &dataIn[0], sizeof(dataIn[0]) );
  }  // end if (radio.available

}  // end getData

is there any way to make the code execution pause until a data item is received?

while (radio.available() == 0)
    ;

Regards, Ray L.

Hi Ray

I am a bit confused here.

Do you mean

while ( radio.available() == 0) { radio.read( &dataIn[0], sizeof(dataIn[0]) ); } // end while (radio.available

or

while (radio.available() == 0) delay(50); radio.read( &dataIn[0], sizeof(dataIn[0]) 0;

The second one but the delay is not necessary. Why would you wait? There is no harm going to check again right away. If not you’ll have lost 50 ms.

At 115200 bauds, 50 ms is enough to receive 576 characters and the incoming buffer is 64… so it’s a really bad idea, you are at risk of loosing data in an overflow depending how this is managed and if the sender stop sending or not

So just

while (!radio.available())[color=red];[/color] // note the ';' -> means no instruction. Just loop until you receive something

In English that reads as keep checking while nothing is available.

Not sure why you have a stray 0 at the end of your line - I suppose you meant to type the closing bracket and forgot to press shift :slight_smile:

J-M-L: Not sure why you have a stray 0 at the end of your line - I suppose you meant to type the closing bracket and forgot to press shift :)

You're on it! :)

vagulus: is there any way to make the code execution pause until a data item is received?

If you are planning any non-trivial program I suggest you don't use blocking code. Get the function that checks the radio to set a flag (e.g. newData = true;) when data arrives and have your other code check that value before doing other stuff that depends on the arrival of data.

The flag concept is illustrated in the 2nd and 3rd examples in Serial Input Basics. But note that when radio.available() is true it means that the entire message has been received (at least it does with the nRF2401+ modules).

...F

Hi again robin2

Actually, I am still using the code we worked on a month or so ago. I call getData() in line 676 in Trolley.ino. Console receives the command sent in line Trolley(670) but the Trolley program does not wait for the response (which can be some seconds) - it prints the warning Trolley(688) and calls approachEnd().
It is essential that Trolley waits for the response. That’s the problem with waiting. I was hoping that Trolley(674) would make it wait. Sadly, I have a hardware problem (I have been forced to shift the equipment around too often and something went haywire this afternoon) and I haven’t had a chance to test the sequence. I’ll be very interested in your thoughts though.

Cheers

Console.ino (8.09 KB)

Trolley.ino (14.2 KB)

At 115200 bauds, 50 ms is enough to receive 576 characters and the incoming buffer is 64… so it’s a really bad idea, you are at risk of loosing data in an overflow depending how this is managed and if the sender stop sending or not

Of course, that has nothing to do with getting data from a radio object.

Wanting the Trolley to do nothing (I assume you mean "don't move") while waiting for a message is not the same as wanting the Trolley's controller to do nothing while waiting for a message.

Even with no requests from the Console, you can have the controller busy itself with periodic diagnostics such as:

1) Connection maintenance communications, so the console and trolley can detect if the other goes offline. 2) Power voltage check 3) Functional testing the ultra-sonic sensor to make sure it still works properly.

I have had a quick look at your Trolley.ino - it has grown a lot from the last time and I can't easily understand how all the bits work together.

You have a call to getData() in loop(). Why have you another call to it in travel(). That is poor program design - once is enough. Read, again, what I said in Reply #5

Also you should not use WHILE as it blocks things.

In fact I would not use WHILE anywhere in a program like yours if the WHILE takes more than a few microseconds to complete.

...R

Jiggy-Ninja: Wanting the Trolley to do nothing (I assume you mean "don't move") while waiting for a message is not the same as wanting the Trolley's controller to do nothing while waiting for a message.

Thanks Jiggy-Ninja

This is a simple project, and the only function of the Trolley is to move down a track to a turntable; Console controls the rotation of the turntable; then the trolley moves off on the other track (process is repetitive). Because of this simple focus, I am not worried about wasting CPU time while the trolley is stationary.

Robin2: You have a call to getData() in loop(). Why have you another call to it in travel().

Hi robin2 Let's have a look at the program.

loop() 1. establishes radio link 2. receives 'start' signal from Console 3. control shifts (eventually) to the loop in runTrolley()

runTrolley() 1. calls travel() on the way out 2. calls travel() on the way back

travel() 1. calls approachTT() which runs the trolley to the turntable 2. signals Console that trolley is on table -- Console turns the TT -- Console signals travel() that TT is now realigned 3. calls approachEnd() which runs trolley to end of the track.

Now, the problem is to make the trolley wait on the TT until the rotation of the TT is complete. It is not acceptable that the trolley goes running off while the turntable is still moving. Currently, as the program executes (without trolley(678) at trolley(694) 1. the turntable is still moving 2. the trolley is not accelerated but control still passes to approachEnd().

How would you ensure that the trolley waits until it is safe to move off?

Also you should not use WHILE as it blocks things.

In fact I would not use WHILE anywhere in a program like yours if the WHILE takes more than a few microseconds to complete.

Robin2, you seems to have very simplistic and distorted view on software programming by publishing things out of context thus openly violating your own motto "not to confuse beginners".

"while" is one of the basic language construct and this "blocking is a bad thing" keeps popping up all the time without knowledge why is it used, just because.

If you are serious in your teaching role than I would suggest you retract both of these gems. However, you do what you feel is appropriate. I am outa here. Jim.

@julyjim

In fact I would not use WHILE anywhere in a program like yours if the WHILE takes more than a few microseconds to complete.

I think there is a contextual point in Robin's statement that narrows down his comment to a specific use case scenario and guidance of when it would be acceptable even in this case - all in one sentence

@PaulS

Of course, that has nothing to do with getting data from a radio object.

I'm not sure I get that one.

vagulus: How would you ensure that the trolley waits until it is safe to move off?

Use the concept of the "State Machine" for that sort of thing. When the trolley moves onto the turntable and the table is ready to turn set a variable (tableMoving = true;) and then don't allow anything unpleasant to happen until that variable is changed back to false when the table has stopped and the trolley is safe to move.

"State Machine" is a fancy name for a very simple concept of using variables to keep track of what mode the system is in. For example, in Reply #5 I mentioned a variable to record when data has arrived.

This concept also makes it easy to use loop() as the principal iterative process in the program.

...R

J-M-L: @PaulS

I'm not sure I get that one.

You commented on how many characters are received during a 50 millisecond delay, quoting data about the serial baud rate and serial buffer size. The radio is not a serial device and does not have a baud rate, so the observations were useless.

Hi robin2

I like the State Machine concept. It seems a simple solution relative to the complexity of two-way radio communication.

Robin2:
When the trolley moves onto the turntable and the table is ready to turn set a variable (tableMoving = true;) and then don’t allow anything unpleasant to happen until that variable is changed back to false when the table has stopped and the trolley is safe to move.

However, does that not mean that I will still need a busy-waiting loop to await the change of state of “tableMoving”, ensuring the trolley remains stationary until the table has stopped and the trolley is safe to move? Perhaps something like " while (tableMoving); " ? Would this not still inhibit the use of the otherwise unused CPU time as suggested by Jiggy-Ninja a few posts back?

I was thinking that " if (radio.available) … " did that pausing in some mystical way, but I see in Console(232) that I have once again used a while loop to keep Console waiting for messages from Trolley. Obviously, I have a lot to learn about two-way wireless telegraphy.

PaulS: You commented on how many characters are received during a 50 millisecond delay, quoting data about the serial baud rate and serial buffer size. The radio is not a serial device and does not have a baud rate, so the observations were useless.

Right OK - got it.

I was commenting on the general question in the thread "Does "if (radio.available)" wait for a message" - I was missing context about the underlying "radio" object technology - bluetooth and wifi are radio signals that are often interfacing through Serial for example

Indeed checking the code he posted afterwards, does not apply to nRF24L01 and SPI

One way might be to remove some intelligence from the trolley

It looks like you've got an ultrasonic distance sensor on the trolley that is able to detect its position on the track. Rather than having the console send a "move to turn table" command and requiring the trolley to know the location of the table, you can have it send a "Move to position XXXX" command (maybe with other details like a set speed), and the trolley moves there and stops until it receives a new command. The trolley doesn't need to care about any details of the turn table or anything else on the track, it just follows the marching orders of the console and nothing else. It may also be beneficial to have some way for the console to query the trolley for it's position, or have the trolley period send status packets to the console with that info.

Basically, the sequence would go:

1) Console says "Move to XXX position" which is on the turntable. 2) Trolley moves to XXX and responds "I'm here!" 3) Console spins turn table 4) Console says "Move to YYY position" which is off the turntable.

You get the idea.

Another way can be to let the console micromanage the trolley even further. Move the distance sensor to a fixed point on the end of the track so it gets the reflection off the trolley and is controlled by the console. That way the console always knows the location of the trolley, and it can send it "Move forward" and "Move backward" messages at intervals. Maybe it transmits the command every 50 ms, and if the trolley doesn't get a move message for 100 ms it stops on it's own.

Rather than spreading the intelligence out between the trolley and console, make your console the high-level mastermind and the trolley just a dumb slave that follows orders.