The Netduino forums have been replaced by new forums at community.wildernesslabs.co.
This site has been preserved for archival purposes only
and the ability to make new accounts or posts has been turned off.
For anyone else interested in the Seeedstudio Bluetooth Shield:
You need to configure the shield first to make it discoverable to other Bluetooth devices. This shield is also very chatty, it confirms every configuration and let's you know when a connection is made, lost, etc. Sounds good in theory but it means that you need to parse received data to strip out the chatter from the shield.
Here's the relevant bit of the configuration code:
// initialize the serial port for COM2 (using D2 & D3)_serial = new SerialPort(SerialPorts.COM2, 38400, Parity.None, 8, StopBits.One);// open the serial-port, so we can send & receive data_serial.Open();// add an event-handler for handling incoming data_serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived);// configure seeedstudio:write("rn+STWMOD=0rn", _serial); //set the bluetooth work in slave modewrite("rn+STNA=SeeedBTSlavern", _serial); //set the bluetooth name as "SeeedBTSlave"write("rn+STOAUT=1rn", _serial); // Permit Paired device to connect mewrite("rn+STAUTO=0rn", _serial); // Auto-connection should be forbidden hereThread.Sleep(2000); // This delay is required.write("rn+INQ=1rn", _serial); //make the slave bluetooth inquirable
To strip out the data send by the shield (like "+BTSTATE:4", "CONNECT:OK", etc) I first try to load the data completely - I am not sure, if this works in all circumstances, though. I just read the data until nothing more is available. Then I'm discarding all lines but the last one (this assumes that no line breaks are send) and do a sanity check on that line. You might want to add some magic value or so in the data send to the shield to make this one easier.
static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e){ byte[] bytes = null; int destinationIndex = 0; int read = 0; while (_serial.BytesToRead > 0) { int expected = _serial.BytesToRead; byte[] data = new byte[expected]; int currentRead = _serial.Read(data, 0, expected); read += currentRead; if (bytes == null) { bytes = data; destinationIndex = read; } else { byte[] intermediate = new byte[read]; System.Array.Copy(bytes, intermediate, read - currentRead); System.Array.Copy(data, 0, intermediate, destinationIndex, currentRead); bytes = intermediate; destinationIndex += currentRead; } } if (!_isInitialized) { // just chatter from the shield return; } char[] chars = new char[read]; for (int i = 0; i < read; i++) { char c = (char)bytes[i]; chars[i] = c; } string result = new string(chars); string[] lines = result.Split('r', 'n'); string receivedData = lines[lines.Length - 1]; if (receivedData.Length > 1) { if ((receivedData[0] == '+') || "CONNECT:OK".Equals(receivedData)) { // that's just chatter from the shield like +BTSTATE:4 return; } processReceivedData(receivedData); }}
The shield is documented quite poorly in my opinion, I haven't found a list of configuration options, for example.
Here's the complete Program.cs - have fun hacking!
Robert
using System;using System.Net;using System.Net.Sockets;using System.Threading;using Microsoft.SPOT;using Microsoft.SPOT.Hardware;using SecretLabs.NETMF.Hardware;using SecretLabs.NETMF.Hardware.Netduino;using System.IO.Ports;using System.Text;namespace robert_netduino_seeedstudio_bluetooth{ public class Program { private static SerialPort _serial; private static bool _isInitialized; public static void Main() { Thread.Sleep(2000); // not sure if this delay is required. // initialize the serial port for COM2 (using D2 & D3) _serial = new SerialPort(SerialPorts.COM2, 38400, Parity.None, 8, StopBits.One); // open the serial-port, so we can send & receive data _serial.Open(); // add an event-handler for handling incoming data _serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived); // configure seeedstudio: write("rn+STWMOD=0rn", _serial); //set the bluetooth work in slave mode write("rn+STNA=SeeedBTSlavern", _serial); //set the bluetooth name as "SeeedBTSlave" write("rn+STOAUT=1rn", _serial); // Permit Paired device to connect me write("rn+STAUTO=0rn", _serial); // Auto-connection should be forbidden here Thread.Sleep(2000); // This delay is required. write("rn+INQ=1rn", _serial); //make the slave bluetooth inquirable Thread.Sleep(2000); // not sure if this delay is required. _isInitialized = true; // wait forever... Thread.Sleep(Timeout.Infinite); } private static void write(string command, SerialPort serial, bool addLength = false) { byte[] buffer = System.Text.Encoding.UTF8.GetBytes(command); if (addLength) { int length = buffer.Length; serial.WriteByte((byte)(length >> 24)); serial.WriteByte((byte)((length >> 16) & 0x00ff)); serial.WriteByte((byte)((length >> 8) & 0x0000ff)); serial.WriteByte((byte)((length & 0x000000ff))); } serial.Write(buffer, 0, buffer.Length); } static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e) { byte[] bytes = null; int destinationIndex = 0; int read = 0; while (_serial.BytesToRead > 0) { int expected = _serial.BytesToRead; byte[] data = new byte[expected]; int currentRead = _serial.Read(data, 0, expected); read += currentRead; if (bytes == null) { bytes = data; destinationIndex = read; } else { byte[] intermediate = new byte[read]; System.Array.Copy(bytes, intermediate, read - currentRead); System.Array.Copy(data, 0, intermediate, destinationIndex, currentRead); bytes = intermediate; destinationIndex += currentRead; } } if (!_isInitialized) { // just chatter from the shield return; } char[] chars = new char[read]; for (int i = 0; i < read; i++) { char c = (char)bytes[i]; chars[i] = c; } string result = new string(chars); string[] lines = result.Split('r', 'n'); string receivedData = lines[lines.Length - 1]; if (receivedData.Length > 1) { if ((receivedData[0] == '+') || "CONNECT:OK".Equals(receivedData)) { // that's just chatter from the shield like +BTSTATE:4 return; } processReceivedData(receivedData); } } private static void processReceivedData(string receivedData) { // okay, we have real data. Just send a confirmation back: // an int32 that describes the length of our feedback and then the received data plus something string responseStr = receivedData + " from netduino"; write(responseStr, _serial, addLength: true); } }}
Has anyone been able to connect and use this seed bluetooth shield with a netduino? I'm not completely convinced I have a working module. I've tried it with multiple pin configurations at this point, and I can't get it to be visible to any other bluetooth device, let alone paired or talking.
On the Wiki for the shield, it says that it cannot connect to a computer. Maybe you are having a slave/master problem. I would also hook up a USB to serial adapter to the shield TX/RX and try to talk to it via the AT command set with a PC terminal.
I use a HC-06 Bluetooth Transceiver module (slave) connected with a USB serial adapter to a terminal program on the PC and it pairs/connects just fine to an Android Bluetooth terminal App that was written in Basic4Android. It also works by connecting the module TX/RX to RX/TX on a Netduno. Search for HC-06 Bluetooth Transceiver and HC-05. The HC-05 can be configured as either slave or host.
Thanks for the reply, I eventually gave up on the seed module and bought one of these off amazon. Seems to work like a champ so far and I've been able to connect using a bluetooth dongle from plugable for my pc and raspberry. Only thing slowing me down at this point is the ongoing battle to make linux do anything for me on the raspberry, but that's a whole different problem.
For anyone else interested in the Seeedstudio Bluetooth Shield:
You need to configure the shield first to make it discoverable to other Bluetooth devices. This shield is also very chatty, it confirms every configuration and let's you know when a connection is made, lost, etc. Sounds good in theory but it means that you need to parse received data to strip out the chatter from the shield.
Here's the relevant bit of the configuration code:
// initialize the serial port for COM2 (using D2 & D3)_serial = new SerialPort(SerialPorts.COM2, 38400, Parity.None, 8, StopBits.One);// open the serial-port, so we can send & receive data_serial.Open();// add an event-handler for handling incoming data_serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived);// configure seeedstudio:write("rn+STWMOD=0rn", _serial); //set the bluetooth work in slave modewrite("rn+STNA=SeeedBTSlavern", _serial); //set the bluetooth name as "SeeedBTSlave"write("rn+STOAUT=1rn", _serial); // Permit Paired device to connect mewrite("rn+STAUTO=0rn", _serial); // Auto-connection should be forbidden hereThread.Sleep(2000); // This delay is required.write("rn+INQ=1rn", _serial); //make the slave bluetooth inquirable
To strip out the data send by the shield (like "+BTSTATE:4", "CONNECT:OK", etc) I first try to load the data completely - I am not sure, if this works in all circumstances, though. I just read the data until nothing more is available. Then I'm discarding all lines but the last one (this assumes that no line breaks are send) and do a sanity check on that line. You might want to add some magic value or so in the data send to the shield to make this one easier.
static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e){ byte[] bytes = null; int destinationIndex = 0; int read = 0; while (_serial.BytesToRead > 0) { int expected = _serial.BytesToRead; byte[] data = new byte[expected]; int currentRead = _serial.Read(data, 0, expected); read += currentRead; if (bytes == null) { bytes = data; destinationIndex = read; } else { byte[] intermediate = new byte[read]; System.Array.Copy(bytes, intermediate, read - currentRead); System.Array.Copy(data, 0, intermediate, destinationIndex, currentRead); bytes = intermediate; destinationIndex += currentRead; } } if (!_isInitialized) { // just chatter from the shield return; } char[] chars = new char[read]; for (int i = 0; i < read; i++) { char c = (char)bytes[i]; chars[i] = c; } string result = new string(chars); string[] lines = result.Split('r', 'n'); string receivedData = lines[lines.Length - 1]; if (receivedData.Length > 1) { if ((receivedData[0] == '+') || "CONNECT:OK".Equals(receivedData)) { // that's just chatter from the shield like +BTSTATE:4 return; } processReceivedData(receivedData); }}
The shield is documented quite poorly in my opinion, I haven't found a list of configuration options, for example.
Here's the complete Program.cs - have fun hacking!
Robert
using System;using System.Net;using System.Net.Sockets;using System.Threading;using Microsoft.SPOT;using Microsoft.SPOT.Hardware;using SecretLabs.NETMF.Hardware;using SecretLabs.NETMF.Hardware.Netduino;using System.IO.Ports;using System.Text;namespace robert_netduino_seeedstudio_bluetooth{ public class Program { private static SerialPort _serial; private static bool _isInitialized; public static void Main() { Thread.Sleep(2000); // not sure if this delay is required. // initialize the serial port for COM2 (using D2 & D3) _serial = new SerialPort(SerialPorts.COM2, 38400, Parity.None, 8, StopBits.One); // open the serial-port, so we can send & receive data _serial.Open(); // add an event-handler for handling incoming data _serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived); // configure seeedstudio: write("rn+STWMOD=0rn", _serial); //set the bluetooth work in slave mode write("rn+STNA=SeeedBTSlavern", _serial); //set the bluetooth name as "SeeedBTSlave" write("rn+STOAUT=1rn", _serial); // Permit Paired device to connect me write("rn+STAUTO=0rn", _serial); // Auto-connection should be forbidden here Thread.Sleep(2000); // This delay is required. write("rn+INQ=1rn", _serial); //make the slave bluetooth inquirable Thread.Sleep(2000); // not sure if this delay is required. _isInitialized = true; // wait forever... Thread.Sleep(Timeout.Infinite); } private static void write(string command, SerialPort serial, bool addLength = false) { byte[] buffer = System.Text.Encoding.UTF8.GetBytes(command); if (addLength) { int length = buffer.Length; serial.WriteByte((byte)(length >> 24)); serial.WriteByte((byte)((length >> 16) & 0x00ff)); serial.WriteByte((byte)((length >> 8) & 0x0000ff)); serial.WriteByte((byte)((length & 0x000000ff))); } serial.Write(buffer, 0, buffer.Length); } static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e) { byte[] bytes = null; int destinationIndex = 0; int read = 0; while (_serial.BytesToRead > 0) { int expected = _serial.BytesToRead; byte[] data = new byte[expected]; int currentRead = _serial.Read(data, 0, expected); read += currentRead; if (bytes == null) { bytes = data; destinationIndex = read; } else { byte[] intermediate = new byte[read]; System.Array.Copy(bytes, intermediate, read - currentRead); System.Array.Copy(data, 0, intermediate, destinationIndex, currentRead); bytes = intermediate; destinationIndex += currentRead; } } if (!_isInitialized) { // just chatter from the shield return; } char[] chars = new char[read]; for (int i = 0; i < read; i++) { char c = (char)bytes[i]; chars[i] = c; } string result = new string(chars); string[] lines = result.Split('r', 'n'); string receivedData = lines[lines.Length - 1]; if (receivedData.Length > 1) { if ((receivedData[0] == '+') || "CONNECT:OK".Equals(receivedData)) { // that's just chatter from the shield like +BTSTATE:4 return; } processReceivedData(receivedData); } } private static void processReceivedData(string receivedData) { // okay, we have real data. Just send a confirmation back: // an int32 that describes the length of our feedback and then the received data plus something string responseStr = receivedData + " from netduino"; write(responseStr, _serial, addLength: true); } }}
Please also note that I adapted the serial_DataReceived method a bit - I had to sleep for a short while so that the serial interface was able to pump out more data. This is done in the while(_serial.BytesToRead>0) loop, this loop is now:
byte[] bytes = null; int destinationIndex = 0; int read = 0; while (_serial.BytesToRead > 0) { int expected = _serial.BytesToRead; byte[] data = new byte[expected]; int currentRead = _serial.Read(data, 0, expected); read += currentRead; if (bytes == null) { bytes = data; destinationIndex = read; } else { byte[] intermediate = new byte[read]; System.Array.Copy(bytes, intermediate, read - currentRead); System.Array.Copy(data, 0, intermediate, destinationIndex, currentRead); bytes = intermediate; destinationIndex += currentRead; } if (_isInitialized) { // give serial a chance to add more data Thread.Sleep(5); } }