Trying to read data from BLE module

Hi guys,

I am writing an app to read data from BLE following up this tutorial http://iot.appinventor.mit.edu/assets/tutorials/MIT_App_Inventor_Basic_Connection.pdf

I add a callback function to read data from the BLE module

It doesn't work for me. The app does connect to BLE module but doesn't receive anything from the other end.

I am using RN4871 from Microchip in transparent UART mode. I am able to verify data on the UART line from the microcontroller to the BLE module by hook up the scope and an USB-to-UART dongle as a UART sniffer.

I am able to send / receive data from the app Serial Bluetooth Terminal, but strangely not able to do so with Microchip Bluetooth Data app.

I am running to a dead end.

Any help is appreciated.

-Simon

1 Like

Your pdf only leads up to connection.

Is there a pdf that takes you further?

BLE needs you to register for whatever data type you want to receive.

There is a project for ESP32 which itself is a microcontroller and a BLE module all in one. You have the luxury of choosing your own custom service UUID I guess, hence you are able to write to that UUID on the app as well. Apart from that the traffic from BLE module to the phone does have a service UUID attached to each data package I believe. Which described by the block function with serviceUuid, characteristicUuid and stringValues (or byteValues).

Yeah. I've tried to read data from incoming package (taken from the pic I attached before)
2222

It doesn't matter the data type is byte or String. It just does nothing like it doesn't receive anything. But the other app, Serial Bluetooth Terminal (from android app store), is receiving/sending data just fine.

I might miss something here.

Edit:

  • How do I "debug" this app? I want to see if the callback is triggered.
  • I think I need to register the callback function in order receives data.
    The transparent UART service UUID is 49535343-FE7D-4AE5-8FA9-9FAFD205E455 and the characteristic UUID for receiving is 49535343-1E4D-4BD9-BA61-23C647249616

We need to see ALL your blocks on this Simon. For example, you have a when BytesReceived Block, but have you registered for bytes first?

Edit: We also need to see the Script that sends the data, the App and the microprocessor need to be singing the same song.

Can you also give an example of the data you are sending? It may be exceeding the MTU (Maximum Transmission Unit or Data Packet) length. Time intervals are very important too.

Thanks ABG and Chris.

I solved my problem. Obviously I didn't register the correct callback function to the BLE object.
Just have to do that "call BluetoothLE1.RegisterForByte". This is me totally not understand how BLE works.

Below is my sample app for those who stumble upon RN4871 in transparent UART mode.

Function blocks

User interface

Note: the UUIDs for transparent UART service and its characteristic are listed in RN4871 datasheet, section appendix, in case you missed that like me.

I use STM32 as the main application. Here is the code to send data
555

Result on the phone
666

And if you hook up a sniffer on the UART lines you will get neat output like this
888

Of course in real application I would never send data as char array but a whole struct like this
777

Sorry if I sound weird and use weird terms like callback function. I come from C/C++ background and I am not familiar with graphical programming language.

Hi Simon

We come from dodgy backgrounds too :grin:

Don't send any kind of value decoration, in this instance just send the value - the App can postfix 'RPM' - it's important because you want to keep within the bytes available for a BLE packet , which is 32 bytes in total (the BT packet data + payload). You also do not need a null at the end of your data, just use \n.

Using a delay - usually it is better to use elapsed milliseconds since a delay blocks everything. When sending multiple values, delimit with something that is unlikely to also turn up in the data. I use the bar char for this.

Thanks for your advise.

Just to clarify (and maybe out of scope), those functions in the sample are my custom functions and run at the lowest priority in my application. All other functions are interrupt-driven so that I don't mind using block-function such as delay(). Even so, I still don't want the interrupts mess up the transmission over UART, hence I use DMA (Direct Memory Access) and let the hardware handle it independently to the processor. My application is digital ignition for classic car/motorcycle which needs precise timing.

I don't prefer sending data as text but as a byte array or struct. For example the struct myData above has totally 5 bytes: first byte indicate what kind of data it is and the next 4 bytes will be actual value according to the type of message. Imagine you have 1001 types of message going back and forth on the CAN bus in your car that tell all kind of information: battery voltage, speedo, signal lights, steering wheel data, ABS data, air bag data, engine temperature, intake air temperature... It is next to impossible to send all of those information as string. Even if you are able to do that, it is awfully inefficient. But in C, the possible way is to format data as a struct. I am not sure how I do that in Java or using function blocks of AI. I will get there, eventually.

-Simon

Hi Simon

Without the advantage of struct in Block-based languages I think you are left with a regime where you do send an id byte followed by a value. The id byte can correlate to a List (Blocks List) in the App. This would allow the sending of any value combination and remain lean - a large amount of data could be sent over multiple packets. It is possible in some cases to increase the MTU (BLE v4.2/v5.0 max payload = 247 bytes), provided the device itself can handle it.

1 Like

Wow. Nice!

Chris,
Yep, definitely I will do that.

The traffic to the microcontroller side, on the UART lines as in my application, is byte-by-byte basis. Basically you receive a byte each time and there is no telling end of a package or begin of a package. To solve that problem, I assume you can employ a timeout mechanism to flush an incomplete package and start a new package if your microcontroller doesn't have feature like line idle detection.

If you are using ESP32 as BLE module and as the main processor, I think you don't have to deal with limitation of UART transmission. Your life would be easier, wouldn't it :slight_smile:

-Simon
PS: I like having conversation like this, benefit for me as well as the community.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.