Other Parts Discussed in Thread: CC2420
Dear all,
I am using TelosB which is mounted with CC2420 for radio communication.
Here I am trying to achieve clock synchronisation between the TelosB, and to the clock of the network.
So far, I have managed to retrieve the clock of the network.
The system works as follows:
- The tag starts its own counter which increments 7.25ms
- (The value of counter * 7.25)/(10^-6) to convert the value is microseconds.
- The tag only receives if the data packet is the right type.
- Value of clock from the network is also multiplied by 7.25ms to compare with the counter of the tag.
- These will be compared, and if the difference between two values are bigger than 15us then it will have to sync. However, still some with error grows over the time (clock drift of the TelosB).
- To correct this error, need to keeping track of past network's clock and the internal counter value when they were received and calculating the ratio between the elapsed time relative to TelosB and to the network. This number is the drift coefficient and is used to correct delta.
- app_vars.compensatedtime = ((app_vars.current_time - app_vars.capture_previous_time)/app_vars.alpha)+app_vars.capture_time; whre alpha is
- app_vars.localdelta = app_vars.current_time - app_vars.previous_time;
- app_vars.networkdelta = app_vars.capture_time - app_vars.capture_previous_time;
- app_vars.alpha = app_vars.localdelta/app_vars.networkdelta;
By doing this, I should be able to get a relative error less than 15us, which I do not. I believe that there might be a mistake I have made in my code.
The code is attached in this file, any help will be greatly appreciated.
Thank you
#include "sctimer.h"
#include "stdint.h"
#include "string.h"
#include "stdlib.h"
#include "board.h"
#include "radio.h"
#include "leds.h"
#include "uart.h"
//=========================== defines =========================================
#define LENGTH_PACKET 125+LENGTH_CRC ///< maximum length is 127 bytes
#define CHANNEL 20
#define LENGTH_SERIAL_FRAME 8 ///< length of the serial frame
#define LENGTH 8 ///< length of the serial frame
//=========================== variables =======================================
typedef struct {
//radio
uint8_t num_startFrame;
uint8_t num_endFrame;
//ultrasound
uint8_t num_startUSFrame;
uint8_t num_endUSFrame;
} app_dbg_t;
app_dbg_t app_dbg;
typedef struct {
// rx packet
volatile uint8_t rxpk_done;
uint8_t rxpk_buf[LENGTH_PACKET];
uint8_t rxpk_len;
// uart
uint8_t uart_txFrame[LENGTH_SERIAL_FRAME];
uint8_t uart_counterFrame[LENGTH];
uint8_t uart_counterByte;
uint8_t uart_lastTxByte;
volatile uint8_t uart_done;
volatile uint8_t uart_counterdone;
//ASN
volatile uint64_t ASN;
volatile uint64_t num_asn;
volatile uint64_t alpha;
volatile float localdelta;
volatile float networkdelta;
volatile float previous_time;
volatile float current_time;
volatile float capture_previous_time;
volatile float capture_time;
volatile float compensatedtime;
} app_vars_t;
app_vars_t app_vars;
//=========================== prototypes ======================================
// radio
void cb_startFrame(PORT_TIMER_WIDTH timestamp);
void cb_endFrame(PORT_TIMER_WIDTH timestamp);
// uart
void cb_uartTxDone(void);
//ASN counter
void cb_asncounter(void);
//=========================== main ============================================
int mote_main(void) {
// clear local variables
memset(&app_vars,0,sizeof(app_vars_t));
// initialize board
board_init();
// set asn counter
sctimer_setasnreadCb(cb_asncounter);
// add callback functions radio
sctimer_setStartFrameCb(cb_startFrame);
sctimer_setEndFrameCb(cb_endFrame);
// setup UART
uart_setCallbacks(cb_uartTxDone);
// prepare radio
radio_rfOn();
radio_setFrequency(CHANNEL);
// switch in RX
radio_rxEnable();
radio_rxNow();
while (1) {
// sleep while waiting for at least one of the rxpk_done to be set
app_vars.rxpk_done = 0;
while (app_vars.rxpk_done == 0) {
board_sleep();
}
// if I get here, I just received a packet
//===== send notification over serial port
// format frame to send over serial port, displays the value of ASN retrieved from the manager
if (app_vars.rxpk_buf[0] == 0x08){
app_vars.uart_txFrame[0] = app_vars.rxpk_buf[17]; // ASN #1
app_vars.uart_txFrame[1] = app_vars.rxpk_buf[18]; // ASN #2
app_vars.uart_txFrame[2] = app_vars.rxpk_buf[19]; // ASN #3
app_vars.uart_txFrame[3] = app_vars.rxpk_buf[20]; // ASN #4
app_vars.uart_txFrame[4] = app_vars.rxpk_buf[21]; // ASN #5
app_vars.uart_txFrame[5] = 0xff; // closing flag
app_vars.uart_txFrame[6] = 0xff; // closing flag
app_vars.uart_txFrame[7] = 0xff; // closing flag
//app_vars.uart_done = 0;
//app_vars.uart_lastTxByte = 0;
app_vars.ASN = (uint64_t)app_vars.uart_txFrame[0] + ((uint64_t)app_vars.uart_txFrame[1]<<8) + ((uint64_t)app_vars.uart_txFrame[2]<<16)+((uint64_t)app_vars.uart_txFrame[3]<<24)+((uint64_t)app_vars.uart_txFrame[4]<<32);
app_vars.capture_time = (app_vars.ASN * 7.25)/100000; //in us, value from the manager
app_vars.current_time =(app_vars.num_asn*7.25)/100000; //in us, counter within TelosB
if(app_vars.current_time - app_vars.capture_time > 15 || app_vars.capture_time - app_vars.current_time > 15){
app_vars.current_time = app_vars.capture_time;
leds_all_off();
app_vars.compensatedtime = ((app_vars.current_time - app_vars.capture_previous_time)/app_vars.alpha)+app_vars.capture_time;
app_vars.localdelta = app_vars.current_time - app_vars.previous_time;
app_vars.networkdelta = app_vars.capture_time - app_vars.capture_previous_time;
app_vars.alpha = app_vars.localdelta/app_vars.networkdelta;
app_vars.previous_time = app_vars.compensatedtime; //stored compensated current-time to use it as a referece for alpha
app_vars.capture_previous_time = app_vars.capture_time; //stored capture_time value of ASN
app_vars.num_asn = (app_vars.compensatedtime*1000000)/7.25;
/* app_vars.uart_counterFrame[0] = app_vars.compensatedtime;
app_vars.uart_counterFrame[1] = app_vars.compensatedtime>>8;
app_vars.uart_counterFrame[2] = app_vars.compensatedtime>>16;
app_vars.uart_counterFrame[3] = app_vars.compensatedtime>>24;
app_vars.uart_counterFrame[4] = app_vars.compensatedtime>>32;
app_vars.uart_counterFrame[5] = app_vars.compensatedtime>>40;
app_vars.uart_counterFrame[6] = app_vars.compensatedtime>>48;
app_vars.uart_counterFrame[7] = app_vars.compensatedtime>>56;
app_vars.uart_done = 0;
app_vars.uart_lastTxByte = 0;
app_vars.uart_counterByte = 0;
// send app_vars.uart_txFrame over UART
uart_clearTxInterrupts();
uart_enableInterrupts();
//uart_writeByte(app_vars.uart_txFrame[app_vars.uart_lastTxByte]);
uart_writeByte(app_vars.uart_counterFrame[app_vars.uart_counterByte]);
while (app_vars.uart_done==0); // busy wait to finish
uart_disableInterrupts();*/
}
else {
leds_all_on();
/*
app_vars.uart_counterFrame[0] = app_vars.compensatedtime;
app_vars.uart_counterFrame[1] = app_vars.compensatedtime>>8;
app_vars.uart_counterFrame[2] = app_vars.compensatedtime>>16;
app_vars.uart_counterFrame[3] = app_vars.compensatedtime>>24;
app_vars.uart_counterFrame[4] = app_vars.compensatedtime>>32;
app_vars.uart_counterFrame[5] = app_vars.compensatedtime>>40;
app_vars.uart_counterFrame[6] = app_vars.compensatedtime>>48;
app_vars.uart_counterFrame[7] = app_vars.compensatedtime>>56;
app_vars.uart_done = 0;
app_vars.uart_lastTxByte = 0;
app_vars.uart_counterByte = 0;
// send app_vars.uart_txFrame over UART
uart_clearTxInterrupts();
uart_enableInterrupts();
//uart_writeByte(app_vars.uart_txFrame[app_vars.uart_lastTxByte]);
uart_writeByte(app_vars.uart_counterFrame[app_vars.uart_counterByte]);
while (app_vars.uart_done==0); // busy wait to finish
uart_disableInterrupts();*/
}
}
else {
app_vars.uart_done=1;
}
}
}
//=========================== callbacks =======================================
//===== radio
void cb_startFrame(PORT_TIMER_WIDTH timestamp) {
// update debug stats
app_dbg.num_startFrame++;
}
void cb_endFrame(PORT_TIMER_WIDTH timestamp) {
// update debug stats
app_dbg.num_endFrame++;
// indicate I just received a packet
app_vars.rxpk_done = 1;
// get packet from radio
radio_getReceivedFrame(
app_vars.rxpk_buf,
&app_vars.rxpk_len,
sizeof(app_vars.rxpk_buf));
}
//==== ASN counter
void cb_asncounter(void){
app_vars.num_asn++;
}
//===== uart
void cb_uartTxDone(void) {
uart_clearTxInterrupts();
// prepare to send the next byte
// app_vars.uart_lastTxByte++;
app_vars.uart_counterByte++;
/* if (app_vars.uart_lastTxByte<sizeof(app_vars.uart_txFrame)) {
uart_writeByte(app_vars.uart_txFrame[app_vars.uart_lastTxByte]);
}else */if(app_vars.uart_counterByte<sizeof(app_vars.uart_counterFrame)){
uart_writeByte(app_vars.uart_counterFrame[app_vars.uart_counterByte]);
}
else {
app_vars.uart_done=1;
}
}