Tidied up HC-05 handling (on an ESP32 at least)
Now using SENSE line from HC-05 to detect a client is connected. Runs with either sort of HC-05 module, provided the 5 pin regulator style is set to 9600 data mode. Removed #ifdef BLUETOOTH from .ino file, Bluetooth functions report now anyway with/without client.
This commit is contained in:
parent
7be3424359
commit
2799ec3352
|
@ -19,22 +19,38 @@ sRxLine RxLine;
|
|||
|
||||
bool Bluetooth_ATCommand(const char* cmd);
|
||||
|
||||
const int BTRates[] = {
|
||||
9600, 38400, 115200, 19200, 57600, 2400, 4800, 1200
|
||||
};
|
||||
|
||||
bool bHC05Available = false;
|
||||
// Search for a HC-05 BlueTooth adapter, trying the more common baud rates first.
|
||||
// As we cannot power up with the key pin high we are at the mercy of the baud rate
|
||||
// stored in the module.
|
||||
// **IMPORTANT**
|
||||
// We must use a HC-05 module that uses a 3 pin 3.3V regulator (NOT 5 pin).
|
||||
// On those modules, the EN input drive pin 34 and can be used to switch to AT
|
||||
// command mode from data mode by raising EN high.
|
||||
// ** BEWARE**
|
||||
// The other style modules (with a 5 pin regulator) will disable the HC-05's power
|
||||
// when the EN pin is low!!!!
|
||||
//
|
||||
// Once in command mode we can start interrogating using a simple "AT" command and
|
||||
// checking for a response.
|
||||
// If no response, try another baud rate till we do find a response.
|
||||
// We can then proceed and configure the device's name, and force 9600 data rate
|
||||
|
||||
void Bluetooth_Init()
|
||||
{
|
||||
const int BTRates[] = {
|
||||
9600, 38400, 115200, 19200, 57600, 2400, 4800, 1200
|
||||
};
|
||||
|
||||
RxLine.clear();
|
||||
|
||||
// attach to the SENSE line from the HC-05 module
|
||||
// this line goes high when a BT client is connected :-)
|
||||
pinMode(HC05_Sense, INPUT);
|
||||
|
||||
// search for BlueTooth adapter, trying the common baud rates, then less common
|
||||
// as the device cannot be guaranteed to power up with the key pin high
|
||||
// we are at the mercy of the baud rate stored in the module.
|
||||
digitalWrite(KeyPin, HIGH);
|
||||
delay(5000);
|
||||
Serial2.begin(9600, SERIAL_8N1, Rx2Pin, Tx2Pin); // need to explicitly specify pins for pin multiplexer!);
|
||||
digitalWrite(KeyPin, HIGH); // request HC-05 module to enter command mode
|
||||
// Open Serial2, explicitly specify pins for pin multiplexer!);
|
||||
Serial2.begin(9600, SERIAL_8N1, Rx2Pin, Tx2Pin);
|
||||
|
||||
DebugPort.println("\r\n\r\nAttempting to detect HC-05 Bluetooth module...");
|
||||
|
||||
|
@ -44,88 +60,85 @@ void Bluetooth_Init()
|
|||
DebugPort.print(" @ ");
|
||||
DebugPort.print(BTRates[BTidx]);
|
||||
DebugPort.print(" baud... ");
|
||||
Serial2.begin(BTRates[BTidx], SERIAL_8N1, Rx2Pin, Tx2Pin); // open serial port at a certain baud rate
|
||||
Serial2.begin(BTRates[BTidx], SERIAL_8N1, Rx2Pin, Tx2Pin); // open serial port at a std.baud rate
|
||||
delay(10);
|
||||
Serial2.print("\r\n"); // clear the throat!
|
||||
delay(100);
|
||||
Serial2.print("\r\n");
|
||||
Serial2.setTimeout(100);
|
||||
|
||||
if(Bluetooth_ATCommand("AT\r\n")) {
|
||||
DebugPort.println(" OK.");
|
||||
break;
|
||||
}
|
||||
if(Bluetooth_ATCommand("AT\r\n")) {
|
||||
if(Bluetooth_ATCommand("AT\r\n")) { // probe with a simple "AT"
|
||||
DebugPort.println(" OK."); // got a response - woo hoo found the module!
|
||||
break;
|
||||
}
|
||||
if(Bluetooth_ATCommand("AT\r\n")) { // sometimes a second try is good...
|
||||
DebugPort.println(" OK.");
|
||||
break;
|
||||
}
|
||||
|
||||
// failed, try another baud rate
|
||||
DebugPort.println("");
|
||||
Serial2.flush();
|
||||
Serial2.end();
|
||||
delay(1000);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
DebugPort.println("");
|
||||
if(BTidx == maxTries) {
|
||||
DebugPort.println("FAILED to detect HC-05 Bluetooth module :-(");
|
||||
// we could not get anywhere with teh AT commands, but maybe this is the other module
|
||||
// plough on and assume 9600 baud, but at the mercy of whatever the module name is...
|
||||
DebugPort.println("FAILED to detect a HC-05 Bluetooth module :-(");
|
||||
// leave the EN pin high - if other style module keeps it powered!
|
||||
|
||||
// assume it is 9600, and just (try to) use it like that...
|
||||
// we will sense the STATE line to prove a client is hanging off the link...
|
||||
DebugPort.println("ASSUMING a HC-05 module @ 9600baud (Unknown name)");
|
||||
Serial2.begin(9600, SERIAL_8N1, Rx2Pin, Tx2Pin);
|
||||
}
|
||||
else {
|
||||
/*// if(BTRates[BTidx] == 115200) {
|
||||
if(BTRates[BTidx] == 9600) {
|
||||
// DebugPort.println("HC-05 found and already set to 115200 baud, skipping Init.");
|
||||
DebugPort.println("HC-05 found and already set to 9600 baud, skipping Init.");
|
||||
bHC05Available = true;
|
||||
}
|
||||
else*/ {
|
||||
do {
|
||||
DebugPort.println("HC-05 found");
|
||||
// found a HC-05 module at one of its supported baud rates.
|
||||
// now program it's name and force a 9600 baud data interface.
|
||||
// this is the defacto standard as shipped!
|
||||
|
||||
DebugPort.print(" Setting Name to \"Diesel Heater\"... ");
|
||||
if(!Bluetooth_ATCommand("AT+NAME=\"Diesel Heater\"\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
break;
|
||||
}
|
||||
DebugPort.println("OK");
|
||||
DebugPort.println("HC-05 found");
|
||||
|
||||
// DebugPort.print(" Setting baud rate to 115200N81...");
|
||||
// if(!Bluetooth_ATCommand("AT+UART=115200,1,0\r\n")) {
|
||||
DebugPort.print(" Setting baud rate to 9600N81...");
|
||||
if(!Bluetooth_ATCommand("AT+UART=9600,1,0\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
break;
|
||||
};
|
||||
DebugPort.println("OK");
|
||||
do { // so we can break!
|
||||
DebugPort.print(" Setting Name to \"Diesel Heater\"... ");
|
||||
if(!Bluetooth_ATCommand("AT+NAME=\"Diesel Heater\"\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
break;
|
||||
}
|
||||
DebugPort.println("OK");
|
||||
|
||||
// Serial2.begin(115200, SERIAL_8N1, Rx2Pin, Tx2Pin);
|
||||
Serial2.begin(9600, SERIAL_8N1, Rx2Pin, Tx2Pin);
|
||||
bHC05Available = true;
|
||||
DebugPort.print(" Setting baud rate to 9600N81...");
|
||||
if(!Bluetooth_ATCommand("AT+UART=9600,1,0\r\n")) {
|
||||
DebugPort.println("FAILED");
|
||||
break;
|
||||
};
|
||||
DebugPort.println("OK");
|
||||
|
||||
} while(0);
|
||||
Serial2.begin(9600, SERIAL_8N1, Rx2Pin, Tx2Pin);
|
||||
|
||||
}
|
||||
// leave HC-05 command mode, return to data mode
|
||||
digitalWrite(KeyPin, LOW);
|
||||
} while (0); // yeah lame, allows break prior though :-)
|
||||
}
|
||||
digitalWrite(KeyPin, LOW); // leave HC-05 command mode
|
||||
|
||||
delay(500);
|
||||
|
||||
if(!bHC05Available)
|
||||
Serial2.end(); // close serial port if no module found
|
||||
delay(50);
|
||||
|
||||
DebugPort.println("");
|
||||
}
|
||||
|
||||
void Bluetooth_Check()
|
||||
{
|
||||
{
|
||||
// check for data coming back over Bluetooth
|
||||
if(bHC05Available) {
|
||||
if(Serial2.available()) {
|
||||
char rxVal = Serial2.read();
|
||||
if(isControl(rxVal)) { // "End of Line"
|
||||
Command_Interpret(RxLine.Line);
|
||||
RxLine.clear();
|
||||
}
|
||||
else {
|
||||
RxLine.append(rxVal); // append new char to our Rx buffer
|
||||
}
|
||||
if(Serial2.available()) {
|
||||
char rxVal = Serial2.read();
|
||||
if(isControl(rxVal)) { // "End of Line"
|
||||
Command_Interpret(RxLine.Line);
|
||||
RxLine.clear();
|
||||
}
|
||||
else {
|
||||
RxLine.append(rxVal); // append new char to our Rx buffer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,39 +147,42 @@ void Bluetooth_Check()
|
|||
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm)
|
||||
{
|
||||
DebugPort.print(millis());
|
||||
DebugReportFrame(pHdr, Frame, lineterm ? "\r\n" : " ");
|
||||
DebugPort.print("ms ");
|
||||
// DebugReportFrame(pHdr, Frame, lineterm ? "\r\n" : " ");
|
||||
DebugReportFrame(pHdr, Frame, " ");
|
||||
|
||||
if(bHC05Available) {
|
||||
if(digitalRead(HC05_Sense)) {
|
||||
if(Frame.verifyCRC()) {
|
||||
digitalWrite(LED, !digitalRead(LED)); // toggle LED
|
||||
// send data frame to HC-05
|
||||
Serial2.print(pHdr);
|
||||
Serial2.write(Frame.Data, 24);
|
||||
// toggle LED
|
||||
digitalWrite(LED, !digitalRead(LED)); // toggle LED
|
||||
}
|
||||
else {
|
||||
DebugPort.print("Bluetooth data not sent, CRC error ");
|
||||
DebugPort.println(pHdr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DebugPort.println("No Bluetooth client");
|
||||
DebugPort.print("No Bluetooth client");
|
||||
// force LED off
|
||||
digitalWrite(LED, 0);
|
||||
}
|
||||
if(lineterm)
|
||||
DebugPort.println("");
|
||||
}
|
||||
|
||||
// local function, typically to perform Hayes commands with HC-05
|
||||
bool Bluetooth_ATCommand(const char* cmd)
|
||||
{
|
||||
// if(bHC05Available) {
|
||||
Serial2.print(cmd);
|
||||
char RxBuffer[16];
|
||||
memset(RxBuffer, 0, 16);
|
||||
int read = Serial2.readBytesUntil('\n', RxBuffer, 16); // \n is not included in returned string!
|
||||
if((read == 3) && (0 == strcmp(RxBuffer, "OK\r")) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
// }
|
||||
// return false;
|
||||
Serial2.print(cmd);
|
||||
char RxBuffer[16];
|
||||
memset(RxBuffer, 0, 16);
|
||||
int read = Serial2.readBytesUntil('\n', RxBuffer, 16); // \n is not included in returned string!
|
||||
if((read == 3) && (0 == strcmp(RxBuffer, "OK\r")) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#else // ESP32_USE_HC05
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
Chinese Heater Half Duplex Serial Data Sending Tool
|
||||
|
||||
Connects to the blue wire of a Chinese heater, which is the half duplex serial link.
|
||||
|
@ -68,12 +68,9 @@
|
|||
#include "NVStorage.h"
|
||||
#include "debugport.h"
|
||||
|
||||
#define BLUETOOTH
|
||||
#define DEBUG_BTRX
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
#include "Bluetooth.h"
|
||||
#endif
|
||||
|
||||
#if defined(__arm__)
|
||||
// Required for Arduino Due, UARTclass is derived from HardwareSerial
|
||||
|
@ -117,7 +114,7 @@ CProtocol HeaterFrame1; // data packet received from heater in response t
|
|||
CProtocol HeaterFrame2; // data packet received from heater in response to our packet
|
||||
CProtocol DefaultBTCParams(CProtocol::CtrlMode); // defines the default parameters, used in case of no OEM controller
|
||||
long lastRxTime; // used to observe inter character delays
|
||||
int hasController = 0;
|
||||
bool hasOEMController = false;
|
||||
|
||||
// setup Non Volatile storage
|
||||
// this is very much hardware dependent, we can use the ESP32's FLASH
|
||||
|
@ -170,9 +167,7 @@ void setup()
|
|||
DefaultBTCParams.setFan_Min(1680);
|
||||
DefaultBTCParams.setFan_Max(4500);
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
Bluetooth_Init();
|
||||
#endif
|
||||
|
||||
// create pointer to CHeaterStorage
|
||||
// via the magic of polymorphism we can use this to access whatever
|
||||
|
@ -202,9 +197,7 @@ void loop()
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
Bluetooth_Check(); // check for Bluetooth activity
|
||||
#endif
|
||||
|
||||
// Handle time interval where we send data to the blue wire
|
||||
if(CommState.is(CommStates::BTC_Tx)) {
|
||||
|
@ -223,17 +216,11 @@ void loop()
|
|||
// have not seen any receive data for a second.
|
||||
// OEM controller is probably not connected.
|
||||
// Skip state machine immediately to BTC_Tx, sending our own settings.
|
||||
hasController = 0;
|
||||
hasOEMController = false;
|
||||
CommState.set(CommStates::BTC_Tx);
|
||||
bool isBTCmaster = true;
|
||||
TxManage.PrepareFrame(DefaultBTCParams, isBTCmaster); // use our parameters, and mix in NV storage values
|
||||
TxManage.Start(timenow);
|
||||
#ifdef BLUETOOTH
|
||||
// Bluetooth_SendFrame("[BTC]", TxManage.getFrame(), false); // BTC => Bluetooth Controller :-)
|
||||
// Bluetooth_SendFrame("[BTC]", TxManage.getFrame(), true); // BTC => Bluetooth Controller :-)
|
||||
#else
|
||||
DebugReportFrame("BTC ", OEMCtrlFrame, " ");
|
||||
#endif
|
||||
}
|
||||
|
||||
// precautionary action if all 24 bytes were not received whilst expecting them
|
||||
|
@ -264,7 +251,7 @@ void loop()
|
|||
if( CommState.is(CommStates::Idle) && (RxTimeElapsed > 100)) {
|
||||
DebugPort.print(RxTimeElapsed);
|
||||
DebugPort.println(" OEM Controller re-sync");
|
||||
hasController = 1;
|
||||
hasOEMController = true;
|
||||
CommState.set(CommStates::OEMCtrlRx);
|
||||
}
|
||||
|
||||
|
@ -296,23 +283,15 @@ void loop()
|
|||
|
||||
if( CommState.is(CommStates::OEMCtrlReport) ) {
|
||||
// filled controller frame, report
|
||||
#ifdef BLUETOOTH
|
||||
// echo received OEM controller frame over Bluetooth, using [OEM] header
|
||||
Bluetooth_SendFrame("[OEM]", OEMCtrlFrame, true);
|
||||
#else
|
||||
DebugReportFrame("OEM ", OEMCtrlFrame, " ");
|
||||
#endif
|
||||
CommState.set(CommStates::HeaterRx1);
|
||||
}
|
||||
|
||||
else if(CommState.is(CommStates::HeaterReport1) ) {
|
||||
// received heater frame (after controller message), report
|
||||
#ifdef BLUETOOTH
|
||||
// echo heater reponse data to Bluetooth client
|
||||
Bluetooth_SendFrame("[HTR]", HeaterFrame1);
|
||||
#else
|
||||
DebugReportFrame("Htr1 ", HeaterFrame1, "\r\n");
|
||||
#endif
|
||||
|
||||
if(digitalRead(ListenOnlyPin)) {
|
||||
bool isBTCmaster = false;
|
||||
|
@ -328,20 +307,21 @@ void loop()
|
|||
else if( CommState.is(CommStates::HeaterReport2) ) {
|
||||
// received heater frame (after our control message), report
|
||||
delay(5);
|
||||
#ifdef BLUETOOTH
|
||||
if(!hasController) {
|
||||
if(!hasOEMController) {
|
||||
Bluetooth_SendFrame("[BTC]", TxManage.getFrame(), true); // BTC => Bluetooth Controller :-)
|
||||
Bluetooth_SendFrame("[HTR]", HeaterFrame2); // pin not grounded, suppress duplicate to BT
|
||||
}
|
||||
#else
|
||||
DebugReportFrame("Htr2 ", HeaterFrame2, "\r\n");
|
||||
#endif
|
||||
else {
|
||||
DebugReportFrame("Htr2 ", HeaterFrame2, "\r\n");
|
||||
}
|
||||
// if(!digitalRead(ListenOnlyPin)) {
|
||||
// }
|
||||
CommState.set(CommStates::Idle);
|
||||
|
||||
#ifdef SHOW_HEAP
|
||||
Serial.print("Free heap ");
|
||||
Serial.println(ESP.getFreeHeap());
|
||||
#endif
|
||||
}
|
||||
|
||||
} // loop
|
||||
|
|
|
@ -5,4 +5,4 @@ const int Tx1Pin = 18;
|
|||
const int Rx1Pin = 19;
|
||||
const int Tx2Pin = 16;
|
||||
const int Rx2Pin = 17;
|
||||
|
||||
const int HC05_Sense = 4;
|
||||
|
|
Loading…
Reference in a new issue