HM-10 Bluetooth 4 BLE Modules

Since I first posted about the HM-10 the firmware has been updated many times and some of the commands have changed. Therefore, I decided to redo the guide. For the main article I am using modules with firmware 5.49 (regular) except the one I am using for the firmware update guide which started with v5.40 and become 5.47.

There have been several firmware updates since this guide was written, as of March 2020 the latest is v707.

Updated 2019-08-25
I thought it was time for a minor update.

There are now 4 versions of the HM-10. The differences are usb pads and a crystal.
1 – with usb pads and the additional crystal
2 – with usb pads without the extra crystal
3 – no usb pads but with the additional crystal
4 – no usb pads, no extra crystal.


Docs and data sheet
The docs zip file is available by clicking on one of the HM-10 images on the Huamao Technology products page or download directly here.


The data sheet in the download shows v606/v701 and is not up-todate; it does not include the new AT+READOF command and has the old AT+CO command. It does include AT+PACK which was introduced in v702 though. Huamao version control looks to be as good as mine…..

The readme in the archive is not up-to-date either, see the one that comes with the firmware download.

The latest firmware is v705 and can be downloaded from Huamao here. Here are all the changes since v700. I have not used any of the 7xx firmwares.
If you update from < v700 remember the default UART baud rate changed to 115200.

HM-10/11 CC2540/1

-Add AT+READOF command
AT+READOF?, used to read long char value
P1: 2 Bytes, Start Index.
P2: 4 Bytes, Char Handle.

-Modify AT+CO command
AT+CO[P3][P4][P5], used to make connection.
P1: 1 Byte, Devie type.
P2: 12 Bytes, Device MAC
P3: 4 Bytes, Notify Handle
P4: 4 Bytes, Write Handle
P5: 2 Bytes, Write property.
P1 and P2 must be input;

-Add AT+INDICA_ON command

-Made wakeup function better
-Add AT+PACK command used to modify data in Advertisement package.
P1, P2, P3, P4, P5, P6 length all is 2.
P1, P2, P3, P4, P5, P6 value 00~FF

-Add AT+SET_WAY command

-Default baud rate change to 115200
-Removed AT+ANCS command
-Removed AT+COMP command
-Removed AT+128B command
-Added new function used to support different brand BLE device
-Added AT+FINDSERVICES? command
-Added AT+FINDALLCHARS? command
-Added AT+NOTIFY_ON command
-Added AT+NTOIFYOFF command
-Added AT+READCHAR command
-Added AT+CHAR command
-Added AT+READDATA command
-Added AT+READDESC command
-Added AT+SEND_DATA command

I always had issues using the HM-10 with other modules. I never got them to fully work with modules like the BT05 and the AT09. The BT05 & AT09 could receive data from the HM-10 but not the other way round.
I emailed Huamao a few times about this a while ago and didn’t get any replies but it looks like they at least addressed the problem. I haven’t had time to try though.

Firmware download page You can get the how to update guide from the same page (or see below). I note that firmware v703 and v701 are no longer available.

2019-02 Firmware version 7.02 now available. The download link says V701 but the file says 702.
Note that in V700 onwards:
– the default baud rate change to 115200.
– accepts commands with and without line endings.
– better compatibility for other BLE modules. See the readme file that comes with the download.

2018-03-24 Jinan Huamao support say that the HM-10 (original ones, not copies) are compatible with Android 8. I do not have Android 8 so have not tried and cannot confirm.
They have now added a comment on their website saying the HM-10 works with Android 8.

HM-10s with firmware V605 are now available but Jinan Huamao are not releasing the firmware. Not sure if this is just for now or permanently. V603 is the latest firmware available for download.

It appears that Jinan Huamao are trying to crack down on fakes. Apart from not releasing the latest firmware the latest HM-10s have “HM-10” screen printed on the PCB. EDIT: looks like they changed their mind. Newer firmwares are now available.

Image taken from the Jinan Huamao website
Image taken from the Jinan Huamao website

Firmware 6.01 now available (bug fixes, no new commands)
2017-10.xx Firmware 6.03 now available Extended the CO command. Added AT+MPIO (multi PIO control). See the readme file for details. The manual has not been updated at this time (Nov 2017).

Firmware version 5.49 is now available from the Jinan Huamao website. There are 2 versions; regular and long name. The regular firmware does not have an updated read me so I don’t know what changes, if any, have been made. The long name firmware adds, you guessed it, long names. Device names can now be up to 29 characters. At the same time the iBeacon function and the ANCS function have been removed. Unless you desperately need long names I suggest you stay with the regular firmware.

Bluetooth 4 BLE
HM-10 Services and Characteristics
Get Started With the HM-10
Getting an Arduino talking to the HM-10
HM-10 AT Commands: Using the Arduino’s serial monitor to talk to the HM-10
Scanning for other HM-10s
Arduino to Arduino using HM-10s
HM-10 to HM-10: Turning an LED on and off
HM-10 Programmable Pins
HM-10 Stand-alone MODE 2 and Controlling LEDs
HM-10 Stand-alone: Remote Light Sensor
HM-10: Add a second Custom Characteristic
Using the HM-10 with non-HM-10 modules (not fully working)
HM-10 as an iBeacon
HM-10 Updating the firmware
HM-10 Downloads




The HM-10 is a small 3.3v SMD Bluetooth 4.0 BLE module based on the TI CC2540 or CC2541 Bluetooth SOC (System On Chip). The HM-10 is made by Jinan Huamao and is one of many Bluetooth devices they produce including the HM-11 which is operationally the same as the HM-10 but has a smaller footprint with fewer pins broken out.

There are 2 versions of the HM-10; the HM-10C and the HM-10S

The HM-10C does not have the pads along the bottom (the usb connections) and has 26 pads instead of 34 which makes it a little cheaper to produce. There may be other differences (such as the type of crystal used) due to the date of manufacture. Operationally the two are the same though.

HM-10 Basic specs

  • +2.5v to +3.3v
  • Requires up to 50mA
  • Uses around 9mA when in an active state
  • Use 50-200uA when asleep
  • RF power: -23dbm, -6dbm, 0dbm, 6dbm
  • Bluetooth version 4.0 BLE
  • Default baud rate pre firmware V700 is 9600
  • Default baud rate firmware V700 and up is 115200
  • Default PIN is 000000
  • Default name is HMSoft
  • Based on the CC2540 or the CC2541 chip

The latest HM-10s all appear to the the CC2541 chip. This is the same as the CC2540 except it is lower power and has a shorter range. The CC254x is based on the 8051 and runs at 32MHz.

The HM-10 is has become a very popular Bluetooth 4 BLE module for use with the Arduino. In part due to the standard UART serial connection that makes it fairly straight forward to connect to an Arduino. The UART layer is a good thing and a bad thing, it allows ease of use but it hides the BLE layer so you have no control over the actual BLE side of things. The HM-10 is Bluetooth version 4.0 only. This means it cannot connect to Bluetooth 2/2.1 modules such as the HC-06 and HC-05.

The HM-10 is controlled via AT commands which are sent over the serial UART connection. There are a host of commands, some simple, some more complex, and these are covered later.


HM-10 on a breakout board

The HM-10 is also available mounted to a breakout board that exposes the power and UART connections to breadboard friendly male pins. The breakout board includes a 3.3v power regulator that makes them 5V compatible. This makes them ideal for hobbyists like me. You should note that the RX pin is is still 3.3v and when using a 5v Arduino you should covert the Arduino’s 5v TX to 3.3v for the HM-10 RX.


Pin Description
STATE   Connection status
LOW when not connected. HIGH when connected
VCC Power in. 3.6v to 6v
GND Common ground
TXD Serial UART transmit
RXD Serial UART receive
BRK Break pin. When there is an active connection, bringing the BRK pin LOW breaks the connection

On board LED

The on board LED blinks when waiting for connection. It blinks half a second on, half a second off.
The LED becomes solid on when a connection is made and returns to blinking when the connection is broken.
The LED changes to solid on when pairing. After pairing it returns to flashing. It basically makes a connection to pair and so turns on the LED to show the connection status. After pairing is completed the connection is closed and the LED is turned off.

The behavior of the LED can be changed using the PIO1 command.
“AT+PIO10” – Default setting. When not connected the LED blinks 500ms on, 500ms off. When connected the LED is solid on.
“AT+PIO11” – When not connected the LED is off. When connected the LED is solid on.


The STATE pin is LOW when there is no connection and goes HIGH when a connections is established.


The BRK pin allows you to cancel a connection. When there is an active connection, bringing the BRK pin momentarily LOW breaks the connection. When there is no connection making the BRK HIGH or LOW has no effect. Although not strictly required, pulling the BRK pin HIGH for normal use will stop the pin floating.



There are lots of comments on the internet about fake HM-10s and even Jinan Huamao includes information in the data sheets. I do not see the non-HM-10s as fakes, I see them as similar devices with different firmware. To me if they were fakes they would copy the firmware.
I think a lot of the problem comes from how the non-HM-10s are sold, especially on places like ebay and aliexpress. You will often see modules sold as HM-10s when they are in fact not. One of the easiest ways to spot the non-HM-10s was the lack of a crystal, unfortunately you can now buy actual HM-10s without the crystal so the confusion is likely to get worse.


Bluetooth 4 BLE

BLE is not an upgrade to Bluetooth Classic, it is a different system with different intended uses. BLE works in a very different way to the earlier Bluetooth. BLE is designed for low energy applications and achieves this by using infrequent small packets of data. It is not really designed for continuous connections and large amounts of data. For this, Bluetooth Classic is a better choice. In essence, BLE achieves its low power consumption by not being connected very often, unlike Bluetooth Classic which maintains a constant connection.

While you can create a classic style connection using 2 HM-10s, and I give an example below, they were not designed for this and if this is all you need then you would be better suited with Bluetooth Classic modules like the HC-05s or a HC-05 and a HC-06.

There are 2 ways BLE devices can talk to each other; Broadcaster + Observer, and, Central + Peripheral. The HM-10 can use both methods.

  • With Broadcaster + Observer there isn’t a standard connection, the Broadcaster, usually some kind of sensor, sends out periodic signals (advertising packets) which the Observer listens for. The Broadcaster does not normally know if anything is listening or not.
  • The Central + Peripheral scenario is more like (but not exactly the same) as the classic connection. When the Central (master) device finds a Peripheral (slave) device it wants to connect to it initiates a connection and takes on the master role managing the connection and timings.


HM-10 Services and Characteristics

BLE is all about services and characteristics and like all BLE devices, the HM-10 has a set of services and each service has a set of related characteristics. Characteristics are where the values are, some are READ, some are WRITE, and some are READ and WRITE.

All the services on the HM-10 are predefined except one. This is a custom service that has one custom characteristic. Predefined services and characteristics are ones where the UUID and the name are set by the Bluetooth governing body. For example, the characteristic 0x2A00 is the device name and when a device has this characteristic it should always be the device name.

A full list of the predefined services can be found here and a list of the characteristics is here.

The HM-10 uses the custom characteristic to send and receive the data it receives over the serial UART interface. It works by setting the value of the custom characteristic to the value of the data to be transmitted. It then sends out a notification to the remote device to say there is new data available.
When you tell the the HM-10 to transmit “HELLO”, it first sets the value of the custom characteristic to “HELLO” and then it sends out a notification telling the remote device “Hey, I have new data, come and get it.” The remote device is scanning for the notifications and when it receives one it knows there is a new value, so it reads the data and then sends back a message saying “Thanks, I have it”.

The custom characteristic can hold up to 20 characters, this means to send a string longer than 20 characters the HM-10 splits the data in to 20 character segments and sends each one in turn until none are left.

UUID: 00001800-0000-1000-8000-00805F9B34FB

  • UUID: 00002A00-0000-1000-8000-00805F9B34FB
  • READ
  • UUID: 00002A01-0000-1000-8000-00805F9B34FB
  • READ
  • UUID: 00002A02-0000-1000-8000-00805F9B34FB
  • UUID: 00002A03-0000-1000-8000-00805F9B34FB
  • UUID: 00002A04-0000-1000-8000-00805F9B34FB
  • READ

UUID: 00001801-0000-1000-8000-00805F9B34FB

  • UUID: 00002A05-0000-1000-8000-00805F9B34FB

UUID: 0000FFE0-0000-1000-8000-00805F9B34FB

  • UUID: 0000FFE1-0000-1000-8000-00805F9B34FB

The main part of the custom service UUID (FFE0) the main part of the custom characteristic UUID (FFE1) can be changed via AT commands. A second characteristic can also be added.


Get Started With the HM-10

First, lets use an Android device to read the services and characteristics from the HM-10. Power on the HM-10, you can use an Arduino for this but all we need is 5V to HM-10 VCC and GND to HM-10 GND.
If done correctly, the LED on the HM-10 should be flashing. When a connection is established the LED will be become solid on.

Checking the HM-10 with an Android Device

Depending on your Android device and the version of Android you are running the HM-10 may or may not show up when searching for Bluetooth devices under the Android Settings.

Samsung S7 with Android 6.0.1 – Finds the HM-10 and allows pairing.
Sony Z3 Compact running Android 4.4.4 – Finds the HM-10 and allows pairing.
Huawei honor pro 4 running Android 4.4.4 – Does not find the HM-10

HM-10_S7_SCRN_001HM-10_Sony Z3_SCRN_001HM-10_honorPro4_SCRN_001

The Samsung S7 and the Sony Z3 Compact find the HM-10 through Settings but the honor Pro 4 does not. When using a BLE app all phones can find the HM-10 though.

If you device does not find the HM-10 under Bluetooth settings, try using the BLE Scanner app.

The modules can be paired using the default pin 000000 (unless you have changed it of course).

To connect to the HM-10 and to read the services and characteristics we need to use a BLE app. Here I am using BLE Scanner. There are many other similar apps available such as B-BLE.


Reading the characteristics of the HM-10 using using BLE Scanner

Open the BLE Scanner app and find the HM-10. Tap the CONNECT button to get the app to connect to the HM-10 and start reading its properties.


Clicking the small down arrows will expand the services and display the characteristics.

Tapping one of the HM-10_BLE-Scanner_009_R_20 labels will read the characteristic value. For example, under Device Name, tapping the HM-10_BLE-Scanner_009_R_20 reads and then shows the device name value.

R = Read value
W = Write Value
I = Toggle indications on and off
N = Toggle notifications on and off

Under Custom Service you can see the HM-10s default service and characteristic values. You can also see that the HM-10s custom characteristic has Read, Write, and Notify attributes.

I mentioned earlier that BLE is all about services and characteristics and the HM-10 works by setting the value of a custom characteristic to match the value of the data to be transmitted (the data received via the serial connection). This can be seen when using the BLE Scanner app.

Using the circuit and sketch from Getting an Arduino talking to the HM-10 (see below), connect the Arduino and HM-10 and open the serial monitor. You should have something like the below. Use the “AT” command to confirm communication is working. If it is the HM-10 will reply with an “OK”

Now, in the BLE Scanner app, connect to the HM-10 by tapping the CONNECT button.

Open up the “CUSTOM SERVICE” section and turn notifications on by tapping the HM-10_SERV+CHAR_003_N_Icon_015 icon.

Now, what ever you type in the serial monitor should appear as the value of the custom characteristic within the BLE Scanner app

To send text from the app to the serial monitor, tap the HM-10_SERV+CHAR_007_Wicon_015 Write icon and enter something in the popup text box. You will notice that the value of the custom characteristic changes to whatever you typed. The text should also appear in the serial monitor.



Getting an Arduino talking to the HM-10

Next we will connect the HM-10 to an Arduino and try basic serial communication and AT commands.

Note: AT commands only work when the HM-10 is not connected. After a connection is made the commands are treated as data. “AT” is the exception, the “AT” command breaks the connection.


Connect the modules as per the following:
– HM-10 TX pin to Arduino D8
– HM-10 RX pin to a voltage divider and then to Arduino D9*
– HM-10 GND to GND
– HM-10 VCC to +5V

*The pins on the actual HM-10 (the small daughter board) are 3.3v only. They are not officially 5v tolerant so use a voltage divider or something else to bring the voltage down to 3.3v.

I am using AltSoftSerial to talk to the modules. AltSoftSerial uses pin D9 for transmit and pin D8 to receive. You will need add the AltSoftSerial library to the Arduino IDE before you can compile the below sketches.


The HM-10 is a 3.3v device. The breakout board converts the +5v vcc to 3.3v to power the HM-10 but the RX pin is still 3.3v. Therefore, we need to bring down the Arduinos 5V TX pin to 3.3V. A simple way to do this is by using a voltage divider made from 2 resistors. I use a 1k ohm resistor and a 2k ohm resistor. 1K+2K = 3K. 2K is 2 thirds of 3K and 2 thirds of 5V is 3.3v.

The Arduino will see the 3.3v signal from the HM-10 TX pin as HIGH so we can connect the HM-10 TX pin directly to the Arduino RX pin (D8).

HM-10_SerialMonitor_011_VoltageDivider_800I am using a premade voltage divider. Because I make a lot of this kind of breadboard circuit I make small breadboard modules. One of these is a voltage divider.

If you want to be special you can place a LED on the STATE pin. Remember to add a resistor. The STATE pin is 3.3v when HIGH so using Ohm’s law we find that a 100ohm resistor would be OK. I didn’t have one on hand so I used a 220ohm one that I did have. Using larger resistors is OK but you shouldn’t use smaller ones. The LED will blink in sync with the on board LED.


Serial Sketch

After building the circuit upload the following sketch. This is a simple serial in, serial out program. Whatever the Arduino receives from the serial monitor it relays to the HM-10. What ever it receives from the HM-10 it copies to the serial monitor.

The HM-10 does not like end of line characters* (newline and carriage return (/n/r)) and normally you would not add them to commands. Here I am using them but noted that although the sketch prints the characters in the serial monitor it does not send them to the HM-10. This help make the examples easier to read.

*The upcoming 6.05 firmware adds free style line endings(add or not add /n/r).

The sketch uses AltSoftSerial which will need to be added to the Arduino IDE or copied to the library folder before you can compile.

//  SerialIn_SerialOut_HM-10_01
//  Uses hardware serial to talk to the host computer and AltSoftSerial for communication with the bluetooth module
//  What ever is entered in the serial monitor is sent to the connected device
//  Anything received from the connected device is copied to the serial monitor
//  Does not send line endings to the HM-10
//  Pins
//  BT VCC to Arduino 5V out. 
//  BT GND to GND
//  Arduino D8 (SS RX) - BT TX no need voltage divider 
//  Arduino D9 (SS TX) - BT RX through a voltage divider (5v to 3.3v)
#include <AltSoftSerial.h>
AltSoftSerial BTserial; 
char c=' ';
boolean NL = true;
void setup() 
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");
    Serial.println("BTserial started at 9600");
void loop()
    // Read from the Bluetooth module and send to the Arduino Serial Monitor
    if (BTserial.available())
        c =;
    // Read from the Serial Monitor and send to the Bluetooth module
    if (Serial.available())
        c =;
        // do not send line end characters to the HM-10
        if (c!=10 & c!=13 ) 
        // Echo the user input to the main window. 
        // If there is a new line print the ">" character.
        if (NL) { Serial.print("\r\n>");  NL = false; }
        if (c==10) { NL = true; }


HM-10 AT Commands: Using the Arduino’s serial monitor to talk to the HM-10

Open the serial monitor and you should see something similar to:

The HM-10 requires commands to be in upper case and normally without line end characters added. Here the sketch takes care of the line end characters for us. It does not send them to the Bluetooth module but will print them when echoing the command to the serial monitor main window. This is not really required but it means the commands will be on individual lines and be easier to read in the following examples. Normally, when working with the HM-10, everything is printed on one line.

Remember when using other sketches or a USB to serial UART adapter to set line endings to “No line ending” at the bottom of the serial monitor.

At the bottom of the serial monitor, set the baud rate to 9600 and using the above sketch means we can have line end characters selected:

To see if the connections are correct we use the “AT” command. The “AT” command is used to confirm communication is working and all it does is return an “OK”. “AT” can also be used to break an active connection.

Enter “AT” (no quotes) in the text box and click Send. If everything is working you should see “OK”.

To check what firmware the HM-10 has, use AT+VERR?

To check the modules name use AT+NAME?, or use an Android device and search for Bluetooth devices. The default name is HMsoft.

This only works when the HM-10 is in Salve/Peripheral mode. When in Master/Central mode it does not broadcast its name.

To get the modules address, use AT+ADDR?

Change the name using AT+NAME. Later I will be using 2 HM-10s and changing the names will help identify which is which. As you can see from the below I have changed the name to HMsoft-38A3. The “38A3” are the last 4 digits of the mac address.

To get the modules Bluetooth characteristic, either use AT+CHAR? or use a BLE scanner.

To find the UUID use AT+UUID? This returns OK+Get:0xFFE0.


Common AT commands

Here is a list of the main AT commands. Remember that commands should be in uppercase and not include line ending characters (\r\n) unless you are using the above sketch in which case it does not matter if you include line end characters or not.

AT Test Command or Disconnect Command If the module is not connected to a remote device it will reply: “OK”
If the module has a connection then the connection will be closed. If the notification setting is active, the module will reply with “OK+LOST”
AT+NAME? Query the name Returns the name the module broadcasts such as HMsoft.
AT+NAMEnewname Change the name of the module Changes the name broadcast by the module. For example
AT+NAMEmyBTmodule changes the name to myBTmodule.
The maximum length for a new name is 12 characters.
AT+ADDR? Queries the HM-10s mac address Returns the address as a 12 digit hexidecimal number. For example, OK+ADDR:606405D138A3
Queries the firmware version number For example: HMSoft V540
AT+RESET Restarts the module. Returns OK+RESET
Will close an active connection while restarting.
AT+RENEW Restores the default factory settings. A quick and easy way to reset all settings.
AT+BAUD? Query the baud rate used for UART serial communication. This is the speed a host device like an Arduino uses to talk to the BT module. It is not the the speed used to send wireless signals between different modules. Returns the value 0-8, for example, OK+Get:0
0 – 9600
1 – 19200
2 – 38400
3 – 57600
4 – 115200
5 – 4800
6 – 2400
7 – 1200
8 – 230400
The default setting is 0 – 9600.
Remember that both devices, the Arduino and the HM-10 need to use the same baud rate. Garbage characters are usually a sign of mismatched baud rates.
AT+BAUDx Set the baud rate used for UART serial communication. x is a value from 0 to 8. See the above for wwhat value represents which baud rate.
Take care when using with an Arduino. The maximum baud rate the Arduino serial monitor allows is 115200. If you set the baud rate to 230400 with AT+BAUD8 you wont be able to talk to the module.
AT+NOTI Set the notification status If notifications are turned on, the HM-10 will reply to commands with a confirmation message or send out a message when certain events take place, like “OK” for the AT command and “OK+LOST” when a connection is broken.

AT+NOTI0 – turn off notifications
AT+NOTI1 – turn on notifications

AT+NOTI? Query the notification status Returns either 0 or 1:
0 – notifications are off
1 – notifications are on
AT+PASS? Query the password used for pairing. Replies with a 6 digit number like “OK+Get:123456” or whatever the current password is.
AT+PASS Set a new password. The password must be 6 characters long..
AT+PASS123456 sets the new password to 123456
AT+ROLE? Query the current Role; Master or Slave AT+ROLE? returns either 0 or 1.
0 = Slave or Peripheral
1 = Master or Central.
The default setting is 0 (Slave).
AT+ROLEx Set the device role. x is 0 or 1. To change to Slave/Peripheral mode use AT+ROLE0. This will return OK+Set:0
To change to Master/Central mode use AT+ROLE1. This will return OK+Set:1
AT+ROLEx mat require a reset before the changes take place.
AT+IMME? Query the start mode AT+IMME? returns either 0 or 1.
0 = Connect immediately (assuming a previous connection has been applied
1 = Wait for a connection command before connecting (AT+START, AT+CONN, AT+CONL
The default setting is 0 (connect on start).
AT+IMMEx Set the start up mode AT+IMME0 sets auto connect on start*
AT+IMME1 sets manual connection mode
AT+IMMEx is often used together with AT+ROLEx
AT+IMMEx mat require a reset before the changes take place.
AT+RESET Restarts the module
AT+RENEW Resets the module to the factory settings

*If there are no previous connections, HM-10s will auto-connect to any other HM-10 available (normally the one with the strongest signal). The HM-10 (by default) remembers the address of the last module it was connected to and if there is stored a previous connection this will take priority when the HM-10 is retrying to auto-connect.

For a full list of AT commands see the official data sheets:
Data sheet version 5.45 published Jan 2017.
Data sheet version 5.50 published Jul 2017.


Scanning for other HM-10s

For this example I am using 2 HM-10s; one connected to an Arduino as before, and a second simply powered.

To ensure I am using the default factory settings I have used AT+RENEW:

By default the HM-10 is in Slave or Peripheral mode and to scan for other devices we need to put it in to Central or Master mode. We do this using the AT+ROLE command.
AT+ROLE? queries what mode the device is in.
AT+ROLE0 sets the module to Peripheral mode.
AT+ROLE1 sets the module to Central mode.

In older versions of the firmware, AT+ROLE required the HM-10 to be reset either by cycling the power or by using the “AT+RESET” command. In the newer firmwares it auto resets itself (evident by the “” welcome message). Therefore, before we switch to Master/Central mode we need to turn off auto connect with AT+IMME. AT+IMME has 2 options; AT+IMME0 and AT+IMME1.
AT+IMME0 sets the module to auto connect on start up. This is the default mode.
AT+IMME1 sets the module to wait until it receives one of the connection AT commands (AT+START, AT+CON, and AT+CONNL) before attempting to make a connection.

If the modules are set to auto-connect, when we enter AT+ROLE1 the modules will auto connect before we get chance to enter the AT+IMME1 command (they auto-connect fairly quickly).

Use AT+IMME1 to stop the HM-10 auto-connecting.

Use AT+ROLE1 to put the HM-10 in to Central mode.

If you are using an older firmware you will now need to reset the module by either cycling the power or by using the AT+RESET command. If you forget to reset the AT+DISC command will not work.

To scan for other HM-10 modules use the Discover command AT+DISC?

Returned is the address of the module(s) found.


The “OK+DISCE” statement shows that the scan has Ended.

The results are stored in a list, the list starts at position 0, and can be used to make a connection using the “AT+CONNx” command rather than having to use the full address. The x is the index number or list position value. So, if the HM-10 only finds one module the result will be stored at index 0 and “AT+CONN0” can be used to connect to it. When more than one module is found the addresses will be stored in the order they are discovered.

After a connection is made the list is cleared. This means if you break the connection you need to use the “AT+DISC?” command again. For experimenting with AT commands using “AT+CONNx” is fine, but I suggest using the full address to make sketches more robust and easier to write.

Note: AT+DISC? will only find HM-10s that are set to Peripheral mode. You cannot scan for modules set to Central mode.


Arduino to Arduino using HM-10s

Connecting 2 Arduinos using 2 HM-10s is fairly easy. It is straight forward to make a connection and once the connection is established the HM-10s UART layer does all the work for you. The UART layer does mean you have no control over the actual BLE details though. To make a connection, all we need to do is set the main module to manual connection, set to Central mode, and then use the connection command AT+CON. Once connected the HM-10 transfers data by setting the value of a custom characteristic to the data you are sending. The receiving device then reads the value.

For this example I have 2 Arduinos and each Arduino is connected to a HM-10. Both are wired up exactly the same.


and if you are wondering where the second HM-10 is getting power from; the connections are round the back.

I am using 2 different Arduino IDEs. Version 1.82 as the main IDE and version 1.63 as the secondary IDE. This gives me 2 serial monitors. The Arduino on COM6 is #1 and the Arduino on COM9 is #2.



HM-10 to HM-10 manual connection

To make a connection we:
Set the second module to Peripheral mode (the default setting),
Set the main module to manual start mode using “AT+IMME1”.
Then set the main module to Central mode with “AT+ROLE1”.
Then use “AT+CON” to connect. Of course you need to know the address of the second module which can be found using “AT+DISC?”.


Now we have the address of the second HM-10 we can connect using the address or the list index. Here I am using the address and so the command is “AT+CONA81B6AAE5221”. You would need to change the address to suit the modules you are using.

If the connection is successful we get “OK+CONNA” and the LEDs on the HM-10s stop flashing and become steady on.

Now, everything entered in one serial monitor is transmitted to the other.




HM-10 to HM-10 automatic connection

The HM-10 can automatically connect on start up without using a connection command. When there are 2 or more modules and one is in Central mode it will search and connect to another HM-10. This is fully automatic and you have no control over which module it connects to although it would normally pick the one with the strongest signal. Of course, if there are only 2 modules it does not matter. When you have only 2 modules, set one to Peripheral mode and the other to Central mode. They should now connect automatically. Nothing else is required.

If there has been a previous connection, the device last connected to will take priority over other modules. After you have made a manual connection, break the connection (cycle the power) and when ready enter “AT+IMME0” (this turns on auto connect). Then reset the module by either cycling the power or using the “AT+RESET” command. The modules should now auto connect even when there are addition HM-10s in range.

The “AT+IMME1” command stops the auto connect happening. Remember that you cannot use AT commands while there is an active connection (the commands are treated as data) (except “AT” which breaks a connection) so to enter AT commands you need to turn of the remote module and reset the Central one.


HM-10 to HM-10: Turning an LED on and off

We now try LED remote control. This is a very simply example, when a button switch is pressed a remote LED comes on. When the button switch is released the LED goes out.

On Arduino #1 we add a button switch to D2 and on Arduino #2 we add a LED to D4.

The switch on Arduino #1 is pulled down with a 10K resistor. This means pressing the button switch makes the Arduino pin go LOW to HIGH.
The LED on Arduino #2 is connected inline with a 220 ohm resistor (330 ohm is also OK).




The sketch on the master Arduino uses 3 AT commands to set up the Central HM-10 and start the connection. These are the same commands we used in the manual connection example above.

BTserial.print("AT+IMME1" );
BTserial.print("AT+ROLE1" );
BTserial.print("AT+CONA81B6AAE5221" );

This is not really the best solution but it works and it keeps the example easy to understand. Of course, if the HM-10 is already in Central mode and in manual start mode the first 2 commands are not required. The delays allow time for the replies. You could, if you wished, check for the correct reply before moving to the next command. Change the address to suit the modules you are using.

If you are using an older firmware you will need to add a “AT+RESET” command after the “AT+ROLE1”.

You could do away with these commands by using the auto-connect mode.

After this, the sketch checks the status of the pin connected to the button switch and if it has changed sends out 1 of 2 commands.

  • LOW to HIGH. The button switch has been pressed so we want to turn on the LED. This is done by sending a “1” to the remote module.
  • HIGH to LOW. The button switch has been released so we want to turn off the LED. This is done by sending a “0” to the remote module.

Note that we are sending ascii “1” and ascii “0” not the value 1 and the value 0.

// Very simple debouce.
boolean state1 = digitalRead(switchPin); delay(1);
boolean state2 = digitalRead(switchPin); delay(1);
boolean state3 = digitalRead(switchPin); delay(1);
if ((state1 == state2) && (state1==state3))  
    switch_State = state1;  
    if (switch_State != oldswitch_State)
          if ( switch_State == HIGH) { BTserial.print("1" );  Serial.println("1"); }
          else                       { BTserial.print("0" );  Serial.println("0"); }
          oldswitch_State = switch_State;

The secondary Arduino simply checks for a “1” or a “0” and if it finds one of them it either turns the LED on or turns the LED off.

void loop()
    // Read from the Bluetooth module and check if it is a command
    if (BTSerial.available())
        c =;
        // 49 is the ascii code for "1"
        // 48 is the ascii code for "0"
        if (c==49)   { digitalWrite(LEDpin,HIGH);   }
        if (c==48)   { digitalWrite(LEDpin,LOW);    }

Here are the full sketches.

On the first Arduino we have HM-10_Example_01_simpleLED_Central.

// HM-10_Example_01_simpleLED_Central
//  Simple remote control using HM-10s: LED on. LED off
//  Pins
//  BT VCC to Arduino 5V out. 
//  BT GND to GND
//  Arduino D8 (ASS RX) - BT TX no need voltage divider 
//  Arduino D9 (ASS TX) - BT RX through a voltage divider
#include <AltSoftSerial.h>
AltSoftSerial BTserial; 
byte switchPin = 2;
boolean switch_State = LOW;
boolean oldswitch_State = LOW;
void setup() 
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");
    Serial.println("BTserial started at 9600");
    Serial.println(" ");
    pinMode(switchPin, INPUT); 
    // connect to the remote Bluetooth module
    BTserial.print("AT+IMME1" );
    BTserial.print("AT+ROLE1" );
    BTserial.print("AT+CONA81B6AAE5221" );
void loop()
    // Very simple debouce.
    boolean state1 = digitalRead(switchPin); delay(1);
    boolean state2 = digitalRead(switchPin); delay(1);
    boolean state3 = digitalRead(switchPin); delay(1);
    if ((state1 == state2) && (state1==state3))  
        switch_State = state1;  
        if (switch_State != oldswitch_State)
              if ( switch_State == HIGH) { BTserial.print("1" );  Serial.println("1"); }
              else                       { BTserial.print("0" );  Serial.println("0"); }
              oldswitch_State = switch_State;

On the second Arduino we have HM-10_Example_01_simpleLED_Peripheral.

// HM-10_Example_01_simpleLED_Peripheral
//  Pins
//  BT VCC to Arduino 5V out. 
//  BT GND to GND
//  Arduino D8 (ASS RX) - BT TX no need voltage divider 
//  Arduino D9 (ASS TX) - BT RX through a voltage divider
#include <AltSoftSerial.h>
AltSoftSerial BTSerial; 
char c=' ';
byte LEDpin = 4;
void setup() 
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");
    Serial.println("BTserial started at 9600");
    Serial.println(" ");
    pinMode(LEDpin, OUTPUT); 
void loop()
    // Read from the Bluetooth module and check if it is a command
    if (BTSerial.available())
        c =;
        // 49 is the ascii code for "1"
        // 48 is the ascii code for "0"
        if (c==49)   { digitalWrite(LEDpin,HIGH);   }
        if (c==48)   { digitalWrite(LEDpin,LOW);    }

The above works well but what happens when you reset Arduino #1 when there is an Active connection? The LED comes on.

When you reset the Arduinos but not the HM-10s the connection remains active and the AT commands in the setup() function get sent as data and any “1”s in the data get recognised as LED Commands. There is a few things you can do to stop this happening.

  1. Before sending the AT commands, send a welcome message to see if there is an active connection. The remote device would reply to the message.
  2. Check the HM-10 STATE pin before sending the AT commands. The STATE pin is HIGH when there is a connection.
  3. Set the modules to auto connect and get rid of the AT commands. In my opinion this is the best option.

I leave this to you to implement.

A litle later we control an LED with just a HM-10, no second Arduino.



HM-10 Programmable Pins

The HM-10 has 10 pins that can be user controlled, a couple are input only, the others can be input or output. Unfortunately, the pins we can control are not available on the breakout board so we need to attach a connection directly to the actual HM-10 (the small daughter board).



Pin function

The pins we can use are PIO-2 to PIO-11(B).


PIO pins can be used as input or output:

HM-10 PIN Pin Function

NOTE: PIO-2 and PIO-3 can supply up to 20mA. PIO-3 to PIO-11 are only designed to supply 4mA.


HM-10 pin control AT commands

Set the output of a pin HIGH or LOW.
pin = pin number from 2 to B
0/1 = 0 for LOW 1 for HIGH
To set pin PIO-2 to HIGH we use “AT+PIO21” and to set it LOW use “AT+PIO20”

Pin PIO2 can be used for PWN output.
x = a value from 0 to 9.

  • AT+PIO20 = LOW
  • AT+PIO21 = HIGH
  • AT+PIO22 = 100ms PWM
  • AT+PIO23 = 200ms PWM
  • AT+PIO29 = 800ms PWM

Note: The frequency is equal on off. So AT+PIO21 sets the pin to 100ms HIGH and then 100ms LOW.

There are different ways to read the pin state, either by reading each pin individually or reading them all at one time.

Read the current pin status.
pin = pin number from 2 to B.
To read the status for pin PIO2 use AT+PIO2? Returns the status in the form “OK+PIO2:0” OR “OK+PIO2:1”.
0 = LOW and 1 = HIGH.

Note the double question marks.
Query the state of pins PIO2 to PIOB (11).
Returns a single byte in the form “OK+Col:00” to “OK+Col:FF” that represents the current state of the pins PIO4 to PIOB (11). Bits 7 to 0 are mapped to pin POI4 to PIOB.

PIN 4 5 6 7 8 9 A B
BIT 7 6 5 4 3 2 1 0

Read the status of all PIO pins one time.
Returns 4 bytes in the form “OK+PIO?:0000” to “OK+PIO?:03FF”. The last 3 digits are mapped to PIO0 to PIOB; this mean 3FF is 001111111111 or all HIGH. Pins PIO0 and PIO1 (the first 2 digits) are used by the system and there return 0.

Pins PIO4 to PIOB can be used for analogue input.
Read the voltage on a give pin.
pin = PIO pin from 4 to B.
returns the actual voltage in the form of a 3 digit float.
To read the voltage on pin PIOA (10) use “AT+ADCA?”, returns “OK+ADCA:2.80” when 2.8v is applied to the pin and “OK+ADCA:0.00” when the pin is LOW or no voltage is applied.

Set the rate that the pin state registers (inside the CC2541) are updated (querying pins actually queries the register not the pin).
freq = the frequency to update in seconds and is a 2 digit number 00 to 99.
The command will only accept a 2 digit number, “AT+CYC01” rather than “AT+CYC1”.

Notice the double question marks.
Query the current frequency
Returns a 2 digit value in the form “OK+Get:00” TO “OK+Get:99”
The default is 10 seconds.

Pin states can also be set when the HM-10 is first powered on with AT+BEFC and also when a connection is established with AT+AFTC.

Set PIO pin status before a connection / on power.
pinValues = a 3 digit number, 000 to 3FF, that is mapped to pins PIO0 to PIOB.Remember that PIO0 and PIO1 are used by the system and only the pins PIO2 to PIOB are available for use.
To set all the pins (PIO2 to PIOB) HIGH set BEFC to “001111111111” which is “3FF” with “AT+BEFC3FF”.
Pins set using BEFC can be changed later using AT+PIOxv.

Set pin status after a connection is established.
pinValues = a 3 digit number, 000 to 3FF, that is mapped to pins PIO0 to PIOB (same as AT+BECF). Remember that PIO0 and PIO1 are used by the system and only the pins PIO2 to PIOB are available for use.
To set pin PIO2 HIGH when a connection is established set AFT to “001000000000” or “200” with “AT+AFTC200”

Controlling the pins while the HM-10 is connected to a microprocessor, like an Arduino, doesn’t really make sense, after all it is probably better to use an Arduino pin. Where this can be useful is where the HM-10 is being used stand-alone.


HM-10 Peripheral mode: remote pin control

The PIO pins on a remote Peripheral mode HM-10 can be controlled remotely. We can do this because the HM-10 allows the Peripheral device to receive AT commands over wireless and the pins can be controlled with AT commands. When the HM-10 is used remotely and the AT commands are received over wireless, the pin control commands work a little differently. Here we need to to set either MODE1 or MODE2.

PIO pins can be used as input or output:


NOTE: PIO-2 and PIO-3 can supply up to 20mA. PIO-3 to PIO-11 are only designed to supply 4mA.

To tell the HM-10 we want to control the user PIO pins remotely we use “AT+MODE1” and “AT+MODE2”.

Set the PIO pin control mode.
PIO2 and PIO3 to output and pins PIO4 to PIOB to input.

Set the PIO pin control mode.
PIO2 to PIOB as input.

In MODE1 only pins PIO2 and PIO3 are set to output. This means AT+PIOxv only works for these 2 pins. If you try to set one of the other pins the HM-10 will not respond, or, depending on the firmware, it may break and then re-establish the connection.



HM-10 stand-alone: Remote control an LED using MODE2

As a simple example to get started we will turn an LED on and off. First we will do this manually using AT commands and the serial monitor and once we have this working we can add a button switch to the Arduino and have the sketch do the work.


The Master or Central HM-10 is connected to an Arduino. The Peripheral or Slave HM-10 has an LED+resistor connected to PIO-2. I have the remote HM-10 powered from the Arduino but in practise you’d use a separate power supply such as a battery.

Central HM-10

Peripheral HM-10


Manual Process

After putting the circuit together upload the following sketch. The sketch uses the AltSoftSerial library which will need to be installed in to the Arduino IDE before you can compile the sketch.

//  SerialIn_SerialOut_HM-10_01
//  Uses hardware serial to talk to the host computer and AltSoftSerial for communication with the bluetooth module
//  What ever is entered in the serial monitor is sent to the connected device
//  Anything received from the connected device is copied to the serial monitor
//  Does not send line endings to the HM-10
//  Pins
//  BT VCC to Arduino 5V out. 
//  BT GND to GND
//  Arduino D8 (SS RX) - BT TX no need voltage divider 
//  Arduino D9 (SS TX) - BT RX through a voltage divider (5v to 3.3v)
#include <AltSoftSerial.h>
AltSoftSerial BTserial; 
char c=' ';
boolean NL = true;
void setup() 
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");
    Serial.println("BTserial started at 9600");
void loop()
    // Read from the Bluetooth module and send to the Arduino Serial Monitor
    if (BTserial.available())
        c =;
    // Read from the Serial Monitor and send to the Bluetooth module
    if (Serial.available())
        c =;
        if (c!=10 & c!=13 ) 
        // Echo the user input to the main window. The ">" character indicates the user entered text.
        if (NL) { Serial.print("\r\n>");  NL = false; }
        if (c==10) { NL = true; }

There are a few things we need to.
1. Set the Peripheral mode module to accept AT commands over wireless
2, Set the main module to Central mode
3, Make a connection
4, Use AT+PIO commands to turn the remote LED on and off

Set up the Peripheral mode device

To set up the Peripheral device we first need to tell it to accept AT commands over wireless. Unfortunately you cannot do this over wireless so we need to use wires and UART. You can use a computer with a usb-to-serial adapter or an Arduino and the serial sketch. I am using an Arduino and the serial sketch.


  • AT
  • AT+MODE2

Confirm the connections are correct and the HM-10 is reponding by using “AT” and then revert the HM-10 to default settings with “AT+RENEW”. HM-10s default to Peripheral mode.

Get the address. Used for connecting to later.

And finally set Mode to 2. This tells the HM-10 to accept AT commands over wireless.

The module with address A81B6AAE5221 is now set to Peripheral mode and set to allow AT commands over wireless. We can now move the module and add an LED to PIO 2.

Set up the Central mode device

After swapping the HM-10s we are ready to set up the Central mode module.


  • AT
  • AT+IMME1
  • AT+ROLE1
  • AT+PIO21 and AT+PIO20

“AT+PIO21” sets pin PIO 2 HIGH and “AT+PIO20” sets it LOW.

Make sure we are communicating by using “AT” and reset to the default settings with “AT+RENEW”.

Set to manual connection with “AT+IMME1”

Set to Central mode with “AT+ROLE1”

If you are using an older firmware you really need to update it. In the meantime you will need to reset the module before continuing.

Connect to the Peripheral mode module with “AT+CON88C255122F9E”. If the connection is successful the HM-10 will reply with “OK+CONNA” and the LEDs on the 2 HM-10s will stop flashing and be steady on.

To turn the LED on, use “AT+PIO21”

and “AT+PIO20” should turn it off

Note. Depending on the power on and the on-connection settings, the LED may come on when the remote HM-10 is powered or when a connection is made. The PIO pin setting can be set for power on using the “AT+BEFC” command (before connection)and the pin settings can be set when a connection is established using the “AT+AFTC” command (after connection).


Automating the process

Since the remote device is already set up we do not need to change it. To the Central mode HM-10, we set to auto connect on start up by using “AT+IMM0”;

To stop the Central mode module auto connecting, turn off the remote HM-10.
On the Central mode module enter:

  • AT
  • AT+ROLE1

“AT+RENEW” resets the HM-10 to the default factory settings and since IMME0 is the default setting, we do not need to change it.


Now, when the modules are powered on they should auto connect.

We now add a push button switch to pin D2.


and now upload the following sketch.

// HM-10_Example_03_MODE2_LED
//  Simple remote control using HM-10s: LED on. LED off
//  HM-10 in Central mode connected to an Arduino
//  HM-10, no Arduino, LED connected to PIO 2
//  Pins
//  BT VCC to Arduino 5V out. 
//  BT GND to GND
//  Arduino D8 (ASS RX) - BT TX no need voltage divider 
//  Arduino D9 (ASS TX) - BT RX through a voltage divider
#include <AltSoftSerial.h>
AltSoftSerial BTserial; 
byte switchPin = 2;
boolean switch_State = LOW;
boolean oldswitch_State = LOW;
void setup() 
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");
    Serial.println("BTserial started at 9600");
    pinMode(switchPin, INPUT); 
void loop()
    // Very simple debouce.
    boolean state1 = digitalRead(switchPin); delay(1);
    boolean state2 = digitalRead(switchPin); delay(1);
    boolean state3 = digitalRead(switchPin); delay(1);
    if ((state1 == state2) && (state1==state3))  
        switch_State = state1;  
        if (switch_State != oldswitch_State)
              if ( switch_State == HIGH) { BTserial.print("AT+PIO21" );  Serial.println("The LED is ON"); }
              else                       { BTserial.print("AT+PIO20" );  Serial.println("The LED is OFF"); }
              oldswitch_State = switch_State;

The sketch is fairly simple. When the button switch is pressed “AT+PIO21” is sent to the remote HM-10. When the switch is released, “AT+PIO20” is sent. “AT+PIO21” sets PIO-2 HIGH and turns on the LED, “AT+PIO20” sets PIO-2 LOW and turns off the LED.




HM-10 Stand-alone: Remote Light Sensor

Here we create a remote light sensor using a stand-alone HM-10 and a Light Dependent Resistor (LDR). The LDR is connected to peripheral HM-10 pin PIOB. Using MODE1 means we can read the value of PIOB from the Central HM-10 over the wireless connection.


HM-10 Set up

The two modules have been set to auto connect using AT+IMME1 and the Peripheral module is in MODE1.


The Master or Central HM-10 is connected to an Arduino. The Peripheral or Slave HM-10 has an LDR connected to PIOB. I have the remote HM-10 powered from a bread board power adapter but you could also use a battery. The remote HM-10 has +5v on vcc and +3.3v going to the LDR.



The sketch is very simple, it sends “AT+ADCB?” and gets the reply. “AT+ADCB?” requests the voltage on pin PIOB of the remote HM-10.

//  Sketch: HM-10_Example_04A_RemoteLightSensor
//  Master HM-10
//  Pins
//  BT VCC to Arduino 5V out. 
//  BT GND to GND
//  Arduino D8 (ASS RX) - BT TX no need voltage divider 
//  Arduino D9 (ASS TX) - BT RX through a voltage divider
//  Remote HM-10
//  HM-10 vcc to +5V
//  HM-10 GND to GND
//  HM-10 PIOB to LDR/CDS
#include <AltSoftSerial.h>
AltSoftSerial BTSerial; 
char c=' ';
char reply[30];
int pos = 0;
void setup() 
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");
    Serial.println("The HM-10s should be set for auto connect");
    Serial.println("The remote HM-10 should be set for MODE1");
    Serial.println("BTserial started at 9600");
    Serial.println(" ");
void loop()
    pos = 0;
    while ( BTSerial.available() )
        c =;
        reply[pos] = c;
    reply[pos] = '\0';
    Serial.print("Reply = "); Serial.println(reply); 
    delay (3000);


I am just displaying the results in the serial monitor but you could set up something like a flashing LED on the Arduino to warn you if the light is on (or off).



HM-10: Add a second Custom Characteristic

By default the HM-10 comes with a single custom characteristic under a custom service and a second write only characteristic one can be added using the “AT+FFE2” command. “AT+FFE2” was added in firmware 5.45 and extended in version 5.50.

The second custom characteristic only has a WRITE property no READ and the value of this characteristic is sent to the serial UART connection the same as the FFE1 characteristic.

Query the status of the second custom characteristic. Returns either 0 or 1.
0 = not active.
1 = active.

AT+FFE21 start the second custom characteristic
AT+FFE20 stop the second custom characteristic

Although the second custom characteristic is WRITE only you can set it to have a response or not using the “AT+RESP” command.

Query the write response status. Returns 0 or 1.
0 = Write without a response.
1 = Write with a response.

AT+RESP0 set the second custom characteristic to no response
AT+RESP1 set to have a response.

Arduino sketch

Note: I am using sketch SerialIn_SerialOut_HM-10_01.ino which can be downloaded here or copied from below. This sketch adds line end characters to the serial monitor window to make the commands easier to see. The sketch also removes any line end characters before sending the data to the HM-10. This means you can have “Both NL & CR” set in the serial monitor.

After connecting and uploading the sketch, make sure the HM-10 is working by using the AT command. Then use “AT+RENEW” to restore factory settings.

“AT+FFE21” starts the second custom characteristic. I am also adding a write with a response with “AT+RESP1”.

Cycle the power or reset the HM-10 for the changes to take effect.

The second custom characteristic is WRITE only. This means we can use it to send data to the HM-10 but we cannot use it to READ data. Anything we send to the HM-10 is output is the serial UART the same as the first custom characteristic.

To see it in action we can use the BLE Scanner app. Start the app, find and connect to the HM-10, expand the custom service and you should now see 2 custom characteristics:

In the FFE2 characteristic section click the HM-10_SERV+CHAR_007_Wicon_015 W button and a text input window pops up. Enter “HELLO” and tap send.
The characteristic value should change to “HELLO” and “HELLO” should also appear in the serial monitor:



Using The HM-10 With non-HM-10 Modules

Starting with firmware 5.42, Jinan Huamao changed how the HM-10 interacted with non Jinan Huamao modules. Prior the 5.42 the HM-10 connected and communicated with other modules just fine.

Using the later firmwares, I have so far had limited success with connecting HM-10s to the other UART BLE modules like the AT09 and BT05. The HM-10 will connect to the other module and data can be sent from the HM-10 to the remote device but I cannot receive data from the remote device. I had thought that using the self study function (AT+COMP1) meant that the HM-10 read the remote device characteristic’s properties and so meant that notifications would work. This does not seem to be the case though. I get the same results using the self learn mode and not using it. I think there is an issue with the HM-10 reading the other devices notifications.

Update: Additional commands were added in firmare v700 to help with using the HM-10 with other types of modules. I haven’t had chance to try them yet. See the readme that comes with the firmware download for details.
-Added new function used to support different brand BLE device
-Added AT+FINDSERVICES? command
-Added AT+FINDALLCHARS? command
-Added AT+NOTIFY_ON command
-Added AT+NTOIFYOFF command
-Added AT+READCHAR command
-Added AT+CHAR command
-Added AT+READDATA command
-Added AT+READDESC command
-Added AT+SEND_DATA command



HM-10 as an iBeacon

What is a iBeacon

You can think of a iBeacon as an electronic light house. It simply sends out timed signal letting people know it is there. When an app on a mobile device constantly finds a signal it can react is a specific way. For example, in a shop a special discount may be offered as you approach a pair of shoes. Or, matching chairs may be offered when you approach a sofa. Or, the lights turn on when you enter a room. iBeacons themself are not smart, they rely on an external device to react when a signal is received. of course, this does mean the device has to be looking for the signal.

The iBeacon signal consists of “advertisements”. These are small packets of data sent out at regular intervals. The advertisement has a standard format and includes 4 parts; UUID, Major, Minor, and transmit power.

This is a 16 byte value or string. The UUID is generally unique to a manufacturer or company. It can be used to group together related Beacons as well. For example, all Beacons in one store may all have the same UUID.

This is a 2 byte value or string that can be used to create a small group of more closely related Beacons. For example, the furniture department.

Is another 2 byte value or string and is meant to identify individual beacons. This could be used to identify which sofa the shopper is standing in front of.

Transmit Power/Measured Power:
This is not the signal strength as read by the mobile device. It is instead what the strength of the signal should be at 1m from the Beacon. Using the transmit value with the actual signal strength allows the mobile device to calculate the distance from the Beacon. In reality the Transmit power varies from manufacture to manufacture and is sometimes not very accurate, especially on the cheaper modules like the HM-10. My mobile phone is about 6 inches from the HM-10 and the Beacon scanner is telling me the HM-10 about a metre away… Luckily you can change the TX value using the AT+MEAS command.


Turning the HM-10 in to an iBeacon

For the following, I am using a HM-10 with V702 firmware. This means the baud rate is 115200 and I can use line end characters at the end of the AT commands.

To turn the HM-10 in to an iBeacon all that is required is “AT+IBEA1”. This puts the HM-10 in to iBeacon mode using the default settings:

Scanning for iBeacons

To scan for iBeacons you need a mobile device and a beacon scanner app. I am using Android with iBeacon & Eddystone Scanner by flurp laboratories but there are many other apps.


The first page lists all found iBeacons. The second page is a more detailed view for each iBeacon. Here we can see the HM-10 with the default settings.

UUID: 74278BDA-B644-4520-8F0C-720EAF059935.
Major: 65504 (0xFFE0)
Minor: 65505 (0xFFE1)
TX: -59 dBm

All these can be changed if required.

HM-10 iBeacon Commands

AT+IBEA1 Turn on iBeacon mode
AT+IBEA0 Turn off iBeacon mode
AT+IBEA? Query the iBeacon mode Returns OK+Get:1 if the HM-10 is in iBeacon mode and OK+Get:0 if it is not.
AT+MARJxxxxxx Set the iBeacon Marjor value/string AT+MARJ0xFFE0 sets the Major value to 0xFFE0.
Valid values are 0x0001 to 0xFFFE
AT+MARJ? Query the iBeacon Major value/string Returns OK+Get:0xFFE0 (or what ever the Major value is)
AT+MINOxxxxxx Set the module iBeacon Marjor version AT+MINO0xFFE1 sets the Minor value to 0xFFE1.
Valid values are 0x0001 to 0xFFFE
AT+MINO? Query iBeacon Minor value/string Returns OK+Get:0xFFE1 (or what ever the Minor value is)
AT+MEASxxxx Set the TX/transmit value AT+MEAS allows you to calibrate the measured power value. The default is 0xC5.
Valid values are 0x01 to 0xFF

Setting a new UUID is done in segments. The UUID is divided in to 4 parts and each part is changed separately using; AT+IBE0, AT+IBE1, AT+IBE2, and AT+IBE3.

The default iBeacon UUID is: 74278BDA-B644-4520-8F0C-720EAF059935. This is split up as:
Part 1 = 74278BDA
Part 2 = B6444520 (no hyphen)
Part 3 = 8F0C720E (no hyphen)
Part 4 = AF059935

AT+IBE0xxxxxxxx Set UUID AT+IBE012345678 sets the UUID first part to 12345678.
AT+IBE1xxxxxxxx Set UUID AT+IBE122334455 sets the UUID second part to 22334455.
AT+IBE2xxxxxxxx Set UUID AT+IBE2ABCDABCD sets the UUID third part to ABCDABCD.
AT+IBE3xxxxxxxx Set UUID AT+IBE3EEFFEEFF sets the UUID forth part to EEFFEEFF.
AT+IBE0? Query the UUID first part Returns OK+Get:0x74278BDA (or what ever the UUID first part has been set to).
AT+IBE1? Query the UUID second part Returns OK+Get:0xB6444520 (or what ever the UUID second part has been set to).
AT+IBE2? Query the UUID third part Returns OK+Get:0x8F0C720E (or what ever the UUID third part has been set to).
AT+IBE3? Query the UUID forth part Returns OK+Get:0xAF059935 (or what ever the UUID forth part has been set to).

Other Commands

AT+ADVI? Query the advertising interval Returns OK+Get:x where x is 0 to F.
AT+ADVIx Set the advertising interval x is 0 to F

– 0: 100ms
– 1: 252.5ms
– 2: 211.25ms
– 3: 318.75ms
– 4: 417.50ms
– 5: 546.25ms
– 6: 760.00ms
– 7: 852,50ms
– 8: 1022.5ms
– 9: 1285ms
– A: 2000ms
– B: 3000ms
– C: 4000ms
– D: 5000ms
– E: 6000ms
– F: 7000ms

The default for the HM-10 is 0 (100ms). Using a slower interval reduces the amount of power used.

AT+ADTY? Query the advertising type Returns OK+Get:x where x is 0 to 3.
AT+ADTYx Set the advertising type x is 0 to 3

– 0: Advertising ScanResponse, Connectable
– 1: Only allow last device connect in 1.28 seconds
– 2: Only allow Advertising and ScanResponse.
– 3: Only allow Advertising

The default is 0.

Option 3, only allow Advertising, disables connections and lowers the ampout of power used. This can be important when using battery operated iBeacons. When in iBeacon modes 0 and 1 the HM-10 is still connectable and data can be transmitted using FFE1 as usual.

AT+DELOx Set the iBeacon deploy mode Returns OK+DELOx where x is 1 or 2.
1: Broadcast and scan
2: Only allow broadcast only

Option 2 puts the HM-10 in broadcast mode only. This save quite a lot of power and this option should be used if you are creating a simply iBeacon. When using AT+DELO2 the HM-10 will remain boradcast only until the next power cycle (you need to remove power to reset it).

Low power iBeacon

To create a low power iBeacon:
– reduce the advertising invterval as much as possible using AT+ADVIx.
– make it non connectable using AT+ADTY3
– set it to broadcast only using AT+DELO2

When setting up a new iBeacon it is probably wise to reset the HM-10 after all the commands have been entered using AT+RESET.


HM-10: Updating the firmware

Note: Updating the firmware is non-reversable. Once you issue the OK+SBLUP command there is no going back.

One of the nice things about the HM-10 is that Jinan Huamao update the firmware on a fairly regular basis and make all the tools and the latest firmware available from the download centre on their website. They also have a guide on uploading new firmwares.

Like the Arduino, the HM-10 has a boot loader that makes uploading new firmwares fairly straight forward. You will need a Windows PC and a USB to serial UART adaptor though.

Tools required

– Windows PC.
– USB to serial UART adaptor.
– If you want to be extra safe a couple of resistors to form a voltage divider.
– Firmware zip archive.


Get the files

From the download Centre down load the latest HM-10 firmware zip file, place it somewhere convenient such as your desktop, and unpack it.

Note: The firmware for the CC2540 and the CC2541 chips are not the same. You cannot load the CC2540 firmware on the CC251 chip.
All the HM-10s I have use the CC2541 chip and the only firmware available on the Jinan Haumao website is for the CC2541 chip but it is still worth double checking.

This is a zip archive for firmware 5.47 which contains the following 4 files. Other firmwares may be different.
The two files we need are HMSoft.exe, and HMSoft.bin. HMSoft.exe is a Windows app that does the uploading and HMSoft.bin is the actual firmware. HMSoft.exe does not need installing, just double click to run it.

Connecting the HM-10 to a PC

I am using a 5v UART adapter so I am using a voltage divider on the TX pin. Many guides online show connections from a 5V UART adaptors (and 5V Arduinos) TX pin straight to the HM-10 RX pin. I do not advise it. The HM-10 is a 3.3v device and the RX pin is not designed for 5V. To reduce the 5V signal from the UART adapter to 3.3v I am using a voltage divider made from a 1K ohm resistor and a 2k ohm resistor.
The HM-10s TX pin is also 3.3v but 5V UART adaptors will read 3.3v as HIGH so we do not need to convert to 5V. Since I am using the HM-10 on a breakout board that has a 3.3v regulator I can connect 5V VCC directly to the VCC pin on the board.

If you are using a 3.3v UART adapter then you will not need the voltage divider but you will need more than 3.3v to power the HM-10. The voltage regulator on the breakout board requires a minimum of 3.6v to operate.

VCC and GND from the UART adaptor are fed to the + and – rail on the bread board.



Checking we can talk to the HM-10

After setting up the connections we need to check that we can talk to the HM-10. Any terminal app can be used but to keep it simple I generally use the Arduino IDE.

A couple of things to remember. The HM-10 likes commands in uppercase and it does not like line endings.

Open the Arduino IDE and make sure the correct COM port is selected. On my computer this UART adapter is Port 6. You need to remember the port number for later.

Open the Serial Monitor, select “9600 baud” and “No line ending” at the bottom, then enter “AT”. If the connections are correct you will get an “OK”.

If you do not get the “OK”:
– Check you have the correct baud rate. The default is 9600.
– Check that you have “No line ending” selected at the bottom of the Serial Monitor.
– Check that you have the TX and RX connections the right way round.
– Check that you have the correct value resistors and that they are in the right order.

After confirming that we have communication working we can check the existing firmware version with “AT+VERR?”.
As you can see the HM-10 I am updating is version 5.40.

To put the HM-10 in to update mode use the “AT+SBLUP” command. You should get a “OK+SBLUP” reply and the LED on the HM-10 will stop flashing.

We can now close the Serial Monitor.


Actually updating the firmware

Open the folder containing the firmware files and run the HMSoft.exe file. If you are using Win7 or later you may need to run the app in admin mode.

Load the bin file, enter the correct COM port number and then hit the Load Image button.

The firmware file is first written and then verified.

When finished the Download completed successfully dialogue box will pop up and the LED on the HM-10 will start to flash again.

We can now close the updater app and reopen the Serial Monitor to check the new firmware version.

Starting with firmware V700 the default baud rate changed to 115200. When updating from below V700 the HM-10 will need a factory reset before the new settings are activated.
AT+RENEW – restore factory defaults.
AT+RESET – reset the module.


Trouble shooting the firmware update

If you start the update and nothing happens you have probably left the Arduino IDE open. You need to close it to free up the COM port. The update app does not give an error message if the COM port is not available. It just sits there.

If you get a timeout error when updating try again. If you keep getting the error your UART adapter is likely to blame. I have a couple that are not good at high speed (I suspect they have fake FDTI chips) and they give errors when uploading and/or verifying.

If you crash out and the LED on the HM-10 remains solid on. It means it is still in upload mode. It will remain in upload mode even after cycling the power. Just start the update again using the update app.


HM-10 Downloads

HM-10 data sheet V5.50
HM-10 data sheet V5.45
Official update firmware guide
HM-10 Self-learning guide. Requires fw v5.42 or later.

HM-10 Sketches

Sketch: SerialIn_SerialOut_HM-10_01.ino
Sketch: HM-10_Example_01_simpleLED
Sketch: HM-10_Example_03_MODE2_LED
Sketch: HM-10_Example_04A_RemoteLightSensor



Jinan Huamao website. Note this sometimes gets reported as a malware site but I have not had any issues.
Jinan Huamao download page. The firmwares listed are for upgrade only and do not contain the whole file (no boot loader).

Using the HM-10 with App Inventor 2: Arduino, HM-10 and App Inventor 2


294 thoughts on “HM-10 Bluetooth 4 BLE Modules”

  1. From Lars. Sent by contact form:

    I’ve been following your tutorials for the HM-10 module, thanks a lot – they are great! I’m working on a project of my own, where I got communication going between a ATTiny and UNO. Smooth :D

    But now I’m concerned with power consumption and want to throw the HM-10 module connected to the ATTiny in sleep mode between transmissions. The problem I’m having is tat while power is on, its connected to the UNO. While connected I’m not able to send AT commands it seems. Have you looked at this? Do you know how I can send AT commands to a HM-10 with a active connection when I want to sleep it to save power?

    • The default setting is once a connection has been made the AT commands are treated like data and get transmitted.

      I presume the HM-10 connected to the ATTiny is the Peripheral , in which case you can set the Peripheral to allow AT commands over wireless with the AT+MODE command. You can then send the AT+SLEEP command remotely or use the AT+PWRM1 command to put the module to sleep when the connection is broken.

      • Hi Martyn,

        Sorry to bother you, but can you please confirm whether you have tested sending AT+SLEEP remotely after configuring AT+MODE to allow AT commands wirelessly? In my case unfortunately, most other AT commands are working, except AT+SLEEP for some reason!

        Take care.

  2. Hi, Im facing a problem dealing with these cc2541 based modules, maybe you can help me out. I would like to be able to know of the masters proximity from the slave device, with minimum power. How do you think I can accomplish this? What I was planing on doing was to get the module in master mode and scan for devices / compare with master MAC, but the FILT command was discontinued. Do you know why this happened? Cheers.

    • I somehow missed your question.

      You can use the RSSI value to determine proximity but be aware the value is not standard throughout different manufacturers.

      I am presuming you are using a HM-10 as the master device.

      The AT+DISA? command returns the advertising information from found devices and includes the RSSI value. AT+ DISA? will find non HM-10 cc2540/1based modules like the AT09 and BT05.

      The returned information is hex not ascii.

      OK+DISA –> Search start
      <OK+DISA:><Device Address><Device Type><Device RSSI><Rest data length><Rest data>
      OK+DISE –> Search end

      The AT+DISA? command requires fw 5.47 or above.

      I have been meaning to add this to the above guide but have not found the time yet.

  3. Hi Martyn:

    Great overview of the HM-10. Thanks for all your hard work putting it together!

    Some random notes:

    AT+DISI? when HM-10 is in central role scans for beacons in the area and returns all their info in ascii. A nice command for scanning the area.

    AT+ROLE1: When you are switching the HM-10 to central role, I believe that you have to do an AT+RESET command afterwards in order to make the central role take effect.

    AT+SCAN: As of firmware version 543, there is new scan duration command that you can use to make central role scans faster. The default is three seconds, which is quite slow, so it is nice to be able to change this to 1 second now.


  4. Al conectar con la aplicación Bluetooth Scan conecta sin ningun problema, pero, pero al tratar de agregarlo a la lista de dispositivo bluetooth, me indica que el dispositivo hm10 me aparese en el celular un mensaje que dice Vinculo rechazado por la tarjeta

  5. Hi Martyn,
    I’m doing something similar to your LDR example. I have a remote HM10 (which is connected to a sensor) and a central HM10. My problem is that I need to start the connection between the modules once the sensor detects, not before. How can I do this? I can´t send an “AT+CON” from the remote HM10 to do it. Thanks

    • I don’t think you can through software but you could try contacting Jinan Huamao on I have found them to be fairly helpful.

      Can the sensor to used to switch the power to the HM-10? Then have the HM-10s set up for auto connect. If not I would probably use another microprocessor.

  6. I haven’t been too motivated to use HM-10, but I wish I had known about this before……..
    The best rundown on HM-10 that I have seen. Great.

  7. Looks like a great overview of the HM-10.
    Hopwever I have a problem! Every time I type AT into the serial monitor, it disconnects the HM-10 and does not respond with OK. I have triple checked the wiring and thats OK, so any idea why this would happen?

    • When there is a connection “AT” will break the connection. Normally it will not give any response or reply.

      To get a response use “AT+NOT1”. Then when the connection is lost or broken the HM-10 will issue “AT+LOST”

  8. The module does not disconnect now, but I don’t get any response from the Arduino serial port, as shown in your article.
    Any idea how I can get it to respond?

    • Double check you have the correct connections; Arduino TX to HM-10 RX and Arduino RX to HM-10 TX.
      Double check the baud rate.
      Double check you have the correct pins defined in the sketch.

      After double checking, run the sketch, open the serial monitor and cycle the power to the HM-10. At power on the HM-10 issues “” as a welcome message. If you do not get the message in the serial monitor recheck everything again.

  9. Hi, great tutorial and I’m moments away from purchasing a couple of these things but do you happen to know what happens to any altered pin states should the central mode device lose power/connection with the peripheral device in a remote control situation – say I remotely set a normally low pin to high on the peripheral device to turn on an LED, will the remote device then set that pin low again immediately (or at least back to its confgured pre-connection state?) if the connection drops out? Thanks!

    • I haven’t tried this. If I get time at the weekend I will try a few experiments.

      When a new connection is established the pin(s) will be set based on the AFTC settings.

      I don’t know if losing the connection uses the BEFC settings or not. When I get time I will try.

  10. Hi,

    Is there any way of adding bootloader to the original firmware provided by the manufacturer as it is provided without?

    Original firmware have only 248KB (full firmware has 256KB).


  11. Im trying to run this hm10 module on the MEGA. Im using Serial1 as the bluetooth serial as I have connected it to pins 18/19 using the divider. Serial is my monitor which runs off pins 0/1, right? But I enter AT command into the serial monitor and I just get >AT printed out.

    • the >AT is echoed back from the Arduino, it is not the response from the HM-10.

      Yes, pins 0+1 are used for the serial channel to the computer. This is the main hardware serial channel.

      First thing to do is double check the connections. Then check them again. After this I would try using software serial or AltSoftSerial with different pins. This means you can use the sketch without changing it. If this works go back to the hardware serial.

    • I am having exactly the same problem, i can’t manage to receive an answer for the “AT” command. Something curious is that if WRITE from my phone to the module, i can see what i wrote in the Serial Monitor, but it doesn’t work from the Monitor to the phone (using BLE scanner app).
      If i do the same with a HC-06 module everything works just great!

      • This means HM-10 to Arduino is OK but you have a problem with Arduino to HM-10.
        I know you have the HM-06 working but it is worth double checking everting again. Make sure the voltage divider is connected correctly.

        As a test you can place an LED (+resistor) on the Arduino TX pin and see if it blinks when to send data.
        No blink means something wrong with the code.
        Blinks mean something wrong with the connection between Arduino TX and HM-10 RX

        • Thank you Martyn, my problem was with the voltage divider for the RX pin of the module. I wasn’t giving the pin enough voltage to represent a logic ‘1’

  12. hello
    The device shows up at BT05 on my phone and when I try to pair with it I see nothing… I connected it ble scaneer app. but not connected with mobile phone…what is the matter for it

  13. Hi, thank you for the detailed tutorial.

    I am trying to pair the HM-10 with another bluetooth device that requires me to provide a pin. I have successfully paid them, but have got now idea how I can get the HM-10 to send the pin (e.g. 512567) to this device.

    Would you know how to do this? Thank you!

    • The best option, if you have access to the other device, is disable password pairing. If you can’t do this it should work by setting the PIN on the HM-10 to match the other device.

      When pairing, the HM-10 will not ask for the PIN it will use its own PIN.
      (Assuming the HM-10 is acting as the Central device)

      • Thank you, this is where it gets challenging because my peripheral device is a Hexiwear ( wearable and each 6 digit pin it sends back is random. I have attempted to hack the hexiwear to always return the same pin and configure the HM-10 to use the same pin but there isn’t a response from the Hexiwear.

        It seems that there needs to be some kind of command that lets the HM-10 send a pin code to the hexiwear when it asks for one.

        In the raspberry pi, the command line utility that lets the central device provide the pin is bluetoothctl. I am not sure if there’s an equal in Aruduino, or have I gone beyond what a HM-10 could do.

        • Unfortunately the HM-10 does not have the facility to ask for a PIN, it just uses the one saved by the user, and so I doubt it is the right solution here.

          You will probably need to look at other BLE modules where you have control over he Bluetooth side of things, such as those from Nordic, or an Arduino with built in BLE like the 101.

          • Thank you Martyn, this has been a good learning journey and your blog post helped a lot.

            I learnt the possibilities and limitation of HM-10 and I am planning to approach my project differently. Instead of trying to connect to the hexiwear, I will probably try to build a prototype that uses the HM-10 with Arduino in the same way you connect 2 HM-10s.

            Thank you again!

            • Hi jackson I also got same problem you are facing which is pairing hexiwear to HM-10, will you be able to connect it? is there any other way i could connect hexiwear to arduino using some other ble modues if can u please name them .

              • actually, Hexiwear has the mode that dont need to Auth and Pin, so just using HM-10’s AT command: AT+TYPE0 (not pin and auth). Then it can connect. However, I just stop at connecting step. I can not receive or send data from HM-10. I am finding solution

  14. I was having some doubts about your suggestion to add a voltage divider to the RX pin, so I did some research. Hard to find a solid answer, but I did find an interesting discussion in the Arduino forums about a similar issue with another module. Paul__B suggests that using a diode might work even better than resistors (but clearly you are correct that resistors will likely get the job done).

    The electronics details are beyond my understanding, but just for the record, here’s a link of the discussion:

    I have been connecting my arduino pins directly to the HM-10 breakout RX with no bad results to date, but as someone mentioned, that doesn’t prove that what I am doing is correct! :-)

    • The spec for the CC254x chip used in the HM-10 clearly states it is a 3.3v device.

      Some time ago there were similar discussions about the HC-05 and HC-06. The specs stated the chips were 3.3v but people reported using 5V without problem. Other people report problems. I did some TTFs on 3 HC-05s by connecting the RX pin directly to 5V and then ran a a serial send in a loop. The RX pin on all the HC-05s eventually died. Since then I have always advocated better to be safe than sorry.

      There are many ways to reduce the voltage, I use resistors because I have them and they are very common. I have used diodes and also power regulators but prefer resistors.

      Diodes will also work, and I believe they react quicker than resistors, as long as you know the voltage drop, the 4001/4007 are usually (but not always) about 0.7v so 2 in series works (5v – 1.4v = 3.6v. 3.6 is just about OK). At least with resistors you can calculate and achieve exact voltages and resistors tend to be far more common in a hobbyist parts bin.

  15. Hello,

    Thanks for making this big tutorial about hm10, It is helpfull.

    I’m currently struggling with a functionnality I don’t succeeded in doing with HM 10; I would like to read characteristics from a distant devices throught HM10 (a mi flora).

    Communication diagram:
    ESP8266 HM10 Mi flora

    Communication between ESP8266 and HM 10 is OK and working well.

    I would like to read the temperature/moisture … , the corresponding characteristics can be found on existing python scripts working with BLE dongles or integrated BLE chips:

    With HM 10 I’m not able to read the data from the xiaomi miflora. Here what I have done:
    -Discover the Mi flora with the AT+DISI? command and recover the adress–>OK
    -connect to the Mi flora adress in master mode with AT+CON –>OK
    I get an OK+CONNA and after 3 carriage return, nothing happens after…
    I tried after to question characteristic but it returns only the HM 10 characteristic.
    I tried to put the HM 10 in slave mode but the connection to the mi flora fail.

    I’m using HMSoft V545

    Do you think it is possible to recover data from the miflora, if yes do you have some infos to give me?

  16. thank you for your detailed description of the HM-10 BLE module, especially the characteristic description

    i would have a few questions :

    after speed testing with a cortex m0+ (nxp lpc824 30 MHz) with dedicated speed test firmware and either a QT 5.9.1 speed test app on kubuntu 16.04 or an android speed test app on nexus 7 2013, my tests so far have discovered that the hm-10 can at best handle 1 byte / ms in and out
    if i compare this to a regular bt-spp based module it’s by a factor of 5 slower, 5 bytes / ms at 57.6 kBd (max speed at this baud rate) … maybe faster if i up the baud rate

    what i’m after is more inforrmation on the hm-10 :

    hm-10 min “connection interval” time … the ble specs defines it as 7.5 ms … what’s the hm-10 data ???

    hm-10 max “number of pkgs x-mit per connection event” … one or more ???

    since i need more throughput, but would like to stay with low cost chinese devices i was wondering if u had a chance to evaluate the hm-16, which is also cortex m0 based and claims to be faster

    HM-10/11 speed is about 2KB/seconds
    HM-16/17 speed is about 3-8KB/seconds

    as well as lower power

    HM-10/11 in automatic sleep mode 50~400uA
    HM-10/11 in active mode 8.5mA
    HM-16/17 in automatic sleep mode 50~1200uA
    HM-16/17 in active mode 6.5mA

    any ideas on your end would be highly appreciated

    cheers Klaus

  17. just found this as by-packed with the which partially answers one of my questions

    actually it was part of the spec sheet, and i missed it

    HM-10/11 CC2540/1 V538
    1. Add AT+COMI command, config Minimum Link Layer connection interval
    para1 value: 0 ~ 9; Default: 3(20ms);
    0: 7.5ms; 1: 10ms; 2: 15ms; 3: 20ms; 4: 25ms; 5: 30ms; 6: 35ms; 7: 40ms; 8: 45ms; 9: 4000ms
    2. Add AT+COMA command, config Maximum Link Layer connection interval
    para1 value: 0 ~ 9; Default: 7(40ms);
    0: 7.5ms; 1: 10ms; 2: 15ms; 3: 20ms; 4: 25ms; 5: 30ms; 6: 35ms; 7: 40ms; 8: 45ms; 9: 4000ms
    3. Add AT+COLA command, config Link Layer connection slave latency
    para1 value: 0 ~ 4; Default: 0;
    4. Add AT+COSU command, config Link Layer connection supervision timeout
    para1 value: 0 ~ 6; Default: 6(6000ms);
    0: 100ms; 1: 1000ms; 2: 2000ms; 3: 3000ms; 4: 4000ms; 5: 5000ms; 6: 6000ms;
    5. Add AT+COUP command, switch slave role update connection parameter
    para1 value 0, 1; Default: 1(Update on);
    0: Update off; 1: Update on;

  18. sorry for all of my posts … but my hm-10 is now stuck in fw download mode and i have no idea on how to get out of it

    i use my own optically isolated ftdi based usb to 3.3 V interface board which also feeds the hm-10 on the other end of the wires with 3.3 V power

    i know i don’t really need this optical isolation, but i always use it for years now and it always worked on everything … the power through feed is enabled with jumpers

    i switched the module down from 56k7 to 9k6 baud and put into the fw load mode

    the hm-10 led stays on, but the fw update pgm gets always into timeout

    there is only one restriction with my ftdi board, the max supported baud is 57k6 which is limited by the optical isolators, but i’m running now on 9k6

    any thoughts on how to get the hm-10 out of this fw upload mode

    maybe some others might run into a similar situation

    the only other observation i would like to mention was that my cpu chip did not have any readable info about 2540 or 2541 on it, but all other of my modules stated 2541

    tx, cheers Klaus

    • The HM-10 will stay in this mode until a new firmware is successfully uploaded. I believe the upload baud rate is internal to the upload app and the HM-10 boot loader and is not effected by the user set baud rate.

      I suspect the max speed on your board is not high enough. Do you have access to another usb serial convertor?

  19. i get about 1 byte per ms and if i think about right that the hm-10 has a default “connection interval” of 21 ms and one pkg contains a max of 20 bytes, then this would be the 1 byte / ms … just a thought

    now the hm-10 has an at cmd of AT_COMI which is supposed to change the link layer min connection interval down to 7.5 ms (ble min specs) one would think that this might get the speed up by 3

    well … not so fast … my hm-10 rev is 527, which does not support this cmd and the upgrade to a newer rev has bricked the only one i had soldered into my regular test setup … all others are in dedicated hw and i might have some somewhere, but that’s it for today

    thanks to i have now a few hm-16’s on order … what a day

    maybe this helps others to get a better understanding of the bandwidth limits of ble … assuming my thought are correct

    cheers Klaus

    • I haven’t done a lot with bench marks on the HM-10 and have only really used them with Arduinos which adds its own speed limits. When I need better through put or better control I use a different module.

      It wouldn’t hurt to contact Jinan Huamao. I have found them fairly responsive to emails and I have found them helpful :

  20. CHEERS! Just here sharing my experience that may help somebody reading comments, or maybe you (Martyn) could update the post with my hint!

    Used a CC-41-a module (A.k.a “HM-10 clone”) which I flashed firmware+bootloader v540 from this guide:
    Everything done with an Arduino MEGA without no voltage divisor for serial transmission (AFAIK thats risky, but I had no problem) and also using 5V as Vcc.

    Then (trying to update it to v550 or higher) I ended up here looking for a solution with the “timeout error”, and your advise about UART and speed problem helped me to figure it out!
    It was my Arduino sketch when doing Serial.begin(9600) ! Even when 9600 it’s the baud rate recommended, it looks like that’s too slow for the updating software! So I used 115200 as baud rate in the Arduino sketch and worked as spected!

    Hope it helps

  21. Hi martyn I have an issue connecting hexiwear to HM-10 since the hexiwear requires me to provide pairing code in to my HM-10 module. What are the other possible ways i could connect my hexiwear to an arduino using BLE module(since HM-10 doesn’t have the feature of asking for PIN which you mentioned in oneof the commands above).

  22. For what its worth, I’d like to add a few observations which others may appreciate.

    I’ve been working with a couple of Chinese clones (I’d like to call imitations).
    They are sold as HM-10’s but we all know the story about this by now.

    In the terminal, I extracted the firmware versions to be Bolutek- VER 3.0.6
    Both my LG G5 and an older Samsung G4 would see the BLE, but were refused connections via bluetooth on the phones.

    And so I upgraded the firmware to ver. 540, and bingo!…both phones can now connect.
    Going further, I tried upgrading the firmware as Martyn suggests…
    The upgrades went well, however EVERY other version of firmware beyond 5.4 would not allow my phones to connect.
    And so, I went back to pins 7,8,and 11 via the arduino nano on the cmd prompt to downgrade back to 5.4
    All AT commands work and a connection can be made by both phones.

    Kudo’s to Martyn for an outstanding site and such well documented info on these little wonders..
    I’m anxiously waiting for the control panel app to be BLE compliant…
    That will indeed be the cats miou!

    • After 5.40 Jinan Huamao changed how the HM-10 interacts with non- Jinan Huamao modules and introduced Self Learning Mode. I haven’t done anything with this (been meaning to just never got round to it) and as far as I can tell you need to match the UUIDs with the remote module and the the HM-10 will find out what properties the characteristic has (such as read/write/notify).

      With fw 5.40 and before this appears to be the default behavior.

    • Please be aware I haven’t used the HM-10 with this kind of beacon so the below are my thoughts only.

      The HM-10 is very limited in what it can do, and, in my opinion, does not represent true BLE. As a basic beacon scanner it should be OK but you may have issues if you want to connect to the beacon.

      In this case I would recommend another nRF module rather than the HM-10. One where you can create services and characteristics. Something like the one used in this video:

  23. Hi Martyn, thank you for your helpful tutorial on HM-10 Module. I have a module with the TI CC2541 chip but without the external 32kHz crystal connected to an Arduino UNO that reads a sensor. When arduino reads a data, sends it to the bluetooth module but what the reads on my BLE Scanner is often different from what arduino sent. Sometimes BLE Scanner receives a part of the initial string sometimes data are wrongs. Can it be due to the different firmware?


  24. Hey Martyn!
    Thanks a lot for all the information on this post. Really helped!

    One quick question:
    Is there any advantage on having the second write-only characteristic activated? For example, can you achieve a higher-speed or more robust data transfer?

    I’m sending packets of 100 bytes from my phone and some times it looks like HM-10 cannot keep pace (does not send the ACK message, [at least I don’t see it from the app]), so I was wondering if splitting the write and read in different services would help mitigate that.

    Thanks in advance!

    • I haven’t really done a lot with the second characteristic and for the few projects where speed and data integrity were critical I used a different system.

      I do suspect that the problem is likely to be with the UART interface though. I presume you are using UART, if so, what baud rate are you using? If it is fairly slow try increasing it. If using an Arduino, be wary of software serial. It does not like high speeds. If possible use hardware serial or at the very least AltSoftSerial.

  25. Hi Martyn! Thank you very much for creating such a helpful resource!
    I’ve looked through all the sections on your site and can’t find a clear answer to a question I have… I’d like to recreate the remote light sensor project above, but with a standalone HM11 module and using an android or iOS app to read the voltage value on the HM11 input pin (PIO3 it seems). Is this possible to do?



    • I’m not at home so can’t check but…

      The HM-11 can be used exactly the same as the HM-10 except it has less pins so the remote example above should work the same.

      For the battery, check the data sheet. The HM-10/11 has the facility to put the voltage level in to a characteristic. Can’t remember which or how though.

      It may also be worth while checking out the HM-sensor firmware. Again, I can’t remember the details but the docs are available on the Jinan Huamao website.

      • Thanks Martyn! It had occurred to me that using the HMsensor configuration might make it easier… I will flash the HMsensor firmware to the HM11 to see the difference. It is not the battery level that I want to transmit, simply a variable voltage on the input pin (it seems only PIO3 can be set up for this on the HM11). Perhaps it is my lack of knowledge of how to read the sensed pin data from the transmitted characteristic, but I can’t seem to read a varying voltage input to the HM11 using any of the iOS apps (HM10Control, Bluetooth Serial Pro, Liteblue, BLE Scanner etc.)

        • Update: Putting HM11 into Mode1 and using the AT+COL?? or AT+PIO?? command returns state changes on PIO3 pin (the only input enabled pin on HM11) at a rate set using AT+CYC[t], but does not recognise AT+ADC command. Suspect ADC function on HM11 is disabled – have emailed JNHuamao to confirm

      • Hi Martyl, I have been reading the comments here and think this comment best suited my question. I am wanting to advertise the Battery level in the response data. So that I can run AT+DISA? and then view MAC, RSSI, UUID and Battery level. I can’t seem to get this working.

        I have set AT+BATC1, to allow BATT advertising in the response data, but yet it is not visiable via AT+DISA?

        Could you maybe point me in the right direction so that I can advertise the BATT info in the response data of AT+DISA?

        Any help would be appreciated

        • DISA doesn’t add the battery information. DISA is used to scan (or discover) other BLE devices) only.

          It has been a while since I used the HM-10 but if I remember correctly the battery information is transmitted only in the advertising data. It should be covered in the data sheet.

  26. Hey,
    I am trying to create a device that has HM10 to connect serially with my laptop via its built in Bluetooth.
    My HM10 can pair with my laptop. However, I cannot send any data serially because I do not know how to setup my built in Bluetooth to act like a serial port.
    I tried to create a new COMM port but it won’t find my HM10.
    Any help please?

      • hi, i have a very simular problem. i used the app you mentioned, and i can get a connection on my windows 10 laptop. i also found out my build in bluetooth drivers are LE compatible. now the problem, when there is a connection, it doesnt show as a COM port in device manager. how can i get my hm10 (i have a real one, not a fake) to be recognized as a COM port?

  27. Has anyone had any luck connecting to these things on Android 8.1?

    I have a CC41-A clone, and my Pixel 2 nor my wife’s Pixel 1 (both on 8.1) won’t even find them in BLE scanning apps. I have been able to issue AT commands over the serial interface successfully via an Arduino, but no matter what I just can’t see it in Android. I’ve tried AT reset, changing the name, etc, but with no luck.

    I thought I may have a dud unit with a bad aerial or something, but I fired up my RPi 3 and can actually see it when I scan with hcitool there. So it seems to be late version Android specific perhaps?

    There seems to be a tiny bit of discussion around this online, but I can’t find anything particularly useful – eg

    At this point I’m thinking I’ll just use an HC-05 or something and ditch BLE for my application, but it’s a bit of a pain as I’ll need to wait for more parts to arrive. Cheers!

    • It an issue with Android 8. There are still many problems reported with Android 8 in general and a quick google “android 8 ble not good” will return quite a few results. Google say they are working on a fix but the BLE issues were reported last year and the problems still persist.

  28. This is a great writeup, thanks a lot. I have one question left though. Is there a way for the bluetooth module to scan for smartphones it has been paired to before and auto connect to them the same way a bluetooth headset does? Somehow nobody was able to achieve it as far as my research shows.
    I do not need to communicate with the smartphone, just connect to them automatically as an authentication process for a switch I want to trigger afterwards. Is there a way without using an android app for that?

    • This is not something I have done with 2 modules but not with a smartphone but I have some thoughts.

      The phone, by default, is the master device. This means it is the phone that scans for the BT modules and connects when it finds a BT module it has previously been paired with. For the BT module to be the master device would require additional software on the phone.

      Headsets use the HID profile which has different connection methods (such as auto connect) and I am not sure auto connect works with the HM-10. I haven’t tried though.

  29. Great tutorial. I am using the HM-11 for a project and having terrible luck getting it working. The firmware on the HM-11 is V546.

    I am trying to scan for BLE peripherals and iBeacons nearby but I am only able to find my devices if they are within about 1 foot. Once I move the device farther from that the HM-11 is unable to find it. I am using other HM-11’s and some nRF51822 boards for the peripherals/iBeacons.

    To scan for peripherals:
    AT+ROLE1 //set as master
    AT+IMME1 //wait for commands after reset
    AT+RESET //reset
    AT+DISC? //start discovering

    To scan for iBeacons:
    AT+ROLE1 //set as master
    AT+IMME1 //wait for commands after reset
    AT+RESET //reset
    AT+DISI? //start discovering

    I have my power set at 6dbm (AT+POWE3) on the HM-11 central. I am using a 100ms advertising interval for the peripherals/iBeacons. I am still unable to find my peripheral/iBeacons further than about 1 foot away which is quite a problem. I am pretty sure that my hardware is good because I have tried it on multiple HM-11’s which I bought from Digikey.

    Has anyone experienced this? Any help would be greatly appreciated.

  30. Comment from Alex:

    Thank you for your most informative posts, I have found them really useful and clear in my Arduino dabbling !
    I am interested in trying to connect a DS18b 20 to pin 34 (?) of the HM10 and henceforth being able to include the temperature information in the advertising data, to be read by another HM10, connected to an Arduino (Mega).

    Looking at your posts, it seems you know how this could be made to work, yet I haven’t seen exactly how to do this. Please could you point me in the right direction?

    I was sort of assuming that one would use AT commands to instruct the HM10 to read the one wire data from the DS18b 20 on pin 34, then attach that data to the advertising data, but can this be done once, or does this AT command have to be sent to the remote HM10 every time you want the temp data?

    I would be most grateful for any assistance you could provide.
    Kind Regards

  31. Hi, thanks very much for this page as it has been incredibly useful, although i have managed to get a few knock-off ‘HM-10s’ and have got two working and connecting. I have also managed to unknowingly purchase two MLT-BT05 chips, which look very similar to the HM-10s. I have ran your code and can get the serial monitor to display text i send through my phone to the MLT-BT05 however i can’t get the AT commands to work.

    Using the normal AT commands there is no response though after playing about with it I’ve noticed it will respond to “ATAT” with OK (this will not break an active connection) and other doubled up commands such as “AT+HELP?AT+HELP?” wit ERR.

    As far as i’m aware i have it set up correctly with 9600 BAUD and Both NL & CR (as the MLT-BT05 requires). Have you seen anything like this before or can you offer any advice. any help is much appreciated.

    Cheers Ciaran

  32. After update Android OS from 7.0.x(Nougat) to 8.0.x(Oreo)
    HM-10 is no longer discoverable on the phone at all.
    Have anyone facing this problem?
    I’m not sure is this Android OS bug or HM-10’s problem.

  33. Dear all,

    we are working on HM10 and firmware version is 2.0.
    We are trying to update the firmware using arduino but nothing reply from it.
    We follow as same step as mentioned but still get same issue.

    AT+HELP command not work so please suggest right direction what we do ?


  34. Hello,
    We are using HM10 and version is 2.0 so we need to update the firmware but
    when we send command “AT+SBLUP” but get error resturn back.

    need help to sort out issue.


  35. Hi Sir
    i am using HM-10 BLE device and i want to upgrade firmware via Arduino so i getting error .I done this step
    STEP 1 CCLoader.ino skecth upload with Arduino IDE
    STEP 2 Connect HM-10 to Arduino WIth
    STEP 3 open CMD and Wirte CCLoader.exe 9 HMSoft.bin 0 or 1
    in Step 3 i will get Wait for Arduino respond and Nothing is Done

      • Hi Sir
        i am using HM-10 version 2 upgarde firmware so
        i Done Send Command AT then replay is OK
        but i Send command OK+SBLUP but no responce and
        i open HMsoft.exe Load bin file but Error geting “”Timeout Waiting from target responce

  36. Hello! Would you like to tell me, what i need change? I used first scatch(simple serial) and ble scanner. I wrote in terminal and i saw value in ble scanner. I have a problem, when i wrote command AT, then i saw it in value without response.

  37. i wanted to update my firmware but and error occurs, “Timeout waiting for response from target”. please help thank you in advance

  38. Hi, thank you for your article. I have a problem that when I enter commands such as “AT+CON” OR “At+disc?” They output nothing

  39. Very helpful doc.Thank you.

    Occasionally, I get a null character back at the end of the response to AT+RESET or AT+RENEW. It’s easy enough to add some code to throw it away, but do you know what’s causing it?


    • For the older firmware’s I haven’t come across this or I simply haven’t noticed.

      If you are using a new module with the latest firmware (6.05 ) then it may be line end characters.

  40. Would it possible to configure master device to switch among multiple Peripheral modules?

    This is may be scenario if you need to read samples from multiple sensors from a central devices via bluetooth.


    • Using the HM-10 to would need to connect to each remote device in turn.
      1 – connect to remote #1
      2 – read data
      3 – disconnect
      4 – connect to remote #2
      5 – read data
      6 – disconnect
      With other modules, like the RN4870, you could use advertisements. This would allow you to read data without making a connection.

  41. Hi Martyn. Great post, Thanks.
    I have been using hm-10 modules with firmware v540 for a long time with no problem. Recently I bought some modules with firmware v604 and all seem not to be able to wake through uart. Meaning, when I send a long text the module used to respond ok+wake and then I was able to send other at commands. Now the long text does not seem to return anything and the module stays in sleep mode. I downgraded to firmware v540 successfully but then the module was not discoverable in role0 and did not discover any other devices in role1.
    Have you noticed this behaviour? Do you have any idea how to resolve this? I saw in a comment above that there is a 605 firmware. Where can I find this? I did not see it in Jinan Huamao website.

    Thanks a lot!

    • I haven’t but I haven’t really used the HM-10s for a while. Contact Jinan Huamao support. I have found them quite helpful. Bare in mind that English is not their first language so keep the questions as clear and short as possible.

  42. Hi Martin, It’s a very helpful post.
    Is it possible to connect an hm10 as master to multiple hm10 slaves like a star or mesh network?

      • Hi, Martin I am using arduino uno as USB to TTL Converter (by grounding RESET Pin of Arduino) for entering AT Commands. So, how to implement this (connect read and disconnect)

  43. Hi, thanks for this very detailed and useful tutorial.
    I can’t get READ property working in BLE Scanner APP. Garbage characters are always read: “_@9”.
    How can I set the value of a READ property in HM10?
    I tried sending chars on UART and then pressing R in Ble scanner, but the same “_@9” always appears.
    Thanks a lot,


  44. Hi all,
    I tried AT+SLEEP in HM10. Led is switched OFF, but the module is still visible by BLE Scanner and connection can be established.
    Is this the right behaviour? I expected the module to be switched off on Bluetooth.

  45. After more tests.

    – The value 0x7c010a5f4a39 is always reported to the APP when a read is attempted.
    – If Notification is enabled in the APP, bytes sent by the device are correctly reported by the APP.

    As reported in the “Product Parameters”, READ characteristic is not mentioned:

    “Characteristic: Notify and Write (Modifiable use AT+UUID command)”

    Is READ characteristic really supported?



  46. I am trying to connect HM-10 with VNA2-BT Adapter (BLE to CAN).I am unable to discover and connect VNA-BT.
    i am issuing commands:
    Can someone tell me how to establish the connection?

  47. Hi martym
    I m trying to connect my HM-10 module to smartphone via Bluetooth …….and I m also trying to get the RSSI value …… can you help me how to do it???
    none of the command given below is working :

    • I think there are a couple of ways to get the RSSI value.

      1. use AT+SHOW2 or AT+SHOW3 before the AT+DISC command

      If AT+SHOW1 is setup, you will receive then Name information as follow
      Recv: OK+NAME: xxx
      After send Name value, will send two extra “\r\n” value ASCII byte

      If AT+SHOW2 is setup, you will receive then RSSI information as follow
      Recv: OK+RSSI: xxx\r\n

      If AT+SHOW3 is setup, you will receive then RSSI information and Name information
      Recv: OK+DIS[P0]:234567890123
      Recv: OK+NAME: xxx

      2. Use OK+DISC[P0:P1:P2:P3:P4]
      P0: Device MAC (6Byte)
      P1: Device Type(1Byte)
      P2: Device RSSI(1Byte)
      P3: Rest Data Length
      P4: Rest Data

      3. use AT+RSSI
      This only works when there is a connection.

      • Hi.

        I am trying to connect my HM-10 module to a BLE device. My hope is to connect the two devices and the check the RSSI value of the BLE device when they are connected. The BLE device is the peripheral device.

        My problem occurs because I am unable to send AT commands when the connection is established. So if I try AT+RSSI when the devices are connected nothing will occur.

        I cannot do option two because my BLE devices goes to sleep when not connected so it isn’t picked up with the Scans (AT+DISC?)

        I have run AT+ROLE1 and AT+IMME1 follwed by AT+RESET so that it is in the central role.

        Do you have any tips to make the AT commands work during the connection (Override default behaviour where anything entered is precieved as data)? Or another way to find RSSI when connected?

        • Hi.

          I am trying to connect my HM-10 module to a BLE device. My hope is to connect the two devices and the check the RSSI value of the BLE device when they are connected. The BLE device is the peripheral device.

          My problem occurs because I am unable to send AT commands when the connection is established. So if I try AT+RSSI when the devices are connected nothing will occur.

          I cannot do option two because my BLE devices goes to sleep when not connected so it isn’t picked up with the Scans (AT+DISC?)

          I have run AT+ROLE1 and AT+IMME1 follwed by AT+RESET so that it is in the central role.

          Do you have any tips to make the AT commands work during the connection (Override default behaviour where anything entered is precieved as data)? Or another way to find RSSI when connected?

  48. Hi Martym,

    is this HM-10 able to achieve Piconet and Scatternet?
    I am looking for a bluetooth module that, can connect and communicate to multiple slave (up to 7) in a round robin manner. Could you advice? Thanks in advance

    • Unfortunately no and I am not sure if any of the cheap BLE modules can. The only ones I know of at the moment are the Microchip BTLC1000 and SAMB11.

      To form a network with HM-10s you need to connect and disconnect to each node in turn. This is cumbersome but possible.

      • Hi Martyn,

        I am using BLE 112 dongle with PC. Using the Bluegiga GUI tool, dongle is successfully read the data from HM-10. However, I unable to write data to the HM-10 with Service = FFE0; Character = FFE1.

        Could you advice? what i need to do in order to send data to the HM-10? or what need to be done on HM-10 in order to receive data

        • i had fix the write issue by using two char id with AT+FFE21
          then write to UUID:CHAR = FFE2.

          For the read, UUID:CHAR =FFE1 is always give me the HM-10 address. My labview software is not able to catch the data except the default data (HM-10 Address).

          Please advice. is there any way to make the HM-10 stop overwriting the data in FFE1?

  49. Have you located the schematic for the breakout board for the module you shown above ?
    I am trying to connect to an FTDI Basic adapter from Sparkfun.
    I was under the wrong impression that the Rx/Tx lines were also 5V as the documentation did not say they were 3.3V.
    Have I destroyed my modules ?

  50. I think I bought one as shown above from the link below.

    I believe this is exactly what you have and the product title says “Bluetooth 4.0 module with logic level translator” but you stated “You should note that the RX pin is is still 3.3v and when using a 5v”

    If I use it without a voltage divider, it’s going to die eventually. right?

  51. Are there any recommended vendors for the HM-10? There’s some on Amazon but I’m concerned about getting fakes so I’m avoiding eBay + ali express.

    • I don’t have recommanded suppliers. All I can suggest is to check and then double check with the vendor. It is likely that the genuine HM-10s are a little bit more expensive.

  52. Hey man!

    First off, thanks for writing up such a detailed article! It really helped me out connecting my two HM-10 modules to the uno and nano that I’m currently using.

    But I am having a slight problem with using one that has a button and sending a “1” to the other to light up an LED

    So far on both serial monitors are reading correctly, from the Master is sending a “1” and the slave is receiving the appropriate value. But for whatever reason, the LED isn’t lighting up when it gets the “1”

    For sanity sake, I double checked everything with the “Button” basic sketch that’s on the IDE and it works.

    Got any idea of what could be wrong?

  53. Hello!

    Nice work on the tutorial.

    Do you know how to get the exact time of arrival of the signal of each nearby device using the AT commands? Thanks!

    Best regards,


  54. Martyn,
    Thank you for such a wonderful introduction to HM-10 hardware.

    One question regarding the suitability of the HM-10 for my first project:
    I have an old salvaged instrument which collects data (temperature) and transmits via 1wire (Tx) and ground. The instrument is “dumb” and just spits out all of the collected data whenever a button is pressed. The output rate is fixed at 19,200. It does not accept any commands via an Rx signal.

    I’ve read that the default factory baud rate is set at 9600, but it can be changed via AT+ commands via the serial port. QUESTION: Once the HM-10 baud rate has been changed – will it “remember” the new baud rate after the power is removed from the HW-10?

    Thank you for your efforts.

    • The baud rate is changes with AT+Baud. See above. Once set the baud rate is remembered and does not change when the module is reset.


  55. Martyn,
    This is very encouraging! Thank you for the reply.

    Can you recommend a supplier for known good (non-fake) modules? Preferably modules with the breakout board already attached?

  56. Hello.

    Thank you for your detailed article.

    I want to send at+disc? command in order to scan for nearby BLE beacons.

    However, it takes up to 3 seconds to respond with the at+disce.

    I want to discover the ble beacons instantaneously or less than a second.
    Am i missing something here ?
    Is there any at command i can send to keep the HM-10 in scanning mode without waiting for the at+disce to end my scanning process?

    Thanks a million for everything!

    • Unfortunately it can take a few seconds for a full scan on the HM-10. If fast scans is something you need it may be better to look at more high end modules, especially ones that can scan in the background.

  57. Hello,
    Thank you for this document, it is of a great help for the understanding of Bluetooth LE.
    I need to connect a heart rate sensor (Polar OH1) to a Windows 10 PC. I tried the Universal Windows Platform (UWP) without success (problem of version, difficult connection, ..). On the other hand, the OH1 sensor works very well with an Android Smartphone (BLE scanner application).
    I am wondering about the possible operation of the OH1 sensor with an HM-10 module in master mode.
    In order for the OH1 sensor to send the heart rate value it must first be connected, then send 0x01 to the “Client Characteristic Configuration descriptor” according to the developer documentation:,_H7,_H10_and_OH1_Heart_rate_sensors
    How to do with the OH1 module?
    Thank you for your reply.

    • I think it is unlikely the HM-10 will work for this. It is designed for transparent serial bridges rather than connecting to other devices and has a limited range of UUIDs.

      You need a BT modules that allows you to created you own profiles and UUIDs or one that has the heart rate profile already set up.

  58. Hello,
    Thank you for your reply.
    As I understand it, the HM-10 module does not have a GATT service.
    I will try other Bluetooth LE modules, which has GATT service and central role (eg Microchip RN4870).

  59. Hello,

    Thank you for the article, it’s an invaluable reference guide.

    I’m trying to read sensor data from a Wiced Sense2 Kit as the slave device, using the HM-10 in master mode.
    Here’s the description of the custom service (customized UUIDs and writable custom characteristic, to match HM-10 internal GATT) using BLE Search:

    Wiced Sense 2 internal GATT:
    Custom Service:
    Properties: READ, WRITE, NOTIFY
    Hex: 0x00000000…
    Client Characteristic Configuration (R): 0x9202 (Notifications or indications disabled)

    I found, in Jinan Huamao’s website, an information about the upgrade of the AT+CO command (in V603, mine is in V605) to accept also Device Write Property UUID and Device Notify Property UUID, after the original Device Type and Device MAC parameters.
    I managed to get the AT+CO working without the additional UUID parameters, but I get a blank reply when I send both additional parameters as 33EF.

    Have you had experience with notifications using HM-10 in master mode?

    Best regards,

    • I had some issues getting the HM-10 fully working with other modules. It was fairly straight forward for the other module to read data from the HM-10 but not the other way around. Admittedly I didn’t put a lot of effort in to this. I believe (not sure) that is was an issue with notifications. At the time I was playing with other modules so it was easier for me to simply not use the HM-10.

      I have found Jinan responsive to emails so it would be worth while contacting them. If you do, please let me know how yo get on.

  60. Martyn- I can successfully SCAN my HM-10 board and communicate with it (explore UUID VALUES) using LightBlue in iOS.
    QUESTION-The HM-10 does not appear in the “My Devices” list screen in iOS (Settings:Bluetooth:MyDevices). I expected it to show in the list along with my various devices -including my car! Shouldn’t the HM-10 show up there? Regards, and thanks for your efforts.

  61. Não estou conseguindo conectar o modulo com meu celular POSITIVO SELFI. O que pode está errado? Sempre aparece uma mensagem de erro “PIN OU SENHA INCORRETOS” já mudei a senha e nome do modulo mas nada adiantou. desde já agradeço sua ajuda.

  62. Thanks for sharing this!

    I wonder if it is possible to use higher than 230k baudrates. Also, have you tried using SPI instead of USART? (which, according to the IC datasheet, should support up to 4 MHz).

  63. This is a great tutorial, thank you !

    A word of advice to people who can not follow instructions :) : I tried to use 12k and 22k resistors to create the voltage divider. This does not work (although it worked with an HC05 and an AT09). On a genuine HM10, using 12k and 22k results in the RX pin staying at a higher voltage (3.35V) than what the divider provides (2.9V). I am guessing there is a pull up resistor, and with 10k+ resistors when the arduino TX pin goes LOW, the voltage on the HM10’s RX pin does not go low enough to reister as LOW.
    After switching to 1.2k and 2.2k (trying my best to follow instruction with what I have at hand ;) ) the module works as expected.

    • Man, I’m so glad I saw this post after tearing my hair out and spending a whole day on this. I got my multimeter out and checked the resistors as I cannot read colour codes on them anymore, ahh for my youth. Any the 1k was not 1k but 10k. Hence no OK. I got the right ones and then inadvertently put them the wrong way round, still no OK. Did what Antoine and you said and rechecked and yay now getting OK. What a battle. Thanks for such great articles, really appreciate it. Gordon

  64. Hello,

    I think there is a mistake in the section explaining the ‘remote control pin’ features: in the table, MODE 2 column lists all the pins as OUTPUT.
    However the following text says :
    Set the PIO pin control mode.
    PIO2 to PIOB as input.’


  65. Hello,

    I need some help with AT+CYCxx command.
    The manual says:
    Required AT+MODE1, when PIO state is change, module will send OK+Col:[xx] to UART or remote side. This command is set send interval.
    What I experiment is:
    when all (8) inputs are LOW nothing is transmited and when one or more are HIGH transmision is at the speed fixed with CYC command.
    Is this correct? I really need the other behaviour.
    Thank for help

  66. Fantastic article. Thanks for writing this up. I will be reading it again more closely since I’m trying to write a iOS app to use BLE. Do you have any articles that show simple example code Swift 4.x in Xcode 10.1 for how to connect and read / write bytes in iphone app?

  67. Hi,

    I have some questions,
    1. Can we change descriptors on some services.
    2. Can we change all code of HM10 to make special device for commercial product

  68. Hi Martyn, I had purchased ten HM-10 BLE modules which all have the same MAC address. I thought the MAC address had to be unique. Is there anyway to change the MAC address? Have you had any experience with modules having the same MAC, being on at the same time with multiple phones trying to connect and communicate at the same time? I had two modules with two Lenovo tablets running BT Serial Terminal and each connected to a module but when one disconnected, there was a GATT error when trying to connect. Then both tablets would not see the modules anymore when scanning. It killed both tablets and they needed to be rebooted.

  69. Hi,

    The latest firmware version 7 has some new commands that allow to send data to non HM-10 devices.
    P1: Send method 2 Bytes, “WR”, “WN”
    P2: Chars Handle 2 Bytes // This is the handle of the characteristic I want to send data.
    P3: data what you want to send

    The problem is that I need to send data in hex format, but I don’t know how to do it.
    Any suggestions?

  70. Marty is the subject matter expert. Flashing upgrade was painless and content was applied 2018.12.30. No issues just green lights.

  71. Hey Martyn,

    regarding the chicken-egg problem that you mention in section „Set up the Peripheral mode device“: Would it work to cross-wire the RX/TXs of TWO mode-0 units, then connect the smartphone with ONE unit an configure the OTHER unit through the one?



  72. Hey Martyn.

    Thanks for all information about HM10. Can I ask question, I have Final Project with bluetooth HM10 and the promblem is, what is indicators of bluetooth connect or not (I mean in HM10, not led blink or not indicator)?. I will make a algorithm if hm10 connected with other hm10 will turn On the LED but if disconnceted will turn off the LED

  73. Hi Martyn, I have many HM-10 BLE modules (non genuine single crystal) which all have the same MAC address. I thought the MAC address had to be unique. Is there anyway to change the MAC address?

  74. Hey dear,
    i have tried all the way but it is not working. whatever command im typing exactly same is showing in the serial monitor, it is not replying with OK or with any reply.
    Also confused whether ZS-040 is MH10 or HC-05. I have already tried every thing assuming it as HC05, nothing worked.

    kindly help ..

      • Hey Martyn,
        thanks for reply but i have confirmed about module it is HM10. today again i tried a lot. i am able to send text through BLE scanner to serial monitor but serial monitor AT commands are not being replied by module as OK.
        Sketch: C:\Users\dell\Downloads\
        Uploaded: Feb 9 2019

        BTserial started at 9600






        whatever i write the same only comes in serial monitor window.

        please help it would be great pleasure.


  75. Also my BT module LED is blinking every 1or2 sec it is showing in android mobile but when connecting it showing connection rejected as it is already paired but no detail could be accessed.

    • some things that come to mind.

      1 – check your connections.
      2 – check the baud rate.
      3 – Do you have a genuine HM-10 or one of the other similar;ar BLE modules.

  76. Hi Martyn,
    Thanks for your fantastic article.
    I have been using the HC05 to communicate with the Arduino Mega from an Android phone, but now have swapped over to the HM10.
    Currently I have HM10 TX to Ard RX and vice versa, but no voltage divider and I find that the BLE scanner I am using ‘LightBlue’ can see all the data that the Arduino is generating. However, I would also like to be able to load new sketches to the Arduino over the air, using my PC’s bluetooth dongle. At the moment I don’t seem to be able to see any output to the serial monitor using the bluetooth COM port ! When I successfully managed this with the HC06, I had to use the state pin with a 1uF capacitor to the reset pin on the Arduino to force a reset so that I could load a sketch over the air – could I use the state pin on the HM10 the same way? Or perhaps I have to use the programmeable pins? If you have any pointers on any of these issues, I would be most grateful, many thanks. Al

  77. Hello everyone, thank you for so detailed information about this module, which let me make it up & running even with attiny. I have small question which I hope someone could cover. I need when the HM-10 is near the Raspberry pi, to run the script once. Now i did this in a nasty way using own program that is parsing hcidump output for the HM-10 MAC.

    Maybe there is a more nice way to do that?

  78. Martyn,
    Amazing article, thanks a lot for the effort!
    Maybe you or other readers can help, I couldn’t find a description of HM-10 as Central reading iBeacon devices such as the NRF52810 ABSensor.
    I am trying to read the accelerator values. I can see the device listing after AT+DISI? but it fails on AT+CONaddress and return OK+CONNF after 10 seconds.
    Any idea about that?

  79. Hello.

    Thank you for your detailed article.

    I want to send at+disc? command in order to scan for nearby BLE. Can AT+DISC? command put in the void loop on Arduino?

    I will make automatically discovery every 8 second, I try in arduino but no respond

    • You can put the command in the void loop but you need to give it time to scan.

      After calling AT+DISC? keep checking for incoming serial data and check the received data for the “OK+DISCE” reply. Once you have this you know the scan has finished.

  80. Hi Martyn
    You pages have been invaluable to me, but I have a problem I am unable to resolve. I have two CC2541 modules. I have flashed them with genuine HM-10 firmware and then updated the firmware to the latest version, V701.
    I have one as a Master and one as a peripheral. A discovery from the Master finds the peripheral. When connecting, using, for example, AT+CONN0, works fine.
    Using the mac address, for example, AT+CON1234567890AB fails.
    I get OK+CONNA, and then OK+CONNF. I have confirmed that the address in the discovery matches the address reported by the peripheral. Any ideas?
    Thanks, Tony

    • I have the same problem,
      My version is V609,

      I get “OK+CONNA”
      then after 5 sec I get “OK+CONNF”

      If you found any solution please share it.

  81. Hi Martin,
    My thanks too for your tutorial. This is what makes internet such a great place!

    I have a ‘fake’ HM-10 as the middle module in this picture:

    I successfully flashed the HM-10 firmware CC2541hm10v540.bin and it now advertises as HMSoft V540. Attached it to an Arduno Uno with voltage divider and most AT commands work. My smartphone (Wileyfox 2+ with LineageOS 14) detects the module and pairs with it.

    However, I can’t make the module detect my smartphone or other bluetooth devices. I faithfully executed

    AT+ DISC?
    which returns

    (same goes for variants as AT+INQ etc…)
    and now I am stuck…

    • I redid this with official HM-10s and everything worked. The only that comes to mind is if the modules do not have crystals their frequencies could be off. I have a couple of AT05 boards that will only connect to each other for this reason.

  82. Hey guys

    Thank you Martyn for such an amazing resource you have here :)

    I just found out a potential valuable information in case you want to use the ADC in the HM-10. I tried to read voltage values coming from a potentiometer powered at 3.3v and it was all fine.

    But then I tried to read voltage values coming from a capacitive moisture sensor, such as the DFRobot one, and all that AT+ADCB? read was a big 0.

    It turns out that you NEED to condition the signal, with a proper opAmp configured as a voltage follower, for instance. Otherwise, you would always read 0v. Why? It seems that HM-10 does not have its ADC buffered for you to use it out-of-the-box.

    You can measure the signal voltage coming from the sensor with your multimeter and the values you read will make sense. But connected to the ADC is a different story.

    When connected to the HM-10 the measured voltage from the moisture sensor was between 180mV (wet) and 300mV (dry). Our beloved HM-10 reads all those voltage values as 0.

    If you power your prototype with as little as 3v or 5v you will need a proper rail-to-rail opAmp. LM358 for example won’t make it. I got a TLV2462 from adafruit and bingo! Configured as a buffer, now AT+ADCB? returns meaningful values.


  83. A good document Martin and I intend to put it to good use.

    I’d like to order some HC-10s who do you recommend as a good supplier please

  84. HELLO

    • I finally found a solution but not easy. I have to use my iphone who was prg to auto connect. And i write a sketch on arduino to send a long string 80 car or more to wake up de slave and with chance my iphone connect to the module and i was able to AT+RENEW.

  85. Hey Martyn,

    This is an excellent tutorial! I’m trying to secure the connection between peripheral (HM-10) and a central Android/iOS device. Is it possible to encrypt the connection?

    Michael Gabay

    • Forgot to thank Martyn for brilliant work he’s been on hm-10 subject as whole. A year ago I had no clue of possibilites which modern technology offers. Now I’m finalizing a little project that basicly allows me to control my home appliances via my mobile phone, thaks to Martyn and Danila Loginov’s great article on software side (

      For the Quote: I’ve been looking on this subject, since one of the main reasons for selecting the HM-10 over older HC-boards was an illusion of improved security along with new technology. What I’ve found so far, seems that it’s up to manufacturer (jnhuamao in this case) to decide if encryption is really there and how securely it has been configured. Quite much the only way for the end-user of hm-10’s to affect security is setting pin-code and bonding devices in a secure location where’s no risk off eavesdropping nor MITM-attack.

      Communication with no pin-code set is quite easy to decrypt. Same thing if somebody is listening traffic during the pairing process. If these precautions have not been taken, device is as good as with no encyption at all.

      My process is at this stage for now, since I haven’t yet been able to connect device with pin-code set, so I’ll have to dig on that first (update firmware & test different combinations of devices).

      To make good and reliable estimate of security ble 4.0 offers, quite much only way is to think like a hacker and sniff the traffic by yourself. There’s dozens of links on the net how to do this with basic arduino electronics, so I won’t deeper on this subject – for now. After I get back to my lab I can share some data and better guess if hm-10 has any (meaningful) level of encryption applied.

      Securitywise, I would assume that moving to BLE 4.2/5 -devices would be best option with less effort.

  86. Hello Martyn.
    first, than you for all this information. Great work.
    i have just one question. i followed your guide and everything work fine.
    My hm-10 as a slave is connected to my arduino and i use my iphone to connect to my hm-10.
    Before connecting, AT command works fine on my arduino serial terminal. but when i connect my iphone, AT command dont work anymore. like your said, when a connection is established, the AT command on my arduino should disconnect the BT module. But the command is send to the terminal on my iphone as text. But AT command send by my iphone work. Why the command AT dont cut the connection send by arduino directly to the slave module attach to it? thanhs for any help.

    Martin Boucher

  87. Hello,

    firstly, thanks a lot for the sheet.
    I try to connect the mi flower care devices to arduino by hm-10 BLE. I update version of hm-10. Everythins seems like OK. When I write the command “AT+DISA?” , I take a huge response like bytes. There are a lot of different characters.

    How can I mean the data? How should I convert them string? and lastly will I need to use esp8266?

    thank you

  88. can you please tell me how it operates on 3.3V but VCC needs to be 5V inout, cant we just use 3.3v output of boards like arduino pro mini 3.3v

      • (tesekkurler) thanks, just another quick question, do you mean that I can use hm10 with a arduino running 3.3v (actually powered by 3.7v battery) without V divider on RX pin ?

        • evet, HM-10’in Vcc pinini arduino’nun 3.3V çıkışına bağlayabilirsin voltage divider’a ihtiyaç olmadan.

          yes you can directly connect Vcc pin of HM-10 to 3.3V out of arduino uno without need any voltage divider.

            • turk musunuz bilemedigim icin basa ipucu babinda yazmistim, cok tesekkurler bilgiler icin arduino pro mini 3.3v clone’u alip 3.7 v pil ile besleyecegim regulator var diyorlar o yuzden vcc 3.3v’e regule olur diye umuyordum insallah calisir, haber ederim, tekrar tesekkurler

              • 3.3’e regule olur bencede. her hangi bir V çıkışıda 3.3 çıkışına sahip olur. direkt bağla gitsin.

                kolay gelsin.

    • The actual HM-10 is a 3.3v device. This is the small board. See the very first images above.

      The larger HM-10 is a HM-10 on a breakout board. The breakout board has a 5v to 3.3v convertor allowing 5V to be used.

      To use 3.3v, find the VCC pin on the small board and connect to the 3.3v out of the Arduino.

  89. Hey, I am still facing issue getting a responce back from my HM-10, no AT command is working! It works fine when I connect it through an andriod App but not at serial monitor? what might be the issue here.

    • double check the connections
      double check the baud rate
      double check upper or lower case
      double check line end characters
      and finally, double check you have a HM-10.

    • I too am having this problem. I type AT and get no response.
      YET, I can take the BRK pin low and get OK+WAKE at terminal. I can connect to nRF Connect on my android and manually send AT commands and get a response. And when I connect or disconnect I can see OK+CONN or OK+LOST. So I assume the HM10 is fine. I know that the input to the HM10 divider is getting the AT bits as I connected it to a cheap USB logic analyser and can see the bits going into the resistor divider, though not at the actual RX pin itself??? (I don’t know if the logic analyser can work with 3.3v (or 2/3 of 5v) Guess I’ll have to put a scope on the actual pin. It’s all very weird and frustrating. I followed the advice below and even tried with another HM10 (though obtained from same place).

      • I haven’t used the HM-10s for a while but since you are getting communication from the HM-10 I suspect one of two things:
        1 – the write/output connection from MCP to the HM-10
        2 – the end of line characters.

        The use and type of EOL characters has changed in newer firmwares, check the data sheet for the fw you are using.

  90. Once a client has connected to my HM-10, I cannot interrupt via serial the connection, without disconnecting power from the module.

    How can I switch from the data mode to the AT mode? I appreciate any hint!


  91. Tldr: Texas Instrument’s documentation on CC2541 tells how to enable/disable encryption. Jnhuamao doc’s for HM-10 tells that it’s there, but as with all cheap electonic’s datasheets: It doesn’t mean it has been applied on practice at all and if it’s still secure considering todays requirements, since few vulnerabilities have been found on ble 4.0 since it’s release.

  92. Good day!
    * Copyright@2013 All rights reserved. *AT+VERSION +VERSION=Firmware V3.0.6,Bluetooth V4.0 LE

    I can’t understand how to transfer and receive data between two modules using the commands:
    * AT+UUID Get/Set system SERVER_UUID . *
    * AT+CHAR Get/Set system CHAR_UUID . *
    Communication is established, but data is not transmitted.

  93. Thanks for the very helpful page! I thought I would list a couple of issues and work arounds I had when working with hm-10 or variants.

    The main issue was that I understood that I needed to manually pair the ble module in android before I could connect to it in an app. I found that I do not need to pair when TYPE is set to 0 (not need pin code). The other issue I had was that I was not aware that most of the bluetooth terminal apps on android do not support ble and would fail to connect. I think that most users who use the Hm-10 or alternative parts come from using hc-05/06 devices which are used very differently to properly pair and connect to.

    Also I got a response for huamo about who they recommend for supplier. They suggest using:
    supplier: szhenghongtong on alibaba.

    Thanks again!

  94. I have discovered what causes most people to initially observe that the HM-10 does not respond to AT commands. Command characters must be sent out in rapid succession; otherwise, the command times out and is rejected without an error code. This means that typing on a terminal server into the unit’s serial port cannot be done fast enough. The Arduino terminal works because it buffers the entire command line, then sends all of those characters out with no intervening time.

  95. Truly excellent article!
    Detailed and specific. The only useable information I have found on using the HM-10 in central/master mode.
    Thanks for all your hard work.

  96. Hello at all:)

    I am using the HM10 module as a beacon (not Ibeacon but simply just advertising every 500ms as ADVT3) and run into a problem.

    I want to save power and have set the module up with auto sleep with PWRM0. When I start the module it draws around 0,2mA but after a few seconds (or minutes) it suddenly takes 8mA and stays at that level until the next reset.

    Does someone know that issue and/or has a solution?

  97. Hi, I am actually using a BLE-Nano from amazon instead of an HM-10, but I think the process should be the same for setting it up. I’m running into an issue with compiling your serial sketch example. I’m getting an error saying “AltSoftSerial.h: No such file or directory” I assume it just can’t find AltSoftSerial.h, but the weird thing is, when I select a teensy under the boards tab, it compiles fine. I am using a Mac on Arduino 1.8.10. If you know what could be the issue, please let me know. Thanks!

  98. Hello,
    I am trying to build a project with BLE (HM-10). I’ll attempt to explain what I’m trying to achieve through the project. And then write my questions.
    The project includes installing BLEs in college that should send a downloadable pdf/text messages or important notifications to students (in its range of course). This file will be received by students through an Android app(that we would want to develop).

    Our current idea is to use –
    1 Arduino Uno and 1 primary BLE(HM-10) connected through wires.

    And the primary BLE (HM-10) could wirelessly broadcast the data to a group of secondary BLEs.

    And a student could receive a file through one of these secondary BLEs (HM-10) placed across the college.

    1. How should I build a network of BLEs?
    2. What all will I require for programming this system? (How to program the HM-10 modules for what I want to achieve?)
    3. Is it possible for an HM-10 to send a file to android phone?
    4. How does the HM-10 and android phone connection work for sending text or file to each other? (Will a student who is receiving data from the module have to first pair with the BLE? Will it have to do it every time it wants to receive a file?)

  99. Thanks for a great article. I can now turn a LED on and off from my desktop and from my Android, so complete home automation can’t be far away! I am sure I could never have got it working without the detail you have provided.
    FWIW I was stumped for a long time with no response from the module connected to an Ardiuno Mega. I shifted it to a UNO, exactly the same configuration and code, and it worked first time. I suspect a small difference in the Tx signal level (I used a 1k/2k divider) or perhaps the 3.3v Rx signal level from the module. Whatever, for those having trouble with communication between 5v Arduino and the module check the voltage levels for both signals as that might be a very simple fix.

    • Hello. If i’m not wrong, the library used in your code use the pin 8 & 9(Rx Tx) for Uno but if you have a mega 2560, pin 8 and 9 are mapped on pin 46 and 48 for the mega. I struggled a bit on this one. Hoping it will help.

  100. Hi! I changed the baud rate to 2400 – unintentionally, it should be 38400, AT+BAUD2 but it seems that my module interpreted as 2400.
    Problem is now it doesn’t accept any command, only “AT”, returning “Ok”. Any other command returns two lines with message “ERROR” and the module was rendered unusable. I tested the procedure in another module with the same result.
    Any ideas on how can I recover the modules to an operational state?

  101. Hey
    actually i’m not working could i knew what will be the solution that i write commands in At terminal and it is not working as the module did not send me any response like am not writing at all .
    i’m using HMsensor
    and i paired with Bluetooth already

  102. Hi Martyn,

    Top most article you mention 4 hm-10 variants, 2 having USB pads.

    Do you know any application using the USB pads?
    Is it functioning as actual USB (firmware emulation)

    I haven’t found any so far.

  103. hello
    The device shows up at HMSoft on my phone and when I try to pair with it I see nothing… I connected it ble scaneer app. but not connected with mobile phone…

  104. Hello Martyn, the chip CC2541 does the CC2541 chip have an analog input ? I will know well can I connect the CC2541 (hm10) with a battery to know its state through a mobile application that I will develop it, that’s why I need an analog input.

  105. I’m going to make a connected object based on the CC2541 (hm10) chip and I like to know the battery level of this object? and I will develop a mobile application for this connected object through this application I will know the battery level in % .. so I need an analog input for the battery .. does the CC2541 have an input analog?

    • If you are using the HM-10 then there is a AT command to get the battery level (AT+BATC?), check the data sheet for details.

      If you are using a different module, check the data sheet for the specific module.

      If you are programming the CC2541 directly, the chip has analogue to digital pins (the HM-10 makes use of these) but you will need to code the scan yourself.

  106. Hi,
    I am working on the smart parking system. Can I use HM-10 BLE as ibeacon for indoor navigation system?
    Kindly help. if you can share any similar kind of application for reference that’s would be great.
    Thanks in advance,

  107. Hi,
    I have set BAUD rate to 230400, and like it’s writted i can’t talk to the module Anymore…
    I have tried to flash the HM-10 to restore it but chip is not detected.

    Do you have a solution to restore factory settings without use any AT command ? (or juste reset to the default BAUD rate ?)
    NB : i can still see the module bluetooth with my phone

    Thanks for your help :)

  108. Hi,

    I have an amendment to the section on how to make the HM-10 work with non-HM-10 modules.

    After plenty of testing, the command AT+SET_WAY did the trick for me. I first had to identify the necessary parameter with AT+FINDSERVICES? and AT+FINDALLCHARS?. This got an HM-10 communicating seamlessly with an ESP32 BLE server.

    Great work here, by the way. Best wishes

  109. What an impressive article, thanks for the extensive work! This will be such a great help for my project (replace an LCD screen controlling an ebike via UART, control some element via gpio and measure the battery voltage).
    Many thanks again

  110. Hello,
    Thank you for the article.
    I have been trying to find information around the internet on the sleep mode but even the datasheet couldn’t answer my question. Can a central device find the slave if the slave is in sleep mode? Could an attempt to find the sleeping device with AT+DISC find it and then connect to it?
    Thank you very much for your help.

    • Hello. Yes, when the slave go into sleep, it still emit and the master can find it and connect to and waking the slave. But your slave must be in AT+IMME0. I used this in my project and works great. Hoping it gonna help.
      Good luck

  111. IDK if it’s me, but I would plug the 1k into the ground and the 2k into D9, if you want 3.3 volts, correct me if I’m wrong

  112. Is it possible to send characteristics from HM-10 BLE 4.0 to other Bluetooth device?
    I want to use HM-10 to read temperature from iBBQ thermometer.

    I found some info but I can’t figure out how to send it from HM-10

    ‘Internet search keywords “iBBQ”, “BLE 4.0”, “Bluetooth BBQ thermometer”
    ‘Youtube BBQ thermometer hacking

    ‘The iBBQ is a Bluetooth LE Gatt Device
    ‘@DeviceName: iBBQ

    ‘Standard Descriptor:
    ‘@ClientCharacteristicConfigurationDescriptor: @uuid16{0x2902}

    ‘Its main service at @uuid16{0xfff0} contains the following characteristics:
    ‘@SettingsResult: @uuid16{0xfff1} @notify returns results from control messages
    ‘@AccountAndVerify: @uuid16{0xfff2} @write deals with the pairing process
    ‘@HistoryData: @uuid16{0xfff3} @notify is not yet properly documented
    ‘@RealtimeData: @uuid16{0xfff4} @notify returns the results from probes
    ‘@SettingsData: @uuid16{0xfff5} @write is where control messages are sent

    ‘Here are some hardcoded messages:
    ‘@CredentialsMessage: (:byte[]) { 0x21, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0xb8, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00}
    ‘@RealtimeDataEnableMessage: (:byte[]) { 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00}
    ‘@UnitsFahrenheitMessage: (:byte[]) { 0x02, 0x01, 0x00, 0x00, 0x00, 0x00}
    ‘@UnitsCelsiusMessage: (:byte[]) { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}
    ‘@RequestBatteryLevelMessage: (:byte[]) { 0x08, 0x24, 0x00, 0x00, 0x00, 0x00 }
    ‘@SetTargetTempMessage: (:byte[]) { 0x01, , , , , }

    ‘initiate-login ::
    ‘ write @CredentialsMessage to characteristic @AccountAndVerify
    ‘enable-realtime-data ::
    ‘ enable notifications on @ClientCharacteristicConfigurationDescriptor
    ‘ write @RealtimeDataEnableMessage to characteristic @SettingsData

    ‘Is there anything special to do to receive data on FFF0/FFF4 and FFF0/FFF1 ?
    ‘I dont receive any data on these two. All others are working fine. eg. 1800/2A00.
    ‘I can change from °C to °F, but i cant read any responce for e.g. Barttery on FFF0/FFF1 and probe data on FFF0/FFF4.

    ‘Same here, sending initiate login seems to keep the connexion open, but I didn’t receive realtime data at all.

    ‘I found the solution:
    ‘You need to subscribe to the probe data by sending x0001 to FFF0/FFF4
    ‘To unsubscribe send x0000 to FFF0/FFF4
    ‘For Control Message e.g. Battery level subscribe by sending x0001 to FFF0/FFF1
    ‘To unsubscribe send x0000 to FFF0/FFF1

    ‘The device is very strict, you need to follow the procedure of sending initiate-login and then enable-realtime-data

    ‘the client caracteristics configuration descriptior has to be configured in order to read the data.
    ‘Writing 0x0100 in 0x2902 let me received notifications.

    ‘Yes indeed, I did not document that because I understood this as standard bluetooth le!

    • Hey Man,

      I’m working on something similar to you. I’m using the HM-10 to communicate with my Health watch.

      The Health watch is a BLE watch I wear on my hand, it stores, heart rate, blood sugar, steps I’ve taken, and many more.

      – Health Service UUID: 0x0AF0
      – Heart rate characteristics UUID: 0x0AF1
      – Blood sugar characteristics UUID: 0x0AF2.

      Please help me, I’m totally lost. What AT commands are you using to read/write to the iBBQ?

      I send AT+CO1F313EE410464 to my HM-10 and it successfully connects to Watch health watch and then what? What AT commands or binary commands do i send to read/write to the Health watch?

  113. Hi, Martyn!
    I am trying find an app, which could be compatible with HM-10 and my iphone 5C. Iphone 5C has its ios version before the 11.0. Then I tryed a lot to find an app for it and a didn’t find it. I saw that your expirience on HM-10 is very high and I thought perhaps you could help me indicating an app. I would like to connect with my Arduino Uno via bluetooth HM-10 and my iphone 5C. Which app could make this task?
    I am very greatful in advance for any help.

  114. Hi,
    I wonder if someone can help with this problem with HM-10.
    I had the working well when all of a sudden the following happened:
    when I send AT+DISC? all I get back is OK+DISCOK+DISCE with absolutely no connection data. I have four modules powered up and none of them will find anything.
    I have tried all other AT commands and they work as per normal.

  115. When trying to update the firmware I run into an error. I can select COM6 but then when I try to open the serial monitor I get “Error opening serial port ‘COM6’. (Port busy)”. COM6 is definitely the correct port as it only shows up when the board is connected. Has anybody else had this error?

    • Are you using an Arduino Nano? I had that problem when moving from a Mega2560 to a Nano 33 BLE. The Nanos appear to use two COM ports and I found that I had to set the right one when uploading.

  116. with manually entering the modules do connect to each other but if I go for connecting them through code they won’t connect. i’m trying to use your two arduino the one with switch and the other with LED. Please help.

  117. Good morning,
    I’m being a bit thick. I’m trying to connect a HM-11 to a Windows 10 laptop using the InTheHand library – but that only lets me connect as BLE.

    How do I connect wirelessly to the HM-11 from Windows 10 so that I can use it to send commands to and receive data from an Arduino?

    Thanks in advance, have a great day.

  118. I recently purchased the HM-18 module, the Bluetooth 5.0 version of the HM-10. While using your ATCommands sketch with my arduino, I changed the default Baud rate to 0 (9600). Now I cannot reestablish a link in the sketch. I know the module is still working, and advertising, but I can no longer communicate with it via the arduino. Are you familiar with this and do you have any advice?

  119. Hi,
    i work with H-10 i don’t know the firmware version because I’m not get reply for the commands :
    AT+VERR? or AT+VERS?.
    i configure the device :
    I have problem to connect, the Cellular Phone is not request PIN code.

  120. I have built a device that communicates with an iPhone, using the BLE module HM-10. I wish to speed up the rate of data exchange between the two units. Can I do this by using AT commands?

    • Unfortunately you cannot change the wireless communication speed. This handled by the Bluetooth functions in the firmware. The only spped you can change is the UART buad rate used for the HM-10 to communicate with the device it is physically connected to.

  121. Hello, I’m having a problem with my HM 10 module, the module reject the pairing from my android phone, thus, my software for home control using HM 10 won’t work. How overcome that problem? Thanks in advance

  122. Hi Martyn,
    I am fairly new to the HM-10 and I was reading your article to try to understand more about it. I have it configured to IMME 1 and ROLE 0, and I need to make it so that only the other device (my phone) can initiate a connection with the HM-10, rather than allowing the HM-10 to connect with any paired devices once turned on. I thought having IMME set to 1 would fix this, but my android device no longer detects the HM-10. Is there any way to achieve the desired outcome with only an Arduino nano and a HM-10? Thanks :)

  123. Hello,

    I’m using the HM-19 which is similar to the HM-10. I can successfully scan my apartment for all BLE devices using AT+DISC?

    I can successfully connect to my Health Watch using AT+CO1F313EE410464.
    (My Health watch is a BLE wearable watch similar to the Apple Watch)

    Please, how can I READ/WRITE to/from the Health Watch?

    The Health Watch has a Service UUID of 0x0FA0
    The Health Watch stores my ‘Heart rate and Blood sugar’ at Characteristic UUID of 0x0AF6. Which has Read/Write properties.

    Please, what are the AT commands that I have to send to the HM-10 to read my ‘Blood sugar’ from the health watch?

    Thank you.

  124. Hello,

    I purchased a Genuine HM-10 and am having difficulties with self-learning functions. I am running the latest firmware
    So, here is all Services of the device I am connecting to
    ALL Services
    All Characteristics

    I then use the following AT commands

    I can read data but I cannot write. Any help is appreciated, thank you!

  125. Hi I found a strange error, all connections seem to be correct because In the BLE scanner application I can send text to the computer and vice versa. But I can’t send AT Command to bluetooth via serial monitor on computer. HM10 doesn’t respond anything. If I type a word, BLE Scanner reveive it not a word but a characters one by one. My HM10 version is 608.

  126. Hello, A few years ago, I built a garage door opening mechanism from an Arduino Nano, classic Bluetooth (HM-05) and a basic relay.
    I wrote an Android app which would pair & bond to the HM-05 using passcode. I discovered the HM-05 device would store at least 3 secrets for 3 different phones, which meant I could allow whole family to use garage door opener via their own phone.
    Now, all these years later my entire family & I have iPhones which only use BLE. I switched up my device and added an HM-18 ( amazon link) which does support iOS & will pair & bond, but unfortunately will only save one secret at a time. As soon as it pairs/bonds with another phone then it removes the secret for the other phone.
    I don’t know how I got so lucky with those original HM-05s that they worked with multiple phones, but now I am wondering if you know of :
    1) Any device which will a) pair / bond with iOS device & b) will allow multiple iOS devices to pair / bond?
    2) any way to force the HM-18 to store multiple secrets? — solder a jumper or something?
    Thanks for any help you may provide.

  127. Hi,
    I haven’t looked at your stuff for ages, and maintained that the HM-10 was more trouble than it is worth. I now see that you have hugely expanded this site and I assume that this is because HM-10 has been upgraded in firmware over the years and is now a viable proposition, so it is time for me to change my mind about this….

    So, do I understand correctly that the HM-10 is now a viable drop-in replacement for the HC-05? I ask this particularly because not only should it be time to progress, but also because I don’t hear complaints about fake and/or dud HM-10s.

    I also note that you use AltSoftSerial. Is there any magic therein that is particularly relevant to the HM-10?

    Thank you

    • The main update to the HM-10 was the self learning mode. This is used to scan services and characteristics from other devices. Prior to this it was difficult to use the HM-10 with non-HM modules.

      The HM-10 can replace the HC -05 but, depending on h0w it is used, may not be straight forward.

      The HM-10 is BLE and the HC series are Bluetooth Classic/2.0 EDR. If you are using them using them in pairs via UART then either version works pretty much the same.
      If you are using them with mobile devices then there are some big differences. The HC series is Android only and the HM-10 is Android or IOS. BT Classic is still better for some uses, such as high volume data, but I prefer BLE because of how it connects to devices. BT Classic requires pairing and authorizing on the device before using an app whereas BLE can be controlled entire within an app. This makes BLE a better user experience.

      Having said all that, I haven’t done anything new with Bluetooth for a while. I have moved on to ESP32s and ESP8266s.

  128. Hi Martyn, I’m trying to interface with a peripheral device which expects an 8 byte request, and responds (through a notify characteristic) with a 50 byte response. I only get 20 bytes back, so it seems like the 20 byte write limit applies to reads as well, but the data is not split, it’s lost :(
    Anyway, moving to esp32wArduino, thanks for the guide :)

  129. Hi, I’m new to bluetooth modules, not to arduino and other hardware. I have 2 issues :
    I have 2 HC-05 modules, 1 master 1 slave, the master set to connect to 1 device and BAND to the mac address of the slave. They connect OK.
    The problem : The input for the master is 916 bytes at baudrate 115200 every second (P1 meter data). It is send correctly, I can see that on my phone using BT Terminal. But at the serial output of the slave some bytes are missing or incorrect. What can be the problem ?
    Second issue : to resolve above problem I tried the same with 2 HM-10 modules. The data is send by the master correctly via bluetooth according my phone. But at the serial output of the slave nothing appears. Any idea waht the problem may be ?
    thanks, regards, Sjors


Leave a Reply to Al Wells Cancel reply