HC-06 (Bluetooth) Configuration (RN-42 Code Added)
JonnyMac
Posts: 9,547
I haven't searched the forums, but I'll bet the HC-06 made it onto the list of Erco specials -- it's an $8 Bluetooth module that is available everywhere. I've been playing with a few Bluetooth modules for an upcoming project. I have the Parallax RN42 module, an XB-socket compatible RN42 module from Sparkfun, and an HC-06 that I bought from eBay (which, surprisingly, shipped from Los Angeles so I had it in two days instead of four weeks).
The HC-06 is cheap and easy to use (just look at the number of Arduino tutorials for it....), but it's finicky if you want to change the settings. You see, it doesn't use a line-ending character for commands, it uses a timeout period -- and that's pretty darned fast.
I want my BT modules to have unique names and pairing codes, so I wrote the attached configuration program. Honestly, it's overkill, but with a point. I've recently created a parsing engine (subject of my April column) for a bunch of projects and I used this to make setup of the HC-06 easier. For example, instead of sending "AT+BAUD8" I can enter "BAUD 115200" -- and when I request a baud rate change in the module (which should be done after everything else is set), the serial link to the module is restarted with the new baud rate. This is useful if the module is set to something other than the default (9600). In my case, I'm using 115200. If I want to change something, I start the configuration tool and enter "AT" -- if I get "OK" back, I know I'm connected. If I don't, I use the BAUD setting until AT gives the correct response. It's easier to do than to explain.
I'm having fun with Bluetooth. A couple weeks ago Rick Galinson and I were having dinner and I set an activity board with HC-06 on the table. I pulled out my phone, started a little app (created with MIT App Inventor 2), and made things happen. We giggled like kids. It's no big technological feat, but the ability to control our Propeller projects from a cell phone with a bit of code and an $8 module makes us very happy.
The HC-06 is cheap and easy to use (just look at the number of Arduino tutorials for it....), but it's finicky if you want to change the settings. You see, it doesn't use a line-ending character for commands, it uses a timeout period -- and that's pretty darned fast.
I want my BT modules to have unique names and pairing codes, so I wrote the attached configuration program. Honestly, it's overkill, but with a point. I've recently created a parsing engine (subject of my April column) for a bunch of projects and I used this to make setup of the HC-06 easier. For example, instead of sending "AT+BAUD8" I can enter "BAUD 115200" -- and when I request a baud rate change in the module (which should be done after everything else is set), the serial link to the module is restarted with the new baud rate. This is useful if the module is set to something other than the default (9600). In my case, I'm using 115200. If I want to change something, I start the configuration tool and enter "AT" -- if I get "OK" back, I know I'm connected. If I don't, I use the BAUD setting until AT gives the correct response. It's easier to do than to explain.
I'm having fun with Bluetooth. A couple weeks ago Rick Galinson and I were having dinner and I set an activity board with HC-06 on the table. I pulled out my phone, started a little app (created with MIT App Inventor 2), and made things happen. We giggled like kids. It's no big technological feat, but the ability to control our Propeller projects from a cell phone with a bit of code and an $8 module makes us very happy.

Comments
Now I just have to invent more time to implement those ideas. :-/
It could be updated to do that, yes, but the RN-42 is far more friendly to setup. I've attached my RN-42 terminal program which basically echoes what you type into PST, and takes from the RN-42 and sends it to PST. Easy-peasy.
The first BT module I had was the Parallax RN-42, then I got the XBee socket compatible unit from Sparkfun. BT is fun -- I just wish creating a cool little app for my Android was as easy as programming in Spin.
re:-- I just wish creating a cool little app for my Android was as easy as programming in Spin.
Have you tried Basic for Android? I know you like basic LOL
By purchasing the hosted Mac builder service you agree to our terms.
B4A Enterprise + B4i Enterprise
Requires a local Mac computer
$189 instead of $238 USD
With Hosted Mac Builder (1 year)
$199 instead of $266 USD
B4A (Android)
Standard
Includes two months of free upgrades.
$59 USD
Basic for Android:
http://www.b4x.com/store.html
http://www.basic4ppc.com/android/screenshots.html
I tried it once and it was easy and affordable. I had a trial version at the time.
Bluetooth (serial ports) was listed.
Thanks!! I'll try it next week.
It turns out that I had a really old version so I was able to get the upgrade at a good deal -- just the Android stuff.
I'm really busy with some big projects, so it may be a month or two before I really dig in. I have played a bit with MIT App Inventor, but don't enjoy the blocks programming interface.
Not much to look at, but it does work well.
https://play.google.com/store/apps/details?id=com.tecit.datareader.android.getblue.full&hl=en
http://www.picaxeforum.co.uk/showthread.php?27141-RoboRemoFree-App-with-the-HC-06
BTW, here is a helpful comparison of HC05/HC06 modules: http://mcuoneclipse.com/2013/06/19/using-the-hc-06-bluetooth-module/
-- http://forums.parallax.com/showthread.php/159920-Android-Control-of-Propeller-using-Joystick-BT-Commander-App-Spin-Code
An Arduino enthusiast has created a nice little robot control app for Android; I waded through his code and ported it to the Propeller. It would be a little work, but it could be used with the BS2 as well.
There's a bit of an error on that page: you can in fact put the HC-06 in master mode. The problem is that it wants to pair with the first BT module it finds -- this could make things tricky.
OK, Before I go any further I want to clarify this comment in your jm_rn-42_terminal.spin file:
Connect RN-42.RTS to RN-42.CTS
So just a jumper wire from RTS to CTS on the RN-42 module, correct? I know it may seem like a moot question but I do not want to burn up my RN-42 or my PPDB.
-- http://forums.parallax.com/showthread.php/159920-Android-Control-of-Propeller-using-Joystick-BT-Commander-App-Spin-Code
That ultimately gives -100 to +100. You can use this method to convert that range to servo values.
Why don't you post you code -- that would be easier than guessing.
'' ================================================================================================= '' '' File....... jm_joystick_bt_commander.spin '' Purpose.... Explorer program for Joystick BT Commander '' -- tested with Parallax RN-42 '' -- tested with $8 HC-06 from eBay '' Author..... Jon "JonnyMac" McPhalen '' Copyright (c) 2015 Jon McPhalen '' -- see below for terms of use '' E-mail..... [email]jon@jonmcphalen.com[/email] '' Started.... '' Updated.... 31 JAN 2015 '' '' ================================================================================================= con { timing } _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 ' use 5MHz crystal CLK_FREQ = _xinfreq * (_clkmode >> 6) ' system freq as a constant MS_001 = CLK_FREQ / 1_000 ' ticks in 1ms US_001 = CLK_FREQ / 1_000_000 ' ticks in 1us con { activity board io pins } RX1 = 31 ' programming / terminal TX1 = 30 SDA = 29 ' eeprom / i2c SCL = 28 AUD_RT = 27 ' audio (d/a) outputs AUD_LF = 26 LED_R = 27 ' leds (on audio outputs) LED_L = 26 SD_CS = 25 ' usd card SD_DI = 24 SD_CLK = 23 SD_DO = 22 ADC_CS = 21 ' adc input ADC_CLK = 20 ADC_DO = 19 { miso } ADC_DI = 18 { mosi } SVO_6 = 6 ' servo headers SVO_5 = 7 SVO_4 = 15 SVO_3 = 14 SVO_2 = 13 SVO_1 = 12 RX2 = 11 ' to rn-42 tx pin (do for xb module) TX2 = 10 ' to rn-42 rx pin (di for xb module) con TRM_BAUD = 115_200 BT_BAUD = 115_200 ' must match bt uart configuration #0, NUL, SOH, STX, ETX, EOT, ENQ ' packet framing characters #0, SC, MN, HR ' soft rtc registers obj term : "jm_fullduplexserial" ' * serial for terminal btio : "jm_fullduplexserial" ' * serial for rn-42 adc : "jm_adc124s021" ' for onboard adc io : "jm_io" ' basic io time : "jm_time" ' delays/timing ' * uses cog when loaded var long xpos ' signed x position value long ypos ' signed y position value byte buttons ' button bits byte lastbuttons ' for detecting chages byte data1[13] ' data fields in JBTC display byte data2[13] byte data3[13] byte buf[8] ' raw input buffer from JBTC byte buflen ' # bytes in input buffer byte cmd[8] ' good command from JBTC byte cmdlen ' length of command byte rtc[3] ' seconds, minuts, hours dat Header byte "Joystick BT Commander Demo", 13 byte "-- tested with V5.2", 13 byte 0 TimeStr byte "00:00:00", 0 pub main setup ' start objects time.start ' restart millis timer update_jbtc ' update buttons and data display repeat if (get_packet) ' request next packet bytemove(@cmd, @buf, 8+1) ' copy good packet if (cmdlen == 8) ' 8 bytes = joystick position get_joystick elseif (cmdlen == 3) ' 3 bytes = button update get_button process_button ' call handler for button that changed show_jbtc_input ' report jbtc value to terminal if (time.millis => 1000) ' new second? time.adjust(-1000) ' back-up 1s if (++rtc[SC] == 60) ' update seconds rtc[SC] := 0 if (++rtc[MN] == 60) ' update minutes rtc[MN] := 0 if (++rtc[HR] == 24) ' update hours rtc[HR] := 0 dec2(@TimeStr[0], rtc[HR]) ' convert rtc bytes to string dec2(@TimeStr[3], rtc[MN]) dec2(@TimeStr[6], rtc[SC]) bytemove(@data1, @TimeStr, 9) ' copy to data1 slot update_jbtc ' send to jbtc else term.tx(term#CLS) term.str(string("Bad packet or timeout")) pub get_packet | c, idx '' Waits for next packet from bluetooth device '' -- will timeout if no data for 1 second bytefill(@buf, 0, 8+1) ' clear buffer and length repeat c := btio.rxtime(1000) ' wait for 1st byte if (c < 0) ' timeout? quit elseif(c == STX) ' start of packet? buf[0] := c buflen := 1 quit if (buflen == 1) ' packet detected? repeat idx from 1 to 7 ' up to 7 more bytes c := btio.rxtime(2) ' wait (up to 2ms) for next byte if ((c => 0) and (c < $80)) ' if valid buf[idx] := c ' add to buffer ++buflen ' update length if (c == ETX) ' end marker return true ' good packet else return false ' timeout in middle of packet return false ' timeout or packet error pub get_joystick '' Process joystick command from JBTC '' -- JBTC sends joystick packet as <STX> <X100> <X10> <X1> <Y100> <Y10> <Y1> <ETX> '' * x and y digits are ascii chars xpos := get_dec3(@cmd[1]) ypos := get_dec3(@cmd[4]) pub get_dec3(p_buf) | value '' Converts three ASCII chars to decimal value '' -- JBTC sends values (as strings) from "100" to "300" to represent -100 to +100 value := (byte[p_buf++] - "0") * 100 ' ascii to decimal converstion value += (byte[p_buf++] - "0") * 10 value += (byte[p_buf] - "0") value -= 200 ' remove offset from value return value pub get_button | b, mask '' Process button command from JBTC '' -- JBTC sends values from "A" to "L" '' * "A" = B1 on, "B" = B1 off, "C" = B2 on, etc. b := cmd[1] if ((b < "A") or (b > "L")) ' validate button event code return b -= "A" ' convert command char to decimal (0..11) mask := 1 << (b >> 1) ' create mask for button if (b & 1) ' if bit0 set ("B", "D", "F", etc.) buttons &= !mask ' clear button bit else buttons |= mask ' else set button bit pub process_button | delta '' Isolates button that changed to call handler '' -- will pass 0 (off) or button mask (on) to hanler delta := (buttons ^ lastbuttons) & %111111 ' find change lastbuttons := buttons ' save for next change case delta ' process changed input %000001 : b1_change(buttons & delta) ' pass new state as mask %000010 : b2_change(buttons & delta) %000100 : b3_change(buttons & delta) %001000 : b4_change(buttons & delta) %010000 : b5_change(buttons & delta) %100000 : b6_change(buttons & delta) pub b1_change(state) if (state) io.high(26) else io.low(26) pub b2_change(state) if (state) io.high(27) else io.low(27) pub b3_change(state) pub b4_change(state) pub b5_change(state) pub b6_change(state) ' clear other buttons when B6 pressed if (state) buttons := %000000 lastbuttons := %000000 ' call events that could be effected by clearing buttons b1_change(0) b2_change(0) update_jbtc pub update_jbtc '' Sends button status and data fields (ascii) to jbtc btio.tx(STX) btio.bin(buttons, 6) ' update buttons btio.tx($01) btio.str(@data1) btio.tx($04) btio.str(@data2) btio.tx($05) btio.str(@data3) btio.tx(ETX) pub show_jbtc_input | p_buf '' Show data from JBTC '' -- also displays local rtc that is sent back to JBTC term.tx(term#HOME) ' refresh report header term.str(@Header) move_crsr(0, 3) ' show packet size term.hex(cmdlen, 1) term.tx(":") term.tx(" ") p_buf := @cmd ' show packet bytes repeat cmdlen term.hex(byte[p_buf++], 2) term.tx(" ") term.tx(term#CLREOL) move_crsr(0, 5) ' show x position/speed term.str(string("X...... ")) term.rjdec(xpos, 6, " ") move_crsr(0, 6) ' show x position/speed term.str(string("Y...... ")) term.rjdec(ypos, 6, " ") move_crsr(0, 7) ' show x position/speed term.str(string("Btns... ")) term.bin(buttons, 6) move_crsr(0, 9) term.str(string("RTC.... ")) term.str(@TimeStr) pub dec2(p_str, val) '' Convert val to 2-digit ascii string at p_str byte[p_str][0] := val / 10 + "0" byte[p_str][1] := val // 10 + "0" return p_str ' for inline printing of str pub move_crsr(x, y) term.tx(term#GOTOXY) term.tx(x) term.tx(y) pub setup '' Setup objects for project term.start(RX1, TX1, %0000, TRM_BAUD) ' start serial for terminal btio.start(RX2, TX2, %0000, BT_BAUD) ' start serial for bluetooth adc.start(ADC_CS, ADC_CLK, ADC_DI, ADC_DO) ' connect to adc time.start ' for pause and timing time.pause(2000) ' let bt module start term.tx(term#CLS) dat { license } {{ Terms of Use: MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. }}Some days I just want to give up....