Programming Style Guide

These are some practical advises about how to get the most of the Waspmote API libraries without using a high amount of the hardware resources.

1.Declaring variables using little memory
A method to avoid wasting memory is declaring variables using less memory. This can be done studying the variables and the value they can be assigned, selecting an appropriate type for each one.


Example of good programming method
{
	uint8_t var1=0;
	var1=23;
}

Example of bad programming method
{
	int var1=0;
	var1=5;
}

In the previous examples, 'var1' is declared as uint8_t and as integer. The difference between both types is that the first one only occupies 8bits and the second one occupies 32bits. If in our code, 'var1' is not going to take a value greater than 255 it has no sense declaring it as integer.

2.Using dynamic memory
If large data structures are going to be used a useful option to manage it is using dynamic memory.
We recommend to use the function 'calloc' to allocate our data structure and function 'free' to de-allocate it.


Example of use
{
	uint8_t* var1 = (uint8_t*) calloc(10,sizeof(uint8_t));
	free(var1);
}

In the previous example 'var' is declared as a pointer of uint8_t, allocating 10 elements of size uint8_t. This function initializes these positions with a zero value. After using the allocated elements we can free them.

3.Pointers and dynamic memory
When using pointers and dynamic memory, there is a little task to do after freeing memory. Function 'free' only makes available the previously reserved memory, but it doesn't change the pointer and where it is pointing. Due to this, it is recommended to change the pointer, pointing it to a NULL position to avoid future problems in loops.


Example of use
{
	uint8_t* var1 = (uint8_t*) calloc(10,sizeof(uint8_t));
	free(var1);
	var1=NULL;
}

4.Problems using function 'sprintf'
Function 'sprintf' can't be used more than once inside a global function or code will crash. This is a bad AVR compiler behavior no related with Waspmote API. If you want to use more than once, a possible solution is calling a function only for executing 'sprintf'.


Example of use
{
	void setup()
	{
 		 USB.begin();
	}

	char command[30];

	void loop()
	{
		sprintf(command,"%s%u,0","Hello!",8);
		auxFunction();
  	      USB.println(command);
   	     delay(2000);
	}

	void	auxFunction()
	{
		sprintf(command, "%s %s %u", command, "Bye!", 9);
	}
}

5.Memory problems using 'USB.print' or 'XBee.print'
We have to be careful using these kind of functions due to the amount of memory the compiler reserves for them.


Example of use
{
	XBee.print(“Test message!”);
	USB.println(“Test message!”);
}

The strings printed in the previous example occupy memory, so if many calls of these functions are done, memory may be completed and the code would crash.
To avoid this problem, the strings to print can be defined as 'define'.


Example of use
{
	#define  Message  “Test Message!”
	XBee.print(Message);
	USB.println(Message);
}

6.Freeing UART buffer after 'X' packets sent via XBee
Due to the UART buffer length, after many packets sent via XBee, this buffer must be flushed. So, a condition should be added in your main code to control this issue, making a call to 'Xbee.flush()' after many packets sent via XBee.

7.Dynamic memory sending XBee packets
To send packets using Waspmote API, a 'packetXBee' structure must be created.
Due to this structure occupies more than 500Bytes, it is recommended to use functions 'calloc' and 'free' to allocate the structure and after using it, free the reserved memory. The structure size is variable depending on data length, that can be modified inside Waspmote API.


Example of use
{
	packetXBee* paq_sent;
	paq_sent=(packetXBee*) calloc(1,sizeof(packetXBee));
	paq_sent->mode=UNICAST;
  	paq_sent->MY_known=0;
	paq_sent->packetID=0x52;
  	paq_sent->opt=0;
  	xbee802.hops=0;
  	xbee802.setOriginParams(paq_sent, "5678", MY_TYPE);
  	xbee802.setDestinationParams(paq_sent, "0013A20040558A2F", data, MAC_TYPE);
  	xbee802.sendXBee(paq_sent);
	free(paq_sent);
	paq_sent=NULL;
}

8.Dynamic memory receiving XBee packets
When a packet is received via XBee, some space is reserved in memory to store it. Due to this matter, after treating this packet, the reserved space must be freed. If the packets are not freed, the code will crash when no more memory is available.


Example of use
{
	xbee802.readXBee();
            while(xbee802.pos>0)
        	{
		// Treat the received packet

		free(xbee802.packet_finished[xbee802.pos-1]);
	          	xbee802.packet_finished[xbee802.pos-1]=NULL;
          		xbee802.pos--;
	}
}

9.Getting free memory
A function to get the available memory has been developed in Waspmote API. Due to similar problems as explained previously with 'sprintf', this function can generate problems depend on the rest of the functions used in main code. So, if you experiment problems while using it, follow the recommendations explained previously for 'sprintf'.


Example of use
{
	uint16_t memory=0;
	Utils.getFreeMemory();
	memory=Utils.freeMemory;
	USB.print(“Available free memory: “);
	USB.println(Utils.freeMemory);
}

© 2009 Libelium Comunicaciones Distribuidas S.L.

| Terms of use