With the release of Android 8.0 (“Oreo”), I as well as others have noticed that they cannot find some HM-10 clone BLE modules when scanning for them with an Android 8.0 phone. Why is that happening and what can you do about it?
tl;dr, the issue is due to a bug in the firmware of those modules, typically referred to as CC41 firmware. Fixing these modules is too much of a hassle and you would probably be better off getting a new module for communicating with Android 8.0 and perhaps use the problematic ones for iOS and pre Android 8.0 devices only.
update: it has been reported that Android 9 went back to the “relaxed” behavior. You might want to check your problematic modules with other versions of Android if you are having this issue. See more details in the comments.
I have several projects which involve BLE, most noticeably Fochica, a system that alerts parents if they have unintentionally left their children in a vehicle. As a result I have been dealing with all sort of BLE modules in the last couple of years. Many of these modules are in a category called “HM-10 clones”. I have written an Arduino sketch, arduino-ble-ident-n-set, to help identify the specific module type and to help configure it easily.
Typically listed or sold as just “HM-10” these modules are a group of modules that share a form factor, pin layout and a micro-controller (the TI CC2541). While trying to mimic the original HM-10 by “Jinan Huamao technology Co” they differ by firmware, breakout board and daughter board. When ordering online it is very difficult to know which exact combination you will get. Only the original HM-10 modules have some kind of support, while other variations are mostly made by anonymous clone manufactures. I personally have dozens of modules with 6 different unique combinations, including 2 variants of CC41, 2 variants of MLT-BT05, an original HM-10 and a botched CC41 that I will describe in more detail later in the article.
When these modules fail, it could be due to an issue in the daughter board, the breakout board or in the firmware. This case is due to a bug in the CC41 firmware. When a BLE device receives a scan request it responds with a scan response. The response includes information about the device such as device name, services offered, etc. The length of the response depends on the amount of bytes in the response fields. The CC41 firmware always sends a response with length of 31 bytes. It basically performs a “read beyond bound” from the variable that stores the scan response. The first part of the 31 bytes is a valid scan response and the second part is some padding containing either uninitialized memory or data of the next variable in memory.
iOS and pre Android 8.0 systems ignored this corrupt data but starting with Android 8.0 Google decided to perform stricter validation of this data. This was probably done to prevent potential security issues, crashes and to follow the standard more closely. The malformed response is ignored and the resulting behavior is as if the CC41 is not responding at all.
I was able to reproduce and observe this behavior with the following BLE sniffing setup:
- TI SmartRF Protocol Packet Sniffer software – http://www.ti.com/tool/PACKET-SNIFFER
- CC2540 USB device – http://www.ti.com/tool/cc2540emk-usb – I got mine from eBay, probably a clone.
- SmartRF Flash Programmer software – http://www.ti.com/tool/flash-programmer
- TI SmartRF04EB programmer device – http://www.ti.com/tool/CC-DEBUGGER – I got mine from eBay, probably a clone. For a more DIY approach, there are articles showing how you can use an Arduino as a TI programmer.
The steps are:
- Install the right software versions for your matching devices.
- Install a driver for the programmer. Program the “CC2540 USB” device with “Texas Instruments\SmartRF Tools\Packet Sniffer\bin\general\firmware\sniffer_fw_cc2540_usb.hex” firmware.
- Connect the CC2540 USB to your computer and run the packet sniffer software.
I found the following guide from TI useful.
We can now observe BLE traffic. Setting a filter on scan responses will make it easier to see the bug. Here are some responses from different BLE devices:
CC41: 0D 09 46 6F 63 68 69 63 61 5F 33 31 41 44 00 00 81 00 10 00 FF FF FF FF FF FF FF FF FF FF
ESP32: 02 01 06 0F 09 45 53 50 5F 47 41 54 54 53 5F 44 45 4D 4F 02 0A EB 05 03 EE 00 FF 00
HM-10: 07 09 48 4D 53 6F 66 74
MLT-BT05-V4.0: 09 09 4D 4C 54 2D 42 54 30 35
Local name, Field type, Length, Junk.
I have color-coded the various parts to easily convey the issue in the response. For exact protocol details see the specifications.
- A spontaneous idea might be to change the name of the CC41 device to something longer such that we have a valid response or at least a zero-padded one. However, the CC41 firmware doesn’t allow to set a name longer than 18 characters.
- Most modules send only their name in response to a scan, while the ESP32 device in this example was programmed to send 3 other fields as well.
It is unlikely that Android’s new behavior will change so the typical resolution would be to update the firmware of the device to a bug free version. Unfortunately Bolutek, who seem to be the company behind the CC41, doesn’t provide updated CC41 firmware or any easy way to upload the firmware to the device. We are left with the following options:
- Use another module
- Painful process to flash a different working available firmware
- Trying to hack the device
Use another module
This is probably the easiest option in terms of invested time. HM-10 clone modules are sold at $2 a piece so if you need to replace just a few it might be easier to order another HM-10 (clone) module. New modules will most likely come with a different firmware such as a MLT-BT05 variant, or even better an original HM-10 which has means for over-the-serial flash updates. If you still get a CC41 module nowadays I feel it is a valid reason to ask for a refund.
Personally I am a bit tired of dealing with issues of the HM-10 ecosystem. You never know what you will get as the variability is so high. Most modules have an anonymous entity behind them and no way to get updates. The original model lost its value as a unique identifier of a specific model and became a generic identifier. Pairing/bonding is poorly implemented in the clones compared to alternatives. Due to these reasons and more you too might want to stay away from HM-10 all together.
Nowadays I prefer using an ESP32 instead of an Arduino + HM-10 combination. The main reasons are:
- It is a bit more complex but you have full control of the firmware, you can define your own services/characteristics and use this for more than just wireless UART.
- There is a company behind the device and you don’t need to do any wiring as the BLE (+BT+WiFi) is built into to the micro-controller.
- The ESP32 is a much more powerful chip than a typical Uno/Nano but still can be programmed the same way from an Arduino IDE.
- The ESP32 now has a decent BLE library.
The big difference between the two approaches is that with the ESP32 you don’t have a separate firmware for the external module, instead the code of the BLE is compiled together with the code of your program. When you upload your code you upload both your program and any BLE related code/libraries.
Re-flashing to another firmware
Those looking to “fix” their CC41 flashed modules can flash them with a different firmware. The only other firmware I am aware of that is available in a file that can be flashed is the HM-10 original firmware. Any modules with other firmware that I have tested always came “chip locked” so you can’t read the firmware from the module. I guess the HM-10 firmware once leaked or was distributed without a “chip lock”, which resulted in its availability. If you are aware of another firmware that exists for this purpose, please mention that in the comments.
There are advantages and disadvantages to flashing the HM-10 original firmware to a clone device.
- Pairing/bonding works better and with more phones models and OS versions
- Ability to do over-the-serial updates
- Works with Android 8.0
- Works better as a beacon (iBeacon)
- Less bugs in general
- You will need to cut the shrink warp of your module
- You will need to do some soldering
- You will probably need to buy/build some tools (clips, programmer, etc)
- You might have to fix issues and apply workarounds to make the STATE pin work as expected
PSA: The jnhuamao.cn site contained downloads with trojans and was classified as a malicious site on several instances so if you are downloading executables from there you have a chance of getting infected. You can do the process without going there which is what I would recommend, otherwise be careful.
The instructions below are not going to be a complete tutorial for re-flashing the CC41, for detailed instructions, firmware files and discussion see the following resources:
- JDY-08 : bluetooth 4.0 module
- How to flash genuine HM-10 firmware on CC2541 (make genuine HM-10 from CC41) – Video
I used the following tools to re-flash the module:
- SmartRF Flash Programmer software – http://www.ti.com/tool/flash-programmer
- TI SmartRF04EB programmer device – http://www.ti.com/tool/CC-DEBUGGER – I got mine from eBay, probably a clone. See CCLoader for a DIY approach.
- DIP16 programming clip/clamp – an option to consider instead of soldering wires to the module
The steps I took for flashing
- Cutting the transparent shrink wrap that protects the module. You should consider taping it back when you are done flashing.
- Identifying the pins needed for programming: debug clock, debug data, reset, power 3.3V and ground.
- Adding solder to the pins/pads where connection are to be made.
- Bending the connectors of the DIP16 clip so they align to the pads of the castellated daughter board. They are not the same pitch by default.
- Running the SmartRF programmer software and setting the settings for writing the desired firmware.
- Connecting Gnd to the 2.54mm module pin and the other programmer connections via the clip.
- Connecting the programmer to the USB.
- Performing the program.
- Verifying the result through a BLE app and a serial connection.
This worked surprisingly well. The difficult part was holding the clip in place steady for a good connection to the pads. If the connection is not good, then the device would not be detected in the programmer when it is plugged in.
Fixing the STATE pin
All works well with the new firmware except for the STATE pin. In the clones this pin is supposed to be HIGH when the module is connected and LOW when the module is disconnected. To accomplish that the clones use pin P1_1 (PIO2) which is connected directly to STATE while also having a separate pin P1_2 (PIO1) to drive the on board LED. The default behavior for the LED is to blink when the module is not connected and HIGH when the module is connected.
In the original module, P1_1 is not used and is configured as OUTPUT LOW. Instead P1_2 is used for both the STATE and the LED. This means that by default the STATE will blink when the module is not connected, which is a weird behavior for a digital output signal. To compensate for that, the original HM-10 allows to reconfigure the behavior of P1_2 (PIO1) through AT commands to have it as LOW when the device is not connected. This is one aspect where I believe the clones are actually better than the original. It makes much more sense to have separate digital signal and visual LED indicator pins as each has its own expected logic.
If, like me, you rely on the proper operation of the STATE pin for your application logic, then you will have to make another alteration to the module to reconnect the STATE pin to P1_2 instead of P1_1. Note that it is not enough to bridge the two, you have to actually cut the previous connection, otherwise there will be a short circuit between P1_2 and P1_1. Identify the trace that connects between STATE and pin P1_1 and cut it using a hobby knife. Verify that there is no conductivity. Then solder a bridge between STATE and the P1_2 pin or the LED or the LED resistor (depending on what is convenient on your breakout board). Verify that the two pins are not connected and that STATE is now properly connected to pin P1_2. Using AT commands or arduino-ble-ident-n-set configure the module to drive the LED in a boolean fashion. You should now have a proper STATE pin.
Note, some HM-10 clone modules come with no solder bridge between pin P1_1 and the matching pad on the breakout board. If you intend to re-flash those, this can actually be an advantage. Don’t fix this connection, re-flash the module and then bridge the two pads on the breakout board without bridging the matching pads on the daughter board. This should connect STATE to P1_2 while leaving P1_1 disconnected.
Here you can see a CC41 module which was previously fixed to support STATE, now re-worked to support STATE in a HM-10 configuration:
Perhaps there are additional ways to hack the CC41 module. I am really interested to know if you have any ideas. We know that there is at least one bug in the firmware and perhaps there are others, which can allow us to take control of the device, alter its behavior or dump its firmware. Perhaps somebody has an updated firmware or an original extracted firmware that can be patched…
It is possible to fix misbehaving modules by re-flashing them, but it is not a quick or easy process. Might be better to get new HM-10 modules or switch to alternatives.
It would be nice to have more options.
The importance of software updates is demonstrated once again.
For the benefit of the community and other buyers, you are encouraged to leave reviews for any modules you get from eBay/aliexpress and describe their parameters such as type, version, STATE pin implementation, etc. This is the only way we can beat the huge fragmentation in the market and educate the sellers about the items they sell.
Pingback: HM-10 or CC41-A module? Automatic Arduino BLE module identification | Arik Yavilevich's blog
How do I upvote this article.
Hi Mihai, thanks for the interest. I am not sure if there is a way. Feel free to post on social media if you feel this would be useful to others.
Awesome article! Have you looked at the firmware downloads here and tried any of them? www. jnhuamao .cn/download_rom_en.asp?id=66
~ Gabriel, from ElectricRCAircraftGuy.com
Yes, these downloads are HM-10 upgrade firmware. So if you already have a HM-10 firmware on your module then you could use these to upgrade to the latest version. However, mind that some downloads on the jnhuamao site were reported as malware.
Thanks alot for your great work, I wanted to ask now that I have a cc241(clone hm-10)
1-how can i change its name via at commands?i connected it: vcc-5v , grnd-grnd, tx-rx , rx-tx on arduino uno via jumper wires , but on arduino it never responds to at commands, i but it on Both Nl& CR at 9600 baud rate.
can you help me with it please
2-another question, does changing the name for the original hm-10 ble differ from the method used for the clone cc41.
3-another question, is this a geunuine hm-10 module:
thanks alot in advance
1- These modules are typically 3.3V on the Rx/Tx lines and might be damaged if connected to 5V. The easiest way to change the name without reading too many datasheets would be to use https://github.com/ayavilevich/arduino-ble-ident-n-set
2- Each firmware has slightly different command syntax and command list. So the process to change the name for each module can be similar but different. Best to use the “Arduino BLE module identification and setup sketch”
3- Based on the picture this does look like an original HM-10 module. The seller also guarantees as such. Naturally, check it once it arrives to be sure.
Thanks alot for your help.
Can you offer a link of original genuine hm-10 ble that have voltage adapter so it can work on 5v and can be read be anriod oreo 8/8.1
Here is a link to a module that I strongly believe is a genuine HM-10 and is 5V tolerant:
Do note I have no control over this seller and it sometimes happens on eBay that you get something different from what you have ordered.
If you do order, please report back in the comments what you think about it.
Thank you very much for your usefull content. Really enjoyable to read it. I was wondering whether you had the change to try out the module you seggest with Android 8.x.x Oreo. I bought one to test it, but maybe you already did it. In case you know now another Oreo compatible module for cheap, please share it! I am looking for it for a while 🙂
Thank you very much,
Glad you found the article useful.
I have tried different modules and the only type that doesn’t work with Android 8.0 (Oreo) and up is the CC41. This means that both the original HM-10 and the MLT work fine. As well as modules of the MLT family such as AT-09 and JDY-09.
Now the catch is to know what you will get when you order one on eBay. I am very cautious to recommend a specific listing as often I make several orders from the same listing and got different firmware types. Sellers will just push whatever stock they get for cheap. This is why I think we should add reviews to the items we order and verify.
Having said that, I am pretty certain that the chance of getting a CC41 at this point in time is pretty low. If you get one you should just ask for a full refund. It is obsolete.
Thank you very much for your reply. I actually bought 20 of what I thought were compatible ones and I ended up by asking a refound. They worked but since they were CC41 modules, they weren’t compatible at all. Anyhow thank you for your inputs. I order the module you suggested, I will let you know if it’s actually works. Thx!
Ohh, that must have been very disappointing. Feel free to link to those, so we know what not to order.
I should have asked you in advance. https://www.aliexpress.com/item/Bluetooth-4-0-For-Arduino-Android-IOS-HM-10-BLE-CC2540-CC2541-Serial-Wireless-Module/32659958252.html?spm=a2g0s.9042322.214.171.124424c4dtSkZc3
They work just fine but not with Android Oreo and I also tried to flash the orginal firmware 10 times with no luck!
I tried your sketch code to change ble hm10-cc41 name via at commands, but it sends weird wrong characters at the start of serial monitor and doesnt respond to any at command i send.
here is a screenshot i uplodaded on 4shared.
thanks in advance
sorry here the link
I changed the baud rate to 115200
it reponded finally but still cant detect the cc241 ble module!
“Detecting module type
No response received from module.
Verify that the module is powered. Is the led blinking?
Check that pins are correctly connected and the right values were entered.
Are you using a logic voltage converter for a module that already has such logic on board?
Are you using a module that expects 3.3v logic? You might need to do logic convertion on Arduio’s TX pin (module’s RX pin).
Enter the number of the RX pin on the Arduino, TX on the module  :”
Please post a schematic of your circuit, pin value input you provided to the script and a photo of your module.
I am using arduino uno connected to my laptop
i connceted the cc241 ble as follows
rx of ble to rx 0 of uno
tx of ble to tx 1 of uno
gnd of ble to gnd of uno
vcc of ble to 3.3v of uno
here is the pics
and the module
That is not a correct way to connect such a module. Pin 0 and 1 of the Uno are used for your PC to Uno serial connection. You have to choose other pins.
Also, your module is probably not 5V tolerant. You need to convert the signal to 3.3V.
See https://github.com/fochica/fochica-wiki/wiki/BLE-module-guide for some advice on how to connect correctly.
Okay I changed the pins to
Still same problem occured, i will buy the resistors needed to divide voltage and come try again .
Thanks alot for your help
If you select Rx as 9 and Tx as 8, then Pin 9 will go to the TX of the module and Pin 8 will go to the Rx of the module. Check if that is indeed the case and not vice versa.
Then, when running the arduino-ble-ident-n-set.ino
sketch, enter 9 and then 8 for the pin values.
I wondered if you have come across this issue where the HM10 suddenly stops advertising – it’s definitely HM10 and not the clone, and it doesn’t happen all the time, only occasionally tested with both iOS and Android phones. We’re trying to figure out why it stops responding to scan requests, but then a few hours or days later it starts to work again. We’ve tried to reproduce this issue but haven’t succeeded so far so I just wanted to see if that was happening to you?
I have not experienced something like this, but maybe other readers will share similar issues.
What happens if you power cycle the module?
Have you tried different firmware versions?
I have not tried different firmware versions – only v545. Yes I believe power cycling does get the module to come back to life.
hello Arik, thank you for this article,
i was wondering if there is a way to change the module UUID every time. im trying to make a BLE Beacon using HM-10, but as you know the UUID is easy to detect and could be cloned. So i wanted to know if here is a way to make the UUID of the module change for example every hour.
Regarding the change of the UUID, it depends on the specific module model I guess. Every model has a slightly different set of AT commands. Some commands will allow you to change service UUID, assuming this is the UUID you want to change. See the datasheet for your module.
Regarding the idea of changing the UUID of a device as a way to create a more secure beacon, I am not sure how that makes it more secure. Can still be copied. Note that for a normal BLE beacon, the payload is separate from the UUID.
Hello Arik and thank you for your answer,
well the idea is to use anArduino with the HM-10 module, and i want to hide the UUID or make it change every while, because if i get the UUID i can easly clone it and then have control of a lot of stuff. so i was wondering if there is a way to hide the UUID of my HM-10 module.
Thank you for this article. If have spent a lot of hours on trying to read/subscribe to the written data the HM-10 is receiving, but I am not sure how the get the data displayed correctly.
I am following this article: https://medium.com/@yostane/using-the-at-09-ble-module-with-the-arduino-3bc7d5cb0ac2
The program writes new HEX values like “4F”, but I am not certain if the HM-10 is sending the data out? I have tried 10 different apps and nothing is working..
Hope you can help 🙂
Please describe the scenario in more detail. Who is sending data to who? What are the devices on both ends and what roles they play? What apps did you try and what was the error/result? What code you are using? etc.
Pingback: Flash HM-10 and BT-05 firmware – LouWii's Blog
The ESP32 module creates 2 com ports when paired to PC windows 10 but not HM-10, anybody knows why ?
An ESP32 is a micro-controller that can be programmed with some firmware to do an infinite number of functions.
A HM-10 is a module using a TI CC2540 micro-controller chip which is programmed to do a specific serial to BLE function.
So comparing these two without explaining what is running on the ESP32 is like comparing apples and oranges.
Looks like Android 9 accepts these broken devices again
Nice. Thanks for the update.
If you have a link to an announcement or a change-log about the issue, please share.
the check is relaxed with Android 9 here: https://android-review.googlesource.com/c/platform/system/bt/+/579282
Now there is a way to flash the CC2541 chip with raspberry pi directly over gpio pins:
Also useful if developing custom firmware.
Hi Alexander, thanks for the info.
It was already possible to flash the CC2541 with simple means (no dedicated programmer) before. See https://github.com/RedBearLab/CCLoader
The issue is that there are no open firmware versions for this that I am aware of. So there are not much things you can flash on the chip of this board to make it work.
Hi, I have an HM-10 Cs2451 and I can’t find the Firmware any ideas
Nice article, very informative. About the ESP32 alternative.
The BIG problem with ESP32 the issue with BLE power consumption is not solved yet (June 2020).
The minimum power output you can get in transmission is around 130mA while in idle is about 70mA. If you compare with these modules (~5mA in transmission) is a decisive reason to discard ESP32 if you need to operate it with batteries.
Awesome article Arik, thank you so much!
It’s 2022 and on there are newer firmware versions available (v709/710). I’m wondering if it’s safe to flash these to my HM-10 clone that is using the CC2541 chip?
Under all articles, people are mentioning and flashing v540 which is from 2016.
Personally I can’t say. Haven’t used these modules lately. However maybe other readers can share their feedback.