BluetoothClient how do you send a character followed by a byte?

BluetoothClient how to send a character followed by a byte?
My code:

Post your sketch and your exported .aia file.

To associate incoming messages with stuff you just sent from your app, use a global variable to store that value ('A'?) for use by the Clock Timer that accepts responses.

Do not expect immediate responses in the same event where you sent the 'A'.

In the meantime, read

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.

...

ProiectStefanArduino.ino (6.6 KB)
ProiectFinal.aia (270.2 KB)

On Automat I want the fan speed to be automatically set by the temperature conditions read from the Arduino sensor.
On Manual, the fan speed should be set by the slider in the application.
It works well on Automat, the issue is when switching to Manual. The Manual command is not recognized by Arduino IDE and the speed of fan is not changing.

Let's track how you signal and how the signal is processed.

You use this variable to receive commands from AI2:

int vent;                   //variabila care stochează valoarea vitezei în procente
String comanda;
byte ventVitMan;                 //variabila care stochează modul de lucru

So the variable is comanda, and its type is String.

Here is where you receive into it from BlueTooth:

void loop() 
{
  umid = dht.readHumidity();     //citeşte umiditatea de la senzorul DHT11
  temp = dht.readTemperature();  //citeşte temperatura de la senzorul DHT11

  if (btSerial.available()) 
  {
    comanda = btSerial.read();  //citeşte comanda M = manual A = Automat
    //switch (mod)
    if(comanda == 'Automat') 
    {
      //case 'A':  //modul automat

        if (temp == 0)  //dacă temperatura este 0°C (se scoate senzorul din bread board)
        
...

Specifically, the line

    if(comanda == 'Automat') 

is testing the variable contents.

That raises the questions:

  • What is the AI2 app sending?
  • where does the incoming message end?
  • How does that == test work if there is something after 'Manual' incoming into that variable?

Here's where you send your 'Manual':

Is that one byte number fouling up your == test by clumping into the comanda String?

How does the

 btSerial.read();  

know how many bytes to bring in?

Mixing data types in your data traffic complicates things.

It is easier to switch to all text, and use Line Feed (\n) at end of message and ':' between markers like 'Manual' and the text representation of your slider thumb behind the ':' in the message.

There is an Arduino command to read until a '\n'.

Look for it.

There should also be String operations to turn a piece of test into a number.

Here are some code sample to study, with various pieces you might combine:

(You would be wise to read that whole thread for its many samples.)

1 Like

I made some progress but I don't understand why those strange characters appear.
Maybe someone can enlighten me.


ProiectFinal2.aia (269.1 KB)
ProiectStefanArduino1.ino (6.3 KB)
If I change line 142: delay(50); strange characters appear less often.

I just checked your blocks and didn't find any setup for the "TimerInterval" which may be the issue. Your mobile app and the controller you have are not synchronized. Try adding a delay after "if (btSerial.available() > 0)"(line 59)to ensure the RX is ready and you may need to adjust the timer interval in the app as well .

TimerInterval = 100 is the default value.
Do I have to set equal values in the Arduino and in the App?
I thought the RX was ready as soon as I powered it up.

"ready" refers to completion of reception of the whole packet. In your case whenever there's at least one character in the RX buffer you are trying to access it while if you include a delay before reading the RX buffer you make sure you received everything before reading. the delay could be done in different methods either using the delay function or maybe using a while loop until nothing else is being received (while(!receiving)). On the other end, you could include acknowledgment packets to better synchronize the transmission of packets on both ends.

I understand. But how can I empty the RX buffer every time before sending something?
Should I send an empty package first and then the one with useful information?
Should I send a recognition character at the beginning of the useful information, and the reading should start after that character?

I think you meant "before receiving something". My point is not just about emptying the RX buffer(you could do it at the end of your 'void loop()' function) its about starting to read from the RX buffer when all data has been received(i.e no more data is being received at the same time while reading from the rx buffer)(from the microntroller side).

Yes it is about before receiving something.
In my application the character | indicates that there is no more data to read.
This is send at every 200ms. I can change this but no effect.
blocks

global ValSlider is Integer Value (0-255).
So, for example the app send this string "Aut:128|"

In Arduino:
command = btSerial.readStringUntil(':'); - I get "Aut"
speed = btSerial.readStringUntil('|'); - I get "128"

I found the solution here: