123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- #include <Arduino.h>
- #include <HC05.h>
-
- #ifdef DEBUG_SW_PORT
- SoftwareSerial DEBUG_SW_PORT;
- #endif
-
- #ifdef HC05_SOFTWARE_SERIAL
- HC05::HC05(int cmdPin, int statePin, uint8_t rx, uint8_t tx):_btSerial(rx,tx,0)
- #else
- #define _btSerial HC05_HW_SERIAL_PORT
- HC05::HC05(int cmdPin, int statePin)
- #endif
- {
- pinMode(cmdPin, OUTPUT);
- _cmdPin = cmdPin;
- cmdMode = false;
- #ifdef HC05_STATE_PIN
- pinMode(statePin, INPUT);
- _statePin = statePin;
- #endif
- _bufsize = sizeof(_buffer)/sizeof(char);
- }
-
- static const unsigned long rates[] =
- {4800,9600,19200,38400,57600,115200};
-
- unsigned long HC05::findBaud()
- {
- const int bt_rx = 4;
- const int bt_tx = 5;
- int numRates = sizeof(rates)/sizeof(unsigned long);
- int response = false;
- int recvd = 0;
- //char _buffer[128];
-
- DEBUG_PRINTLN("findBaud");
- setCmdPin(HIGH);
- delay(100);
- for(int rn = 0; rn < numRates; rn++)
- {
- _btSerial.begin(rates[rn]);
- _btSerial.setTimeout(100);
- _btSerial.flush();
- DEBUG_WRITE("Trying ");
- DEBUG_PRINT(rates[rn]);
- DEBUG_WRITE("... ");
- _btSerial.write("AT\r\n");
- recvd = _btSerial.readBytes(_buffer,_bufsize);
- if (recvd > 0)
- {
- DEBUG_PRINTLN("Found.");
- // FIXME: refactor to a single return
- setCmdPin(LOW);
- return(rates[rn]);
- }
- else
- {
- DEBUG_PRINTLN("x");
- }
- }
- setCmdPin(LOW);
- DEBUG_WRITE("\r\nNo connection\r\n");
- return(0);
- }
- bool HC05::cmd(String cmd, unsigned long timeout)
- {
- return this->cmd(cmd.c_str(), timeout);
- }
-
- bool HC05::cmd(const char* cmd, unsigned long timeout)
- {
- _lastError = -1;
- _stringBuffer = "";
- _stringData = "";
- int recvd = 0;
- DEBUG_PRINTLN(cmd);
-
- setCmdPin(HIGH);
- // No spec for how long it takes to enter command mode, but 100ms
- // seems to work- assuming the output has been drained.
- delay(100);
- _btSerial.write(cmd);
- _btSerial.write("\r\n");
- _btSerial.setTimeout(timeout);
- do
- {
- // ATTENTION: At least through Arduino v1.0.3, it is not possible
- // to tell the difference between a timeout and
- // receiving only the termination character (NL in this
- // case), because the termination character is not
- // returned and timeout is not returned as a unique
- // indication.
- // In this case the result would be an early return
- // of a multiline response before the OK is received.
- // The return would incorrectly indicate an error (no
- // OK response).
- recvd = _btSerial.readBytesUntil('\n', _buffer, _bufsize);
- if (recvd > 0)
- {
- _buffer[recvd] = 0;
- _stringBuffer += _buffer;
- _stringBuffer += "\n";
- // DEBUG_WRITE((uint8_t *)_buffer,recvd);
- // DEBUG_WRITE('\n');
- }
- else
- {
- DEBUG_PRINTLN("timeout 1");
- }
- }
- while ((recvd > 0) && (_buffer[0] != 'O' || _buffer[1] != 'K'));
-
- setCmdPin(LOW);
-
- // Empirically determined that it takes some time to reliably exit
- // command mode. The appeared to be a baud rate dependency and with
- // >100ms required at 9600 baud.
- delay(150);
- DEBUG_WRITE(_stringBuffer.c_str());
-
- if (_buffer[0] == 'O' && _buffer[1] == 'K') {
- return true;
- }
-
- if (_stringBuffer.startsWith("ERROR:(")) {
- String errorCode = _stringBuffer.substring(7, _stringBuffer.length() - 3);
- _lastError = errorCode.toInt();
- DEBUG_WRITE("Error: ");
- DEBUG_PRINTLN(_lastError);
- } else {
- _lastError = -1;
- }
-
- return false;
- }
-
-
- /*
- * If setBaud() is called while the HC-05 is connected, then
- * it will be disconnected when AT+RESET command is issued, and
- * it may take 2 (or more?) connection attempts to reconnect. The extra
- * connect attempts may be a host side issue and not specific to the
- * HC-05 module.
- */
- void HC05::setBaud(unsigned long baud, unsigned long stopbits, unsigned long parity)
- {
- int recvd = 0;
- setCmdPin(HIGH);
- delay(200);
- DEBUG_WRITE("AT+UART=");
- _btSerial.write("AT+UART=");
- DEBUG_PRINT(baud);
- _btSerial.print(baud);
-
- DEBUG_PRINT(",");
- _btSerial.print(",");
-
- DEBUG_PRINT(stopbits);
- _btSerial.print(stopbits);
-
- DEBUG_PRINT(",");
- _btSerial.print(",");
-
- DEBUG_PRINT(parity);
- _btSerial.print(parity);
-
- DEBUG_WRITE("\r\n");
- _btSerial.write("\r\n");
-
- recvd = _btSerial.readBytes(_buffer,_bufsize);
- if (recvd > 0)
- {
- DEBUG_WRITE((uint8_t *)_buffer,recvd);
- }
- else
- {
- DEBUG_PRINTLN("timeout 2");
- }
- cmd("AT+RESET");
- setCmdPin(LOW);
- _btSerial.begin(baud);
- delay(1000);
- }
-
- // Usually parity is none, and there is only one stop bit, so this
- // simpler call will do the job.
- void HC05::setBaud(unsigned long baud)
- {
- setBaud(baud, 0, 0);
- }
-
-
- int HC05::available()
- {
- _btSerial.available();
- }
-
- int HC05::peek()
- {
- _btSerial.peek();
- }
-
- void HC05::flush()
- {
- _btSerial.flush();
- }
-
- int HC05::read()
- {
- _btSerial.read();
- }
-
- void HC05::begin(unsigned long baud)
- {
- _btSerial.begin(baud);
- }
-
- #ifndef HC05_SOFTWARE_SERIAL
- // only hardware serial ports support parity/stop bit configuration
- void HC05::begin(unsigned long baud, uint8_t config)
- {
- _btSerial.begin(baud, config);
- }
- #endif
-
- #ifdef HC05_STATE_PIN
- bool HC05::connected()
- {
- return(digitalRead(_statePin)?true:false);
- }
- #endif
-
- size_t HC05::write(uint8_t byte)
- {
- #ifdef HC05_STATE_PIN
- // The down side of this check is that the status gets checked for
- // every byte written out. That doesn't seem efficient.
- if (digitalRead(_statePin) != HIGH)
- {
- DEBUG_PRINT("No Connection, waiting...");
- while (digitalRead(_statePin) == LOW)
- {
- delay(100);
- }
- DEBUG_PRINTLN("OK");
- }
- #endif
- _btSerial.write(byte);
- }
-
-
- void HC05::cmdMode2Start(int pwrPin)
- {
- pinMode(pwrPin, OUTPUT);
- digitalWrite(pwrPin, LOW);
- delay(250); // off or reset time
- digitalWrite(_cmdPin, HIGH);
- digitalWrite(pwrPin, HIGH);
- cmdMode = true;
- _btSerial.begin(38400);
- delay(1500); // time for the HC05 to initialize
- }
-
-
- void HC05::cmdMode2End(void)
- {
- digitalWrite(_cmdPin, LOW);
- cmdMode = false;
- delay(1000);
- }
-
- void HC05::setCmdPin(bool state)
- {
- if (cmdMode == false)
- {
- digitalWrite(_cmdPin, state);
- }
- }
-
- bool HC05::atGetCommand(String command, unsigned long timeout)
- {
- return this->atGetCommand1(command, "", timeout);
- }
-
- bool HC05::atGetCommand1(String command, String arg1, unsigned long timeout)
- {
- if (this->cmd("AT+" + command + "?" + arg1, timeout)) {
- if (_stringBuffer.startsWith("+" + command + ":")) {
- _stringData = _stringBuffer.substring(command.length() + 2, _stringBuffer.length() - 6);
- DEBUG_PRINTLN(_stringData);
- }
- return true;
- }
- return false;
- }
-
- bool HC05::atTest(unsigned long timeout)
- {
- return this->cmd("AT", timeout);
- }
-
- bool HC05::atReset(unsigned long timeout)
- {
- return this->cmd("AT+RESET", timeout);
- }
-
- bool HC05::atVersion(unsigned long timeout)
- {
- return this->atGetCommand("VERSION", timeout);
- }
-
- bool HC05::atRestore(unsigned long timeout)
- {
- return this->cmd("AT+ORGL", timeout);
- }
-
- bool HC05::atGetAddress(unsigned long timeout)
- {
- return this->atGetCommand("ADDR", timeout);
- }
-
- bool HC05::atGetName(unsigned long timeout)
- {
- return this->atGetCommand("NAME", timeout);
- }
-
- bool HC05::atSetName(String name, unsigned long timeout)
- {
- return this->cmd("AT+NAME=" + name, timeout);
- }
-
- bool HC05::atGetRemoteName(String address, unsigned long timeout)
- {
- return this->atGetCommand1("RNAME", address, timeout);
- }
-
- bool HC05::atGetRole(unsigned long timeout)
- {
- return this->atGetCommand("ROLE", timeout);
- }
-
- bool HC05::atSetRole(Roles role, unsigned long timeout)
- {
- return this->cmd("AT+ROLE=" + role, timeout);
- }
-
- bool HC05::atGetPassKey(unsigned long timeout)
- {
- return this->atGetCommand("PSWD", timeout);
- }
-
- bool HC05::atSetPassKey(String passKey, unsigned long timeout)
- {
- return this->cmd("AT+PSWD=" + passKey, timeout);
- }
|