I'm fiddling with my
remaining hardware drawer. It was about 2009-2010 when I bought an UART_SB 2.2 on SeeedStudio; don't know
why I got it. A little later I bought a solderable
Bluetooth Bee and practiced
2mm-pitched hand soldering with a 60 W soldering station!! Arrrgh.
Well, I now have this beast working either as a "USBserial to Bluetooth" adapter for the PC or "TTL serial to Bluetooth" adapter for the Arduino. I spent three entire evenings to figure out a working sequence, and finally was able to print on the LCD of the Arduino Mega a string sent via Bluetooth from Linux PC and getting an answer.
First, it requires a long initialization
(ouch!) up to fourteen seconds at boot time before it can accept a connection (while everything other completes in less than 60 milliseconds).
I think this is due to an old firmware release of the soldered
BluetoothBee unit. It does not answer "OK" to commands, but a rather clumsy "WORK:SLAVER". So I checked for a capitalized "K" instead of "OK" - it gets both "OK" and "ORK...".
So in my
.ino source I wrote a function
bluebee(char*) that:
- waits 120msec
- sends the command string with Serial3.print
- reads any incoming characters
- if a 'K' is received, then flush incoming characters in 30msec and return "OK"
- if the function is running for more than 3.3 seconds, then call for "FAIL".
And then initialized it on the
Arduino Mega using:
delay(1000); // at boot: wait 1sec before sending commands
bluebee("\r\n+STWMOD=0\r\n"); // 0: client (slave) mode
bluebee("\r\n+STNA=MyArdu\r\n"); // set bluetooth hostname
bluebee("\r\n+STAUTO=0\r\n"); // 0: disable "autoconnect last paired device"
bluebee("\r\n+STOAUT=1\r\n"); // 1: enable paired device to connect
bluebee("\r\n+STPIN=0000\r\n"); // set a pin to accept incoming connections
delay(2000); // required pause after setting up the pin
Serial3.print("\r\n+INQ=1\r\n"); // 1: enable inquiring
delay(2000); // required pause after sending the INQ=1
Yes, the
+INQ=1 command does not answer anything. Yes, those delays are quite tight, do not reduce them. Yes, I did not use the +STBD to setup baudrate because I was happy with the default 38400; you don't need ultra-turbo speeds to send a few characters at a time.
Connections: the TX3/RX3 of the ArduinoMega are connected to the RX/TX pins of the UARTSB (note the mini-dip-switches on "5V" and "Bluetooth"), while the +5V and GND are required on the USB plug side. I cut a miniUSB connector and soldered its red/black (+/-) cables to the 5V/GND pins of the Arduino Mega.
For debugging reasons, I added to the
.ino source a loop to print on the LCD of the ArduinoMega the incoming characters of the
Serial3 port.
Operation:
- apply power to turn on the ArduinoMega
- wait for its boot and bluetooth initialization
- on the Linux PC bluetooth section, select "Setup (pair) a new device"
- wait the name to appear in the device list (the above example uses "MyArdu")
- choose a pin number to pair it (the above example uses 0000)
Yes, the UARTSB+BluetoothBee do not have "memory": on my PC I have to delete the pairing ad redo it again every time the ArduinoMega is rebooted.
If I forget to delete/redo the pairing, the cat /dev/rfcomm0 shown below will silently terminate in about 3.7 seconds because a rebooted BluetoothBee does not "remember" having paired with my PC.
Then release (if already assigned) and create the radiofreq communications channel
/dev/rfcomm0 as a serial port (type 1). If you don't remember the fixed address of the BluetoothBee you can use the
hcitool scan --flush command to find out after the initialization is completed (in the example below it is
00:18:E4:E5:E6:E7).
hcitool scan --flush
sudo rfcomm release 0; sleep 1 ; sudo rfcomm bind 0 00:18:E4:E5:E6:E7 1
Now if I write something on
/dev/rfcomm0 I get a bizarre "Transport endpoint is not connected" error. This is due to the BluetoothBee requiring some time to get a connection up and running.
Note that if you did neither pairing nor rfcomm bind but the /dev/rfcomm0 is still there, you may even get a "no error" on a write... but it will not reach the Arduino.
So I open a terminal window and start
cat /dev/rfcomm0 and then in another terminal window I can write using
echo ' #OMG it works! ' >/dev/rfcomm0
Trick explained: the cat /dev/rfcomm0 opens the port and stays there waiting for a line of characters. After some time (some five seconds), the BluetoothBee is ready to accept characters.
Note that the Arduino
HardwareSerial library has a limited serial buffer - on the Mega it is only 64 characters. This means that if I try to write 70 characters at a time, the entire Bluetooth packet is received by the Bee, then sent to the
HardwareSerial library of the Arduino Mega which fills immediately the 64 bytes buffer, losing the extra six characters. The Arduino should continuously consume incoming characters
(while(Serial3.available()) { processthisbyte(Serial3.read()); ...) because the 64 bytes buffer will fill in some 16 milliseconds (at 38400 baud speed).
Note: Ubuntu 14.04 Bluetooth Settings has a bug in the "Bluetooth New Device Setup": it forgets the entered pin. So I need first to wait some 10 seconds that the BluetoothBee device appears in its list, then click on it, then click on Pin Options; then select "0000 [most headsets/GPS/etc]" and "Close" the dialog, then click again on the BluetoothBee device in the list, then select again "0000" (most of the times it was "Auto" again) and "Close", and then "Continue". It should
not require to enter a six-digit pin...!
Note: when actually "connected", the BluetoothBee name is listed in
bold characters in the
Settings / Bluetooth window of the Unity Control Center.
Note: one I got you may try to use
/dev/rfcomm1 if you think that
rfcomm0 is stuck
Yes, this old BluetoothBee has its drawbacks but it works:
- ArduinoMega has the UART_SB + BluetoothBee ready to accept a "secure" wireless serial channel ("secure" means that you use a non-trivial pin like 0000... but only setup it after you are sure that everything works with the default 0000), that I placed on the TX3/RX3 (because I don't want to fiddle with pins 0/1 TX/RX unless absolutely required); you may consider the SoftwareSerial if you don't have a Mega;
- once established a connection, ArduinoMega can regularly read incoming characters using Serial.available and Serial3.read and then answer with Serial.write functions
- on the PC side, it is required to pair again, then release/bind the port, and then open the connection and wait a little while before sending characters.
The above examples use
cat and
echo but once the serial wireless channel is established, I can work out multiple interrogations. I used a thread for a fake "open channel to read" (to emulate the
cat) that gets killed as soon as the main task is "go": here is the
rubytalkswitharduino.rb script:
#!/usr/bin/env ruby
fake = Thread.new do
fpfake = File.open '/dev/rfcomm0'
while true
fpfake.gets
end
end
ok = Thread.new do
sleep 5
fp = File.open '/dev/rfcomm0', 'w+'
Thread.kill fake
fp.puts " [Ruby: #{$$} OK] "
puts "PID #{$$} talked; response:"
puts fp.gets
fp.puts " <#OMG: #{Time.now}> "
while true
print fp.read(1)
end
end
ok.join
Note that the
gets requires a newline (then
Serial3.println on the Arduino side). Note also that the
gets in the fake thread does not have to get actual data (it just has to stay there waiting for the rfchannel to warm-up). My ArduinoMega just answered to "OK" and "OMG" commands sending
(Serial3.println) some text.
Below, the complete sequence script (note that the
"sleep 30" was to be sure that some time passed after last
"rfcomm release 0"):
sleep 30
sudo rfcomm bind 0 00:18:E4:E5:E6:E7 1
sleep 1
ruby ./rubytalkswitharduino.rb