Bluetooth receiving data(text) to app from Arduino

Screenshot 2023-08-22 213342
Screenshot 2023-08-22 213250



Hi,
I have a project to do: send and receive data (text, numbers).
Sending part is done as only two values need to be sent, which is easy because it is only two(picture).
But the problem is with receiving part, as it is a random number of values (at least only 1 or 0 ), let's say from 5 to 25 or more, depending on an operator,
I question which way I can receive data ( as in the picture ) and not index them separately, receiving data accordingly to the time received from the Bluetooth(instead of indexing them one by one as in the picture).
Many thanks

Show how you are sending the data from your sketch?

Screenshot 2023-08-23 143957
Hi, the first part (3 values) are real results, and the other 3 are just numbers.
Thanks

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.
BlueToothClient1_Properties
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.

Here is an updated blocks sample illustrating these ideas ...

BlueTooth_delimiter_sample.aia (3.4 KB) global message

1 Like

Sorry for late response,firstly Thanks for help I'm far away in MIT inventor,very beginner.I will try to use your suggestions tomorrow,but do u know why now showing this error ?.befor works normally, but now, for some reason started showing those results in array.? thanks

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.
BlueToothClient1_Properties
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.

Here is an updated blocks sample illustrating these ideas ...

BlueTooth_delimiter_sample.aia (3.4 KB) global message

Hi, I tried to use this model, but not working, see attachment, I just wonder do I need to initialize the table to set Bluetooth client in sted of screen 1.I attached my code and copy of my app
project3005.aia (178.7 KB)
sketch_sep2a.ino (12.2 KB)
thanks for help

You reversed two parameters:


Instead, you need

ABG,
I am still working through understanding how your blocks are parsing the delimited data to the variables. I am not sure I yet have it clear (but getting there)
I am using some Micropython code on a RP2040/HC-05 and am repeatedly sending the following comma-delimited set of two values (r1 and p1) on about a 250mS interval, using this code;
uart0.write(str(r1) + "," + str(p1) + "\r\n")
I know this is being sent correctly, as Serial Terminal shows it as (for example)
0.4,1.0
10.2,0.9
0.5,35.4
etc
etc
The two string values can each randomly change from 0.0 to (approx) 70.9.
i.e.
0.7,12.8
23.4,0.7
0.3,0.9
42.3,1.2
etc
etc
I send them as these two string values with the comma delimiter so that I always know which is the first and second value - because they can wander randomly. The \r\n provides an end of dataset break for every transmission of the two values.
When I use your example, my first label text value is over-written immediately and is blanked out. The other two fields remain as their default and dont get changed. I presume I need to add a capture for the \r\n characters that signify an end of the data packet? Or am I missing something else (like a received data buffer overflow perhaps?
I havent modified your demo blocks, they are as per your last message above, so I havent attached mine here. TIA for some guidance while I work through your demo to (better) understand it.

Working through things I tripped onto the issue.
I had "Secure" selected in the Bluetooth Client settings.
De-selecting this solved the issue.
All works OK now, with the delimiter character set at "10" triggering the end of bytes capture in the .ReceiveText block correctly by seeing the LF.
Now I just need to become 100% with understanding your blocks, but they work OK for me now. Thanks.

[Solved]
Where would I find the 'set Label.Text of component to' block. I have similar dark green blocks for any of my Labels but I cannot find this block that you have used anywhere in MIT App Inventor or the guide. I know it is associated to 'Label' because of the dark green color, and I found a 'set Label.Text' block with a single socket, but that is about as close as I can get. TIA.
[I found it under 'Any Label']

It's an Any (Generic) block.

You can get it in two ways:

  • From the Any Component branch of the Blocks Pallette in the Blocks Editor
  • from an existing Set Labeln.Text To block by right clicking on its Make Generic option.