Hello.
I am new to BLE. I am trying to make a simple app to send and receive data between my Android phone and Arduino UNO connected to a BLE module (CH9141).
I can send data (bytes) from the app to Arduino sucesfully. The service UUID is correct and the char. UUID begins with 0000FFF2...
But in the app I can not receive data sent from Arduino. Which UUID have I to use? 0000FFF3 for both writing and reading or 0000FFF2 for writing and 0000FFF1 for reading?
Also do the variable types need to match in the app and Arduino? I want to send 2 byte messages to arduino and 2-3 integers ending with "\n" from Arduino to the app.
Thanks.
BLE_test.aia (201.5 KB)
Post your .ino code
This is confusing.
I don't see any BLE libraries and calls in your .ino, only classic BlueTooth:
ino code
#include <SoftwareSerial.h>
SoftwareSerial BTserial(2, 3); // RX | TX
// Connect the CH9141 TX to the Arduino RX on pin 2.
// Connect the CH9141 RX to the Arduino TX on pin 3 through 1k resistor and to ground through 2k resistor (voltage divider).
#define LEDpin 8
byte read;
unsigned long currentTime;
unsigned long lastTime;
unsigned long interval = 1000; // milliseconds
int value = 12;
void setup() {
Serial.begin(9600);
Serial.println("Waiting for incomming data from CH9141BLE2U");
BTserial.begin(9600);
pinMode(LEDpin, OUTPUT);
digitalWrite(LEDpin, 0);
delay(500);
}
void loop() {
currentTime = millis();
if (currentTime - lastTime >= interval) {
Serial.println(value);
BTserial.println(value);
value++;
lastTime = currentTime;
}
// Keep reading from CH9141 and send to Arduino Serial Monitor and toggle the led
if (BTserial.available() > 0) {
read = BTserial.read();
Serial.println(read);
digitalWrite(LEDpin, read);
}
}
Resolution to confusion:
The .ino only talks to the BLE chip, as documented at
Read through the doc for the UUIDs your app will need, as well as any AT commands the ino may need to send to set up the BLE chip.
Just in case:
This requires text conversion in your .ino, (usually done via print and println to BTserial) and using the BLE blocks that register for and receive text in your app.
Check the BLE component for an attribute that determines what end of message delimiter to expect. 10 = \n in decimal.
If using commas as delimiters in your text messages, split at c omma in the app and verify length of list before trying to select from the list, to avoid surprises.
yes.
Solved.
With an amazing help of the manufacturer of CH9141 I got it to work.
For writting (sending) data use characteristic UUID 0000FFF2xxx. For reading (receiving) data, set RegisterForBytes(Strings, etc.) to characteristic UUID 0000FFF1xxx.
Could you post your aia and ino files here for the next CH9141 users?
This is somehow working version. It can send and receive single data.
My questions to AI2 masters:
1/ I would like to send 2 byte data. In my classic BT app I am sending 1st byte as command and 2nd byte as value. In this BLE version when I drag the slider or press the LED button quickly, the values switch randomly - it can be seen on the Arduino Serial Monitor.
Classic BT has "callBTClient.Send2ByteNumber" event.
2/ I am receiving the data from Arduino as strings. I can split them but I want pure numbers without this: [" "]
Again, in classic BT there are "callBTClient.BytesAvailableToReceive", I can create a list and nicely split. Then the displayed values are just numbers.
BLE_test.aia (203.0 KB)
BT_CH9141_LED.ino (1.7 KB)
Please any ideas how to fix these two things?
Thank you
You know that is just the count of how many bytes would arrive from the BT buffer if you would do a read, and not the actual byte values, right?
Yes, I know.
My problem is that when I am sending (writing) 2 values of "2" and "thumbPosition" slowly, the values show on the Serial Monitor as they should be, that is:
2 \t thumbPosition
But by faster movement of the slider they randomly switch order to:
thumbPosition \t 2
This behavior can be a bit reduced by commenting Serial.print(ln) the values on the Serial Monitor, but sometimes it still happens.
Loss of synchronization happens when you don't include message delimiters like \n and don't look for them in your input stream .
Here is standard advice for classic Bluetooth:
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.
Regarding sliders, they trigger events too often for data transmission to keep up
This is avoided by having the slider just update a global variable and leave the transmission to a separate Clock Timer that watches the global variable and compares it to another variable with the prior cycle value. Transmit only if the value changes, at the slower clock Timer rate.
Good idea to have a Timer for the slider. I will try it.
Regarding other post from you - I know all the things related to classic BT. I am receiving just numbers (as strings) separated by eg. "|", so I can split them easily.
But in BLE I get the "when BLE1.StringsReceived.stringValues" as numbers separated by "|" and in brackets [" "]. These brackets drive me crazy... After splitting the string at "|" the first item appears as "["value", the middle items are just values and the last item is "value"]"
Stringvalues is an AI2 list, even if it has only a single item. The trailing 's' in the name is a poor hint.
Treat it like a list and check its list length, then select items by number.