Strings received through Bluetooth

I have an issue, i made a microvoltmeter as a project and since I want to go to a competition with it i want to also make an app.
The problem is I don't know how to make the strings of information I receive show nicely
There always come happens an waterfall effect and the information on sceen keeps changing places.
This is how it starts


And then it goes like this

My block is looking like this

I would need help to fix it for tomorrow presentation

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.

Specific advice:

Counting bytes is a risky approach, because you will fall out of sync soon as message lengths change and you enter conversations in the middle.

Use commas between your data pairs, and use \n only at the end.
Then use \n (ASCII 10) as your message delimiter.

When you have a complete message in a global variable, run it through a text Replace block to replace commas with line feeds (\n).

If your message length is longer than can fit in a single message, send them individually and sort them out by their identifiers.

Hey, on the code println() is at the end of each of my lines that i need to be sent and shown on the application
Made the changes on delimiter for my Bluetooth client
As for everything else I am not sure I understand how to do them exactly, I am not experienced at all with those things
If you could provide me some guidance i would greatly accept it

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

BlueTooth_delimiter_sample.aia (3.4 KB) global message

The preceding post is for comma delimited long messages.

If you insist on sending single data per line, you would need to assign eight labels, one per named datum, and send the incoming global message through an eight rung if/then/elseif ladder checking if the message should be dropped into which label text

Use the blue mutator control on the if block to add rungs.

Test if message contains 'i1:' for labeli1...

Hey, the situation is like this, i don't really know what to do so i implemented what you gave me, it works the app does not crash anymore and it changes nicely buuut it does it all only one first line, all the messages that are sent are going in the first label...

This is how my blocks look like atm
I am sorry for burdening you but it's been troubling for a while and i don't know how to do it
I also did not know how to get all the blocks you showed there but thanks for the file i managed to make use of the backpack

Dear @Cho0coCheese, the blocks you've posted aren't actually applying what @ABG has suggested.
As he said, if you transmit each data with a println(), each transmission ends with the Linefeed, therefore the split at "\n" will only generate a list with a unique element (the received data) and therefore the block "min" will have always a "1" in the list of items, thus always showing the data in the first label.
What he said is to transmit the whole pattern of data, each one separated by a "," (comma), and ended only once with a \n . In other words you can do:
BT.print(data1);
BT.print(',');
BT.print(data2);
BT.print(',');
........
BT.print(data7);
BT.print(',');
BT.println(data8);

So only after having received the last data, sent by means of a println(), the BTclient will stop receiving, and the split at ',' block will do its job. Otherwise if you transmit each data with a println(), each data will end with a \n and you will have to fill 8 separate labels each one related to a specific data. But, to obtain a correct addressing between data and its label, you'd better add in the transmitted data also its ID (like i1data1, i2data2, ...i8data8) and an if/then/else loop has to be used to perform the correct labels' assignment . (I'd rather suggest you to use the first approach)

Hoping this would help you.

1 Like


Ok so I really am stuck here, this is how my blocks look like

This is what my app looks like, it only shows the first row which changes the values one by one

This is what I want my app to look like. I am sorry if I am bothering you, but this is the first time I'm trying to make an app, and due to my deadline for tomorrow when I have to present it in a competition I am really starting to panic :')
It does not matter if the text is written only on one label, I only want it to show my values one above the other, like it shows in the screenshot above

(Canned Reply: ABG- Export & Upload .aia)
Export your .aia file and upload it here.

export_and_upload_aia

.

Also upload your latest sketch .ino

Testcontinuarea.aia (290.9 KB)

cod ArduinoIDE comentat.txt (11.9 KB)
Here is the code, i don't have the sketch file because one of the colleagues i am going with made it and this version is before he corrected the incorect value shown on A2

So you are sending one line per reading:


//10. Bluetooth Communication
void sendNextBTChannel() {
  if (Serial.availableForWrite()) {
    // Trimite toate datele indiferent de mod
    Serial.println("Tensiuni");
    
    if (abs(averages.a0) >= 1000000) {
      Serial.print("A0: ");
      Serial.print(averages.a0 / 10000000.0, 4);
      Serial.println(" V");
    } else if (abs(averages.a0) >= 1000) {
      Serial.print("A0: ");
      Serial.print(averages.a0 / 10000.0, 4);
      Serial.println(" mV");
    } else {
      Serial.print("A0: ");
      Serial.print(averages.a0 / 10.0, 1);
      Serial.println(" μV");
    }
 /*   if (abs(averages.a1) >= 1000000) {
      Serial.print("A1: ");
      Serial.print(averages.a1 / 10000000.0, 4);
      Serial.println(" V");
    } else if (abs(averages.a1) >= 1000) {
      Serial.print("A1: ");
      Serial.print(averages.a1 / 10000.0, 4);
      Serial.println(" mV");
    } else {
      Serial.print("A1: ");
      Serial.print(averages.a1 / 10.0, 1);
      Serial.println(" μV");
    }
    if (abs(averages.a2) >= 1000000) {
      Serial.print("A2: ");
      Serial.print(averages.a2 / 10000000.0, 4);
      Serial.println(" V");
    } else if (abs(averages.a2) >= 1000) {
      Serial.print("A2: ");
      Serial.print(averages.a2 / 10000.0, 4);
      Serial.println(" mV");
    } else {
      Serial.print("A2: ");
      Serial.print(averages.a2 / 10.0, 1);
      Serial.println(" μV");
    }
    if (abs(averages.a3) >= 1000000) {
      Serial.print("A3: ");
      Serial.print(averages.a3 / 10000000.0, 4);
      Serial.println(" V");
    } else if (abs(averages.a3) >= 1000) {
      Serial.print("A3: ");
      Serial.print(averages.a3 / 10000.0, 4);
      Serial.println(" mV");
    } else {
      Serial.print("A3: ");
      Serial.print(averages.a3 / 10.0, 1);
      Serial.println(" μV");
    }
 */   // Curenți
    Serial.println("Curenti");
    Serial.print("i1: ");
    Serial.print(averages.current1, 3);
    Serial.println(" mA");
    Serial.print("i2: ");
    Serial.print(averages.current2, 3);
    Serial.println(" mA");
    Serial.print("i3: ");
    Serial.print(averages.current3, 3);
    Serial.println(" mA");
    Serial.println(" ");
  }
}

Your aia will need to reflect that, if you have no control over the input.

Yes it sends one line per reading
Could you show me how can i make my aia reflect that?


Testcontinuarea (1).aia (291.3 KB)
explanation in next post.

I set up a dictionary mapping message prefixes (part before the ':') to Labels.

Yours were scrambled, so I leave it up to you to unscramble them.
Shame you didn't name them.

Each incoming message is sent to be split at ':' to a modifies procedure:

The incoming split character is a ':', so by splitting the message at ':' item 1 is the part to use as lookup key into the dictionary of Labels.
You probably want an extra Label to catch messages that don't have a ':' or have a key not in the table, for CYA.

1 Like

Thank you very much
It's midnight, i hope i will be able to get to it in the morning...... I apologize for being slow and having you come back multiple times here....