Bluetooth connectivity problems NXT to Mac OS X

Discussion specific to the intelligent brick, sensors, motors, and more.
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: Bluetooth connectivity problems NXT to Mac OS X

Post by afanofosc »

I think that the difference may be with using the NXT iterator, i.e., createNXTIterator and iNXTIterator_getNXT, vs using createNXT. With Bluetooth connections I generally tell people to use an alias for a full Bluetooth brick resource string in their nxt.dat file. If you do this then my Pascal code in FantomSpirit.pas in TFantomSpirit.Open will call createNXT with the full string name rather than creating an iterator. It has been a long while since I wrote this code but I vaguely recall that using the iterator caused that dialog to be shown. My recollection could be wrong. I would try using the createNXT option if you are currently using the iterator option and see if that changes things for you. After I call createNXT, if it happens to fail, then I call pairBluetooth and then I try calling createNXT again.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
tcwan
Posts: 186
Joined: 30 Sep 2010, 07:39

Re: Bluetooth connectivity problems NXT to Mac OS X

Post by tcwan »

afanofosc wrote:I think that the difference may be with using the NXT iterator, i.e., createNXTIterator and iNXTIterator_getNXT, vs using createNXT. With Bluetooth connections I generally tell people to use an alias for a full Bluetooth brick resource string in their nxt.dat file. If you do this then my Pascal code in FantomSpirit.pas in TFantomSpirit.Open will call createNXT with the full string name rather than creating an iterator. It has been a long while since I wrote this code but I vaguely recall that using the iterator caused that dialog to be shown. My recollection could be wrong. I would try using the createNXT option if you are currently using the iterator option and see if that changes things for you. After I call createNXT, if it happens to fail, then I call pairBluetooth and then I try calling createNXT again.

John Hansen
Hi John,

I think your description is correct. You'd first try to open the NXT() assuming that the connection succeeded, then if not, the sequence of events you described follows.

I tried using createNXT() after checking that isPaired() is true, but it fails to create the NXT object. I passed it the fully qualified BT resource string, i.e., BTH:NXT:xx:xx:xx:xx:xx:xx::1, as well as the truncated version (without ::1), but both failed.

In addition, how can I check the BT PIN stored in the NXT? I remember setting it previously (probably left as default) but I'm not sure how to find out what the value is, either on the Mac or on the NXT.
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: Bluetooth connectivity problems NXT to Mac OS X

Post by afanofosc »

You can ask the NXT what the pin code is for connections 0 through 3. The NXC API function that does this is BTConnectionPinCode but you can read this from the NXT if you are already connected using IOMapRead from Comm.mod at offset ((p)*47)+958 where p is the connection number. 16 bytes for this field.

If you are already paired then you don't need to know the pin. If you are not already paired then you can use whatever pin you want so long as you enter the right value on the NXT when it prompts you to enter a pin. Personally, I would recommend always using 1234. I hard-code this pin value in my FantomSpirit code. I do not use isPaired as I never had any success with that function, though it has been years since I last experimented with it.

I know for certain that calling createNXT works on a Mac with a proper bluetooth brick resource string. Here's one for one of my NXTs:

BTH::JCH2::00:16:53:FF:01:56::5

The NXT name portion has to exactly match your NXT's name, which is NXT by default but is easily changed. The virtual serial port number (5) at the end does not seem to be critical to successfully creating the NXT or not. I would recommend always connecting using a full brick resource name which you either lookup for your users or you have them create manually.

Here's the code I use which works if the NXT is already paired:

Code: Select all

      fNXTHandle := createNXT(PChar(pName), status, 0);
If it is not already paired then calling pairBluetooth followed by another call to createNXT also works.

Code: Select all

          status := kStatusNoError;
          pairBluetooth(PChar(pName), '1234', pairedResNamePC, status);
          pName := pairedResNamePC;
          if status >= kStatusNoError then
          begin
            status := kStatusNoError;
            fNXTHandle := createNXT(PChar(pName), status, 0);
            if status >= kStatusNoError then
            begin
              fActive := True;
              Result := True;
            end;
          end;
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
tcwan
Posts: 186
Joined: 30 Sep 2010, 07:39

Re: Bluetooth connectivity problems NXT to Mac OS X

Post by tcwan »

tcwan wrote:
lizard381 wrote: The problem is I'm not able to select NXT, it just stays there with the Select button grayed out. Has anyone had a similar experience? I called Lego tech support and they said it was because it's one of the new Macbooks with an incompatible bluetooth chipset, but after hanging up I realised that this doesn't make sense since NeXT Tools can connect...

Kami
I see the dialog box as well, but I can select the NXT on my Mac.
Interestingly NeXT Tool does not bring up the dialog. I'm trying to understand why there is a difference.
Ok. I've finally managed to recreate the main.cpp example in XCode 3.2.6, Mac OSX 10.6.7. In the Edit Project Settings Dialog, I *MUST* configure the SDK for Architecture "32-bit Intel", Base SDK "Mac OSX 10.5". Selecting 32/64 or 10.6 will cause the linker to fail to link the VISA framework.

The project can be created as an empty C++ project in XCode, and then populated with the following:
  • 1. All Fantom *.h include files
    2. The visatype.h include file
    3. The Fantom and VISA frameworks (Add Framework, choose Other... and navigate to the correct path /Library/Frameworks/...)
    4. The main.cpp example file from the Fantom SDK documentation
There are some missing pieces to the main.cpp example for execution on the Mac. If you compile it as a straight C++ program, you'll see the NSAutoreleasePool leaks as Kami (lizard381) mentioned, and the BT dialog box does not allow selection. To solve this, the XCode project must be contain an Objective-C++ main.mm instead. Everything else is pretty much identical to the C++ only project, except that main.cpp is now main.mm, and the code is modified as follows:
  • 1. The C++ main() is renamed (I used maincpp())
    2. Add FoundationKit and AppKit Frameworks (these are default frameworks)
    3. There must be an Objective-C++ main() which does the following:
    (a) Initialize NSApplication
    (b) Create the NSAutoreleasePool and manage its disposal after the maincpp() exits.
For more information, look for the NSApplication Class Reference in the XCode Documentation, and also create an empty Cocoa project and an empty iOS project to inspect the main.m contents.

Code: Select all

//
//  main.mm
//  FantomTest2
//
//  Created by tcmac on 18/05/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <Cocoa/Cocoa.h>

#include "fantom/iNXT.h"
#include "fantom/iNXTIterator.h"
#include "fantom/tStatus.h"

#include <string.h>
#include <iostream>

int maincpp(int argc, char *argv[]);

int main(int argc, char *argv[]) {
    [NSApplication sharedApplication];
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = maincpp(argc, argv);
    [pool release];
    return retVal;
	
}


/*
 © Copyright 2006,
 National Instruments Corporation.
 All rights reserved.
 
 Originated:  10 March 2006
 */

// includes...


// globally-scoped globals...

// private globals...

// methods...


int _VI_FUNCC maincpp( int argc, char** argv )
{
	nFANTOM100::tStatus status;
	nFANTOM100::iNXTIterator* nxtIteratorPtr = NULL;
	nFANTOM100::iNXT* nxtPtr = NULL;
	nFANTOM100::iFile* filePtr = NULL;
	nFANTOM100::iFileIterator* fileIteratorPtr = NULL;
	
	// Create an NXT iterator object which is used to find all accessible NXT devices.
	nxtIteratorPtr = nFANTOM100::iNXT::createNXTIterator(
														 true /* don't search for NXTs over Bluetooth (only search USB) */,
														 0 /* timeout for Bluetooth discovery ignored */, status );
	
	// Creating the NXT iterator object could fail, better check status before dereferencing a
	//    potentially NULL pointer.
	if( status.isNotFatal())
	{
		// Create an NXT object for the first NXT that was found.  Note that if a NXT is found
		//    over BT, the computer and the NXT must be paired before an NXT object can be
		//    created.  This can be done programatically using the iNXT::pairBluetooth method.
		nxtPtr = nxtIteratorPtr->getNXT( status );
		
		// Destroy the NXT iterator object which we no longer need
		nFANTOM100::iNXT::destroyNXTIterator( nxtIteratorPtr );
	}
	
	// Creating the NXT object could fail, better check status before dereferencing a potentially
	//    NULL pointer.
	if( status.isNotFatal())
	{
		ViUInt8 protocolVersionMajor = 0;
		ViUInt8 protocolVersionMinor = 0;
		ViUInt8 firmwareVersionMajor = 0;
		ViUInt8 firmwareVersionMinor = 0;
		
		// Query the version numbers for the protocol and firmware installed on the NXT.
		nxtPtr->getFirmwareVersion( protocolVersionMajor, protocolVersionMinor,
								   firmwareVersionMajor, firmwareVersionMinor, status );
		
		// This is a direct command to play a tone.
		ViUInt8 directCommandBuffer[] = { 0x03, 0x00, 0x18, 0x10, 0x00 };
		
		// Send the direct command to the NXT.
		nxtPtr->sendDirectCommand( false /* a response is not required for this direct command */,
								  reinterpret_cast< ViByte* >( directCommandBuffer ), sizeof( directCommandBuffer ),
								  NULL /* no response buffer */, 0 /* no response buffer, specify 0 for size */, status );
		
		// Create a file object
		filePtr = nxtPtr->createFile( "example.log", status );
	}
	
	// Creating the file object could fail, better check status before dereferencing a
	//    potentially NULL pointer.
	if( status.isNotFatal())
	{
		ViUInt8 fileBuffer[100] = {};
		ViUInt32 fileSizeInBytes = 100;
		for( ViUInt8 index = 0; index < fileSizeInBytes; ++index )
		{
			fileBuffer[index] = index;
		}
		
		// Open the file for writing, this will also create this file on the NXT.
		filePtr->openForWrite( fileSizeInBytes, status );
		
		// Write the file contents.
		filePtr->write( fileBuffer, fileSizeInBytes, status );
		
		// Close the file.
		filePtr->close( status );
		
		// Destroy the file object.  Note that this does not affect the file on the NXT.
		nxtPtr->destroyFile( filePtr );
		
		// Create a file iterator object which is used to find files on the NXT.
		fileIteratorPtr = nxtPtr->createFileIterator( "*.*" /* find all files on the NXT */,
													 status );
	}
	
	// Creating the file iterator object could fail, better check status before dereferencing a
	//    potentially NULL pointer.
	if( status.isNotFatal())
	{
		ViChar fileName[20];
		
		// Iterate through all of the files on the NXT until we find our log file.  Obviously,
		//    this isn't necessary in this simple example but is for illustrative purposes.
		while( status.isNotFatal())
		{
			fileIteratorPtr->getName( fileName, status );
			if( 0 == ::strcmp( fileName, "example.log" ))
			{
				break;
			}
			
			fileIteratorPtr->advance( status );
		}
		
		// Now that we have found our log file, create a file object that corresponds to it.
		filePtr = fileIteratorPtr->getFile( status );
		
		// Destroy the file iterator.
		nxtPtr->destroyFileIterator( fileIteratorPtr );
	}
	
	// Creating the file object could fail, better check status before dereferencing a
	//    potentially NULL pointer.
	if( status.isNotFatal())
	{
		ViUInt8 fileBuffer[100] = {};
		ViUInt32 fileSizeInBytes = 100;
		
		// Open the file for reading.
		filePtr->openForRead( status );
		
		// Read the file contents.
		filePtr->read( fileBuffer, fileSizeInBytes, status );
		
		// Close the file.
		filePtr->close( status );
		
		// Remove the file.  This deletes the file from the NXT.
		filePtr->remove( status );
		
		// Destroy the file object.
		nxtPtr->destroyFile( filePtr );
	}
	
	// Destroy the NXT object.
	nFANTOM100::iNXT::destroyNXT( nxtPtr );
	
	return 0;
}
lizard381
Posts: 44
Joined: 16 Nov 2010, 19:57

Re: Bluetooth connectivity problems NXT to Mac OS X

Post by lizard381 »

afanofosc wrote:I think that the difference may be with using the NXT iterator, i.e., createNXTIterator and iNXTIterator_getNXT, vs using createNXT. With Bluetooth connections I generally tell people to use an alias for a full Bluetooth brick resource string in their nxt.dat file. If you do this then my Pascal code in FantomSpirit.pas in TFantomSpirit.Open will call createNXT with the full string name rather than creating an iterator. It has been a long while since I wrote this code but I vaguely recall that using the iterator caused that dialog to be shown. My recollection could be wrong. I would try using the createNXT option if you are currently using the iterator option and see if that changes things for you. After I call createNXT, if it happens to fail, then I call pairBluetooth and then I try calling createNXT again.
Thank you so much John!! I thought I'd tried bypassing the nxt iterator before but perhaps I did something else wrong. Anyway, this worked like a charm.
tcwan wrote:There are some missing pieces to the main.cpp example for execution on the Mac. If you compile it as a straight C++ program, you'll see the NSAutoreleasePool leaks as Kami (lizard381) mentioned, and the BT dialog box does not allow selection. To solve this, the XCode project must be contain an Objective-C++ main.mm instead. Everything else is pretty much identical to the C++ only project, except that main.cpp is now main.mm, and the code is modified as follows:

1. The C++ main() is renamed (I used maincpp())
2. Add FoundationKit and AppKit Frameworks (these are default frameworks)
3. There must be an Objective-C++ main() which does the following:
(a) Initialize NSApplication
(b) Create the NSAutoreleasePool and manage its disposal after the maincpp() exits.
Interesting, I have a similar solution, I didn't rename main.cpp to main.mm, instead I created a .mm file that has functions to create and drain the pools, then called those functions from main.cpp. I'll have to try adding the app kit framework and see if that fixes the iterator problem.
I haven't grown past my playing with Legos stage and I don't think I want to :)
Blog: http://nuhlikklebickle.blogspot.com
Kami
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest