Nordic USB ANT Stick & Garmin HRM in VC++

Hi!

I’m new here, but I’ve a problem which was maybe discussed a couple of times, but still wasn’t answered properly. At least I wasn’t able to find a suitable solution in the topics I got from using the search engine. Therefore I’m really sorry if this is an unnessary post.

Here is the thing:

I’m new to the ANT protocol and I’m trying to establish a very simple ANT connection between the Nordic USB ANT Stick (http://www.sparkfun.com/commerce/produc … ts_id=8840) and the Garmin Hearth Rate Monitor in C++/MFC using Microsoft Visual Studio 2008. I found the ant_dll.cpp, ant_dll.h and the ant_dll.dll on the http://www.thisisant.com site and managed to include them successfully into my project, so that I can compile the code.

Unfortunately nothing exciting happens from there. The “ProcessProtocolEvent” and “ProcessChannelEvent” routines (see code below) are never executed, that means there is no messaging happening between the USB stick and the HRM. To be honest I’m not quite sure, if the stick is installed properly, because it doesn’t appear in the device manager as “USB ANT Stick” in the “USB controllers” section, but instead appearas as “Unknown device” without attached drivers. I contacted the support from thisisant.com, but I only got this answer: “The USB stick you are using is designed by Sparkfun, uses different hardware than the Dynastream USB sticks and interface boards, and thus, is not compatible with our drivers.”. So maybe that’s the problem, that the stick is not installed properly, because I don’t have the right drivers. On the sparkfun product site of the stick it says that you need the FTDI driver and everything should work. I have these drivers and they are working fine. After plugging in, the “USB Serial Port” and the “USB Serial Converter” were installed. I tried the “Example VB Program for Garmin HRMs”, but the only thing working is the “Open” button, which opens the channel and acknowledges that by displaying “open” I think. But when I press the big button, which says “Check Heart Rate”, I get a couple of error popup messages saying bad parameters. I know that this problem was discussed in another topic, but there was not real solution given, except that someone mentioned that he could solve it without telling exactly how.

Here is the important part of the code:

...
#include "antdefines.h"
#include "antmessage.h"
#include "global.h"
#include "types.h"
#include "ant_dll.h"

#define ANT_CHANNEL ((UCHAR) 7)  // My virtual COM port is 7

static UCHAR GARMIN_KEY[] = "...";

static UCHAR aucTxBuf[17];         ///< Buffer to hold messages that are sent to the ANT device
static UCHAR aucRxBuf[17];         ///< Buffer to hold channel specific RF messages and events received from the ANT device
static UCHAR aucResponseBuf[10];   ///< Buffer to hold the response to configuration commands

// CGarminHRMDlg message handlers

UCHAR ProcessChannelEvent(UCHAR ucChannel, UCHAR ucMessageCode)
{
	switch(ucMessageCode)
	{
		case EVENT_RX_ACKNOWLEDGED:
			break;
		case EVENT_RX_BROADCAST:    // A Broadcast message has been received sucessfully
			break;
		case EVENT_TX:
			break;
		case EVENT_TRANSFER_TX_COMPLETED:   // A Acknowledged packet was sucessfully sent
			break;
		case EVENT_RX_FAIL_GO_TO_SEARCH:    // If we ever go back to search we fail the test
			break;
		case EVENT_RX_SEARCH_TIMEOUT:       // If we timeout on the search we faile the test
			break;
		case EVENT_RX_FAIL:                 // We failed to receive a message at the designated message period
			break;
		case EVENT_TRANSFER_TX_FAILED:      // We failed to get a reply for the acknowledged packet we sent
			break;
		case EVENT_CHANNEL_CLOSED:
			break;
	}

	return 1;
}

UCHAR ProcessProtocolEvent(UCHAR ucChannel, UCHAR ucMessageCode)
{
	switch(ucMessageCode)
	{
		case MESG_CAPABILITIES_ID:
			
			break;
		case MESG_RESPONSE_EVENT_ID:
		{   
			switch (aucResponseBuf[1])
			{
				case MESG_ASSIGN_CHANNEL_ID:
					break;
				case MESG_UNASSIGN_CHANNEL_ID:
					break;
				case MESG_CHANNEL_ID_ID:
					break;
				case MESG_CHANNEL_MESG_PERIOD_ID:
					break;
				case MESG_CHANNEL_RADIO_FREQ_ID:
					break;
				case MESG_OPEN_CHANNEL_ID:
					break;
				case MESG_CLOSE_CHANNEL_ID:
					break;
				case MESG_CHANNEL_SEARCH_TIMEOUT_ID:
				default:
					break;
			}
			break;
		}    
	}

	return 1;
}

BOOL CGarminHRMDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	ANT_Load();
	ANT_ResetSystem();
	Sleep(20); 

	ANT_Init(ANT_CHANNEL, 4800);

	ANT_AssignResponseFunction( (RESPONSE_FUNC)ProcessProtocolEvent, aucResponseBuf );
	ANT_AssignChannelEventFunction( ANT_CHANNEL, (CHANNEL_EVENT_FUNC)ProcessChannelEvent, aucRxBuf );

        // Trying to get a message
	ANT_RequestMessage(ANT_CHANNEL, MESG_CHANNEL_ID_ID);

	return TRUE; 
}

void CGarminHRMDlg::OnBnClickedOpen()
{
	// Rx channel
	ANT_AssignChannel(ANT_CHANNEL, 0x00, 0);	
	Sleep(20);

	// Using the Garmin parameters
	ANT_SetChannelId(ANT_CHANNEL, 0, 0, 0);
	Sleep(20); 
	ANT_SetNetworkKey(ANT_CHANNEL, GARMIN_KEY);
	Sleep(20); 
	ANT_SetChannelSearchTimeout(ANT_CHANNEL, 255);
	Sleep(20); 
	ANT_SetChannelPeriod(ANT_CHANNEL, 0x1f86);
	Sleep(20); 
	ANT_SetChannelRFFreq(ANT_CHANNEL, 0x39);
	Sleep(20); 

	ANT_OpenChannel(ANT_CHANNEL);

	Sleep(1000);
    
        // Again trying to get a message
        ANT_RequestMessage(0,MESG_CAPABILITIES_ID);	
}

void CGarminHRMDlg::OnClose()
{
	ANT_CloseChannel(ANT_CHANNEL);
	ANT_Close();

	CDialog::OnClose();
}


void CGarminHRMDlg::OnCancel()
{
	ANT_CloseChannel(ANT_CHANNEL);
	ANT_Close();

	CDialog::OnCancel();
}

It is a simple dialog-based application using MFC and the ANT commands are linked dynamicly using “GetProcAddress”. I have an “Open” button which calls the “OnBnClickedOpen” routine which should establish a connection. I have looked at many examples and they basicly look the same. But please correct me if I did something wrong. I trying for two days now to get that thing working and I’m quite desperate now. Actually right now it would be enough for me already, if I just manage receiving messages in my “ProcessChannelEvent” routine, meaning just establishing a basic connection without data processing. :slight_smile:

As I said I’m quite helpless right now, because I don’t know if at least the stick it self is working, because none of the examples is working quite well. So please help me. :roll:

[Admin edit: ANT asked us to remove the Garmin key.]

Take a look here: http://developer.garmin.com/forum/viewtopic.php?t=410

There are a couple of versions for windows on there at least one of which should work.

Thanks a lot for your help. I’ve seen this site but it wasn’t quite helping because none of the applications was really useful. I also thought that the ANT driver is not configured to access ANT by using USB, in this case by using the FTDI chip commands. So I tried this on my own and I managed now to get a connection and even a feedback from the HRM. I didn’t use the ant.dll, but instead transmitted the ANT messages (like they are explained in the Message Protocol) with the FTDI commands. And it works! It’s actually like in the “Example ATMega168 Configuration” on the product site. It’s kind of a “roundabout way” and quite a lot of work to transmit every single specific byte for each ANT command with FT_Write(…) instead of just using ANT_AssignChannel(), for example. And receiving data is of course also more complicated, because of analyzing every received byte. But I don’t care because it works (for now). :smiley:

But thanks a lot for your help anyway.

You are mixing up the COM port number and the ANT channel.

This ANT_Init(ANT_CHANNEL, 4800) should be something like ANT_Init(ANT_PORT, 4800) where ANT_PORT is defined to your COM port. ANT_CHANNEL should be 0, 1, 2 or 3.

You also call ANT_RequestMessage(ANT_CHANNEL, MESG_CHANNEL_ID_ID) before an ANT channel is set up.

Orin.

Yes, I know. I already realized that mistake, but that didn’t solve the main problem. It seemed like nothing happens using the ANT_… commands. And I think that these commands are supposed to communicate with the ANT chip through a COM port. And the stick is using the FTDI chip to create a virtual COM port through USB. So the ANT_… commmand cannot work, because they cannot access the ANT chip through the FTDI chip. But this is only a theory, but it seems like that it’s becoming more and more true. Because I tried to send the ANT commands through FTDI chip using it’s own commands for data transfer, like I discribed it in my last post, and it suddenly worked. Maybe this should be working using the Virtual-COM-Port-Feature from the FTDI chip, which transmits the data from COM to USB and vice versa the moment they are arriving at the chip so that ANT commands can access their destination again, but that doesn’t seem to work. I have a virtual COM port installed (COM7) and 7 was the value I used in ANT_Init(ANT_PORT, 4800) for ANT_PORT. I also checked the settings (baud rate, …) of the COM7 in the device manager, but nothing worked. I think I’ll keep the complicated way through FTDI (for now), because it works. But thanks for your help anyway.

Izzo

I am also doing the same thing for a class project,I wrote a c# code to send the hex. values, but it just doesn’t seem to work.i am wondering whether it is necessary to have the spark fun USB ANT stick to get the communication working,right now i am using an rs232 shifter to interface with the nr424ap1 antena.

please help me out if anybody is able to get it working.

also i will update if i make some progress!!!

cheers

Actually I managed now to get the whole thing working. As I already said in my last post, you cannot use the ANT_… commands with the sparkfun USB stick, because it uses the FTDI chip for the serial connection to the ANT chip. You have to use the FTDI command FT_Write(…) and transmit every single byte for every comand of the ANT like it is described in the message protocol of ANT on page 20 and 30, respectively. Which means you send the sync byte first, then the message length and so on. This is quite a lot of work, because you have to write your own library for communication, but that’s the only way to get this working through the sparkfun USB stick. [This[/b] actually helped me a lot. Just compare every byte you send with the one that smysnk uses in his code (look for txda).
From my personal experience I know that the ChannelSearchTimeout value is very important! Because in that time that you specified, the ANT chip is searching for devices but NOT connecting them yet. The connection happens only after the timeout. That was my big mistake, because I had a very large timeout specified and never got a connection! Therefore send the MESG_CHANNEL_STATUS_ID message and look if the returned value is a 1 (=assigned) and not 2 (=searching).
I know this is pretty much at the moment, when you just started. I’m working for 3 weeks now with the USB stick and the HRM and actually I managed this wednesday to finally receive the heart rate. So don’t give you. :wink:
Izzo](nRF24AP1 - ANT Code - Garmin Heart-Rate Monitor - SparkFun Electronics Forum)

Hi!

Congratulation! As you did it!

Did you mind if i asking for the full coding that you have done?

I am a student and still new with VC++ and HR coding…

I’ve founds lots of HR code for garmin HR ANT strip but most of them were working under linux which is i’m not familiar yet.

Thus, i would like to ask for your code and see what exactly happen on it.

I’m not really understand regarding to your explaination on FTDI things.

Best REgards,

Sara

Izzo:
Actually I managed now to get the whole thing working. As I already said in my last post, you cannot use the ANT_… commands with the sparkfun USB stick, because it uses the FTDI chip for the serial connection to the ANT chip. You have to use the FTDI command FT_Write(…) and transmit every single byte for every comand of the ANT like it is described in the message protocol of ANT on page 20 and 30, respectively. Which means you send the sync byte first, then the message length and so on. This is quite a lot of work, because you have to write your own library for communication, but that’s the only way to get this working through the sparkfun USB stick. [This[/b] actually helped me a lot. Just compare every byte you send with the one that smysnk uses in his code (look for txda).
From my personal experience I know that the ChannelSearchTimeout value is very important! Because in that time that you specified, the ANT chip is searching for devices but NOT connecting them yet. The connection happens only after the timeout. That was my big mistake, because I had a very large timeout specified and never got a connection! Therefore send the MESG_CHANNEL_STATUS_ID message and look if the returned value is a 1 (=assigned) and not 2 (=searching).
I know this is pretty much at the moment, when you just started. I’m working for 3 weeks now with the USB stick and the HRM and actually I managed this wednesday to finally receive the heart rate. So don’t give you. :wink:
Izzo[/quote]](nRF24AP1 - ANT Code - Garmin Heart-Rate Monitor - SparkFun Electronics Forum)