By "timing loops" do you mean loops that create a delay by just wasting time?
Yes, it does have one that is used to create a 200ms delay to prevent BT write messages from overloading the Arduino serial read buffer.
There are also 3 clocks that are used to trigger other program tasks.
When a clock-triggered task is running, I've tried disabling the other clocks, but I forgot about the 200ms delay routine. That may be the key to solving the problem.
Thanks for the question.
That shouldn't be the issue...
Do you use while or for loops?
It would really help if you provided a screenshot of your relevant blocks, so we can see what you are trying to do, and where the problem may be.
To get an image of your blocks, right click in the Blocks Editor and select "Download Blocks as Image". You might want to use an image editor to crop etc. if required. Then post it here in the community.
Taifun
Trying to push the limits! Snippets, Tutorials and Extensions from Pura Vida Apps by Taifun.
If you export the aia and upload it. I can take a whack at it.
Here is a picture of what I think are the relevant blocks. The timers are BT_timer at 500ms, Command_timer at 1000ms, and SpeedSender at 200ms.
All timers are initially disabled so that they don't cause any trouble while the BT client is started.
The delay routine is only called by the loadAllParam procedure, which sends 6 short messages via BT. The delay allows the Arduino which receives the messages to process them without overloading the buffer. One message will not overload the buffer, but all 6 at once certainly could. Without the delay the later messages corrupt the buffer. The "isn't responding" message does NOT occur while loadAllParam is executing.
The other timer routines have some disabled blocks, which I was disabling in an effort to disable other timers while a timer routine was executing, to try to prevent timer calls from interfering with each other.
- I'm not sure I understand why this should cause a problem. If another timer event occurs during the delay, will it not just be queued, then executed when the delay is over? Why should this result in an"isn't responding" message? Especially because the delays aren't that long. Moreover, if the other timers are disabled during the delay, shouldn't this prevent any interference?
I guess my question really comes down to: How tied up must the queue or delay be to cause the app to consider itself unresponsive, so that it sends me the "isn't responding" message? Recall that my app is NOT locking up and being unresponsive. It's running in the background all the time.
- Another detail that is not explained anywhere: In the delay routine, I assume that Command_timer is running all the time, even if disabled and not triggering timer events. In that case, I should be able to call the GetMillis and Now methods at any time and get a valid result. Is this assumption correct?
This is deeper into Android than I have delved.
A Google search on your app symptoms found wide spread complaints
https://www.reddit.com/r/AndroidQuestions/comments/15o8469/comment/mqvdw1f/
It's not just an AI2 problem.
Are you also receiving some information from the robot? Please provide some relevant blocks of that
Taifun
Yes, I am receiving information from the robot. I have a dialog that displays all the messages, and that works fine, even when I get the "isn't responding" message.
However, I think the problem has been solved, and from an unexpected source. When I establish the BT link, I was using this block to do it:
For the Connect call, I must have been thinking in C, where a TRUE answer satisfies the IF statement.
It seems AI2 requires an explilcit comparison with TRUE to work.
I changed the block to this, and that seems to solve the problem. I've run the app several times with this block, and the "isn't responding" message has not reared its ugly head.
Thank you to everyone who tried to help anyway.
No; that's not necessary
What happens in procedure read_incoming_msg and interp_cmd?
Also you could try a delay of only 100ms...
Tsifun
I believe I tried a 100ms delay before, but it sometimes wasn't enough.
I've included the read_incoming_msg and interp_cmd routines, but they're pretty straightforward.
Good luck with them.
you are using several while loops in that procedure and my guess is, the issue is coming from there
reading an incoming message does not need to be so complicated...
let me ask @ABG for an example of a simple solution... sorry, I currently do not have much time to prepare something...
Taifun
I see you are nibbling away at the Bluetooth input buffer one character at a time in a laborious attempt at grabbing complete messages.
It's much easier to use \n message delimiters.
Here's standard advice...
Be sure to use println() at the end of each message to send from the sending device, to signal end of message.
Only use print() in the middle of a message.
Be sure not to println() in the middle of a message, or you will break it into two short messages and mess up the item count after you split the message in AI2.
Do not rely on timing for this, which is unreliable.
In the AI2 Designer, set the Delimiter attribute of the BlueTooth Client component to 10 to recognize the End of Line character.
Also, return data is not immediately available after sending a request,
you have to start a Clock Timer repeating and watch for its arrival in the Clock Timer event. The repeat rate of the Clock Timer should be faster than the transmission rate in the sending device, to not flood the AI2 buffers.
In your Clock Timer, you should check
Is the BlueTooth Client still Connected?
Is Bytes Available > 0?
IF Bytes Available > 0 THEN
set message var to BT.ReceiveText(-1)
This takes advantage of a special case in the ReceiveText block:
ReceiveText(numberOfBytes)
Receive text from the connected Bluetooth device. If numberOfBytes is less than 0, read until a delimiter byte value is received.
If you are sending multiple data values per message separated by | or comma, have your message split into a local or global variable for inspection before trying to select list items from it. Test if (length of list(split list result) >= expected list length) before doing any select list item operations, to avoid taking a long walk on a short pier. This bulletproofing is necessary in case your sending device sneaks in some commentary messages with the data values.
Some people send temperature and humidity in separate messages with distinctive prefixes like "t:" (for temperature) and "h:" (for humidity).
(That's YAML format.)
The AI2 Charts component can recognize these and graph them. See Bluetooth Client Polling Rate - #12 by ABG
To receive YAML format messages, test if the incoming message contains ':' . If true, split it at ':' into a list variable, and find the prefix in item 1 and the value in item 2.
More, with blocks...
Here is a simple BlueTooth text receiver sample, for single value per line:
More complicated, multiple values per message...
Here is an updated blocks sample illustrating these ideas ...

I read the incoming message character by character. I have had problems in the past with corrupted messages, so I have found that this procedure, though tedious, is necessary to weed out corrupt characters and messages. The while loops do not impose a time delay. They are part of the logic to determine whether to continue reading more characters from the buffer.
After more exploration, I believe the problem occurs when the BT connection is being established. Sometimes it seems to take longer than others, and this is when the "isn't responding" occurs.
The "isn't responding" always seems to occur during app initialization. If it doesn't happen then, it never happens. I believe it is part of the BT connection initialization.
For your information, here is the BT initialization routine. After some rejiggering, this one seems to work every time, and does not cause "isn't responding" messages.
Yes, but the while loop waits until something happens... and if that does not happen in a reasonable amount of time you app gets unresponsive
Your screenshot looks fine, we now are not able to find out your issue anymore, but that's ok
As mentioned earlier you do not have to compare a boolean value with true
If Connect ...
Then connected
Else not connected
Taifun
I've discovered that the problem is NOT yet solved.
I've also concluded that the problem doesn't appear to be with any of my code, but rather occurs during the app initialization.
Since the app is event driven, I presume that screen initialization is the first thing that occurs.
I've programmed the app to deliver a diagnostic message to a text box when screen initialization begins.
I've noticed that there is a several second delay between when the app screen appears and when the diagnostic message shows up. This delay is not always the same.
When the delay is long, that is when the "isn't responding" message appears.
Maybe my phone is busy doing something else, although I have no other active apps running.
Maybe there is something about my app that requires a lot of background computation (although my app only has buttons, labels, text boxes and a sprite).
At any rate there is no code running when the "isn't responding" message appears, so I am at a loss to find a solution.
If anyone has any idea what's going on, I'd like to hear it.
What happens when an app starts?
What happens between when the screen appears and the app actually begins executing code?
Here is the initialization code.
As I said, there is a delay of a few seconds between when the app screen appears and the "Begin screen intialization" message appears.
Who knows what happens during that time?
Something in that period is what is causing the "isn't responding" message to appear.
It doesn't happen every time, but often enough to be very annoying, and once it appears, it keeps reappearing, even though the app is running fine.
the Screen1.Initialize event is the first event which will be executed
However what happens might not what you expect to happen, read more about it here
you expect to get the "Begin screen initialization" message directly at the beginning, but this is not the case... you get it after BT_autoConnect has finished
which means, we have to look at your procedure BT_autoConnect
Taifun
You might find it helpful to move that bt connect procedure call out of screen1.initialize into a one shot immediate clock timer enabled at the end of screen1.initialize.
Leave word in a Label that the connection attempt has started, before enabling the timer.
This takes slow processes out of the foreground thread
I have read that article, but it does not explain what is happening to me.
The screen initialization is the first thing that happens, and it executes step by step.
The following excerpt from a screenshot shows the diagnostic messages from the app. The most recent messages are at the bottom of the list.
You can see the first one is about screen initialization.
The messages are ALWAYS in this order.
[The lines beginning with '>' are messages sent from the app to the robot. Lines beginning with '<' are messages received from the robot.]
The timer events are not enabled until AFTER the BT client is connected. Therefore, they cannot be causing any delays before screen initialization. The app has no events that would initiate any other app activity until AFTER the BT client is connected.
NOTHING in my code gets executed until after screen initialization. That is why I am mystified as to why there is such a delay between when the screen appears and the "Begin screen initialization" message.
Once the BT connection is made, the app runs fine, with or without the "isn't responding" messages. The IR message only appears if there is a long delay between the app screen appearing and the beginning of the initialization routine.
Just for completeness, here is a screenshot of the app. It's just buttons, lables, and text boxes. The red dot is a sprite that can be dragged around to control the robot. But I never touch the screen until the BT connection is established.
Please provide a screenshot of that procedure
This is the relevant part
Any GUI changes during an event handler are not displayed until the event has completed.
So the "Begin screen initialization" message gets displayed after BT_autoConnect has finished
To get what you expect (i.e.first display the message, then do the processing) you have to use a clock as @ABG already explained
Taifun