Welcome Guest,Register Now
Log In

ANT Forum

Welcome guest, please Login or Register

   

ANT Time Synchronization Receiver Trigger Stops Randomly

Rank

Total Posts: 3

Joined 2016-08-17

PM

Hello,

I am using s332 v2.0 softdevice. My code is bare minimum based on time sync example. I have tested with s212 as well but both have same problems. In either case the time sync works fine if i select ant time period like 7500 and event time period 75. If i go below 75 it does not work. Also I have tried several combinations of ant and event time periods and some work and some don't. Is there some mathematical relation between these two that i need to follow?      
Avatar
RankRankRankRank

Total Posts: 745

Joined 2012-09-14

PM

Hi,

There is no required relationship between the event time period and the ANT channel period, except that the ANT channel period could exceed the event time period, meaning the "invalidation" feature should be enabled to indicate to receivers that any consecutive messages sent after the first message with the new event time that it's invalid.

The ANT Channel Period should also match on both the transmitter and all of the receivers.

Could you discuss your use case further? Did you require time periods faster than ~2ms? Could you describe the behavior you are seeing when the "trigger stops randomly?" As you decrease the event period, more factors could come into play, but time sync itself should be able to operate properly.

The application has to be able to handle all the ANT events in between each of the timer events.      
Rank

Total Posts: 3

Joined 2016-08-17

PM

Hi,

Well in my application I would like to have ANT channel period at 20Hz. With that I would ideally want the time sync clock to work at 1 Khz. Based on the examples codes available in the application I cannot get this to work on the nrf52 development board. What i get working it that ant frequency should be twice the time sync clock. Based on my understanding there should be no such limitation as RTC 2 is just a counter and say every 1 ms it triggers a toggle on GPIO. The Ant time sync would just match the phase of the two trigger events and the ANT channel period determined how often do we want to correct the counter's trigger.

What I do is use a scope on transmitter and receiver and check the gpio toggle frequency. without the Ant both triggers work fine even at 1Khz but with the ant time sync on the receiver i see that the trigger stops (that is on the scope i get a fixed high or low) this is when ever we correct counter with ANT. Now in some cases this pause is temporary but in some cases this is permanent and i have to reset the receiver and turn the transmitter off to get the response..

Currently this is the only ANT event that I have.

Here is the main code on the receiver's side

void ant_evt_dispatch(ant_evt_t * p_ant_evt)
{
ANT_MESSAGE * pstEventMessage = (ANT_MESSAGE *) p_ant_evt;


if ((pstEventMessage->ANT_MESSAGE_ucMesgID == MESG_BROADCAST_DATA_ID) // Check if this is a broadcast message
&& (pstEventMessage->ANT_MESSAGE_aucPayload[0] == TIME_SYNC_PAGE)) // Check if this is the time synchronization page
{

//nrf_drv_rtc_disable(&m_rtc);
// Get 4-byte RTC1 time stamp from extended data
time_stamp = (pstEventMessage->ANT_MESSAGE_aucExtData[2] << 16) +
(pstEventMessage->ANT_MESSAGE_aucExtData[1] << 8) +
pstEventMessage->ANT_MESSAGE_aucExtData[0];
//pstEventMessage->ANT_MESSAGE_aucExtData[3] << 24) +


// Get time sync offset from time sync packet
offset = (pstEventMessage->ANT_MESSAGE_aucPayload[7] << 8) +
pstEventMessage->ANT_MESSAGE_aucPayload[6];

// Calculate the next event time
comp_chann_val = time_stamp - offset + LED_INVERT_PERIOD;
// Setup RTC to fire during the next period
nrf_drv_rtc_cc_set(&m_rtc, ANT_RTC_CHANNEL, comp_chann_val, true);
//nrf_drv_rtc_enable(&m_rtc);
}
}

static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
if (int_type == NRF_DRV_RTC_INT_COMPARE0)
{
nrf_gpio_pin_toggle(17);

// Get the current RTC counter value
uint32_t count = nrf_drv_rtc_counter_get(&m_rtc);
// Set the RTC channel to interrupt again after the LED_INVERT_PERIOD
ret_code_t err_code = nrf_drv_rtc_cc_set(&m_rtc,
ANT_RTC_CHANNEL,
count + LED_INVERT_PERIOD,
true);


}
}


static void ant_channel_rx_broadcast_setup(void)
{
uint32_t err_code;
ANT_TIME_STAMP_CONFIG stampConfig;

// Configure ANT Channel
ant_channel_config_t broadcast_channel_config =
{
.channel_number = ANT_BROADCAST_CHANNEL_NUMBER,
.channel_type = CHANNEL_TYPE_SLAVE,
.ext_assign = EXT_ASSIGN_NONE,
.rf_freq = RF_FREQ,
.transmission_type = CHAN_ID_TRANS_TYPE,
.device_type = CHAN_ID_DEV_TYPE,
.device_number = CHAN_ID_DEV_NUM,
.channel_period = CHAN_PERIOD,
.network_number = ANT_NETWORK_NUMBER,
};

// Configure received message timestamp to use RTC1 (4 byte counter)
stampConfig.ucTimeBase = ANT_TIME_BASE_ALT2;
stampConfig.bTimeStampEnabled = true;
err_code = sd_ant_time_stamp_config_set(&stampConfig;);
APP_ERROR_CHECK(err_code);

// Initialize channel configuration
err_code = ant_channel_init(&broadcast;_channel_config);
APP_ERROR_CHECK(err_code);

// Disable high priority search timeout and set the proper channel number
ant_search_config_t ant_search_config = DEFAULT_ANT_SEARCH_CONFIG(ANT_BROADCAST_CHANNEL_NUMBER);
ant_search_config.high_priority_timeout = ANT_HIGH_PRIORITY_TIMEOUT_DISABLE;

// Set search timeout
err_code = ant_search_init(&ant;_search_config);
APP_ERROR_CHECK(err_code);

// Open channel.
err_code = sd_ant_channel_open(ANT_BROADCAST_CHANNEL_NUMBER);
APP_ERROR_CHECK(err_code);
}

static void rtc_config(void)
{
uint32_t err_code;

// Initialize RTC instance
nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;

err_code = nrf_drv_rtc_init(&m_rtc, &config;, rtc_handler);
APP_ERROR_CHECK(err_code);

// Enable tick event & interrupt
nrf_drv_rtc_tick_enable(&m_rtc, true);

// Set compare channel to trigger interrupt after LED_INVERT_PERIOD
err_code = nrf_drv_rtc_cc_set(&m_rtc, ANT_RTC_CHANNEL, LED_INVERT_PERIOD, true);
APP_ERROR_CHECK(err_code);

// Power on RTC instance
nrf_drv_rtc_enable(&m_rtc);



}

This is the code for Transmitter's side

void ant_time_sync_message_send()
{
uint32_t err_code;
uint8_t message_payload[ANT_STANDARD_DATA_PAYLOAD_SIZE];

uint32_t counter;

// Get the current RTC counter value
counter = nrf_drv_rtc_counter_get(&m_rtc);
nrf_drv_rtc_cc_set(&m_rtc, ANT_RTC_CHANNEL, counter + LED_INVERT_PERIOD, true);

// Assign a new value to the broadcast data.
memset(message_payload, 0, ANT_STANDARD_DATA_PAYLOAD_SIZE);
message_payload[0] = TIME_SYNC_PAGE;
message_payload[4] = 0;
message_payload[5] = 0;
message_payload[6] = (uint8_t) LSB_32(counter); // 2-byte counter LSB
message_payload[7] = (uint8_t) LSB_32(counter >> 8); // 2-byte counter MSB

// Broadcast the data.
err_code = sd_ant_time_sync_broadcast_tx(ANT_BROADCAST_CHANNEL_NUMBER,
     
Avatar
RankRankRankRank

Total Posts: 745

Joined 2012-09-14

PM

After some testing, it appears the issue is that the counter is getting ahead of the events, as with a 1kHz timer, events are occurring before the value has even been sent. This means that the counter has already advanced past the next event time sent by the master.

I have attached a similar project as to the one in the SDK, but it includes fixes for the receiver to compensate for events which may have occurred before the channel sent the message.

// Calculate the next blink time
cc time_stamp offset BLINKY_PERIOD;
      
cc &= 0xFFFFFF// Mask off lower 24 bits 
   
// Make sure we are ahead of the counter
// NOTE: For fast events you may be several events behind, in
// this case you will want a more efficient algorithm for bringing 
// the period inline with the counter
while (cc <= NRF_RTC1->COUNTER)
{
   bLedIsOn 
= !bLedIsOn;   // Flip LED state
   
cc += BLINKY_PERIOD;    // Advance to next period
   
cc &= 0xFFFFFF;         // Mask off lower 24 bits
}

//Setup RTC to blink during the next period
NRF_RTC1->CC[0] cc
     

File Attachments

Rank

Total Posts: 3

Joined 2016-08-17

PM

Thanks for the code. It works great. I have one more question. Is is necessary to use NRF_CLOCK_LF_SRC_XTAL. I am using NRF_CLOCK_LF_SRC_RC but that doesnot work as well as the code you have provided me with. With NRF_CLOCK_LF_SRC_RC I still get a drop for a few pulses randomly.      
Avatar
RankRankRankRank

Total Posts: 745

Joined 2012-09-14

PM

It is necessary to use NRF_CLOCK_LF_SRC_XTAL, the RC source is far less accurate than the external crystal, and ANT is specced for 50PPM or better which the RC source cannot provide.