步驟1:硬件:
HC-05 SMD模塊(我從aliexpress獲得)
Arduino Nano(同樣來自aliexpress)
3x7cm雙面原型板(同樣來自aliexpress)
兩個LED
單芯線的耦合
2.54厘米標頭
步驟2:HC-05模塊:
實際上,我使用的參考手冊是關于具有不同產品編號的模塊的,但是實際上,它是與HC-05相同的模塊(我發現它寫得很好并且帶有漂亮的圖形)。該模塊的名稱為 EGBT-045MS ,您可以在此處找到該手冊。
特別是,我們對以下8個引腳感興趣:
引腳1,2 :TX,RX:將發送/接收引腳連接到Arduino上的串行(或軟件串行)引腳。
引腳12,13 :Vcc,GND:為模塊加電。
引腳31,32 :指示LED,特別是“狀態” LED和“以數據模式連接” LED
pin 11 》:重置引腳,用于重置模塊以切換操作模式(AT/DATA)
引腳34 :命令模式引腳,用于
步驟3:連接:
要連接5v主機,您需要在HC-05 RX引腳上使用分壓器(電阻器對),而不必在Vcc上使用因為它是5v容忍的(這就是手冊至少說了。)
現在,說實話,我為3.3v Arduino pro mini進行了連接,但是后來我使用了5v Arduino Nano,并且我沒有遵循指南向其添加電阻器RX線。但是,猜猜是什么,它可以正常工作,所以我將其保持不變;)
注意:我并不是說它將與您一起使用還是這種方式是正確的,我認為它只是偶然地與我合作。請按照接線圖進行正確連接。
現在,將HC-05正確放置在原型板上(注意,HC-05是間距為1.5毫米,而面包板的間距為2.45毫米。因此,孔沒有對齊,但只有很少的相鄰電纜,您可以設法將其穿過)
接下來,放置Arduino Nano和HC-05引腳,兩個用于LED的電阻器,LED本身(從另一端連接到GND),我還為I2C顯示設置了連接(將在附近的另一條說明中添加和解釋)
注意: 我沒有將HC-05連接線連接到特定的Arduino引腳,我現在通過跳線進行此操作,以使其與其他組件(如果有)保持模塊化。
步驟4:AT模式和HC-05重置。
在大多數參考文獻中,要求您手動斷開/重新連接HC-05的電源,以便將其放入AT模式(引腳34置于高電平)或返回數據模式(同一引腳為低電平狀態)。如果您的應用程序需要按順序從/向AT命令模式來回切換,則沒有任何意義。
訣竅是允許Arduino控制Reset引腳(11號引腳)來重置模塊。該過程如下
進入AT命令模式:
digitalWrite(pinEn,HIGH); // Set the Enable pin (no.34) to HIGH, and keep it during the AT command
digitalWrite(pinRe,LOW); // Set the Reset pin (no.11) to LOW, this postpones the module in preparation to reset
delay(100); // A short delay (should be more that 10 ms) to simulate a negative pulse on the reset pin
digitalWrite(pinRe,HIGH); // Set the Reset pin back to HIGH, and with Enable pin set to HIGH, the module restarts in AT Command mode.
進入數據傳輸模式:
digitalWrite(pinEn,LOW); // Set the Enable pin (no.34) to LOW, and keep it during the data transmission mode
digitalWrite(pinRe,LOW); // Set the Reset pin (no.11) to LOW, this postpones the module in preparation to reset
delay(100); // A short delay (should be more that 10 ms) to simulate a negative pulse on the reset pin
digitalWrite(pinRe,HIGH); // Set the Reset pin back to HIGH, and with Enable pin set to LOW, the module restarts in Data transmission mode.
第5步:交互使用用戶輸入
在我們的程序中,用戶可以在三種模式之一中操作模塊
AT命令模式: :您可以通過在串行終端中鍵入‘#start’來啟用它,您需要在其中鍵入每個命令,并從中讀取確切的響應
數據傳輸模式: :您可以通過在序列號中鍵入‘#end’來啟用它終端,其中與模塊的所有無線通訊都將列在串行監視器中,并且無法控制模塊參數。
操作菜單模式: ,您可以通過在串行終端中鍵入‘#op’來啟用它,這會將模塊放入AT命令模式,但不是由用戶直接提供命令,而是通過具有預定義操作的交互式菜單來發出命令。
操作菜單允許進行以下操作:
顯示模塊設置
名稱,波特率,角色,連接模式,密碼
修改當前設置
修改模塊名稱
修改UART設置
修改配對代碼/密碼
切換角色(主/從)
更改連接模式
后退。..
重置為原始設置
僅限主機操作
發現附近的設備
與設備配對
連接到設備
從配對列表中刪除設備
綁定設備
返回。..
第6步:代碼:
下面是Arduino代碼(您也可以下載文件本身)
請注意該程序中密集的字符串用法。我遇到了很多問題,因為如果這樣做,我可以通過以下說明解決其中的幾個問題:
使用‘String.reserve()’函數為字符串實例預先保留動態內存,這樣可以更好地處理堆中的內存分配。但這還不夠,因為它不能保證任何事情。
使用‘F()’宏:它允許將字符串存儲在閃存而不是RAM中。它僅適用于print/println操作中的靜態字符串。這非常有用,但還不夠用(對動態字符串無濟于事)
減少保留的字符串數:如果這不是您真正想要的,不要詢問最多10個設備。例如3個就足夠了。
在任何情況下該程序都將執行并上載的問題,但是它將以意外的方式運行,響應的查詢與您鍵入的查詢不同,并且
解決該問題的方法是使用char數組(或char *)代替字符串。這是我的下一步,但現在我沒有時間去做;)
/*
* AT_AT_mode.ino - a wizard for HC-05 bluetooth modules
* Copyright (c) 2016 Rami Baddour. All right reserved.
* http://ramibaddour.com/ https://ch.linkedin.com/in/ramibaddour
*
* A program to view, set, modify and use the HC-05 bluetooth with an interactive textural menus
* over serial monitore
*
* You can include parts of the code that does specific functionality (e.g. search for devices)
* to your own program
*
* Note that this code uses intensively the String class, which has some unpredictable behaviour
* when virtual memory is not possible to researve. IT is tested to work perfectly when restricting
* number of recorded searched devices to 3. above this can have some problems with displyed strings.
*
* Newer version will use char arrays instead, hopefully with better stability.
*
*
*/
#include
SoftwareSerial mySerial(5, 4);// RX, TX where the HC-05 is connected
#define pinRe 3 // the Reset pin, connected to HC-05 pin No. 11
#define pinEn 6 // the Enable pin, connected to HC-05 pin No. 34
#define INQ1 1 // Inquire Acces mode: 0-standard 1-RSSI(default)
#define INQ2 100 // Maximum number of devices responce: 0-to-32000
#define INQ3 30 // Inquire timeout: 1-to-48 sec
#define MAXDEV 1 // Maximum number of devices to record.
#define PAIRTO “25” // Pairing timout in seconds
#define MAXSTRLEN 50 // maximum buffer researved for string variables.
#define ATSTART “#start” // The token string to start AT command input
#define ATEND “#end” // The token string to end AT command or Operational menu input
#define ATOP “#op” // The token string to start the operation menu.
// column widths in character count for the discovred BT devices‘ list
#define colW1 6
#define colW2 45
#define colW3 20
#define colW4 7
int8_t currIn = -1; // The current input, records the user selection and used within the program state machine
int8_t currSt = -1; // the current state, defines the current status in regards to the menu selections
int8_t deviceCount = 0; // the Reset pin, connected to HC-05 pin No. 13
int devCount = 0; // how many devices in total have been discovered in the last device inquiry
int devLoc = 0; // the location of the selected device within the list of discovered devices.
String serialStr, tmpName, tmpRes; //some string variables to be used later
//define a data structure for each descovered device. It inlcudes basic information like the name, address, RRSI and Service class
typedef struct inqDevices{
String Name;
String Address;
String RSSI;
String Class;
inqDevices(int defSize=MAXSTRLEN){
Name.reserve(defSize);
Name = “”;
Address.reserve(20);
Address = “”;
RSSI.reserve(20);
RSSI = “”;
Class.reserve(40);
Class = “”;
}
}inqDevice;
inqDevice lstDevices[MAXDEV]; // This function takes a string of any length ’strIn‘ and outputs a the same string but with fixed length ’strLen‘
// which is a substring of the input if length(strIn)》strLen, is the same as ’strIn‘ with the remaining characters
// filled with ’strFillChar‘ character.
// if ’strFill‘ is set to true, the input string is appended to the end of the result string as well.
String strFixed (String strIn, int strLen, boolean strFill = false, String strFillChar = “ ”){
String tmpStr1 = strIn.substring(0,strLen);
int tmpLen = tmpStr1.length();
for (int i=0; i《 (strLen - tmpLen); i++)
tmpStr1 = tmpStr1 + strFillChar;
if (strFill)
tmpStr1 = tmpStr1 + strIn;
return (tmpStr1);
}
// A function to clear the contents of the Device List array strings.
void clearDeviceList(){
for (int i = 0; i // Use the ’discardOK‘ setting if you want the function to discard the ’OK‘ result on the AT command return.
// Use the ’charsToCutFrom‘ and ’charsToCutTo‘ if you want to get only a substring of the AT command return. e.g. if you want to discard
// the ’+INQ:‘ initial part in the ’AT+INQ‘ command responce and get directly the address and signal information of the descovered device.
String getFromMySerial(String strToWrite = “”, bool discardOK=true, int charsToCutFrom = 0, int charsToCutTo = 150){
if (strToWrite != “”)
{
mySerial.println(strToWrite);
delay(50); // these delays may be not necessary, it just to accomodate slow responding HC-05 modules.
}
String tmpStr = (mySerial.readStringUntil(’ ‘));
tmpStr.trim();
delay(50);
if (discardOK)
mySerial.readStringUntil(’ ‘);
return tmpStr.substring(charsToCutFrom, charsToCutTo);
}
// This function is similar to the previous ’getFromMySerial‘。 But this one is used when the answer
// is not guarenteed after a fixed delay. e.g. if you wait to get remote BT device address or name in
// discovery process. also, it is used if you are not expecting a return value at all.
String getFromMySerialSimple(String strToWrite = “”, int charsToCutFrom = 0, int charsToCutTo = 150){
if (strToWrite != “”)
{
mySerial.println(strToWrite);
delay(100);
return “”;
}
else
{
while (!mySerial.available()){delay(10);}
String tmpStr = (mySerial.readStringUntil(’ ‘));
return tmpStr.substring(charsToCutFrom, charsToCutTo);
}
} void setup() {
Serial.begin(57600);
mySerial.begin(38400); // default HC-05 baud rate at AT-mode
Serial.print(F(“to enter AT mode please type ’”));
Serial.print(ATSTART);
Serial.print(F(“‘, to exist type ”));
Serial.print(ATEND);
Serial.print(F(“, or type ’”));
Serial.print(ATOP);
Serial.println(F(“ for the menu”));
pinMode(pinRe, OUTPUT);
pinMode(pinEn, OUTPUT);
serialStr = “”;
serialStr.reserve(MAXSTRLEN);
tmpName.reserve(MAXSTRLEN);
tmpRes.reserve(MAXSTRLEN);
} void loop(){
if (Serial.available()) {
serialStr = (Serial.readStringUntil(‘ ’));
serialStr.trim();
// Entering AT mode, you set EN pin to HIGH, and generate a 100ms negative pulse on the reset pin
if (serialStr.equalsIgnoreCase(ATSTART)) {
Serial.println(F(ATSTART));
Serial.println(F(“You are now in AT mode, Enter AT commands:”));
currIn = -1;
currSt = -5;
digitalWrite(pinEn,HIGH); // Set the Enable pin (no.34) to HIGH, and keep it during the AT command operation
digitalWrite(pinRe,LOW); // Set the Reset pin (no.11) to LOW, this postpones the module in preparation to reset
delay(100); // A short delay (should be more that 10 ms) to simulate a negative pulse on the reset pin
digitalWrite(pinRe,HIGH); // Set the Reset pin back to HIGH, and with Enable pin set to HIGH, the module restarts in AT Command mode.
serialStr = “”;
}
// Exiting AT mode into data transmission mode, you set EN pin to LOW, and generate a 100ms negative pulse on the reset pin
else if (serialStr.equalsIgnoreCase(ATEND)){
currIn = -1;
currSt = -1;
Serial.println(F(ATEND));
Serial.println(F(“You have quit AT mode.”));
digitalWrite(pinEn,LOW); // Set the Enable pin (no.34) to LOW, and keep it during the data transmission mode
digitalWrite(pinRe,LOW); // Set the Reset pin (no.11) to LOW, this postpones the module in preparation to reset
delay(100); // A short delay (should be more that 10 ms) to simulate a negative pulse on the reset pin
digitalWrite(pinRe,HIGH); // Set the Reset pin back to HIGH, and with Enable pin set to LOW, the module restarts in Data transmission mode.
}
// To enter the operational menu mode, you do the same as initiating AT mode, but with the state variablle state to 0 so you enable the menu state machine
else if (serialStr.equalsIgnoreCase(ATOP)){
currIn = 0;
currSt = 0;
Serial.println(F(ATOP));
digitalWrite(pinEn,HIGH);
digitalWrite(pinRe,LOW);
delay(100);
digitalWrite(pinRe,HIGH);
}
// For any other input, this is basically a selection of an item in the menu, or a command in AT mode.
else{
Serial.println(serialStr);
currIn = serialStr.toInt(); //any non-numerical input results in ‘0’
}
// This is when we start the AT mode , all inputs are sent to the bluetooth module.
if (currSt == -5){
mySerial.println(serialStr);
}
}
// In case of responce or input from the bluetooth module itself
if (mySerial.available()){
while (mySerial.available()){
tmpName = (mySerial.readStringUntil(‘ ’));
tmpName.trim();
Serial.println(tmpName);
delay(50);
} }
if (currIn 》= 0){ // enter the state machine only if we get a valid input
switch (currSt){ // the menu display selection
case 0:{ // this is the main menu
switch (currIn){ // based on the user input, selects the corresponding operation and therefore the next state
case 0:
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“Please select from the following operations:”));
Serial.println(F(“ 1- Display the module settings”));
Serial.println(F(“ 2- Modify current settings”));
Serial.println(F(“ 3- Reset to original settings”));
Serial.println(F(“ 4- Master-only operations”));
Serial.println(F(“ 5 -”));
Serial.print(F(“(Option No.) ”));
currIn = -1; // we set to -1 to avoid entering into the state machine indefinately.
break;
case 1:
currSt = 1;
break;
case 2:
currSt = 2;
currIn = 0;
break;
case 3:
currSt = 3;
break;
case 4:
currSt = 4;
currIn = 0;
break;
default:
Serial.println (F(“not a valid input, please select from the list”));
currSt = 0;
currIn = 0;
}
break;
}
case 1:{ // display the module main settings. for each, send the command and wait for the result and display it
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“The current module settings are:”));
Serial.print(F(“ -- Name : ”));
Serial.println(getFromMySerial(“AT+NAME”, true, 6));
Serial.print(F(“ -- Baudrate : ”));
Serial.println(getFromMySerial(“AT+UART”, true, 6));
Serial.print(F(“ -- Role : ”));
if (getFromMySerial(“AT+ROLE”, true, 6) == “1”)
Serial.println(F(“Master”));
else
Serial.println(F(“Slave”));
Serial.print(F(“ -- Conn. Mode : ”));
tmpRes = getFromMySerial(“AT+CMODE”, true, 6);
if ( tmpRes == “0”)
Serial.println(F(“Single remote connection”));
else if ( tmpRes == “1”)
Serial.println(F(“Any remote connection”));
else
Serial.println(F(“Test mode”));
Serial.print(F(“ -- Passowrd : ”));
Serial.println(getFromMySerial(“AT+PSWD”, true, 6));
currSt = 0;
currIn = 0;
break;
}
case 2:{ // The menu to modify the BT module settings
switch (currIn){
case 0:
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“Please select from the following operations:”));
Serial.println(F(“ 1- Modify the module name”));
Serial.println(F(“ 2- Modify UART settings”));
Serial.println(F(“ 3- Modify the pairing code/PW”));
Serial.println(F(“ 4- Switch the role (Master/Slave)”));
Serial.println(F(“ 5- Change connection mode”));
Serial.println(F(“ 6- Back.。.”));
Serial.print(F(“(Option No.) ”));
currIn = -1;
break;
case 1:
currSt = 21;
currIn = 0;
break;
case 2:
currSt = 22;
currIn = 0;
break;
case 3:
currSt = 23;
currIn = 0;
break;
case 4:
currSt = 24;
currIn = 0;
break;
case 5:
currSt = 25;
currIn = 0;
break;
case 6:
currSt = 0;
currIn = 0;
break;
default:
Serial.println (F(“not a valid input, please select from the list”));
currSt = 2; // stay in the same menu if wrong input is entered
currIn = 0;
break;
}
break;
}
case 21:{ // Modify the module‘s name
Serial.println(F(“----------------------------------------------------------”));
Serial.print(F(“The curent module name is : ”));
Serial.println(getFromMySerial(“AT+NAME”, true, 6));
Serial.println(F(“Please enter a new name, or leave blank to keep the current setting.”));
while (!Serial.available());
tmpName = (Serial.readStringUntil(’ ‘));
tmpName.trim();
if (tmpName == “”)
Serial.println(F(“Name is left unchanged”));
else{
tmpName = “AT+NAME=” + tmpName;
tmpRes = getFromMySerial(tmpName, true);
if (tmpRes == “OK”)
Serial.println (F(“Name change successful”));
else
Serial.println (F(“Faild to change the name, please check the name and try again”));
}
currSt = 2;
currIn = 0;
break;
}
case 22:{ // Modify the serial UART port settings (Baudrate, Stop bit and Parity bits)
Serial.println(F(“----------------------------------------------------------”));
Serial.print(F(“The curent UART (Baudrate) settings are : ”));
tmpName = getFromMySerial(“AT+UART”, true, 6);
String tmpBR = tmpName.substring(0,tmpName.indexOf(’,‘)); // Baud rate
String tmpSB = tmpName.substring(tmpName.indexOf(’,‘)+1,tmpName.indexOf(’,‘)+2);// Stop Bit
String tmpPB = tmpName.substring(tmpName.indexOf(’,‘)+3,tmpName.indexOf(’,‘)+4);// Parity bit
Serial.println(tmpName);
Serial.println(F(“Choose new Baudrate, or leave it blank to keep unchanged. Possible options:”));
Serial.println(F(“(1) 4800 (2) 9600 (3) 19200 (4) 38400 (5) 57600”));
Serial.println(F(“(6) 115200 (7) 234000 (8) 460800 (9) 921600 (10) 1382400”));
while (!Serial.available());
tmpName = (Serial.readStringUntil(’ ‘));
tmpName.trim();
if (tmpName == “”)
{
Serial.print(F(“Baudrate is left unchanged: ”));
Serial.println(tmpBR);
}
else
{
int tmpInt = tmpName.toInt(); //Baudrate
if ((tmpInt 》 0)&&(tmpInt 《 11))
Serial.print(F(“Baudrate channged successfully, the new baudrate is: ”));
switch (tmpInt) {
case 1: case 2: case 3: case 4:
tmpBR = String(2400 * pow(2,tmpInt),0);
Serial.println(tmpBR);
break;
case 5: case 6: case 7: case 8: case 9:
tmpBR = String(1800 * pow(2,tmpInt),0);
Serial.println(tmpBR);
break;
case 10:
tmpBR = “1382400”;
Serial.println(tmpBR);
break;
default:
Serial.println(F(“Incorrect input, baudrate is left unchanged”));
}
}
Serial.println(); // Stop Bits
Serial.println(F(“Choose the number of Stop bits, or leave it blank to keep unchanged. Possible options:”));
Serial.println(F(“(a) 0:1 bit (b) 1:2 bits”));
while (!Serial.available());
tmpName = (Serial.readStringUntil(’ ‘));
tmpName.trim();
if (tmpName == “”)
{
Serial.print(F(“Stop bit number is left unchanged: ”));
Serial.println(tmpSB);
}
else if ((tmpName == “a”)||(tmpName == “A”))
{
tmpSB = “0”;
Serial.print(F(“Stop bit number is channged successfully, the new setting is: ”));
Serial.println(tmpSB);
}
else if ((tmpName == “b”)||(tmpName == “B”))
{
tmpSB = “1”;
Serial.print(F(“Stop bit number is channged successfully, the new setting is: ”));
Serial.println(tmpSB);
}
else
Serial.println(F(“Incorrect input, Stop bit number is left unchanged”));
Serial.println(); //Parity bits
Serial.println(F(“Choose parity bits setting, or leave it blank to keep unchanged. Possible options:”));
Serial.println(F(“(1) no parity (2) odd parity (3) even parity”));
while (!Serial.available());
tmpName = (Serial.readStringUntil(’ ‘));
tmpName.trim();
int tmpInt = tmpName.toInt();
if (tmpName == “”)
{
Serial.print(F(“Parity bits setting is left unchanged: ”));
Serial.println(tmpPB);
}
else if ((tmpInt 》0)&&(tmpInt 《4))
{
tmpPB = tmpName;
Serial.print(F(“Parity bits setting is channged successfully, the new setting is: ”));
Serial.println(tmpPB);
}
else
Serial.println(F(“Incorrect input, Parity bits setting is left unchanged”));
tmpName = “AT+UART=” + tmpBR + “,” + tmpSB + “,” + tmpPB; // The overal UART settings command
String tmpRes = getFromMySerial(tmpName, true);
if (tmpRes == “OK”)
Serial.println (F(“UART settings change successful”));
else
Serial.println (F(“Faild to change the UART settings, please try again”));
currSt = 2;
currIn = 0;
break;
}
case 23:{ // Modify the password (Pairing code)
Serial.println(F(“----------------------------------------------------------”));
Serial.print(F(“The curent pairing code is : ”));
Serial.println(getFromMySerial(“AT+PSWD”, true, 6));
Serial.println(F(“Please enter a new pairing passkey, or leave blank to keep the current code.”));
while (!Serial.available());
tmpName = (Serial.readStringUntil(’ ‘));
tmpName.trim();
if (tmpName == “”)
Serial.println(F(“Pairing passkey is left unchanged”));
else
{
tmpName = “AT+PSWD=” + tmpName;
String tmpRes = getFromMySerial(tmpName, true);
if (tmpRes == “OK”)
Serial.println (F(“Pairing passkey change successful”));
else
Serial.println (F(“Faild to change the Pairing passkey , please check the code and try again”));
}
currSt = 2;
currIn = 0;
break;
}
case 24:{ // Modify the role (Master/Slave/Slave-loop)
Serial.println(F(“----------------------------------------------------------”));
Serial.print(F(“The curent role setting is : ”));
tmpName = getFromMySerial(“AT+ROLE”, true, 6);
tmpName.trim();
Serial.print(tmpName);
if (tmpName == “0”)
Serial.println(F(“ [Slave]”));
else if (tmpName == “1”)
Serial.println(F(“ [Master]”));
else if (tmpName == “2”)
Serial.println(F(“ [Slave-loop]”));
Serial.println(F(“Choose a new role, or leave it blank to keep unchanged. Possible options:”));
Serial.println(F(“(0) 0:Slave (1) 1:Master (2) 2:Slave-loop”));
while (!Serial.available());
tmpName = (Serial.readStringUntil(’ ‘));
tmpName.trim();
if (tmpName == “”)
{
Serial.print(F(“Role is left unchanged: ”));
}
else
{
int tmpInt = tmpName.toInt();
switch (tmpInt)
{
case 0: case 1: case 2:
tmpName = “AT+ROLE=” + tmpName;
tmpRes = getFromMySerial(tmpName, true);
if (tmpRes == “OK”)
Serial.println (F(“Role change successful”));
else
Serial.println (F(“Faild to change the role, please try again”));
break;
default:
Serial.println(F(“Incorrect input, role is left unchanged”));
break;
}
}
currSt = 2;
currIn = 0;
break;
}
case 25:{ // Change the connection mode
Serial.println(F(“----------------------------------------------------------”));
Serial.print(F(“The curent connection mode is : ”));
tmpName = getFromMySerial(“AT+CMODE”, true, 6);
tmpName.trim();
Serial.print(tmpName);
if (tmpName == “0”)
Serial.println(F(“ [Single remote connection]”));
else if (tmpName == “1”)
Serial.println(F(“ [Any remote connection]”));
else if (tmpName == “2”)
Serial.println(F(“ [Test mode]”));
Serial.println(F(“Choose a new connection mode, or leave it blank to keep unchanged. Possible options:”));
Serial.println(F(“(0) 0:Single remote connection (1) 1:Any remote connection (2) 2:Test mode”));
while (!Serial.available());
tmpName = (Serial.readStringUntil(’ ‘));
tmpName.trim();
if (tmpName == “”)
{
Serial.print(F(“Connection mode is left unchanged: ”));
}
else
{
int tmpInt = tmpName.toInt();
switch (tmpInt)
{
case 0: case 1: case 2:
tmpName = “AT+CMODE=” + tmpName;
tmpRes = getFromMySerial(tmpName, true);
if (tmpRes == “OK”)
Serial.println (F(“Connection mode change successful”));
else
Serial.println (F(“Faild to change the connection mode, please try again”));
break;
default:
Serial.println(F(“Incorrect input, connection mode is left unchanged”));
break;
}
}
currSt = 2;
currIn = 0;
break;
}
case 3:{ // Reset the module to the original settings
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“The module settings are reset to original”));
getFromMySerial(“AT+ORGL”, false, 6);
Serial.print(F(“ -- Name : ”));
Serial.println(getFromMySerial(“AT+NAME”, true, 6));
Serial.print(F(“ -- Baudrate : ”));
Serial.println(getFromMySerial(“AT+UART”, true, 6));
Serial.print(F(“ -- Role : ”));
if (getFromMySerial(“AT+ROLE”, true, 6) == “1”)
Serial.println(F(“Master”));
else
Serial.println(F(“Slave”));
Serial.print(F(“ -- Passowrd : ”));
Serial.println(getFromMySerial(“AT+PSWD”, true, 6));
currSt = 0;
currIn = 0;
break;
}
case 4:{ // The menu to perform the Master module operations.
if (getFromMySerial(“AT+ROLE”, true, 6) != “1”) { // Check if the module role=1 which mean the module is master.
Serial.println(F(“The module should be in Master role to perform these operations, please change the role.”));
currSt = 2;
currIn = 0;
}
else{
switch (currIn){
case 0:
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“Please select from the following operations:”));
Serial.println(F(“ 1- Discover nearby devices”));
Serial.println(F(“ 2- Pair with a device”));
Serial.println(F(“ 3- Connect to a device”));
Serial.println(F(“ 4- Remove devices from pairing list”));
Serial.println(F(“ 5- Bind with a device”));
Serial.println(F(“ 6- Back.。.”));
Serial.print(F(“(Option No.) ”));
currIn = -1;
break;
case 1:
currSt = 41; currIn = 0; break;
case 2:
currSt = 42; currIn = 0; break;
case 3:
currSt = 43; currIn = 0; break;
case 4:
currSt = 44; currIn = 0; break;
case 5:
currSt = 45; currIn = 0; break;
case 6:
currSt = 0; currIn = 0; break;
default:
Serial.println (F(“not a valid input, please select from the list”));
currSt = 4; currIn = 0; break;
}
}
break;
}
case 41:{ // Inquire nearby devices (addresses + names)
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“List of nearby devices:”));
getFromMySerial(“AT+INIT”, true); // Discard the result, it may result in error if the SPP profile is already opened
tmpName = String(“AT+INQM=” + String(INQ1) + “,” + String(INQ2) + “,” + String(INQ3));
tmpRes = getFromMySerial(tmpName, true);
if (tmpRes != “OK”)
Serial.println (F(“Inquire mode setting failed”));
else
{
getFromMySerialSimple(“AT+INQ”); // As multiple devices might be discovered, only execute the command then wait on serial for each new line until “OK” is received
clearDeviceList();
tmpName = getFromMySerialSimple(“”, 5); // at least, we have on result even if no devices were discovered, which is the “OK” output at the end of the inquire process
while ((tmpName !=“”)) // As “OK” is less than 5 characters long, the result will be empty string when OK is received.
{
int ind1st = tmpName.indexOf(’,‘); // the index of the first comma
int ind2nd = tmpName.indexOf(’,‘,ind1st + 1); // the index of the second comma
String devAddr = tmpName.substring(0,ind1st); // The device’s address
String devClas = tmpName.substring(ind1st+1,ind2nd); // The device‘s service class
String devRSSI = tmpName.substring(ind2nd+1); // The device’s RSSI
devLoc = searchDeviceList(devAddr); // check ifthe device address is already discovered, As in most cases the same deie can be discovered multiple times with different RSSI and/or different service classes
if ((devLoc 《 0)&& devCount 《 MAXDEV) // a new device, not found in the list, but there is still empty slot in the list (did not exceed the maximum number of stored devices)
{
lstDevices[devCount].Address = devAddr; // we store the new device data
lstDevices[devCount].Class = devClas;
lstDevices[devCount].RSSI = devRSSI;
devCount++;
}
delay(10);
tmpName = getFromMySerialSimple(“”, 5); // get the next input from MySerial (i.e. BT device)
}
Serial.println (strFixed(“+”,colW1 + colW2 + colW3 + colW4 + 3,true,“-”)); // draw a table with the results
Serial.println (“| ” + strFixed(“Ind.”,colW1)+ strFixed(“BT Device Name:”,colW2) + strFixed(“BT Device Address”,colW3) + strFixed(“Paired”,colW4)+ “ |”);
Serial.println (“| ” + strFixed(“-----”,colW1)+ strFixed(“----------------”,colW2) + strFixed(“------------------”,colW3) + strFixed(“-------”,colW4)+ “ |”);
for (int i=0; i devCount){ // if a numerical input exceeds the number of stored/discovered devices
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“The selected index is out of bounds, please select within the list of available devices”));
Serial.print(F(“(Option No.) ”));
currIn = -3; // stay in the same menu, until a correct index is entered or ‘q’ for exitting to previous menu
}
else{
devLoc = currIn - 1; // the index starts with 0
tmpName = lstDevices[devLoc].Address;
tmpName.replace(“:”,“,”);
tmpName = String(“AT+PAIR=” + tmpName+“,”+PAIRTO);
tmpRes = getFromMySerialSimple(tmpName);
tmpRes = getFromMySerialSimple(“”); // we do this as the pairing process can take longer, so we cannot rely on the timeout in the readstringuntil()
tmpRes.trim();
if (tmpRes == “OK”)
{
Serial.println ((“You are now paired with the device ” + lstDevices[devLoc].Name +“ [” + lstDevices[devLoc].Address + “]”));
}
else
{
Serial.println (tmpName);
Serial.println (tmpRes);
Serial.println (F(“Could not pair with the device, try again or initiat another search for devices”));
}
currSt = 4;
currIn = 0;
}
break;
}
case 43:{ // Connect with one of the discovered devices
if (currIn == 0){
if (serialStr.equalsIgnoreCase(“q”)){ //‘q’ to quite to previous menu
currSt = 4;
currIn = 0;
}
else{
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“Select the device index that you want to connect to, q to abort ”));
Serial.print(F(“(Option No.) ”));
currIn = -3;
}
}
else if (currIn 》 devCount){ // if a numerical input exceeds the number of stored/discovered devices
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“The selected index is out of bounds, please select within the list of available devices”));
Serial.print(F(“(Option No.) ”));
currIn = -3;
}
else{
devLoc = currIn - 1; // the index starts with 0
tmpName = lstDevices[devLoc].Address;
tmpName.replace(“:”,“,”);
tmpName = String(“AT+LINK=” + tmpName);
tmpRes = getFromMySerialSimple(tmpName);
tmpRes = getFromMySerialSimple(“”); // we do this as the linking/connecting process can take longer, so we cannot rely on the timeout in the readstringuntil()
tmpRes.trim();
if (tmpRes == “OK”){
Serial.println ((“You are now connected with the device ” + lstDevices[devLoc].Name +“ [” + lstDevices[devLoc].Address + “], type ‘#end’ to disconnect and reset.”));
currSt = 6;
currIn = 0;
}
else{
Serial.println (tmpName);
Serial.println (tmpRes);
Serial.println (F(“Could not connect with the device, try again or initiat another search for devices”));
}
currSt = 4;
currIn = 0;
}
break;
serialStr = “”;
}
case 44:{
if (currIn == 0)
{
if (serialStr.equalsIgnoreCase(“q”))
{
currSt = 4;
currIn = 0;
}
else if (serialStr.equalsIgnoreCase(“a”))
{
tmpRes = getFromMySerial(String(“AT+ADCN”), true, 6);
tmpRes.trim();
int tmpCount = tmpRes.toInt();
for (int i=0; i devCount)
{
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“The selected index is out of bounds, please select within the list of available devices”));
Serial.print(F(“(Option No.) ”));
currIn = -4;
}
else
{
devLoc = currIn - 1;
tmpName = lstDevices[devLoc].Address;
tmpName.replace(“:”,“,”);
tmpRes = getFromMySerial(String(“AT+FSAD=”)+ tmpName, true);
tmpRes.trim();
if (tmpRes == “OK”)
{
tmpRes = getFromMySerial(String(“AT+RMSAD=”)+ tmpName, true);
tmpRes.trim();
if (tmpRes == “OK”)
{
Serial.println((“The device ” + lstDevices[devLoc].Name +“ [” + lstDevices[devLoc].Address + “] is removed from the paired devices list”));
}
}
else
{
Serial.println (F(“The device is not within the paired devices list.”));
}
currIn = 0;
}
break;
}
case 45:{
if (currIn == 0)
{
if (serialStr.equalsIgnoreCase(“q”))
{
currSt = 4;
currIn = 0;
}
else
{
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“Select the device index that you want to bind with, q to abort ”));
Serial.print(F(“(Option No.) ”));
currIn = -3;
}
}
else if (currIn 》 devCount)
{
Serial.println(F(“----------------------------------------------------------”));
Serial.println(F(“The selected index is out of bounds, please select within the list of available devices”));
Serial.print(F(“(Option No.) ”));
currIn = -3;
}
else
{
devLoc = currIn - 1;
tmpName = lstDevices[devLoc].Address;
tmpName.replace(“:”,“,”);
tmpName = String(“AT+BIND=” + tmpName);
tmpRes = getFromMySerialSimple(tmpName);
tmpRes = getFromMySerialSimple(“”);
tmpRes.trim();
if (tmpRes == “OK”)
{
Serial.println ((“You are now binded with the device ” + lstDevices[devLoc].Name +“ [” + lstDevices[devLoc].Address + “], type ‘#end’ to disconnect and reset.”));
}
else
{
Serial.println (F(“Could not bind with the device, try again or initiat another search for devices”));
}
currSt = 4;
currIn = 0;
}
break;
}
case 6:{
for (int i=0; i《 serialStr.length(); i++)
mySerial.write(serialStr[i]);
break;
}
}
}
serialStr = “”;
}
責任編輯:wv
-
藍牙模塊
+關注
關注
30文章
575瀏覽量
55738 -
HC-05
+關注
關注
0文章
34瀏覽量
16929
發布評論請先 登錄
相關推薦
評論