| Author |
Message |
|
|
Posted: Feb 28, 2012 - 06:32 AM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
Hi,
I am trying to somehow synchronize a ZigBee network so that I can get all the nodes (except for the coordinator) to sleep at the same time and wake up at the same time (either through a timer or by IRQ).
From what I've read on other threads, a complete sync is impossible because there will be a difference in terms of cycles. I also read that routers were not designed to go to sleep, though it is possible but only by messing with the specifications which I attempt.
I have an idea on how to approach this problem but I need 2 questions answered before I can proceed:
1. I was wondering if there are any functions in BitCloud where I can request the number of children a certain router has.
I know there is a function that returns the number of max children a device can have but I want a specific amount of children on a specific router.
By knowing this, I can determine if a router should sleep or not. If a router has 0 children, I will make a request for it to sleep.
If it has any children, request for the children to sleep. This leads me to my second question.
2. Is there a way/function for a router to request its children to sleep?
So basically, there was be a sleep request going from bottom up to the coordinator until every node is asleep except for the coordinator. The coordinator will then initiate a wake up chain going from top down.
This is just an idea, I'm not even sure if it will work.
Thank you for your time! |
|
|
| |
|
|
|
|
|
Posted: Feb 28, 2012 - 02:22 PM |
|

Joined: Dec 08, 2010
Posts: 152
|
|
|
Quote:
1. I was wondering if there are any functions in BitCloud where I can request the number of children a certain router has.
Have a look at the ZDP Mgmt_Lqi_req.
Quote:
Is there a way/function for a router to request its children to sleep?
I guess not in the ZigBee standard, but you may just send a self defined goto-sleep message to children. And the children shall use the BitCloud SleepRequest function then.
Quote:
The coordinator will then initiate a wake up chain going from top down.
If a device is asleep it will not receive anything. So coordinator can't remote-wakup a device. |
|
|
| |
|
|
|
|
|
Posted: Feb 28, 2012 - 11:36 PM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
Thank you for your reply!
That is true...I forgot that sleeping devices cannot receive anything.
Ok, new idea.
By carefully defining each level of the network by programming different specifications for each level, I can request for the children of each node to sleep (of course the children of the nodes need to make sure they don't have children of their own before going into sleep mode).
Each level will have their own sleep period. The lowest level furthest away from the coordinator will have the longest sleep time while the routers closest to the coordinators will have the shortest sleep time.
That way when the end devices do wake up, they can expect their parents to be awake too.
Of course this also means that the batteries of the nodes closest to the routers will die faster than those at the lowest level.
Another problem with this is that new nodes that join the network need to be pre-assigned to a level in order to give it specific specifications, like its sleeping period.
Can I get your thoughts on this idea? |
|
|
| |
|
|
|
|
|
Posted: Feb 29, 2012 - 01:48 AM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
You are trying to abuse the standard, it will backfire sooner or later.
First of all by assigning different sleep times to different routers you will completely mess up their routing tables. |
_________________ The opinions and views expressed by me on this forum are my own and do not represent my employer or anyone else that I’m affiliated with.
|
| |
|
|
|
|
|
Posted: Feb 29, 2012 - 07:17 AM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
Man this is more complicated than I thought.
Once again thank you for your reply!
So to restate my goal:
I am trying to get the whole network, except the coordinator, to sleep and wake up at the same time. I know that the routers aren't designed to sleep but can by messing with the specifications which I attempt. Accomplishing this task will save a lot of battery life on both the routers and the end device.
I was wondering if you have any ideas or tips on how to make this goal possible?
I'm kind of out of ideas at the moment and wish to present one to my advisor and group members tomorrow. |
|
|
| |
|
|
|
|
|
Posted: Feb 29, 2012 - 04:05 PM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
Contact official support, I think Atmel states support for sleeping routers, I personally don't want to spend my time to support this, but they should.
Or read the documents, may be you'll find some description on how to do that.
My solution would be to use custom protocol on top of MAC or even plain RF-chip. |
_________________ The opinions and views expressed by me on this forum are my own and do not represent my employer or anyone else that I’m affiliated with.
|
| |
|
|
|
|
|
Posted: Mar 01, 2012 - 01:38 AM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
Alright thank you,
Quote:
First of all by assigning different sleep times to different routers you will completely mess up their routing tables.
What happens when you mess up the routing table?
My advisor told me that we (my group) should not care about the routing table since we're not using/referencing it. |
|
|
| |
|
|
|
|
|
Posted: Mar 01, 2012 - 01:44 AM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
| But stack uses it for routing. BitCloud is about 80 kB of code that you don't use directly, it does not mean you can throw it away. |
_________________ The opinions and views expressed by me on this forum are my own and do not represent my employer or anyone else that I’m affiliated with.
|
| |
|
|
|
|
|
Posted: Mar 01, 2012 - 03:43 AM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
I see.
Well I have contacted Atmel, stating my objective and asking for their input.
Just two more questions for clarification:
1. In general, does making a router go to sleep mess up the routing table in any ways?
2. What if the sleeping time differs on each node by, lets say, 1000 ms or 1 second. Would that mess up the routing tables still?
Once again, thank you for clarifying all of this!
It would of been a shame if my group spent hours working on my idea only to find out it messed up the routing table. |
|
|
| |
|
|
|
|
|
Posted: Mar 01, 2012 - 03:47 AM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
I don't know how sleeping routers are implemented in ZigBee and I don't want to know, to me it is abuse of a standard for a particular narrow task.
I don't know how the difference in sleep time might affect stack behavior. This is not only routing tables, there is a lot of stuff inside that might be affected.
LE: BTW, sleeping routers are not part of ZigBee specification, it is just a document by some task force group, which was not even accepted last time I've checked. |
|
|
| |
|
|
|
|
|
Posted: Mar 05, 2012 - 11:42 AM |
|

Joined: Jun 08, 2011
Posts: 84
|
|
|
Quote:
1. In general, does making a router go to sleep mess up the routing table in any ways?
I guess by putting the device to sleep you will lose the routing table entries, so after waking u need to do route discovery again(this will flood the air channel). Orelse you can save the routing table into EEPROM (persistent storage).
Quote:
2. What if the sleeping time differs on each node by, lets say, 1000 ms or 1 second. Would that mess up the routing tables still?
I think bitcloud developer guide from atmel will help you to understand this. There is a section describing the parent loss and child lost indications. Hope stack was written in such a way that once such lost indication appears it ll remove the entry from the network table. I am not sure how internal stack works. Alexru can help us better i guess. |
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2012 - 03:08 AM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
Thanks for the info firebee!
I think the topic is getting a bit sidetracked so I will try to go back on topic
I'm trying to send a message from the coordinator to the router (not router to end device anymore)
I start by editing the "WSNDemoApp.h" by adding
Code:
uint8_t message[65]; // Added by Me
in the section
Code:
typedef struct _AppMessage_t
{
uint8_t messageType;
uint8_t nodeType;
ExtAddr_t extAddr;
ShortAddr_t shortAddr;
uint32_t softVersion;
uint32_t channelMask;
PanId_t panID;
uint8_t workingChannel;
ShortAddr_t parentShortAddr;
uint8_t lqi;
int8_t rssi;
uint8_t message[65]; // Added by Me
//additional field
uint8_t boardType;//1
uint8_t sensorsSize;//1
struct {
int32_t battery;
int32_t temperature;
int32_t light;
} meshbean;
Then I go to the "WSNCoord.c" file, where I want the transmitting message to originate from, and added in these two code
Code:
outgoingMessage.data.message[0] = 0x05; // 1st byte
outgoingMessage.data.message[1] = 0x05; // 2nd byte
but only after globally declaring
Code:
AppMessageRequest_t outgoingMessage;
Finally I edit the "WSNRouter.c" file to abstract the bytes from the message:
Code:
void APS_DataIndRouter(APS_DataInd_t *indData)
{
indData = indData;
AppMessage_t *data = (AppMessage_t *) indData->asdu; // Added by Me
received_data[0] = data->message[0]; // 1st byte
received_data[1] = data->message[1]; // 1st byte
wdt_disable(); // Added by Me
if( (received_data[0] == 0xFF) && (received_data[1] == 0xFF) ) // Added by Me
{
wdt_enable(WDTO_15MS);
while(1);
}
}
but only after globally declaring
Code:
uint8_t received_data[2];
So the way I am testing to see if it works is if the message's first and second byte is 0xFF, then the router will do a soft reset. Else it will do nothing.
I purposely made the 1st and 2nd byte as 0x05 to make sure the router doesn't do anything.
Yet when I program the two boards to test out the code, the router resets.
My question is, what is wrong with my code?
I don't get how my "received_data[0]" and "received_data[1]" could both be 0xFF to make it go into the if-function.
This idea was taken from another thread on avrfreaks (http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=117475&start=0) along with Atmel telling me to read the messages in the APS_DataIndRouter() and APS_DataIndDevice() functions.
I tried to check the outputs using the WSNSensorManager.c file and WSNMonitor but that was a big fail.
Sorry for the lengthy post! |
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2012 - 03:16 AM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
| I don't see any problems with the code. Does statement "wdt_disable(); // Added by Me" means that WDT was also enabled before? Are you sure that reset is caused by a received frame? |
_________________ The opinions and views expressed by me on this forum are my own and do not represent my employer or anyone else that I’m affiliated with.
|
| |
|
|
|
|
|
Posted: Mar 11, 2012 - 05:00 AM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
It was never enabled, I thought I'd just put it there in case it was enabled when/if it does go into the if-function. So upon reset, I would disable it. Not sure if that makes sense hahaha
Anyways I got rid of "wdt_disble();", along with the rest of the added code listed above, and I was able to pinpoint the cause of the router resetting.
It is because of:
Code:
uint8_t message[65]; // Added by Me
in the "WSNDemoApp.h" file
I'm not sure why would cause the router to act that way.
When I comment out the code, the router acts normally (can be detected on WSNMonitor and does not reset).
When I uncomment the code, the router constantly resets.
What are you thoughts on this? |
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2012 - 05:11 AM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
You either really low on memory so stack override happens or something else is wrong in your code.
To rule out the first case post here build output (image size information) and try to reduce buffer size to see if it works with smaller values.
I'd also check USART-related part, you are increasing size of the structure that is also sent to the USART, some buffers might overflow there, but in this case problem should happen on the coordinator.
Note: APS_DataIndRouter() is called only when data that addressed to a router is received, you don't actually show code that sends this data. |
_________________ The opinions and views expressed by me on this forum are my own and do not represent my employer or anyone else that I’m affiliated with.
|
| |
|
|
|
|
|
Posted: Mar 11, 2012 - 07:39 AM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
Nice catch!
It was a memory problem! I reduced the vector from 65 to 2 and the router was back to normal! I guess I should play with the amount of elements to find the maximum value I can use.
Quote:
Note: APS_DataIndRouter() is called only when data that addressed to a router is received, you don't actually show code that sends this data.
I didn't know you had to address it to a router but it would make sense to.
So after reading another thread, I edited my "WSNCoord.c" code to include
Code:
messageParams.profileId = simpleDescriptor.AppProfileId;
messageParams.dstAddrMode = APS_SHORT_ADDRESS;
messageParams.dstAddress.shortAddress = 0xFFFF;
messageParams.dstEndpoint = 1;
messageParams.clusterId = CPU_TO_LE16(1);
messageParams.srcEndpoint = simpleDescriptor.endpoint;
messageParams.txOptions.acknowledgedTransmission = 0;
#ifdef _APS_FRAGMENTATION_
messageParams.txOptions.fragmentationPermitted = 1;
#endif
#ifdef _HIGH_SECURITY_
messageParams.txOptions.securityEnabledTransmission = 1;
#endif
messageParams.radius = 0x0;
outgoingMessage.data.message[0] = 0x05; // 1st byte
outgoingMessage.data.message[1] = 0x05; // 2nd byte
APS_DataReq(&messageParams);
And I globally defined:
Code:
extern APS_DataReq_t messageParams;
The code for the "WSNRouter.c" is now:
Code:
void APS_DataIndRouter(APS_DataInd_t *indData)
{
indData = indData;
AppMessage_t *data = (AppMessage_t *) indData->asdu; // Added by Me
received_data[0] = data->message[0]; // 1st byte
received_data[1] = data->message[1]; // 1st byte
if(received_data[0] == 0xFF) // Added by Me
{
BSP_OffLed(LED_GREEN);
}
}
Would this be the correct way to address the router? |
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2012 - 05:44 PM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
This way you address all devices in the network. To address specific device you need to put address of this device in the request.
I'd debug as bit more, in a basic configuration WSNDemo should not have memory problems with this message size. Application buffer overflows are still possible, of course. |
_________________ The opinions and views expressed by me on this forum are my own and do not represent my employer or anyone else that I’m affiliated with.
|
| |
|
|
|
|
|
Posted: Mar 11, 2012 - 10:02 PM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
Yes, for now I am only working with one router but I will eventually work with multiple ones and I want the coordinator to send the message to all of them in the network.
So I changed my code to
Code:
outgoingMessage.data.message[0] = 0xFF; // 1st byte
outgoingMessage.data.message[1] = 0xFF; // 2nd byte
So the router should be turning off its green LED but it isn't reacting to the coordinator's message. I don't think it is receiving the coordinator's message still.
So here is the current behavior description of the network:
1. Network is formed (both green LED's are on)
2. Coordinator sends data (represented by the boards red led being lit)
3. Router does not react (yellow led represents reading but does not turn on)
4. Router sends data (it's red LED turns on)
5. Coordinator reacts (yellow led turns on)
6. Coordinator sends data again
7. Router still does not react
8. Router sends data
9. Coordinator turns off its yellow led
10. Go back to step 2.
In summary, the yellow led on the router should be lit every time the coordinator tries to send it data, but it isn't.
Yet the yellow led on the coordinator reacts every time the router tries to send it data. I'm guessing it's "polling" or requesting for data from the coordinator. Another note is that the all LEDs are asynchronous to each other except for the coordinator's yellow led reacting to the router sending data.
What do you think the problem is? |
Last edited by bt0618 on Mar 11, 2012 - 10:16 PM; edited 1 time in total
|
| |
|
|
|
|
|
Posted: Mar 11, 2012 - 10:09 PM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
Status code in APS_DataConf() on the coordinator will indicate what the problem is.
LE: Post your complete code of the entire application. |
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2012 - 10:46 PM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
How do I check APS_DataConf(), should I output it onto WSNMonitor and observe its output?
The code is a bit lengthy so I uploaded it onto mediafire: http://www.mediafire.com/?93i572v4hyaoy83
Thank you for all your help so far! |
|
|
| |
|
|
|
|
|
Posted: Mar 11, 2012 - 10:50 PM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
|
bt0618 wrote:
How do I check APS_DataConf(), should I output it onto WSNMonitor and observe its output?
However you like. Use debugger if you have one, blink an LED, etc.
bt0618 wrote:
The code is a bit lengthy so I uploaded it onto mediafire:
You need to fill asduLength and APS_DataConf fields. |
|
|
| |
|
|
|
|
|
Posted: Mar 12, 2012 - 02:03 AM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
So I added:
Code:
messageParams.asduLength = sizeof(outgoingMessage.data);
messageParams.asdu = (uint8_t *)(&outgoingMessage.data);
into my code.
When I tried to do:
Code:
messageParams.APS_DataConf = APS_DataConf();
I get an error saying
Code:
C:\Users\...\Applications\WSNDemo\makefiles\STK600/../../src/WSNCoord.c:95: undefined reference to `APS_DataConf'
in the build console
Am I suppose to declare
Code:
static void APS_DataConf(APS_DataConf_t *confInfo);
at the top of "WSNCoord.c"? |
|
|
| |
|
|
|
|
|
Posted: Mar 12, 2012 - 02:07 AM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
|
bt0618 wrote:
When I tried to do:
Code:
messageParams.APS_DataConf = APS_DataConf();
Code:
messageParams.APS_DataConf = APS_DataConf;
And yes, you need to have this function declared. |
|
|
| |
|
|
|
|
|
Posted: Mar 12, 2012 - 03:02 AM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
Sorry alexru but I still get the same error
Here is my current "WSNCoord.c" code:
Code:
#ifdef _COORDINATOR_
#include <WSNDemoApp.h>
#include <WSNVisualizer.h>
extern AppMessageRequest_t appMessage;
extern APS_DataReq_t messageParams;
extern HAL_AppTimer_t deviceTimer;
extern bool subTaskRequested;
static void APS_DataConf(APS_DataConf_t *confInfo);
static void deviceTimerFired(void);
static void appSensorsesGot(void);
void appInitDeviceCoordinator(void);
// global variables
AppMessageRequest_t outgoingMessage;
void appCoordinatorTaskHandler(AppEvent_t event, void *param)
{
param = param; // warning prevention
switch (appDeviceState)
{
case READING_SENSORS_STATE:
switch (event)
{
case APP_PROCESS:
appReadLqiRssi();
appStartSensorManager();
appGetSensorData(appSensorsesGot);
break;
case APP_READING_DONE:
appDeviceState = SENDING_DEVICE_STATE;
appStopSensorManager();
appPostSubTaskTask();
break;
default:
break;
}
break;
case SENDING_DEVICE_STATE:
switch (event)
{
case APP_PROCESS:
visualizeSerialTx();
appSendMessageToUsart(&appMessage.data, sizeof(AppMessage_t));
/***********/
messageParams.profileId = simpleDescriptor.AppProfileId;
messageParams.dstAddrMode = APS_SHORT_ADDRESS;
messageParams.dstAddress.shortAddress = 0xFFFF;
messageParams.dstEndpoint = 1;
messageParams.clusterId = CPU_TO_LE16(1);
messageParams.srcEndpoint = simpleDescriptor.endpoint;
messageParams.asduLength = sizeof(outgoingMessage.data);
messageParams.asdu = (uint8_t *)(&outgoingMessage.data);
messageParams.txOptions.acknowledgedTransmission = 0;
#ifdef _APS_FRAGMENTATION_
messageParams.txOptions.fragmentationPermitted = 1;
#endif
#ifdef _HIGH_SECURITY_
messageParams.txOptions.securityEnabledTransmission = 1;
#endif
messageParams.radius = 0x0;
messageParams.APS_DataConf = APS_DataConf;
/***********/
outgoingMessage.data.message[0] = 0xFF; // 1st byte
outgoingMessage.data.message[1] = 0xFF; // 2nd byte
APS_DataReq(&messageParams);
/***********/
appDeviceState = STARTING_TIMER_STATE;
appPostSubTaskTask();
break;
default:
break;
}
break;
case STARTING_TIMER_STATE:
switch (event)
{
case APP_PROCESS:
HAL_StartAppTimer(&deviceTimer);
break;
case APP_TIMER_FIRED:
appDeviceState = READING_SENSORS_STATE;
appPostSubTaskTask();
break;
default:
break;
}
break;
case WAITING_DEVICE_STATE:
switch (event)
{
default:
appDeviceState = INITIAL_DEVICE_STATE;
appPostSubTaskTask();
break;
}
break;
case INITIAL_DEVICE_STATE:
switch (event)
{
case APP_PROCESS:
HAL_StopAppTimer(&deviceTimer);
deviceTimer.interval = APP_TIMER_SENDING_PERIOD;
deviceTimer.mode = TIMER_ONE_SHOT_MODE;
deviceTimer.callback = deviceTimerFired;
appDeviceState = READING_SENSORS_STATE;
appPostSubTaskTask();
break;
default:
break;
}
break;
default:
break;
}
}
void appInitDeviceCoordinator(void)
{
appDeviceState = INITIAL_DEVICE_STATE;
appPostSubTaskTask();
}
static void appSensorsesGot(void)
{
appCoordinatorTaskHandler(APP_READING_DONE, NULL);
}
static void deviceTimerFired(void)
{
appCoordinatorTaskHandler(APP_TIMER_FIRED, NULL);
}
void APS_DataIndCoord(APS_DataInd_t *indData)
{
visualizeAirRxFinished();
appSendMessageToUsart(indData->asdu, indData->asduLength);
}
#endif
|
|
|
| |
|
|
|
|
|
Posted: Mar 12, 2012 - 03:29 AM |
|


Joined: Apr 15, 2009
Posts: 4860
Location: San Jose, CA
|
|
You really need to read some book about C programming language.
You've defined a prototype, you also need to define function body:
Code:
static void APS_DataConf(APS_DataConf_t *confInfo)
{
//
}
|
_________________ The opinions and views expressed by me on this forum are my own and do not represent my employer or anyone else that I’m affiliated with.
|
| |
|
|
|
|
|
Posted: Mar 12, 2012 - 05:41 AM |
|

Joined: Feb 02, 2012
Posts: 25
|
|
I admit that I do need to sharpen up my programming skills. I usually work in a pre-built code environment and only do basic C coding.
I do sincerely apologize and thank you for all your help so far.
The good news is that everything works now.
The router reacts exactly how I expected it to.
Once again, thank you for all your help. |
|
|
| |
|
|
|
|
|