<-- Home
Strings of data can be transferred between
computers by wire or by air.
Serial communication is an long proven solid method
to send small amounts of data, like instructions or records from measurement on
a remote device.
An universal asynchronous
receiver-transmitter (UART) is a computer hardware device for asynchronous
serial communication in which the data format and transmission speeds are
configurable as Wikipedia describes it.
The serial port on a PC can be connected by wire to an
other PC's serial port.
If from both wires the TX (transmit) pin from one PC is connected
to the RX (receive) pin of the other PC, the PC's can communicate.
Both PC's must be set to the same transmission speed, the baud rate. The baud
rate is how many bits per second are send over the wires.
A standard communication speed is 9600 baud = 9600 bits
per second. In this string of bits
some are control bits. 9600 baud is roughly 1000 bytes per second.
A baud rate of
115200 is also a common used speed.
There are several methods that can be used to send data through the air.
HM-10 Bluetooth modules use a Texas Instruments C2541 chip for the decoding
of the signal to a string of bits.
A HM-10 or similar BLE module, like JDY-23, can be used with Android and Apple
phones. HC-0x modules, like the popular HC-05, can not be used with Apple
devices. Therefore HM-10 modules are a good choice. They are cheap and can be
connected to Arduino or other MCU's
ESP32 and some Arduino MCU's use the Nordic nRF52 chipsets. They are often
integrated in the processor boards together with an WIFI module.
Bluetooth has a range of 10 meters and can be transmitted and received with a
mobile phone.
There are similar serial radio modules, known as HC-12, that has ranges up to 1000
meter. (See an
example here)
Two HC-12 modules can be used instead of a long cable between two devices. They
are easy to operate but you can not use a phone.
A HM-10 or similar BLE module, like JDY-23, can be used with Android and Apple
phones. HC-0x modules, like the popular HC-05, can not be used with Apple
devices. Therefore HM-10 modules are a good choice.
This page describes how to use a phone to communicate
with an Arduino program to send instructions and received results.
A similar program to communicate with the Nordic nRF
chipset with an ESP32 is described here.
Use the Bluetooth HM-10 BLE module to send and receive
messages with an Arduino
Communication with Bluetooth modules takes place through the serial pin RX and
TX on the Arduino and the Bluetooth module. The library Softwareserial.h makes it possible on
older Arduino's to use other pins than the
standard pins 0 and 1 that are also used to upload programs. One can spare the two pin 6&7 and connect the BLE module to pin 0&1, the serial port pins of Arduino's. This saves a library and some code that has to be used to read and write to pins 6&7. But ... the BLE module interferes the upload of programs to the Arduino and the module must be disconnect before every upload.
With a serial terminal program one can send commands to the receiver that can
be used in the Arduino program to do something.
|
|
HM-10 left and JDY-23 (2nd) BLE modules |
The menu to display in the terminal
The menu is a character array with text to be displayed.
In this example a menu line can not be longer than 41 characters.
//0 1 2 3 4 5
//12345678901234567890123456789012345678901234567890
char menu[][42] = { // menu[][nn] nn is largest length
of sentence in the menu
"Menu",
"A Action A",
"D Enter Date DDDMMYYYY (D25122021",
"I For this info menu",
"R Action R",
"T Enter time as THHMMSS (T071500)",
"Jan 2022" };
The subroutine below translates the received command line to an action.
void ReworkInputString(String InputString) { InputString.trim(); // Remove trailing spaces if (InputString.length()>10) return; // If string is too long for some reason if (InputString[0] > 64 && InputString[0] <123) // If the first charater is a letter { sprintf(sptext,"**** Wrong entry ****"); // Default message Serial.println(InputString); switch (InputString[0]) { case 'A': case 'a': if (InputString.length() == 1) { sprintf(sptext,"Action A"); } break; case 'D': case 'd': if (InputString.length() == 9 ) { int Day, Month, Year; Day = (byte) SConstrainInt(InputString,1,3,0,31); Month = (byte) SConstrainInt(InputString,3,5, 0, 12); Year = SConstrainInt(InputString,5,9, 2000, 3000); sprintf(sptext,"%02d-%02d-%04d",Day, Month, Year); } break; case 'I': case 'i': if (InputString.length() == 1) { SWversion(); sptext[0] = 0; // Clear sptext } break; case 'R': case 'r': if (InputString.length() == 1) { // Reset(); // Reset all settings Tekstprintln("\n**** Reset to default settings ****"); } break; case 'T': case 't': if(InputString.length() >= 7) // T125500 { int Hour, Minute, Second ; Hour = (byte) SConstrainInt(InputString,1,3,0,23); Minute = (byte) SConstrainInt(InputString,3,5,0,59); Second = (byte) SConstrainInt(InputString,5,7,0,59); sprintf(sptext,"%02d:%02d:%02d",Hour, Minute, Second); } break; default: break; } } Tekstprintln(sptext); InputString = ""; }
A working INO file for an Arduino can be found at the
bottom of this page and as file here:
BLEHM-10Menu.ino
There are hardly any apps or programs that can communicate with the HM-10 BLE devices.
Below is one for IOS and one for Android.
If the HM-10 or JDY-23 (C2541 modules are used you need one of apps mentioned
below.
For Apple IOS my free program "BLEserial
HM-10" from the app store can be used.
if the menu program is used in nRF equipped MCU's like the RP2040 Connect or
ESP32 variants use the
free IOS nRF
app.
The priced app BLEserial Pro app.
has more capabilities and connect to both CC25xx and nRF chipsets.
Serial Bluetooth Terminal van Kai Morich works fine as
terminal app with Android.
Connect in the app with your BLE module.
Type a command in the send of enter message box or wait if your program logs
results in the console window.
Change the name of a HM10 BLE with an FTDI
The easiest method to change or program a HM-10 module is using a FTDI
programmer.
Every BLE module can be given a name that it will broadcast and in displayed in
the list of BLE devices in the IOS or Android app.
To change that name do the following:
Connect the 3.3V and GND and TX to RX and RX to TX.
Open an serial monitor like
Termite or de
Arduino Serial monitor and open the serial port
Enter AT in the monitor and OK should show up in the window as response of the
module
AT+NAME followed with the desired name give the module a new broadcasting name.
AT+HELP list the following commands:
********************************************************************
* Command
Description
*
*
---------------------------------------------------------------- *
* AT
Check if the command terminal work normally *
* AT+RESET
Software reboot *
* AT+VERSION
Get firmware, bluetooth, HCI and LMP version *
* AT+HELP
List all the commands
*
* AT+NAME
Get/Set local device name
*
* AT+PIN
Get/Set pin code for pairing
*
* AT+PASS
Get/Set pin code for pairing
*
* AT+BAUD
Get/Set baud rate
*
* AT+LADDR
Get local bluetooth address
*
* AT+ADDR
Get local bluetooth address
*
* AT+DEFAULT Restore
factory default
*
* AT+RENEW
Restore factory default
*
* AT+STATE
Get current state
*
* AT+PWRM
Get/Set power on mode(low power) *
* AT+POWE
Get/Set RF transmit power
*
* AT+SLEEP
Sleep mode
*
* AT+ROLE
Get/Set current role.
*
* AT+PARI
Get/Set UART parity bit.
*
* AT+STOP
Get/Set UART stop bit.
*
* AT+START
System start working. *
* AT+IMME
System wait for command when power on.
*
* AT+IBEA
Switch iBeacon mode. *
* AT+IBE0
Set iBeacon UUID 0.
*
* AT+IBE1
Set iBeacon UUID 1.
*
* AT+IBE2
Set iBeacon UUID 2.
*
* AT+IBE3
Set iBeacon UUID 3.
*
* AT+MARJ
Set iBeacon MARJ .
*
* AT+MINO
Set iBeacon MINO .
*
* AT+MEA
Set iBeacon MEA .
*
* AT+NOTI
Notify connection event .
*
* AT+UUID
Get/Set system SERVER_UUID .
*
* AT+CHAR
Get/Set system CHAR_UUID .
*
*
-----------------------------------------------------------------*
* Note: (M) = The command support slave mode only.
*
* For more information, please visit http://www.cyobd.com
*
* Copyright@2013 www.cyobd.com. All rights
reserved.
*
********************************************************************
Change the name of a HM-10 4.0 BT-BLE Bluetooth-module with
an Arduino
First we need to connect the HM10-module to an Arduino.
Connect VCC to 3.3V on the Arduino and GND to GND, connect pin 6 to TXD and pin
7 to RXD on the Bluetooth-module.
So RX goes to TX and TX is connected to RX; “the wires are crossed”
The module has a default name like CC41-A. First we will change that name.
Load the following sketch into the Arduino Uno:
-------------------------
#include SoftwareSerial mySerial(6, 7); // RX, TX
// Connect HM10 Arduino
Uno
// Pin TXD
Pin 6
// Pin RXD
Pin 7
void setup() {
Serial.begin(9600);
// If the baudrate of the HM-10 module has been
updated,
// you may need to change 9600 by another value
// Once you have found the correct baudrate,
// you can update it using AT+BAUDx command
// e.g. AT+BAUD0 for 9600 bauds
mySerial.begin(9600);
}
void loop() {
char c;
if (Serial.available()) {
c = Serial.read();
mySerial.print(c);
}
if (mySerial.available()) {
c = mySerial.read();
Serial.print(c);
}
}
Start the serial monitor in the Arduino IDE.
Change right under in the monitor the LF&CR settings to “No line ending” and the
baud rate to 9600 Baud
Enter in the Serial monitor:
AT+RESET
AT+NAMEDevice01 (Or any other name you like to give
the module)
AT+RESET
The passkey of the module = 0000 when you pair the devices.
Cheap HM10 modules, bottom one, often lack a crystal but works fine too.
Android & IOS apps for communications
BLE UART serial communication apps for IOS and Android
(2022-2023)
//
============================================================================================
/*
Connect the Bluetooth module GND and 5V and to pin
0 and 1 or 6 and 7 as noted in the comment of the digital pin assignment.
When connected to pin 0 and 1 two digital ports and
the SoftwareSerial library are saved. Also the Bluetooth subroutine can be
omitted.
This omission is accomplished by commenting out the
#define BLUETOOTHMOD with two slashes //
A disadvantage of connecting to pin 0 & 1 is that
upload to the Arduino when the Bluetooth module is connected is not possible
because the module
interferes the upload.
Author .: Ed Nieuwenhuys
Changes.: 0.0.1 Initial program
*/
//
============================================================================================
// //
#define BLUETOOTHMOD // Use this define if
Bluetooth needs other pins than pin 0 and pin 1
// In this example the Bluetooth module is connected
to pin 6 and 7
char VERSION[] = "BLE_HM-10_V01";
#ifdef BLUETOOTHMOD
#include <SoftwareSerial.h> // Arduino for Bluetooth
communication
#endif //BLUETOOTHMOD
//------------------------------------------------------------------------------
// PIN Assignments
//------------------------------------------------------------------------------
enum DigitalPinAssignments { // Digital hardware
constants
RX = 0, // Optionally onnects to Bluetooth TX
TX = 1, // Optionally onnects to Bluetooth RX
PIN02 = 2, // Empty
PIN03 = 3, // Empty
PIN04 = 4, // Empty
PIN05 = 5, // Empty
BT_TX = 6, // Connects to Bluetooth RX
BT_RX = 7, // Connects to Bluetooth TX
PIN08 = 8, // Empty
PIN09 = 9, // Empty
PIN10 = 10, // Empty
PIN11 = 11, // Empty
PIN12 = 12, // Empty
secondsPin = 13, // LED on Arduino
};
enum AnaloguePinAssignments { // Analogue hardware
constants ----
EmptyA0 = 0, // Empty
EmptyA1 = 1, // Empty
EmptyA2 = 2, // Empty
EmptyA3 = 3, // Empty
SDA_pin = 4, // SDA pin
SCL_pin = 5, // SCL pin
EmptyA6 = 6, // Empty
EmptyA7 = 7}; // Empty
char sptext[100]; // For common print use
uint32_t msTick; // The number of millisecond ticks
since we last incremented the second counter
//------------------------------------------------------------------------------
// BLUETOOTH
//------------------------------------------------------------------------------
#ifdef BLUETOOTHMOD // Bluetooth ---------------------
SoftwareSerial Bluetooth(BT_RX, BT_TX); // BT_RX <=>
TXD on BT module, BT_TX <=> RXD on BT module
#endif //BLUETOOTHMOD
//------------------------------------------------------------------------------
// Menu
//------------------------------------------------------------------------------
//0 1 2 3 4 5
//12345678901234567890123456789012345678901234567890
char menu[][42] = { // menu[][nn] nn is largest length
of sentence in the menu
"Menu",
"A Action A",
"D Enter Date DDDMMYYYY (D25122021",
"I For this info menu",
"R Action R",
"T Enter time as THHMMSS (T071500)",
"Jan 2022" };
// ------------------------------------- End
Definitions ---------------------------------------
// //
//------------------------------------------------------------------------------
// ARDUINO Loop
//------------------------------------------------------------------------------
void loop()
{
InputDevicesCheck(); // Check for input from input
devices
EverySecondCheck(); // This subroutine is not
necessary but an example
}
//------------------------------------------------------------------------------
// ARDUINO Setup
//------------------------------------------------------------------------------
// //
void setup()
{
pinMode(secondsPin, OUTPUT );
Serial.begin(9600); // Setup the serial port to 9600
baud
Tekstprintln("\n*********\nSerial started");
#ifdef BLUETOOTHMOD
Bluetooth.begin(9600);
Tekstprintln("Bluetooth enabled");
#endif //BLUETOOTHMOD
}
//------------------------------------------------------------------------------
// Version info
//------------------------------------------------------------------------------
void SWversion(void)
{
unsigned int i;
PrintLine(40);
for (i = 0; i < sizeof(menu) / sizeof(menu[0]);
Tekstprintln(menu[i++]));
PrintLine(40);
}
void PrintLine(byte Lengte)
{
for (int n=0; n<Lengte; n++) {Serial.print(F("-"));}
Serial.println();
}
// //
//------------------------------------------------------------------------------
// Update routine done every second
//------------------------------------------------------------------------------
void EverySecondCheck(void)
{
uint32_t ms = millis() - msTick;
static bool Dpin; // Only write once to improve
program speed in the loop()
if (ms > 1 && Dpin) // With ms>5 LED is ON very short
time
{Dpin = LOW; digitalWrite(secondsPin,LOW);} // Turn
OFF the second on pin 13
if (ms > 999) // Every second enter the loop
{
msTick = millis();
digitalWrite(secondsPin,Dpin = HIGH); // Turn ON the
second on pin
}
}
//------------------------------------------------------------------------------
// Check for input from devices
// This fubction is called from with the loop()
//------------------------------------------------------------------------------
// //
void InputDevicesCheck(void)
{
SerialCheck();
#ifdef BLUETOOTHMOD
BluetoothCheck();
#endif //BLUETOOTHMOD
}
//------------------------------------------------------------------------------
// common print routines
//------------------------------------------------------------------------------
// //
void Tekstprint(char const *tekst)
{
Serial.print(tekst);
#ifdef BLUETOOTHMOD
Bluetooth.print(tekst);
#endif //BLUETOOTHMOD
}
void Tekstprintln(char const *tekst)
{
strcpy(sptext,tekst);
strcat(sptext,"\n"); //sprintf(sptext,"%s\n",tekst);
Tekstprint(sptext);
}
//------------------------------------------------------------------------------
// Check for serial input
//------------------------------------------------------------------------------
void SerialCheck(void)
{
String SerialString = "";
while (Serial.available())
{
char c = Serial.read(); delay(3);
if (c>31 && c<127) SerialString += c; // Allow input
from Space - Del
else c = 0;
}
if (SerialString.length()>0)
ReworkInputString(SerialString); // Rework ReworkInputString();
SerialString = "";
}
#ifdef BLUETOOTHMOD
//------------------------------------------------------------------------------
// Check for Bluetooth input
//------------------------------------------------------------------------------
void BluetoothCheck(void)
{
String BluetoothString = "";
char c = 0;
Bluetooth.listen(); // When using two software serial
ports, you have to switch ports by listen()ing on each one in turn.
while (Bluetooth.available())
{
c = Bluetooth.read();
Serial.print(c);
if (c>31 && c<127) BluetoothString += c;
else c = 0;
delay(3);
}
if (BluetoothString.length()>0)
{
ReworkInputString(BluetoothString); // Rework
ReworkInputString();
BluetoothString = "";
}
}
#endif //BLUETOOTHMOD
// //
//------------------------------------------------------------------------------
// Constrain a string with integers
// The value between the first and last character in a
string is returned between the low and up bounderies
//------------------------------------------------------------------------------
int SConstrainInt(String s,byte first,byte last,int
low,int up){return constrain(s.substring(first, last).toInt(), low, up);}
int SConstrainInt(String s,byte first, int low,int
up){return constrain(s.substring(first).toInt(), low, up);}
//------------------------------------------------------------------------------
// Input from Bluetooth or Serial
//------------------------------------------------------------------------------
// //
void ReworkInputString(String InputString)
{
InputString.trim(); // Remove trailing spaces
if (InputString.length()>10) return; // If string is
too long for some reason
if (InputString[0] > 64 && InputString[0] <123) // If
the first charater is a letter
{
sprintf(sptext,"**** Wrong entry ****"); // Default
message
Serial.println(InputString);
switch (InputString[0])
{
case 'A':
case 'a':
if (InputString.length() == 1)
{
sprintf(sptext,"Action A");
}
break;
case 'D':
case 'd':
if (InputString.length() == 9 )
{
int Day, Month, Year;
Day = (byte) SConstrainInt(InputString,1,3,0,31);
Month = (byte) SConstrainInt(InputString,3,5, 0, 12);
Year = SConstrainInt(InputString,5,9, 2000, 3000);
sprintf(sptext,"%02d-%02d-%04d",Day, Month, Year);
}
break;
case 'I':
case 'i':
if (InputString.length() == 1)
{
SWversion();
sptext[0] = 0; // Clear sptext
}
break;
case 'R':
case 'r':
if (InputString.length() == 1)
{
// Reset(); // Reset all settings
Tekstprintln("\n**** Reset to default settings ****");
}
break;
case 'T':
case 't':
if(InputString.length() >= 7) // T125500
{
int Hour, Minute, Second ;
Hour = (byte) SConstrainInt(InputString,1,3,0,23);
Minute = (byte) SConstrainInt(InputString,3,5,0,59);
Second = (byte) SConstrainInt(InputString,5,7,0,59);
sprintf(sptext,"%02d:%02d:%02d",Hour, Minute, Second);
}
break;
default:
break;
}
}
Tekstprintln(sptext);
InputString = "";
}