[EDIT] Here is Kristian’s post with more detailed explanation of the example sketch.[/EDIT]
Kristian Lauszus from TKJ Electronics, a man behind PS3 and Xbox360 code in USB Host Shield 2.0 library did it again! I’m pleased to announce that the library now supports standard RFCOMM/SPP implementation, thanks to Kristian’s work.
RFCOMM is basic Bluetooth service and SPP is serial port emulator on top of this. The code allows interfacing standard USB Bluetooth dongles to Arduino boards using USB Host Shield v.2.0. Bluetooth dongles (the ones I’ve tested can be seen on a title picture ) are widely available, cost much less than specialized serial Bluetooth modules (I have a couple of powerful class 1 dongles bought on eBay for $1 shipped) and won’t occupy precious serial port on Arduino board. Even though most dongles are compatible with the code, there are also some that don’t work. The code has been tested for compatibility with all major OSes – Linux, MacOS and Windows 7, as well as Android devices. It will likely work with any RFCOMM client, however, more testing is necessary.
The example code is a simple SPP server. It needs to be started before attempting to connect to it from a PC/phone. Once started, the state of the server is printed on a terminal. After that, the device can be discovered/paired/connected to; it is then possible to send characters from one device to the other by means of a keyboard. In the coming days I will write a series of posts with details of connecting different Bluetooth devices to Arduino. In the mean time, enjoy the code! Please give it a try and let me know what you think.
Oleg.
Related posts:
- Mass Storage Support for USB Host Library 2.0 released!
- Bluetooth code for Arduino USB Host
- Sony PS3 Controller support added to USB Host library
- USB Host Shield library Version 2.0 released.
- Wireless Xbox360 controller support for USB Host 2.0 library
- Arduino 1.0-compatible USB Host Library released
- Google Open Accessory Interface for USB Host Shield Library 2.0 released
- Using USB Bluetooth dongle on Arduino to connect to Windows PC
- Using USB Bluetooth dongle on Arduino to connect to Android phone
- USGlobalsat ND-100S GPS receiver works with USB Host library


Oleg, Kristian, marvellous. This is exactly what I was waiting for.
I’m having some issues to get it to work over here, though. I understand you are still working on the PC matters, so I’ll focus on Android. I’m on Gingerbread with a Galaxy S, and when trying to communicate using Blueterm I’m getting:
Wait For Incoming Connection Request
Incoming Request
Remote Name: GalaxyS
Connected to Device: 00:07:AB:04:AC:50
Information request
Scan Disabled
L2CAP Connection Request – PSM: 00 01 SCID: 00 48 Identifier: 03
SDP Incoming Connection Request
SDP Configuration Request
SDP Successfully Configured
Disconnected SDP Channel
L2CAP Connection Request – PSM: 00 03 SCID: 00 49 Identifier: 06
RFCOMM Incoming Connection Request
RFCOMM Configuration Request
RFCOMM Successfully Configured
RFCOMM Channel: 0 Direction: 0 CommandResponse: 1 ChannelType: 2F PF_BIT: 10
Received SABM Command – RFCOMM Data: 3 73 1 D7
RFCOMM Channel: 0 Direction: 0 CommandResponse: 1 ChannelType: EF PF_BIT: 0
Received UIH Parameter Negotiation Command – RFCOMM Data: 1 EF 15 81 11 2 E0 0 0 40 0 0 0 AA
Received Key Request
Bluetooth pin is set too: 1234
RFCOMM Channel: 1 Direction: 0 CommandResponse: 1 ChannelType: 2F PF_BIT: 10
Received SABM Command – RFCOMM Data: B 73 1 92
RFCOMM Channel: 0 Direction: 0 CommandResponse: 1 ChannelType: EF PF_BIT: 0
Send UIH Modem Status Response – RFCOMM Data: 1 EF 9 E1 5 B 8D AA
Send UIH Modem Status Command – RFCOMM Data: 1 EF 9 E3 5 B 8D AA
RFCOMM Channel: 0 Direction: 0 CommandResponse: 1 ChannelType: EF PF_BIT: 0
Send UIH Command with credit – RFCOMM Credit Data: 9 FF 1 FF 5C
RFCOMM Channel: 1 Direction: 0 CommandResponse: 1 ChannelType: EF PF_BIT: 10
Unsupported RFCOMM Data – ChannelType: EF Command: 03
RFCOMM Channel: 1 Direction: 0 CommandResponse: 1 ChannelType: EF PF_BIT: 0
Unsupported RFCOMM Data – ChannelType: EF Command: 67
RFCOMM Channel: 1 Direction: 0 CommandResponse: 1 ChannelType: EF PF_BIT: 0
Unsupported RFCOMM Data – ChannelType: EF Command: 68
This is after entering the PIN in Blueterm and then typing the three characters fgh.
So it seems that with my setup Android is not sending the UIH Remote Port Negotiation Command that you are expecting before completing the connection setup and starting the data exchange?
I’m eager to resolve this (or at least to help resolving it). Would you mind contacting me on oleg at s dot wangnick dot de so as not to spoil this blog?
Kind regards,
Sebastian
Try to move these two lines: https://github.com/felis/USB_Host_Shield_2.0/blob/master/RFCOMM.cpp#L852-853 after this line: https://github.com/felis/USB_Host_Shield_2.0/blob/master/RFCOMM.cpp#L846. That should solve your problem.
I will try to do the same thing with my setup tonight and then maybe push the changes to github.
The problem is that your device never sends the “UIH Command with credit”.
I actually don’t wait for the UIH Remote Port Negotiation Command as I also discovered that some devices does not send it. See this line for more information: https://github.com/felis/USB_Host_Shield_2.0/blob/master/RFCOMM.cpp#L902-909
Regards
Lauszus
hi ,i want to control my servo motor using bluetooth dongle. but im bery new to arduino code.
Hi Ron,
See the “Knob” example for the servo library: https://github.com/arduino/Arduino/blob/master/libraries/Servo/examples/Knob/Knob.ino (File>Examples>Servo>Knob) and then see the example included in the library: https://github.com/felis/USB_Host_Shield_2.0/blob/master/examples/RFCOMM/RFCOMM.ino
Regards
Lauszus
hi lauszus,
thank for ur help i already able to control my servo motor via using usb .now the problem im having is i required to use bluetooth.i already tested using ur rfcomm module and the bluetooth is working fine.but i need combine the code with ur rfcomm code but it can’t compile.can u help me please.
Please send me the compiler error, so I can have an idea of what might be wrong.
Regards
Lauszus
hi lauszus,
it can be compile alr but is not working. maybe i send u my code and hope u can give me a way to combine my code and ur code .
i really appreciate alot for ur help.
thanks.
char val[4];
int pin1 = 22;
int pin2 = 24;
int pin3 = 26;
int pin4 = 28;
int pin5 = 30;
int pin6 = 32;
int index = 0;
void setup()
{
pinMode(pin1, OUTPUT);
pinMode(pin2, OUTPUT);
pinMode(pin3, OUTPUT);
pinMode(pin4, OUTPUT);
pinMode(pin5, OUTPUT);
pinMode(pin6, OUTPUT);
Serial.begin(9600);
}
void loop()
{
if(Serial.available()){
if(index < 3){
val[index] = Serial.read();
Serial.print(val[index]);
index++;
}
val[index] = '';
Serial.println("");
if(index == 3){
if(strcmp("p11", val) == 0){
digitalWrite(pin1, HIGH);
}
else if(strcmp("p10", val) == 0){
digitalWrite(pin1, LOW);
}
else if(strcmp("p21", val) == 0){
digitalWrite(pin2, HIGH);
}
else if(strcmp("p20", val) == 0){
digitalWrite(pin2, LOW);
}
else if(strcmp("p31", val) == 0){
digitalWrite(pin3, HIGH);
}
else if(strcmp("p30", val) == 0){
digitalWrite(pin3, LOW);
}
else if(strcmp("p41", val) == 0){
digitalWrite(pin4, HIGH);
}
else if(strcmp("p40", val) == 0){
digitalWrite(pin4, LOW);
}
else if(strcmp("p51", val) == 0){
digitalWrite(pin5, HIGH);
}
else if(strcmp("p50", val) == 0){
digitalWrite(pin5, LOW);
}
else if(strcmp("p61", val) == 0){
digitalWrite(pin6, HIGH);
}
else if(strcmp("p60", val) == 0){
digitalWrite(pin6, LOW);
}
else if(strcmp("ar1", val) == 0){
digitalWrite(pin1, HIGH);
digitalWrite(pin2, HIGH);
digitalWrite(pin3, HIGH);
}
else if(strcmp("ar0", val) == 0){
digitalWrite(pin1, LOW);
digitalWrite(pin2, LOW);
digitalWrite(pin3, LOW);
}
else if(strcmp("ag1", val) == 0){
digitalWrite(pin4, HIGH);
digitalWrite(pin5, HIGH);
digitalWrite(pin6, HIGH);
}
else if(strcmp("ag0", val) == 0){
digitalWrite(pin4, LOW);
digitalWrite(pin5, LOW);
digitalWrite(pin6, LOW);
}
index = 0;
}
}
}
I have created this gist with the source code: https://gist.github.com/3383715 for you.
Enjoy
Hi,
The example code link isn’t correct. I need it.
Hi,
Great work! This would be the first thing that I would try after getting hands on the USB host shield.
One question though, is it possible that HID profile for BT dongles would be added in the future?
It’s already added to the library in form of the PS3BT library: https://github.com/felis/USB_Host_Shield_2.0/blob/master/PS3BT.cpp and the Wii library: https://github.com/felis/USB_Host_Shield_2.0/blob/master/Wii.cpp.
What specific would you need it for?
hi lauszus,
thanks alot alot for ue help.
i had try the code but it can’t detect the dongle with the code u do for me.but if i try using spp example code it can detect the dongle! may i know why does it happen?
thanks alot anyway.
What error are you getting?
I have added a extra debug message to the gist, so try the new version (https://gist.github.com/3383715) and tell me the error you are getting.
hi lauszus,
there is no error just that the debug msg show osc did not start.but when i just upload the bluetooth spp example it is able to load the bluetooth etc. is working .
my project is just to light up a led using an android phone using bluetooth that all is there any other solution?
thank lauszus for ur effort and help.
Are you using a Arduino Mega ADK? If so you have to uncomment the following line: https://github.com/felis/USB_Host_Shield_2.0/blob/master/avrpins.h#L25
The code works fine for me.
hi lauszus,
sorry to trouble you.im using a uno board with a usb host shield (sparkfun) .
Have you remembered to connect a wire between pin 7 and the reset pin. If it’s still not working try to connect a external power supply. You are not using any of the pins from 7-13 right?
Maybe the issue could be that you define pins above 13 as output ports! Try to change the pins to something like 2,3,4,5, and 6 and see if that works.
hi lauszus,
thank you for ur help. the code u send me i had try compile . however it is not working,i cannnot enable the bluetooth dongle. may i know where did i do wrong?
Please describe your problem in more detail. Try to connect a external power supply to your Arduino. The Sparkfun shield has a power issue when it’s running from USB, since it’s need more than 5V at the VIN for it’s onboard regulator.
Hi Lauszus,
I tried to interface a Mega ADK(reqd. changes made in avrpins.h) to a cheap bluetooth dongle and it seems to initialize it fine with this message in the terminal :
SPP Bluetooth Library Started
Bluetooth Dongle Initialized
HCI Reset complete
Local Bluetooth Address: 00:19:86:00:29:1A
The name is set to: Arduino
Wait For Incoming Connection Request
But, no devices can find it – tried it with a HTC Flyer p510e, Nokia 6300, Motorola RaZr v3m.
A point to note here is that whenever one of the devices finish their search (but fail to find it)the LED on the dongle blinks once.
Dongle details(not much):
HCI version : 3.12288
LMP version : 3.16907
chipset : BCM 2045
Other features of the USB Host library work.
Thanks for the help,
Kabir
Hmm, It’s properly your dongle.
Check out this page at the wiki for confirmed working dongles: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information#wiki-Hardware.
You could try to buy a few different dongles of ebay and then you should properly get some working ones.
Could please try to uncomment this line: https://github.com/felis/USB_Host_Shield_2.0/blob/master/BTD.cpp#L20 and send me the output, so I can see how many endpoints it got?
This is what I get with extra debugging enabled:
SPP Bluetooth Library Started
BTD Init
Addr: 01
Endpoint descriptor:
Length: 07
Type: 05
Address: 81
Attributes: 03
MaxPktSize: 0010
Poll Intrv: 01
Endpoint descriptor:
Length: 07
Type: 05
Address: 82
Attributes: 02
MaxPktSize: 0040
Poll Intrv: 01
Endpoint descriptor:
Length: 07
Type: 05
Address: 02
Attributes: 02
MaxPktSize: 0040
Poll Intrv: 01
Bluetooth Dongle Initialized
HCI Reset complete
Local Bluetooth Address: 00:19:86:00:29:1A
The name is set to: Arduino
Wait For Incoming Connection Request
It looks alright. The only solution I can give you is trying a different Bluetooth dongle.
Can the USB host library be used to make a Bluetooth dongle act as a Bluetooth HID device?
What do you mean. For instance to make the Arduino show up as a Bluetooth joystick? Then the answer is no. Right now it only supports the PS3, Wiimote, Nunchuck, Motion Plus via Bluetooth and also the SPP protocol.
Great and huge effort indeed.
I just get my new Arduino De, and I want to know the feasibility to use this code on it, making use of the two USB ports.
See the reply at my blog: http://blog.tkjelectronics.dk/2012/07/rfcommspp-library-for-arduino/#comment-177476
Wow – the shield and usb bluetooth sketch work great! I took a ps3 controller and a demo using a broken printer carriage controller to work and everyone enjoyed making it move it back and forth by remote control.
Hi! this is very informative. I have Arduino Mega2560 ADK. How can I use usb bluetooth and pendrive interface with it. Is this library can be used for the same? may you send me the example that is implemented on MEGA 2560 ADK.
Thaks.
Thanks, The solution is here!! I forget to comment the line. Now, may I know how can I communicate arduino (with bluetooth) with computer or mobile phone? Thanks for this library.
Hello! Would it be possible to make this SPP Class inherit from the Stream library? It would make sense, I think, and make the problem I’m working with currently much, much easier
See my reply at my blog: http://blog.tkjelectronics.dk/2012/07/rfcommspp-library-for-arduino/#comment-314173.
What problem are you facing?
I’ve implemented an XML-parser, which is currently able to take any stream, parse the received data and react accordingly. By using stream it is possible for me to code without considering wether the input is ethernet or serial or anything else. I’d like to be able to use the Bluetooth communication in the same way, so it can just check if it receives any XML-commands on any of the communication lines, and run the same code for all of it, regardless of source.
I’ve modified the library a bit, and it seems I’ve got it running with the Stream class implemented
I’m working on some of the kinks I’m currently experiencing, but that seems to be more related to the way that I handle the connection afterwards, than the connection itself.
Nice. Can I have a look at the code?
Btw are you danish as well?
I’m danish as well, yes
It’s pretty much just implementing the virtual functions from the Stream class (which included changing some of the functions from uint8 to int and returning -1 instead of 0 for empty):
class SPP : public BluetoothService, public Stream {
…
int available();
int read();
int peek();
void flush();
size_t write(uint8_t);
}
The “tricky” part was recognizing that the Stream class is implementing the Print class, which required the write method to be present. I implemented that as simply:
write(uint8_t c){
print(c);
}
I’ll see about uploading it at some point, when I’ve made sure that it’s not gonna fuck something up
Sorry if my language is a little bit off – It’s been a while since i dabbled with inheritance and polymorphism and all those object-oriented things
Okay super, but does it send the characters as one large string or send them individually?
It would seem that it sends them individually – Is this a problem? It could probably be implemented to start a timer when “the first” char is received and then wait a given time before sending, to allow for sending a larger string.
Yes it’s problem if you just keep sending data through the output endpoint. You will have to call Usb.Task() once and a while to read the input endpoint too. That’s why I implemented my own functions in the first place.
I have also thought about putting it all into a buffer and then when Usb.Task() is called it will both read the input endpoint and also send the buffer through the output endpoint.
I’m not completely sure I understand the problem or the solution. Is it correctly understood that the problem is, that if you keep spamming the output-endpoint with data, you will block the code and potentially never reach the Usb.Task() – Atleast not before a problem with buffersize or timing or something could arise.
I also have a small problem with some sort of internal buffer. When ever I try sending a longer command, the buffer caps out at 63 characters, and then either replaces or appends “PB” at the end of the buffer. When I run the Usb.Task() again, shortly after, the rest of the message is still received and appended to the buffer. I can recreate this bug running just the basics of the Bluetooth communication.
Yes exactly. What will happen is that the dongle will stop responding and you will just get this error message over and over again: https://github.com/felis/USB_Host_Shield_2.0/blob/master/BTD.cpp#L1029-L1039 and you will have to reset the dongle for it to work again.
I’ve done a little bit of digging regarding my problem with the buffer size of 63. It is actually the last 10 or so bytes that are a problem. I get the following byte sequence when I try to read a long message from the buffer:
0×7 0xXX 0×4 0×0 0×50 0×0 0×42 0×0 0×0 0×0 0×1
Where XX is a number increasing by 9(DEC) every time i disconnected and reconnect my bluetooth connection. The 0×50 and 0×42 are the P and B i was talking about. And as I said, this is what I get when I try to read a message from the buffer.
I’m thinking that some pointer somewhere is clashing with something, since theres a variable thats obviously changing whenever I reconnect. This is weird
Can you reproduce the problem? The code is here: http://pastebin.com/Re7aCdrP
I usually send 01234567890123456789012345678901234567890123456789012345678901234567890123456789 to test the communication.
Okay, I’m a little bit sorry that I’m using this as kinda my personal development log, but I think I’ve found the problem. Or if nothing else, a solution to the problem. I found that the LSB of the max-buffer size was set to 64, which kinda matches with the problem I had. I tried setting it larger, but that just gave me a larger error. Instead, i tried setting it smaller, to 53 to be exact, so that my actual, uncorrupted data could fit in. That worked. I can now receive and process data as i want it, without issue.
What i specifically changed was line 287 in SPP.cpp. I changed it to:
rfcommbuf[6] = 0×35; // Max Fram Size LSB – we will just set this to 64
So from 0×40 to 0×35. Now it works
Okay. I set it to 64, as we read 64 bytes from the input endpoint: https://github.com/felis/USB_Host_Shield_2.0/blob/master/BTD.cpp#L752.
But it makes sense setting it to 53, as the data is starting at the 11th byte: https://github.com/felis/USB_Host_Shield_2.0/blob/master/SPP.cpp#L255.
I think a better solution would be to change the line to:
rfcommbuf[6] = BULK_MAXPKTSIZE-11;
You can send a pull request if you like, so you will get some credit for fixing the bug
I just tested it and changing it to:
rfcommbuf[6] = BULK_MAXPKTSIZE-10;
solved the problem.
I guess the reason why you subtract 10, is because the length byte has to be included as well in the package. Actually anything larger than 10 works as well, but 10 is the smallest one where you wouldn’t get any errors.
I tried with 10 but was unable to properly parse my messages. Maybe I wasn’t handling the length byte? Changing it to eleven fixed it for me, so that’s what I submitted to Github.
How is it going with making the SPP Class inherit from the Stream library?
Hey there,
You mentioned some of the dongles are incompatible with the board. How do I find out if a particular dongle will work or not without plugging it into the shield.
It need to have an Interrupt In endpoint, a bulk in endpoint and a bulk out endpoint. There a plenty of software online that let you read the type of endpoint on any USB device. What OS are you using?
I used an lsusb -v on linux and it does appear to have an bulk endpoint (both in and out is supported) . SO you think it would work right? Beacuse the dongle is identical or atleast very similar to the one you have put in the picture which you have said doesnt work. The dongle is from EnterMultimedia(< a href="http://www.enter-multimedia.com/bluetooth.html" title="This one")
Then it most likely is supported, but I can’t say for sure.
Well , currently I am on windows 7 . Which software do you recommend for that?
Hi,
I am a beginner at developing with Arduino. Infact this is my first time. So please don’t mind if this is a noob question. I have an Arduino Mega ADK rev3 which has an inbuilt usb port with which I can connect my Android phone. This is means I do not need a USB Host Shield to do the same. However what I want to know is, can/should I still need to use the USB HOST Shield 2.0 library if I want to establish a communication between my board and my android device? I am a bit confused here. Could you please help me with this basic understanding?
Thanks
My mistake I asked an already answered query, I will try uncommenting the line in your code and work with my board. Thanks
Hi Lauszus,
This is what I want to achieve. I have a separate circuit where I blink an Led with a particular sequence. This sequence represents encoded data. I want to be able to sense this pattern with a photo detector and decode the data from the led blink, and then I want to send this decoded data via bluetooth to my android device. I am a newbie to programming on a board, however I have programmed on Android. Do you think it is possible to achieve what I want with an Arduino. I have ordered the board, but they have still not delivered it. So I am still in the learning phase of my project, contemplating the problems I might run into. Do you think it is a better idea to collate and decode the entire data on the board itself and send it to the android in one go is a better idea? or should I send the information on the fly from the sensor to the android device and decode it in my Android code..please help!
See the reply at my blog: http://blog.tkjelectronics.dk/2012/07/rfcommspp-library-for-arduino/#comment-341851