Part Number: MSP430F1611
Dear all,
I am currently building a wireless ultrasound transmisson and reception system.
My clock of the system is synchrnoised to the wireless network by exchaning the data packet.
I am trying to transmit and receive ultrasound periodically, and this should be possible as TX module and RX module time synchronisation is within 5us error as they share the same master clock(wireless network)
The ultrasound module I am using is HC-SR04, but I have modifeid it so that each one can only transmit and recieve.
Trying to merge these two seems more complicated than I thought, looking at this code:
Pin and Interrupts are initilaised, then it goes while loop where synchronisation of the clock is carried out.
Here is where I face a problem, as the board goes to sleep when it does not receive any packet, the module can't transmit periodically unless it recieves packets which comes in approximately every 6 seconds.
So the Tx module should be able to transmit around 3 times, but It doesn't.
I attached for both Tx and Rx codes here.
// initialising ultrasound
P2DIR |= 0x08; // Set P2.3 as output (1 = out, 0 = in)
P2OUT &= ~0x08; // Set P2.3 low
TACCTL0 = CCIE; // capture/compare interrupt enable
TACTL = TASSEL_1 | MC_1 | ID_2; // Select ACLK, 'counts up' mode, input divider (4)
TACCR0 += 18000; // ~ 2.2s
while (1) {
if (app_vars.trig != 0){ // if flag's been raised with alternation
leds_all_off();
P5OUT ^= 0x10; // toggle red led
P2OUT ^= 0x08; // toggle P2.3 - trig
__delay_cycles(96); // delay ~ 20 us
P2OUT ^= 0x08;
__delay_cycles(240000); // delay 50 ms
P5OUT ^= 0x10;
app_vars.trig = 0; // clear flag
}
// 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.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.current_network_time = (app_vars.ASN * 7.25)*1000000;
app_vars.current_local_time = app_vars.num_asn;
// ----- before calculating the new alpha and stuff you toggle led if error is too big
app_vars.compensated_time = (app_vars.current_local_time - app_vars.previous_local_time)*app_vars.alpha + app_vars.previous_network_time;
/*if (abs(app_vars.current_network_time - app_vars.compensated_time) > 5) {
leds_all_on();
} else {
leds_all_off();
}*/
// ----- then you calculate the new alpha
app_vars.local_delta = app_vars.current_local_time - app_vars.previous_local_time;
app_vars.network_delta = app_vars.current_network_time - app_vars.previous_network_time;
if (app_vars.previous_local_time == 0) {
app_vars.alpha = 1;
} else {
app_vars.alpha = app_vars.local_delta / app_vars.network_delta; // consider smoothening this value over time to reduce noise. Something like an exponential mooving average is easy to implement
// also consider ignoring alpha values that are too big or too small. Something line 1.001 or 0.999 is already strange
}
app_vars.previous_local_time = app_vars.current_local_time;
app_vars.previous_network_time = app_vars.current_network_time;
// ---- printing the values of differences between the calculaetd value and the network
app_vars.compensated_time_dbg = abs((app_vars.compensated_time)-(app_vars.current_network_time));
app_vars.uart_counterFrame[0] = app_vars.compensated_time_dbg;
app_vars.uart_counterFrame[1] = app_vars.compensated_time_dbg>>8;
app_vars.uart_counterFrame[2] = app_vars.compensated_time_dbg>>16;
app_vars.uart_counterFrame[3] = app_vars.compensated_time_dbg>>24;
app_vars.uart_counterFrame[4] = app_vars.compensated_time_dbg>>32;
app_vars.uart_counterFrame[5] = app_vars.compensated_time_dbg>>40;
app_vars.uart_counterFrame[6] = app_vars.compensated_time_dbg>>48;
app_vars.uart_counterFrame[7] = app_vars.compensated_time_dbg>>56;
app_vars.uart_done = 0;
app_vars.uart_counterByte = 0;
// send app_vars.uart_txFrame over UART
uart_clearTxInterrupts();
uart_enableInterrupts();
uart_writeByte(app_vars.uart_counterFrame[app_vars.uart_counterByte]);
while (app_vars.uart_done==0); // busy wait to finish
uart_disableInterrupts();
}
Any Help will be greatly appreciated.
Thank you
Kind regards
Yong Kim
#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;
} 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;
//ultrasound
volatile uint8_t trig;
volatile uint8_t echo;
//ASN
volatile uint64_t ASN;
volatile uint64_t num_asn;
volatile uint64_t alpha;
volatile uint64_t local_delta;
volatile uint64_t network_delta;
volatile uint64_t previous_network_time;
volatile uint64_t current_network_time ;
volatile uint64_t previous_local_time;
volatile uint64_t current_local_time;
volatile uint64_t compensated_time;
volatile uint64_t compensated_time_dbg;
} app_vars_t;
app_vars_t app_vars;
//=========================== prototypes ======================================
// radio
void cb_startFrame(PORT_TIMER_WIDTH timestamp);
void cb_endFrame(PORT_TIMER_WIDTH timestamp);
//ASN counter
void cb_asncounter(void);
// uart
void cb_uartTxDone(void);
//=========================== main ============================================
int mote_main(void) {
// clear local variables
memset(&app_vars,0,sizeof(app_vars_t));
// initialize board
board_init();
// initialising ultrasound
P2DIR |= 0x48; // Set P2.6/3 as output (1 = out, 0 = in)
P2OUT &= ~0x08; // Set P2.3 initially low - For trig
// Echo detection on falling edge
P2DIR &= ~0x80; // Set P2.7 as an input
P2OUT |= 0x80; // put P2.7 initially high
P2IE |= 0x80; // enable P2.7 interrupt
P2IFG &= ~0x80; // clear pin flag in advance
P2IES |= 0x80; // interrupt on falling edge
TACCTL0 = CCIE; // capture/compare interrupt enable
TACTL = TASSEL_1 | MC_1 | ID_2; // Select ACLK, 'counts up' mode, input divider (4)
TACCR0 += 18000; // 18000k@32kHz ~ 550 ms
// 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) {
if (app_vars.trig != 0){ // for timer
P5OUT ^= 0x10; // toggle red led
P2OUT ^= 0x08; // toggle P2.3 - trig
__delay_cycles(100); // delay ~ 20 us
P2OUT ^= 0x08;
__delay_cycles(144000); // delay 50 ms
P5OUT ^= 0x10;
app_vars.trig = 0; // clear flag
}
else if (app_vars.echo != 0){ // for echo
if (TAR < 1000){ // if detected before 30 ms
int j;
for (j=0; j<8; j++){ // flash blue led repeatedly
P5OUT ^= 0x40;
__delay_cycles(96000); // delay 20 ms
}
}
app_vars.echo = 0; // clear flag
}
/*
// 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
else if (app_vars.rxpk_buf[0] == 0x08){
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.current_network_time = (app_vars.ASN * 7.25)*1000000;
app_vars.current_local_time = app_vars.num_asn;
// ----- before calculating the new alpha and stuff you toggle led if error is too big
app_vars.compensated_time = (app_vars.current_local_time - app_vars.previous_local_time)*app_vars.alpha + app_vars.previous_network_time;
/* if (abs(app_vars.current_network_time - app_vars.compensated_time) > 5) {
leds_all_on();
} else {
leds_all_off();
}*/
// ----- then you calculate the new alpha
app_vars.local_delta = app_vars.current_local_time - app_vars.previous_local_time;
app_vars.network_delta = app_vars.current_network_time - app_vars.previous_network_time;
if (app_vars.previous_local_time == 0) {
app_vars.alpha = 1;
} else {
app_vars.alpha = app_vars.local_delta / app_vars.network_delta; // consider smoothening this value over time to reduce noise. Something like an exponential mooving average is easy to implement
// also consider ignoring alpha values that are too big or too small. Something line 1.001 or 0.999 is already strange
}
app_vars.previous_local_time = app_vars.current_local_time;
app_vars.previous_network_time = app_vars.current_network_time;
// ---- printing the values of differences between the calculaetd value and the network
app_vars.compensated_time_dbg = abs((app_vars.compensated_time)-(app_vars.current_network_time));
app_vars.uart_counterFrame[0] = app_vars.compensated_time_dbg;
app_vars.uart_counterFrame[1] = app_vars.compensated_time_dbg>>8;
app_vars.uart_counterFrame[2] = app_vars.compensated_time_dbg>>16;
app_vars.uart_counterFrame[3] = app_vars.compensated_time_dbg>>24;
app_vars.uart_counterFrame[4] = app_vars.compensated_time_dbg>>32;
app_vars.uart_counterFrame[5] = app_vars.compensated_time_dbg>>40;
app_vars.uart_counterFrame[6] = app_vars.compensated_time_dbg>>48;
app_vars.uart_counterFrame[7] = app_vars.compensated_time_dbg>>56;
app_vars.uart_done = 0;
app_vars.uart_counterByte = 0;
// send app_vars.uart_txFrame over UART
uart_clearTxInterrupts();
uart_enableInterrupts();
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;
}
}
//brief This function is called when the TimerA interrupt fires.
#pragma vector = TIMERA0_VECTOR
__interrupt void TIMERA0_ISR (void) {
app_vars.trig = 1; // raise trig flag
}
//brief This function is called when the P2.7 interrupt fires.
#pragma vector = PORT2_VECTOR
__interrupt void PORT2_ISR (void) {
app_vars.echo = 1; // raise echo flag
P2IFG &= ~0x80; // clear pin flag
}
#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;
} 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;
//ultrasound
volatile uint8_t trig;
volatile uint8_t echo;
//ASN
volatile uint64_t ASN;
volatile uint64_t num_asn;
volatile uint64_t alpha;
volatile uint64_t local_delta;
volatile uint64_t network_delta;
volatile uint64_t previous_network_time;
volatile uint64_t current_network_time ;
volatile uint64_t previous_local_time;
volatile uint64_t current_local_time;
volatile uint64_t compensated_time;
volatile uint64_t compensated_time_dbg;
} app_vars_t;
app_vars_t app_vars;
//=========================== prototypes ======================================
// radio
void cb_startFrame(PORT_TIMER_WIDTH timestamp);
void cb_endFrame(PORT_TIMER_WIDTH timestamp);
//ASN counter
void cb_asncounter(void);
// uart
void cb_uartTxDone(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();
// initialising ultrasound
P2DIR |= 0x08; // Set P2.3 as output (1 = out, 0 = in)
P2OUT &= ~0x08; // Set P2.3 low
TACCTL0 = CCIE; // capture/compare interrupt enable
TACTL = TASSEL_1 | MC_1 | ID_2; // Select ACLK, 'counts up' mode, input divider (4)
TACCR0 += 32768; // 18000k@32kHz ~ 550 ms
while (1) {
if (app_vars.trig != 0){ // if flag's been raised with alternation
leds_all_off();
P5OUT ^= 0x10; // toggle red led
P2OUT ^= 0x08; // toggle P2.3 - trig
__delay_cycles(96); // delay ~ 20 us
P2OUT ^= 0x08;
__delay_cycles(240000); // delay 50 ms
P5OUT ^= 0x10;
app_vars.trig = 0; // clear flag
}
// 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.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.current_network_time = (app_vars.ASN * 7.25)*1000000;
app_vars.current_local_time = app_vars.num_asn;
// ----- before calculating the new alpha and stuff you toggle led if error is too big
app_vars.compensated_time = (app_vars.current_local_time - app_vars.previous_local_time)*app_vars.alpha + app_vars.previous_network_time;
/*if (abs(app_vars.current_network_time - app_vars.compensated_time) > 5) {
leds_all_on();
} else {
leds_all_off();
}*/
// ----- then you calculate the new alpha
app_vars.local_delta = app_vars.current_local_time - app_vars.previous_local_time;
app_vars.network_delta = app_vars.current_network_time - app_vars.previous_network_time;
if (app_vars.previous_local_time == 0) {
app_vars.alpha = 1;
} else {
app_vars.alpha = app_vars.local_delta / app_vars.network_delta; // consider smoothening this value over time to reduce noise. Something like an exponential mooving average is easy to implement
// also consider ignoring alpha values that are too big or too small. Something line 1.001 or 0.999 is already strange
}
app_vars.previous_local_time = app_vars.current_local_time;
app_vars.previous_network_time = app_vars.current_network_time;
// ---- printing the values of differences between the calculaetd value and the network
app_vars.compensated_time_dbg = abs((app_vars.compensated_time)-(app_vars.current_network_time));
app_vars.uart_counterFrame[0] = app_vars.compensated_time_dbg;
app_vars.uart_counterFrame[1] = app_vars.compensated_time_dbg>>8;
app_vars.uart_counterFrame[2] = app_vars.compensated_time_dbg>>16;
app_vars.uart_counterFrame[3] = app_vars.compensated_time_dbg>>24;
app_vars.uart_counterFrame[4] = app_vars.compensated_time_dbg>>32;
app_vars.uart_counterFrame[5] = app_vars.compensated_time_dbg>>40;
app_vars.uart_counterFrame[6] = app_vars.compensated_time_dbg>>48;
app_vars.uart_counterFrame[7] = app_vars.compensated_time_dbg>>56;
app_vars.uart_done = 0;
app_vars.uart_counterByte = 0;
// send app_vars.uart_txFrame over UART
uart_clearTxInterrupts();
uart_enableInterrupts();
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;
}
}
//brief This function is called when the TimerA interrupt fires.
#pragma vector = TIMERA0_VECTOR
__interrupt void TIMERA0_ISR (void) {
app_vars.trig = 1; // raise flag
leds_all_on();
}