Home > Uncategorized > ANT+ Between MSP430 (also Arduino) and Android

ANT+ Between MSP430 (also Arduino) and Android

ANT+ what?

ant+ logoSmartphones are equipped with dizzying array of wireless communication capabilities.   Some of these features just go totally unnoticed. One such wireless communication protocol is called ANT+.

A friend of mine wanted to make a working prototype of an idea he had using ANT+ technology. While there are other mcu’s (read atmega/arduino) already had some libraries and code written for communicating against ANT+, it wasn’t enough for me.

  • Most of the existing code only worked as a slave, where it just tried to receive data sent by Garmin Heart Strap.
  • This slave implementation was only on either arduino or PC (python and C)

What I was more interested in was to leverage the ANT+ radio to not just receive data, but also send data. I wanted the mcu to interact with the world and use ANT+ to transmit data to my cellphone, for example. I couldn’t find any suitable implementations, and figured msp430 needs to have more “hacks” to add to its list.

So here goes. I bought two different Sparkfun products for ANT+. Both TI and Nordic has chips with ANT+ capabilities. The Sparkfun ones use nRF24AP1, and comes in 2 varieties.

I used the lesser chip that comes with the Launchpad to drive the ANT+ breakout as the master node. The usb stick will serve as the slave and used as debugging tool. Once the initialization hand shakes and data transmission is sorted out, I can test on the Android platform.

As of this writing, only Sony Ericsson makes phones with chips that can talk ANT+. I found Xperia X8 to be a good low-end unlocked Android phone just for general purpose hacking, with the full ANT+ capabilities onboard. In order to enable ANT+ wireless, you need to download these apps:

Here’s the video of my test setup running.
And all the relevant source code and documentation is hosted on github:

Playing With ANT+

I don’t own a heart strap, and I don’t plan to. Most of the existing code on the internet assumes you either have Garmin or Suunto heart strap sensors. The good news is that guys behind ANT+ has pretty extensive documentation on how the protocol works. They also provide some example code that’s relatively easy to follow, which you can modify to implement your own slave or master node.

In addition, Nordic’s chip nRF24AP1 provides serial interface to control ANT+ radio functions. Perfect, I just need to figure out the serial commands it needs to get it to operate it. My set up was as follows:

  • usb stick on linux PC with either python or C listener
  • msp430 connected to the breakout board which communicates using software UART

The lower end msp430G2xx1 doesn’t have hardware implemented master UART. Dang it. But it’s ok, I had an excellent software UART implementation done by one of the members in www.43oh.com forums.

The ANT+ Protocol

This protocol is pretty powerful. It operates on 2.4GHz band, allows bidirectional communications between nodes. Here’s a list of couple of the notable features:

  • security features (device pairing, network key)
  • multiple networks, multiple channels configurable
  • bidirectional data flow between master & slave
  • various network topology configuration where each nodes can be part of multiple networks
  • supposedly very power efficient

Wow, really? ANT+ turned out to be quite a beefy wireless communication protocol. I wonder why it’s not as widespread as bluetooth? More detailed information about this protocol is available http://www.thisisant.com.

In any case, I wanted to try setting up a simple independent network between two nodes, one acting as master and the other as slave. First, the message structure of ANT+ looks like this. Taken directly from ANT user guide.

So 3 bytes of header, N byes of data, and one last byte for checksum. Every message being sent back and forth between the codes will have this format. Now, in order to pair the 2 nodes together to form an independent network, we need to follow these steps (again taken from ANT guide).

Master Node

  1. Configure Channel
  2. Set Channel ID (discoverable)
  3. Open TX Channel
  4. Transmit data

Slave Node

  1. Configure Channel
  2. Set Channel ID
  3. Open RX Channel

The details of the pairing is a bit more tricky than this, but it illustrates overall steps we need to follow.

Setting Up The Channel

Each channel setup requires both the master and the slave to agree on the same configuration:

  • Network Type
  • RF Frequency (default 2466MHz)
  • Device Number
  • Transmission Type
  • Device Type
  • Channel Type
  • Channel Period
  • Data Type

These configuration parameters are “broadcasted” by both master and slave in the pairing process. It turns out that the delay between each message is also important when pairing the two. I’ve decided to set up my channel in the simplest way possible, so I have these defines in my code:


#define ANT_CH_ID 0x00
#define ANT_CH_TYPE 0x10
#define ANT_NET_ID 0x00
#define ANT_DEV_ID1 0x00
#define ANT_DEV_ID2 0x00
#define ANT_DEV_TYPE 0x00
#define ANT_TX_TYPE 0x00
#define ANT_CH_FREQ 0x0039
#define ANT_CH_PER 0x1f86

Once these configuration parameters are determined, both the mcu and the android app need to honor them when pairing.

Launchpad as ANT+ Master Node

launchpad with ant+ breakoutI used the interrupt-driven software UART from msp430 Launchpad to control the ANT+ breakout. Here’s the picture of my simple hardware setup.

Luckily, the RX, TX, and VCC pins on the breakout aligns perfectly with the launchpad’s corresponding pins. Note that the breakout’s pin labelled RX need to be tied to Launchpad’s TX, and vice versa. To make it work, I just had to make P1.0 on the Launchpad tied low, which corresponds to the Gnd pin on the breakout.

In addition, I’ve rerouted Gnd to P2.4 (unused), so that I can use a small push button to trigger hi-to-low transition interrupt on P1.7 (pulled high with P1REN). I am using this button to replay the ANT+ pairing routine and re-transmit data for debugging.

Here’s the C code that controls the ANT+ breakout. I’ve made the code as simple as possible, and the MSG ID’s for each specific ANT message is hardcoded in hex. The source code is available in git repository here.

#include
#include "uart_rxtx.h"

#define ANT_CH_ID    0x00
#define ANT_CH_TYPE  0x10
#define ANT_NET_ID   0x00
#define ANT_DEV_ID1  0x00
#define ANT_DEV_ID2  0x00
#define ANT_DEV_TYPE 0x00
#define ANT_TX_TYPE  0x00
#define ANT_CH_FREQ  0x0039
#define ANT_CH_PER   0x1f86

#define STOPBIT BIT7
#define LEDBIT BIT4

extern volatile uint8_t HALT;

void _delay_ms(int n)
{
  int i;
  // assumes 2 instructions for loop - could be false
  for(i=0; i    _delay_us(1000); // 1 ms
}

typedef uint8_t uchar;

uchar	txBuffer[32];
uint8_t	txBufferSize;
uint8_t	txBufferPos;

void txMessage(uchar*	message, uint8_t	messageSize)
{
  uint8_t i;
  _BIC_SR(GIE);  // disable interrupt

	txBufferPos		= 0;							   // set position to 0
	txBufferSize	= messageSize + 3;	 // message plus syc, size and checksum
	txBuffer[0]		= 0xa4;							 // sync byte
	txBuffer[1]		= (uchar) messageSize - 1;		// message size - command size (1)

  for(i=0; i    txBuffer[2+i] = message[i];

	// calculate the checksum
	for(i=0; i		txBuffer[txBufferSize - 1] = txBuffer[txBufferSize - 1] ^ txBuffer[i];

  _BIS_SR(GIE);   // enable interrupt

  // now send via UART
  for(i=0; i> 8;
	setup[2] = (ANT_CH_FREQ & 0xFF);    // RF Frequency
	// setup[1] = 0x00;    // Channel ID, 0x00 for HRM, 0x01 for custom
	// setup[2] = 0x39;    // RF Frequency
	txMessage(setup, 3);
}

void setchperiod()
{
	uchar setup[3];
	setup[0] = 0x43;
  setup[1] = (ANT_CH_PER & 0xFF00) >> 8;
	setup[2] = (ANT_CH_PER & 0xFF);    // RF Frequency
	// setup[1] = 0x1f;    // Channel Period LSB
	// setup[2] = 0x86;    // Channel Period MSB
	txMessage(setup, 3);
}

// Opens CH 0
void opench()
{
	uchar setup[2];
	setup[0] = 0x4b;
	setup[1] = 0x00;
	txMessage(setup, 2);
}

// Sends Data=AAAAAAAAAAAAAAAA
void sendHRM(uchar num)
{
	uchar setup[10];
	setup[0] = 0x4e;
	setup[1] = 0x00;
	setup[2] = 0x00;
	setup[3] = 0x00;
	setup[4] = 0x00;
	setup[5] = 0x00;
	setup[6] = 0x00;
	setup[7] = 0x00;
	setup[8] = 0x00;
	setup[9] = num;
	txMessage(setup, 10);
}

void sendData(uchar rand)
{
  uchar setup[4];
  setup[0] = 0x4e;
  setup[1] = rand * rand;
  setup[2] = rand - setup[1];
  setup[3] = rand;
	txMessage(setup, 4);
}

void config(uint8_t msec)
{
  P1OUT |= LEDBIT;

  reset();       _delay_ms(msec);
  assignch();    _delay_ms(msec);
  setrf();       _delay_ms(msec);
  setchperiod(); _delay_ms(msec);
  setchid();     _delay_ms(msec);
  opench();      _delay_ms(msec);

  P1OUT &= ~LEDBIT;
}

void setupButton_hilo(void)
{
  P1DIR &= ~STOPBIT;      // Set P1.0 to output direction

  P1OUT |= STOPBIT;       // set hi
  P1REN |= STOPBIT;       // pull up enable to hi (determined by P1OUT dir)
  P1IES |= STOPBIT;       // P1.3 Hi/lo edge

  P1IE  |= STOPBIT;       // P1.3 interrupt enabled
  P1IFG &= ~STOPBIT;      // P1.3 IFG cleared
}

void setupButton_lohi(void)
{
  P1DIR &= ~STOPBIT;      // Set P1.0 to output direction

  P1OUT &= ~STOPBIT;      // set lo
  P1REN |= STOPBIT;       // pull down enable to lo (determined by P1OUT dir)
  P1IES &= ~STOPBIT;      // P1.3 lo/hi edge

  P1IE  |= STOPBIT;       // P1.3 interrupt enabled
  P1IFG &= ~STOPBIT;      // P1.3 IFG cleared
}

int main()
{
  int j,i;
  uint8_t needconfig, data;
  char c;

  WDTCTL = WDTPW + WDTHOLD;          // Stop WDT
  BCSCTL1 = CALBC1_12MHZ;
  DCOCTL  = CALDCO_12MHZ;
  // BCSCTL1 = CALBC1_1MHZ;
  // DCOCTL  = CALDCO_1MHZ;
  // BCSCTL3 = LFXT1S_0 | XT2S_0 |  XCAP_1;  // ACLK uses external crystal at 32k

  P1SEL = P2SEL = 0x00;
  P1DIR = P2DIR = 0x00;
  P1OUT = P2OUT = 0x00;

  P1DIR |= LEDBIT + BIT6 + BIT5 + BIT0;
  P1DIR |= BIT3;
  P1OUT &= ~BIT0;    // low for ant breakout
  P1OUT &= ~BIT5;    // low for status LED

  setupButton_hilo();

  uart_init();

  _BIS_SR(GIE);   // enable interrupt
  // _BIS_SR(LPM0_bits + GIE);

  P1OUT |= BIT6; _delay_ms(500); P1OUT &= ~BIT6;
  _delay_ms(300);
  P1OUT |= BIT6; _delay_ms(500); P1OUT &= ~BIT6;
  _delay_ms(300);
  P1OUT |= LEDBIT; _delay_ms(500); P1OUT &= ~LEDBIT;
  _delay_ms(300);
  P1OUT |= LEDBIT; _delay_ms(500); P1OUT &= ~LEDBIT;

  // P1SEL  = BIT4; //0x10;                     // P1.4 SMCLK output
  // P1OUT |= BIT6;  // if started ok, green light on
  // config();
  needconfig = 1;

  while(1)
  {
    if(HALT==1 && needconfig==1) continue;

    if(HALT==1)
    {
      if(needconfig==0)
      {
        // reboot the breakout, since it keeps sending the last good data
        P1OUT |= BIT3;
        _delay_ms(50);
        P1OUT &= ~BIT3;
      }
      needconfig = 1;
      _delay_ms(50);

      continue;
    }

    // configure again multiple times
    if(needconfig)
    {
      _delay_ms(50);

      for(i=1; i      {
        if(HALT) break;

        config(5*i);
        if(i!=3) _delay_ms(5*i);
      }
      needconfig = 0;
      continue;
    }

    // send data 20 times
    for(j=0; j    {
      if(uart_in())
      {
        c = uart_getc();
      }
      else
      {
        sendHRM(data++);
        P1OUT ^= BIT6;  // toggle on and off to indicate we are in the main loop
        _delay_ms(100); // 100 msec is crucial here!
      }

      if(HALT) break;
    }
  }

  return 0;
}

Notice that the channel configuration routine repeats 20 times with varying message delay from 5 msec to 100 msec. This way, I can pair against Slave nodes that might have different message delays. It caused me quite a headache to get both master and slave paired up – I couldn’t get them working until I matched the message delay in both the slave and the master nodes.

USB Stick on PC as ANT+ Slave Node

Now we need to check whether we can receive the data being transmitted from our hardware. The ANT+ USB stick is perfect for this purpose because it allows us to “talk” to the ANT+ chip through USB serial communication on the PC. I’ve searched around and found 2 implementations of ANT+ slave node. One is written in C and the other in Python. I’ve tested both and found the python one easier to hack around and much more succinct. Both programs control the ANT+ stick via USB serial bus, and receives the data coming back from the same serial bus in asynchronous thread.

One caveat here is that there’s 50 msec delay between each message transmission. The master needs to match this delay between each channel configuration message to pair with the slave. Here’s the sample output from running the python code that listens on ANT+ traffic generated from the Launchpad:


$ ./ant_twisted.py /dev/ttyUSB0
<-- ['MSG_RESPONSE_EVENT', 'CHAN:00', 'ASSIGN_CHANNEL_ID', '00', 'CHKSUM:a5']
<-- ['MSG_RESPONSE_EVENT', 'CHAN:00', '45', '00', 'CHKSUM:a2']
<-- ['MSG_RESPONSE_EVENT', 'CHAN:1f', '43', '28', 'CHKSUM:93']
<-- ['MSG_RESPONSE_EVENT', 'CHAN:00', 'SET_CHANNEL_ID', '00', 'CHKSUM:b6']
<-- ['MSG_RESPONSE_EVENT', 'CHAN:00', 'OPEN_CHANNEL', '00', 'CHKSUM:ac']
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '00', 'e3']"
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '00', 'e3']"
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '04', 'e7']"
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '04', 'e7']"
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '04', 'e7']"
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '0c', 'ef']"
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '0c', 'ef']"
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '0c', 'ef']"
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '0c', 'ef']"
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '0c', 'ef']"
<-- "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '18', 'fb']"

The git repository for this project also contains the C source that achieves the same thing under tools directory.

Android Phone as ANT+ Slave Node

Getting the android app working was a bit more involved. It was also my first time with an android app, so it took a bit of learning to figure out how the demo app worked. Once you understand the Android framework, however, you’ll appreciate how the demo app’s source code is laid out. The guys over at http://www.thisisant.com did a good job of structuring the demo app and making it easy to follow. Btw, I found this book to be an excellent resource to get familiar with Android quickly.

I had to make a little bit of modification to make the app listen to the same channel I setup for my testing. I am leveraging the existing setup for HRM monitor to listen to my own “fake” data.  Also, I display the hex value of the raw data I transmit along with the decimal value. At each iteration, the code on Launchpad just increments a byte-sized counter and sends this number as the “heart-rate”.

I added an additional routine within BroadcastReceiver anonymous class, which updates the values received into a private data member in AntPlusManager class. There’s also getTest() routine in the same class that returns the value stored. There are only 3 source files for this demo app:

  • AntPlusManager.java – contains the core logic of setting up the channel, receiving data, keeping the most recent data updated on its private data members
  • ANTPlusDemo.java – implements the main activity of this demo app
  • PairingDialog.java – mostly for configuration dialogs and passing the user input into corresponding config members.
The demo app relies on the AntInterface library (compiled .jar file) which you can also download from my github for this project or filling out a simple form here.
       private void antDecodeTest(byte[] ANTRxMessage)
       {
          Log.d(TAG, "antDecodeTest start");

          if(mAntProcessingEnabled)
          {
             Log.d(TAG, "antDecodeHRM: Received broadcast");

             if(mHrmState != ChannelStates.CLOSED)
             {
                Log.d(TAG, "antDecodeHRMM: Tracking data");

                mHrmState = ChannelStates.TRACKING_DATA;
                mCallbackSink.notifyChannelStateChanged(HRM_CHANNEL);
             }

             if(mDeviceNumberHRM == ANTPlusDemo.WILDCARD)
             {
                 try
                 {
                     Log.i(TAG, "antDecodeHRM: Requesting device number");
                     mAntReceiver.ANTRequestMessage(HRM_CHANNEL, AntMesg.MESG_CHANNEL_ID_ID);
                 }
                 catch(AntInterfaceException e)
                 {
                     antError();
                 }
             }

             // Heart rate available in all pages and regardless of toggle bit
             mTest = ANTRxMessage[10];
             mCallbackSink.notifyChannelDataChanged(HRM_CHANNEL);
          }
          Log.d(TAG, "antDecodeTest end");
       }

Overall, the changes were minor. It’s rather a quick and dirty hack to test ANT+ on Android. This modified version of the demo app is also found on my project hosted at github under “android” folder.

Next Steps

I’ve only scratched the surface of the technologies mentioned here. The ANT+ wireless technology is capable of far more complex network configurations and I’ve only tested its most simplistic features. The transmitted data can be processed both by PC or capable Android phones, and it opens much more potential for practical applications of this wireless communication protocol. On the Android side, there are tons of views one can create with the data collected. I’d modify the existing demo app further as time permits. Oohh.. one application of this tech can be temperature sensor / control circuit for my friend who brews beer at home. The monitoring can be done on the Android app and alert when the beer is ready! 🙂

Now that I got the basics covered, we can make something more useful with this technology. One would argue that bluetooth can be used to achieve the same thing (maybe Bluetooth LE?). However, if ANT+ is as power efficient as it claims, we can combine msp430 and ANT+ to create sensors that can truly last for years on a single battery. This sensor in turn, can send data to multiple recipients such as an Android phone. My only gripe is that there aren’t that many android phones out there that comes with ANT+ wireless chip built-in. Perhaps that will change in the future.

In any case, I put this article out there in the hope that someone can benefit from my musings and create awesome applications using technologies mentioned here.

Update [2011.12.14]

I’ve gotten requests for making this work on Arduino. I’ve ported the ANT+ master node code over to Arduino 1.0 and tested it. It works just like it did on msp430. I used the latest version of Arduino IDE (v1.0) which was released not too long ago. It seems like there have been significant library changes since last time I used this. Previously, I merely downloaded the IDE to repurpose the C++ libraries that came with it, since I do most of my dev in Linux. You can find the sketch and an additional library called AntMaster on the same git repository:

https://github.com/jbremnant/msp430ant/tree/master/fw_arduino/antMaster

The AntMaster library is a just the original C functions made into a thin C++ class. You pass the initialized instance of the SoftwareSerial object, and it takes care of the rest.  The main sketch is only few lines as a result, and looks like this:

#include
#include "ant_lib.h"

SoftwareSerial mySerial(2, 3);
AntMaster am(mySerial, 4);  // second argument is pin number for status LED

void setup()
{
  Serial.begin(57600);
  Serial.println("ant master config routine");

  am.config_loop();
}

void loop() // run over and over
{
  delay(500); am.ledon();
  am.sendHRM(3);  // send your data here
  delay(500); am.ledoff();
}

Arduino runs at 5V, but the ANT+ breakout needs to be driven at 3V. I had these logic level converter breakouts handy, and was able to use them without issues. The picture of my test setup shows how I laid things out. It’s simple enough that I think a picture would do fine without the circuit diagrams.

Arduino contains SoftwareSerial library, which I purposely used in this setup. Instead of taking the easy route and use the hardware Serial library, using the software implementation will free up the hardware UART port for serial communication back to the PC. Should you decide to also implement the ANT+ slave node in this fashion, you can receive data from the ANT+ master node and send it over to the PC. (I can picture Processing at work here). In any case, this should help Arduino users out there that might have had trouble finding suitable implementations of ANT+ master node.

Lastly, note that the TX/RX lines are crossed. The RX on the breakout should match against designated software TX pin on the Arduino. In my particular setup, I’ve used PIN2 as RX and PIN3 as TX on the Arduino.

Categories: Uncategorized
  1. November 28, 2011 at 10:26 pm

    Awesome Project!

    Great use of MSP430. I have this gear, now I can do something with it.

    • November 29, 2011 at 12:56 am

      thanks! glad you found it useful.

  2. Alexei
    November 29, 2011 at 12:33 am

    Very nice article. I like the clear explanations with references and demo codes. I wish I had the equipment to test them out. Many thanks.

    • November 29, 2011 at 12:56 am

      Hi Alexei! thanks for visiting. I can lend you my equipment next time I see you. 🙂

  3. Jai
    November 29, 2011 at 2:34 am

    nice project… may i ask for your email? i have a relevant project in mind and i need your advice.

    • November 29, 2011 at 3:10 am

      Hi Jai. Sure, you can reach me at jbremnant at gmail dot com

  4. Lyman Connor
    December 13, 2011 at 11:31 pm

    Thank you so much for posting this…A year ago I started working with some high school students to piece together some labs to develop an ANT+ wireless sensor (Master) that would transmit a load profile (Ft/Lbs) with a small grant from Nordic. ( ANT does not have a “Load Profile” per se at present but we were told that if we developed the prototype that they would make it happen). Being that I am not a programmer, albeit I am an EE, we groveled with trying to find code to support the UART and to be able to get a Nordic AP1/AP2 chip to talk to a AVR 168p on a breadboard….no dice.We then transitioned to a MSP430 and I could not find any supporting documentaion that was clear enough to follow,,,again no dice….We did have some success with using a pair of Arduino Unos paired to an Nordic NRF24AP1 chip although there were several issues one being that all the code was structured for a Slave implementation.I purchased an ANT+ developers license on my own dime in hopes of getting additional support from ANT and it just never materialized..I am going to try to get this working as a new years present to the students who have come up with at least 10 new ideas for this technology from Power Station Transformer Oil monitoring to remote real time Xray dosimeters…..Curious if you are considering porting this to Arduino? Just curious as the writing code in Arduino seemed more intuitive for some reason and we found that using Processing to develope a MMI was very straight forward

    • December 14, 2011 at 1:26 am

      Hi Lyman
      Thank you for taking the time to let me know about your experiences.
      I think it would be trivial to port this over to arduino, and I can definitely help you get things going this year.
      You can contact me via jbremnant at gmail dot com. I’ll look forward to hearing from you.

    • December 14, 2011 at 5:56 am

      I went ahead and tested it on Arduino. Please check the end of the post on my notes on Arduino. Let me know if you can replicate a similar setup and get it working. Good luck!

      • Lyman Connor
        December 15, 2011 at 1:13 pm

        My students and I sincerely appreciate your help…I ordered a few level shifters last night to have them available and will be in touch to let you know how all is going once I get things together.

  5. Ray
    December 15, 2011 at 12:39 am

    @jbremnan: thanks for your posting, I am also playing around with the 24AP1 currently, so far only in slave mode and have various strange effects in pairing with garmin heartrate monitors (I can receive one, but have trouble reading many at the same time), possibly will try to understand ANT better using an own master now. Luckily I got two of the sparkfun boards to save shipping… I am using a linux PC and an NXP ARM cpu and it’s HW UART though.

    @Lyman Connor: I’d have a question to you regarding ANT dev license – could you contact me at ray (funnysign) ray.net?

    • December 15, 2011 at 1:36 pm

      You have multiple heartstraps? I don’t think the slave (receiver) implementations you can find on the internet is configured to do listen from multiple master nodes. I’ll be interested in your findings, however. Please do share when you make things work!

  6. Lyman Connor
    December 17, 2011 at 7:05 pm

    @jbremnan: Received my parts today and I wanted to try to put your Arduino project together as I am excited to get started….I wanted to ask a couple questions regarding wirning.
    1)It appears that you did not terminate Vcc and RTS on the NRF24 break out board, is this correct?
    2)Should I wire the RX and TX lines from the breakout board to the respective pins on my arduino or invert? It appears that you jumped TX-TX and RX-RX?

    • December 17, 2011 at 9:05 pm

      Great, couple of things. You will need to supply 5v to the vcc on HV side, 3.3v on the vcc on the LV side. Both sides share the common gnd. The RTS on the breakout is not connected, and my rx and tx are crossed when connected to breakout. Let me know how it works out!

      • Lyman Connor
        December 27, 2011 at 11:47 pm

        Very nice….First Master ANT+ & Arduino implementation that I have found in the past year that works. I used your breadboard layout and your sketchbook and got this to work first time around. I used ANTWARE II and an ANT AP2 dongle to verify that communication was taking place.

        Next goal is to attempt to get this working in the ANT+ Simulator environment where you should be able to mimic any Master device by adhering to its specific device protocol. The Ant + Display simulator did not recognize the HRM data as I believe that there needs to be an ACK transmitted by the Master to synch data.

  7. December 28, 2011 at 1:42 am

    Awesome! I am really glad it worked. There’s a lot more you can do with ANT+. If you are interested in exploring more functionalities, we can take it offline. 🙂

  8. March 19, 2012 at 12:58 pm

    Hello , Code of launchpad. The setupButton_hilo function you write like below,

    P1IES &= ~STOPBIT;//P1.3 lo/hi edge
    P1IE | = STOPBIT;//P1.3 interrupt enabled
    P1IFG &= ~STOPBIT; //P1.3 IFG cleared

    STOPBIT had defined BIT7, why are you comment p1.3??(I don’t know)
    Can you explain ?(I know p1.3 be used to wait RTS signal!)
    And, the button pin is connect P1.7 & P2.4?

    • March 21, 2012 at 2:07 am

      Right. Ignore the comments. I put them in there while I was debugging and forgot to update it. The source code I posted on git should had the right pin mappings.

  9. March 30, 2012 at 11:35 pm

    I don’t know if this has been said yet, but you really really need to post a link to this on the sparkfun website comment sections for these ant devices. I would post it myself, but I think it would be better for you to do it as you came up with this yourself. I am working on a senior design project and have been trying to get an msp430 to connect to the computer for weeks, this helped me so much.
    Thank you for your effort.

  10. Trevor
    April 27, 2012 at 1:54 pm

    First of all great little tutorial here, very helpful and gives me hope of successfully integrating ant+ into future designs. I did have a question: Could someone clarify the connections between the logic converter and the nordic breakout, I am having trouble seeing what your connections are. Thanks!

    • April 27, 2012 at 6:12 pm

      @Trevor
      Try the following connection from Arduino to High level side of converter.

      HV on converter <- 5V from Arduino
      GND (HV) on converter (on both HV and LV side) <- GND from Arduino
      RXD (HV) on converter <- Pin 3 from Arduino
      TXD (HV) on converter <- Pin 2 from Arduino

      Now Low level side from converter to Nordic breakout

      LV on converter <- 3.3V from Arduino
      GND (LV) on converter Nordic RX
      TXD (LV) on converter -> Nordic TX
      LV on converter -> Nordic VCC
      GND on converter -> Nordic GND

      Let me know how things work out.

  11. loieliv
    August 4, 2012 at 2:30 pm

    I cannot compile the arduino sample
    it always says u
    ndefined reference to `AntMaster::config_loop()’

    • August 4, 2012 at 2:53 pm

      Hi
      The arduino IDE requires you to open ant_lib.h, ant_lib.cpp as well.
      Create a new tab “Ctrl-Shift-N”, or click on the arrow on top right hand corner.
      Load the ant library files and try to compile again.

      • loieliv
        August 5, 2012 at 8:02 am

        thanks that solved it

  12. marwooj
    October 9, 2012 at 6:08 am

    Hi, I have bought decathlon cadence ANT+ sensor that seems no to work as regular ANT+ device should. No way to pair it with anything else than decathlon staff. Would it be able to write python code that finds out Device ID, so I can use this in my desktop software?

  13. Juha
    January 10, 2013 at 5:51 pm

    Hi,
    This was really helpfull so thx a lot! I had some problems inthe beginning. Everything seemd working but the USB stick didn’t receive any traffic. Then suddenly everything started working. Weird. I haven’t really found out why this happened. Anyway I have one question: You are sending data and you increment the counter with 1 every time. Why doesn’t the response in the USB stick reflect that?
    In your blog you had this:
    <– "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '00', 'e3']"
    <– "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '00', 'e3']"
    <– "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '04', 'e7']"
    <– "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '04', 'e7']"
    <– "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '04', 'e7']"
    <– "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '0c', 'ef']"
    <– "['a4', '09', '4e', '00', '00', '00', '00', '00', '00', '00', '00', '0c', 'ef']"
    Why it jumps of 00 to 04? and then to oc. And why are there multiple lines of same data?
    Sorry if you have already answered this in your blog.

    Regards,
    Juha

  14. mark
    January 29, 2013 at 3:43 am

    Anyone making an ANT+ to RS232 or CANBUS commercially?

    I would be interested if someone knows.

  1. November 28, 2011 at 9:01 pm
  2. November 29, 2011 at 1:52 am
  3. November 29, 2011 at 4:02 am
  4. November 29, 2011 at 10:06 am
  5. November 30, 2011 at 10:49 am

Leave a reply to Lyman Connor Cancel reply