If your existing Host-NCP solution is lacking Green Power proxy support and you want to add it to the design these steps will walk you through the process of adding it.
First, go to the ZCL Clusters tab and find the Multiple endpoint configuration section at the top. Click the New button to add an endpoint to your device, this will create a second endpoint on the device with identifier 2. Now we need to convert this to a green power endpoint.
In the Configuration column, click the Primary name, which will bring up a button with 3 dots
Click the box to bring up the Endpoint type window
Select the option Create new endpoint type and name your new endpoint Green Power. Click OK.
Keeping the endpoint selected, go to the pull-down menu for ZCL Device Type and change the device to GP Proxy Basic (under GP devices). When this is selected, this will make the endpoint change to number 242. This should also enable Cluster 0x0021, the Green Power cluster, on the device.
Now go to the Plugins tab and on the search bar, enter Green – this will find 4 plugins in the Green Power section:
Check the box next to the Green Power Client and Green Power Common plugins, this will enable them. There isn't any need to change any of the default settings within the plugins, so you can leave those alone.
At this point you should be able to generate and build your host application with no issue and Green Power will be supported. However support for green power needs to be enabled within the NCP.
As you are configuring your NCP application, go to the plugins tab and enable the Green Power Stack Library plugin. Make sure the Green Power Stack Stub Library is disabled:
Since this is just a proxy, you can leave the settings as defaulted, proxy table size of 5 and sink table size of 0. However you will need to consider your potential network when configuring your table sizes. A larger proxy table might be needed for supporting all devices on the network.
This is all you need for NCP support. You can generate and build your NCP and combined with your new host code, green power proxy support should be ready to go.
What is the maximum allowed power for ZigBee applications under ETSI EN 300 328?
Although ETSI EN 300 328 allows 20dBm RF output power, there is a limitation for PSD (Power Spectral Density) for wide band modulations other than FHSS. This PSD limit restricts the maximum allowed power for ZigBee applications.
Section 22.214.171.124 in EN 300 328 V2.1.1 details the test method for PSD. The ZigBee modulated signal measured according to Option 2, Step 3 (with sweep time set to 10s):
CW signal with the same power level and spectrum analyzer settings:
The peak power difference between the ZigBee and CW signal measured with RMS detector is ~2.3dB. In order to meet the PSD limit of 10dBm per MHz, the maximum allowed power is 12.3dBm (EIRP).
Note: The 12.3dBm power limit is radiated (EIRP), which means that in case of an antenna with 0dBi, the maximum conducted power allowed is 12.3dBm. For antennas with lower gain than 0dBi, conducted power can be increased, while for antennas with higher gain than 0dBi, conducted power should be reduced.
Measurements were performed on an EFR32MG13 based reference board (BRD4158A Rev A01).
So now it’s time to make the physical interface for our light and switch. While being able to send and see messages go across the network is fun, since we are making a light and a switch, we should expect them to act like a light, turning a light source on and off and a switch, taking an input from a button press or similar signal.
First let’s turn our attention to the light, since a light turning on and off is an easier goal to observe. As we have noticed on our last step, we have been toggling one of our cluster attributes, specifically an on-off attribute. What we want is to have our device change based on this attribute’s value. One mechanism that we can use to handle this is through a callback.
A callback is a way that EmberZNet handles events throughout the stack code and application layer as well. If you click on the callbacks tab, you will see a number of calls that can be used throughout your code. These are generally broken down into application callbacks, plugin callbacks, stack callbacks, API callback and cluster callbacks. An in depth look at the callbacks is beyond the scope of this lesson.
For our light code, we are going to need to handle two events. First, at startup we need to enable our lights and configure them. Once that’s done we need to handle the toggling of the light based on the On/Off attribute.
To setup our light, we need to look at the section called “Non-cluster related.” All of these callbacks are in order. As you look down the list you will come across two callbacks Main Init and Main Start, both of these callbacks run at the start of our main() function. Main Init runs right after main executes, but before the network is setup, while Main Start runs right before our main loop executes, after the HAL is done configuring the hardware. In most cases it won’t matter where we set up our LED interface, so for this we will use Main Start, check the box for it.
Next, we need to figure out how to toggle our light on and off. Because this is tied to the on/off cluster, you want to go to the On/Off cluster under the General. Looking through the list, we can find the Server Attribute Changed callback. Since we are operating on the attribute value setting, this is perfect for our needs, check its box as well.
Before we leave this page, make sure at the bottom of your callbacks page you have the “Generate project-specific callbacks file” box checked. This will ensure your new callbacks file is generated for your application.
Before we click generate, we also need to configure all of our GPIOs to work as LEDs. The Thunderboard has 1 green LED, 1 red LED and 4 full color LEDs, for this project we are going to use the full color LEDs. If you read UG309 section 3.4.8, you will see all of the pin definitions, as well as an explanation of how the LEDs are setup.
Next, we need to launch Hardware Configurator (HWConf for short). If you look in your light project, you should see a file named brd4166a_efr32mg12p332f1024gl125.hwconf, this is your header file for your project. Double click on it and it should open in HWConf in the DefaultMode Port I/O. If it isn’t in that format, click that tab at the bottom of the DefaultMode Peripherals window. This view brings us to a graphical representation of the pins, it is where we will set our GPIOs to be available to us within our software.
Setting the GPIOs from within HWConf is fairly straight forward. First you need to go to the Outline view on the top right corner of Studio and open the Port I/O tree. Then click on the Port (A-K) you want to set, this will make those GPIOs become active on the graphical pin grid. Locate the pin you want to setup on the grid (be careful, the pin letters are easy to get confused with their grid identifiers) and click on them. You will then see the Properties of this pin on the middle right of Studio. If you click on the value area within Custom pin name, you will be able to give the pins a name, this will be how you identify the pin in your program.
For example: PJ14 is RGB_LED_ENABLE (note this is configured by default)
Do the same for the following pins – locations provided for easy locating:
Remember all of the names you give these pins.
Once this is done, save your HWConf file, this might take some time as it will generate some new hardware configurations. Then return to Simplicity IDE view and click on your MyLight.isc file. Click the Generate button. After some time you will get a validation window to appear. Make sure that all files on this window are checked, Studio will many times leave the *_callbacks.c file unchecked to not overwrite this. Once all the boxes are checked, click OK to continue.
Finally, it is time to put in some code to make our lights turn on and off. First, locate the callbacks file in your project list. It will be called PROJECTNAME_callbacks.c, in our case, this will be MyLight_callbacks.c, double click on it and the code in this file will appear. You will note that you should have 2 functions in the project: emberAfMainStartCallback and emberAfOnOffClusterServerAttributeChangedCallback.
First let's enable our lights. Since we need to enable our LEDs as our code starts, we will focus our attention to the emberAfMainStartCallback() function. As noted, this function is called right before our program initiates it's loop while it is running.
Now we will need a fuction to initialize our GPIOs, configuring them as output pins. You can look through docs.silabs.com and find the EMLIB section to discover a function to run this setup. To save you some time, the function you are looking for is:
void GPIO_PinModeSet (GPIO_Port_TypeDef port, unsigned int pin, GPIO_Mode_TypeDef mode, unsigned int out)
The function call for this is defined fully here. But we will step you through the function calls for easy reference.
The first two arguments are the port and pin that we want to configure. Because we have defined our pins in HWConf, you can use those names you assigned these pins in the GUI. They will be something like PIN_NAME_PORT and PIN_NAME_PIN, which correspond do the port letter and port number respectively. If you look in your project tree there is a folder called hal-config and in that folder you will find a file hal-config.h, this file contains the names of the ports and pins for easy reference, locate the section
// $[Custom pin names]
The next argument is how the pin is configured. Fortunately all of our GPIOs are set as outputs and our GPIO mode is going to be gpioModePushPull. A full list of pin options can be found here.
Finally because we are using these as output pins, the last argument is the desired initial state of the pin, either 0: off or 1: on.
So to set up RGB_LED_ENABLE, use the following:
GPIO_PinModeSet(RGB_LED_ENABLE_PORT, RGB_LED_ENABLE_PIN, gpioModePushPull, 1);
Do the same for all of your ports and pins. You should certainly make sure that RGB_LED_ENABLE is on at startup. If you want a particular color, the colored LEDs should be enabled as you want for the color you want to output, red, green or blue, or some combination of them all. LEDs 0-3 can be disabled or enabled, they are what we are going to use to turn on the LEDs.
One final warning the LEDs are quite bright, especially if you turn on all three for white, so be careful when looking at them. After doing so, you might decide you want to start with them off.
At this point you can re-compile your code and test to see if your lights come on. Once you have verified that your LEDs are working, you can then implement the on/off feature.
So now we will move down to the function emberAfOnOffClusterServerAttributeChangedCallback. This function is called anytime a server sided attribute on the light changes. It has two variables in its definition which are the endpoint that is being operated on by the change and the attribute itself which is being changed. In our case we want to change anytime we are seeing a call on our defined endpoint on the on/off attribute and change to the state which is set in that attribute. Despite only having a single endpoint in our project, you should wrap this call to make sure you are calling it on a particular endpoint, because you can then expand it to work for additional endpoint. Since our light functionality is our primary endpoint, you should compare the endpoint passed to this function against this. EmberZnet provides a means of getting this with the function emberAfPrimaryEndpoint(), this means we know that we are getting this called against the main light endpoint.
if (endpoint == emberAfPrimaryEndpoint())
Once we have done that, we need to make sure we are operating on the on/off attribute. First you should look at the file attribute-id.h. This file lists all of the attributes in your project and sets a number of defines for these attributes, using these your code will be much more readable. If you go to the section with the On/off cluster, you will see the ZCL_ON_OFF_ATTRIBUTE_ID, which matches that attribute ID. You can then do some comparison or switch statement and use that as the entry into your function.
if(attributeId == ZCL_ON_OFF_ATTRIBUTE_ID)
Now, we need a means of reading our attribute and turning the light on or off based on this attribute. Because this callback is made after the attribute has changed, we can read this attribute to get its state. To do this we will need to look through the documentation of EmberZNet. If you go to Docs.silabs.com, you can find the Ember Application framework API
On the left, if you click Ember Application Framework API Reference it will shows you the sections of the top-level API. At this point we just want the General Application Framework Interface. When you get this page, you will find the Attribute storage section listed at the very top. We are looking for some function to read an attribute, a little searching will find the function emberAfReadServerAttribute, a function that is doing exactly what we want, reading a server attribute, so copy that whole definition and paste it into your code.
EmberAfStatus emberAfReadServerAttribute (uint8_t endpoint, EmberAfClusterId cluster, EmberAfAttributeId attributeID, uint8_t *dataPtr, uint8_t readLength)
Because the function returns an EmberAfStatus, create one to catch the return value. We should only change our LED if the read was successful. You can return to the API guide and look up EmberAfStatus, you will find this is EMBER_ZCL_STATUS_SUCCESS.
if(readStatus == EMBER_ZCL_STATUS_SUCCESS)
Finally we need to make sure we properly read our attribute and change our LED, so go back to emberAfReadServerAttribute function call and let’s set it up properly. We know that our endpoint is the endpoint passed to our callback, so make sure this matches. The cluster ID is that for the on/off cluster. If you look at cluster-id.h, you will see that it is enumerated as ZCL_ON_OFF_CLUSTER_ID, so put that as the 2nd variable in the call. The attribute ID is again ZCL_ON_OFF_ATTRIBUTE_ID, so use that. Finally, we need something to catch the value of the data. I created a boolean type named onOff to catch this, the last two variables of the signature are a pointer to this variable and the size of that variable. In the end our full call looks something like this:
boolean onOff; EmberAfStatus readStatus; readStatus = emberAfReadServerAttribute(endpoint, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, &onOff, sizeof(onOff));
Now we can just use an if-else called against onOff to turn on or turn off our LED. The checking EMLIB again, we see that the function calls for this are:
Make the appropriate calls to the LEDs you want on and off within your code block, save and recompile your code. You can then reflash it to your “light” Thunderboard and use the switch to toggle it from the CLI. If you are able to turn the lights on and off, it’s time to move on to our switch to get it to toggle from the buttons.
In this tutorial we are going to be demonstrating how to build two simple Zigbee 3.0 applications for a light and a switch using Simplicity Studio on the Thunderboard Sense 2.
This project will start by building up a basic set of applications using AppBuilder which will start out as the framework for our light and switch. Then we will add some custom hardware definitions as well as some custom code and expand the base projects provided to tie the software in with the hardware.
When you are finished you will have a light application that controls the states of LEDs based on software attributes and you will have a switch which reacts to a button to send ZCL messages over the air to update the attributes of the light. Below you will find some basic instructions which walk you along the next few lessons as well as code examples and hardware configuration files to get you started.
Some prerequisites you will need for this tutorial:
Simplicity Studio 4 with the latest updates
EmberZNet 6.4.0 or later
Two Thunderboard Sense 2 boards (BRD4166A)
Two WSTKs (BRD4001A)
Two Mini-Simplicity connectors (BRD8010A) and the included 10 pin ribbon cable
You will also need easy access to Simplicity Commander's CLI interface. While it isn't the only way to program your chips, there are a few steps, like token programming, that require Commander.
The videos that went with the older lesson can be found here:
ZigBee Home Automation Developer Tutorial: Light and Switch Overview
ZigBee Home Automation - Light and Switch - part 1
ZigBee Home Automation - Light and Switch - part 2
ZigBee Home Automation - Light and Switch - part 3
ZigBee Home Automation - Light and Switch - part 4
ZigBee Home Automation - Light and Switch - part 5
ZigBee Home Automation - Light and Switch - part 6
ZigBee Home Automation - Light and Switch - part 7
ZigBee Home Automation - Light and Switch - part 8
ZigBee Home Automation - Light and Switch - part 9
ZigBee Home Automation - Light and Switch - part 10
ZigBee Home Automation - Light and Switch - part 11
ZigBee Home Automation - Light and Switch - part 12
We are now in the home stretch and ready to build our switch to work interfacing a button. The first thing we need to do is put some hooks into our project to give us a place to put our code.
If you remember back when you made the switch project, we enabled the Button Interface plugin, as the name suggests, this gives you an interface for buttons within our callbacks section. If you look at the callbacks tab, you will see these callbacks under the Plugin-specific callbacks. There are callbacks for different button states as well as long and short presses. For this example, let’s pick button 0 as it is generally clear of the ribbon cable on the Thunderboard. We also don’t need much more than a single button press, so let’s make use of the Button0 Pressed Short callback, check the box next to that identifier. *
* Quick note – a short press is by default defined as less than 250 mSec, you can look through the plugin code and the button timeout definition within the plugin to see how this is defined.
Like the light, make sure at the bottom of your callbacks page you have the “Generate project-specific callbacks file” box checked. This will ensure your new callbacks file is generated for your application. You can then save your .ISC file and hit generate to add this new callback. You will get a box that talks about overwriting files. Make sure your Project_callsbacks.c file is checked, you should also create backups, just in case. Then hit OK.
When you see the Generation Successful window, you’re ready to move to the next step.
Locate your project callbacks file on the left view titled Project Explorer and open the file in your editor. You will see that your callbacks file now includes a new, blank function named emberAfPluginButtonInterfaceButton0PressedShortCallback(). This function is called anytime the button is pressed for a short time.
Now we need to take our CLI calls and use this function to make these calls happen within this function. Looking back at our configuration, we send two commands via the CLI to send a message:
zcl on-off toggle
and then either
send 0 1 1
which sent our message outright to a node and endpoint we specified, or
which used a binding table entry to remove our need to know the exact device we were sending a message to.
First let’s look at zcl on-off toggle. To do this, we need something that will construct our message for us. We can look in the Application Framework reference guide and then refer to the Ember Application Framework API Reference and then the Application Framework Command Buffer Loading Interface. In here you will find a number of commands that will help load command or response buffers which can be sent out with some form of a send command.
If you search for the word ‘toggle’ through this document, it should find the function
which is a basic command which constructs our command buffer for us automatically. The benefit of this command is that it handled much of the overhead by utilizing the command buffer, making sending the message much easier later. So, add a call to this function to your button callback function.
Now we need to find a command to send our buffer over the air for us. So let’s return to the Application Framework and click over to the General Application Framework Interface and search for functions that deal with sending messages. On this page, you can search for the word messaging, which locates the function that deal with sending messages within the application framework. If you look through this section, there are a lot of functions which you can call.
You could use a function like emberAfSendUnicast. But this has a lot of parameters. And as we noted, the benefit we had about using the a FillCommand function is that the command buffer overhead has been handled for us. If you look down the list, you will find a number of functions that start out emberAfSendCommand… these are the functions we want to look at. Since this is a specific command send directly to a single node, you can use emberAfSendCommandUnicast(). This takes two options, the first is a messages type and the second is some sort of integer argument that differs based on what your message type is.
emberAfSendCommandUnicast (EmberOutgoingMessageType type, uint16_t indexOrDestination)
If you follow the link for the EmberOutgoingMessageType, you will see a number of different message types. EMBER_OUTGOING_DIRECT would allow you to send a message directly to a node id. Alternatively, a few lines down, you will find EMBER_OUTGOING_VIA_BINDING, which would allow you to leverage a previously made binding to send your message. Let’s take a look at each of these and you can pick the way you want to send your toggle.
If you choose to send a direct unicast to your node ID, this is the same operation as using the command send 0 1 1 to send your message. If you take a look at the send command’s help you will see the pieces you are providing with the numbers:
send (args) short id of the device to send the message to The endpoint to send the message from The endpoint to send the message to
Looking at the emberAfSendCommandUnicast function, your two options are a type and destination. In the case of using type EMBER_OUTGOING_DIRECT, the destination is our short ID of our target. As we noted before, you can use 0x0000 since this is a short id.
emberAfSendCommandUnicast (EMBER_OUTGOING_DIRECT, 0x0000);
This takes care of your node address. But we set our endpoints in the send command, and these are not yet handled. We need some function to configure the endpoints. And we need to configure this before we send our message otherwise it will be too late. Let’s return to the top level of the application framework and look around at operations that manipulate endpoints. If you search for the word endpoints, you will eventually come across the command emberAfSetCommandEndpoints(), which requires a source and destination endpoint. In our case we know both end points are 1, so you can hard code that if you would like, If you want, you can use emberAfPrimaryEndpoint() as the first argument because it’s the only endpoint of our device. However, in the case of the destination endpoint, you can only specify 1 as you need to hard code this.
Now you can test this out. Save your callbacks file and compile your code. Put this new application on your “switch” Thunderboard and press button 0, you should see your light turn on and off.
Alternative to sending a direct message to your node, you can leverage the fact that you have already created a binding and send directly to that. The advantage of this is that it already takes care of all of your settings like node address and endpoints. However, now you must know your binding entry to where you can send this to the on/off cluster.
So go to your console and enter the command ‘option binding-table print’ to display your binding table.
# type nwk loc rem clus node eui 0: UNICA 0 0x01 0x01 0x0003 0x0000 (>)000B57FFFEDEA263 1: UNICA 0 0x01 0x01 0x0006 0x0000 (>)000B57FFFEDEA263
The on-off cluster is 0x0006, so we want to send this to binding table entry 1. You can place this in as the second argument to your function:
emberAfSendCommandUnicast (EMBER_OUTGOING_VIA_BINDING, 1);
Like in _DIRECT format, now test this out. Save your callbacks file and compile your code. Put this new application on your “switch” Thunderboard and press button 0, you should see your light turn on and off.
In the end, this isn’t the cleanest code possible. Because this function is hard coded on the button, we are always sending our message. In the included MySwitch_callbacks.c file we have included some code that you can use to check that your network is currently up. We also have print statements to display sensible messages when your light or switch are operating.
Now that we have formed a network, it’s time to verify that we can successfully send messages between our light and switch. To do this will be using simple ZCL commands to start and
First click on the serial console of the switch. At the prompt enter:
zcl on-off toggle
This builds a Zigbee Clusters Library command frame. You can tell it was constructed correctly because of the output:
Msg: clus 0x0006, cmd 0x02, len 3 buffer: 01 00 02
Cluster 0x0006 corresponds to the on-off cluster.
Command 0x02 is the toggle command and length 3 corresponds to the length of the command buffer.
The buffer is 01 for the frame control, 00 for the sequence number and 02 for the command id for toggle.
Now we want to send this command to our light. Because our light is the coordinator, we know it’s Zigbee node ID is 0x0000. Because we want to send these commands from end point 1 on the switch and to endpoint 1 on the light our command to send this would be:
send 0 1 1
Hitting enter you will see on the light that it received a message for it’s 0x0006 cluster with command 02.
T00000000:RX len 3, ep 01, clus 0x0006 (On/off) FC 01 seq 00 cmd 02 payload
On the switch, you will see it received a message as well.
T00000000:RX len 5, ep 01, clus 0x0006 (On/off) FC 08 seq 05 cmd 0B payload[02 00 ]
This is a default response as it is sent back from the light to the switch.
If we look at App Builder, you can see these messages sent in the transaction view, a ZCL: Toggle followed by a ZCL: DefaultResponse. You can look at details of each message as they are sent on the side panel. For example, if you look within the event details of the the DefaultResponse, you can see that the response is Status: SUCCESS, meaning that the message was sent and properly handled.
Because our light is our network coordinator, we know that it’s address is 0x0000. However, most of the time we can’t trust that this will be the case. We need some sort of functionality to get our switch to look for and find our light and then join with the light so that it can easily send messages to the light instead of needing to know the address of the light. Additionally, the switch and light need some means of discovering if they share common clusters, like the off-off cluster. To assist with this, Zigbee provides finding & binding as a standard means of performing just this action.
If you remember back when we created our light and switch, we added a Find and Bind plugin to each device. The Light utilized the Find and Bind Target plugin while the Switch utilized the Find and Bind Initiator plugin. With these plugins, it makes finding and binding easy. Instead of having our light looking for ZCL messages doing endpoint discovery and having to manually construct a full set of ZCL messages to be sent across our network, asking for nodes to identify themselves as well as their endpoints and clusters and then binding like clusters, the plugins will take care of it all for us.
What we will first do is make the light a find and bind target for its endpoints. This will make it monitor network traffic and look for devices which are doing Find and Bind Initiation. To do this we will enter the following command:
plugin find-and-bind target 1
This tells endpoint 1 to act as an endpoint target. You will know the command works because you will see:
Find and Bind Target: Start target: 0x00
Now on the switch we must start it as an initiator. This is a similar function, but instead of target, we use:
plugin find-and-bind initiator 1
When you enter on this, you will see traffic in both the serial window as well as the network capture window as well. The process will be complete when you see
Find and Bind Initiator: Complete: 0x00
In the serial console.
Looking at the network traffic, you can see:
1. Our switch sends out a broadcast ZCL: IdentifyQuery. This is responded to by our light.
2. Then the switch asks the light for its full EUI64 address, the light responds to this with its EUI64.
3. Then finally the switch sends a simple descriptor request to get cluster information from the light. The light responds with 5 clusters which it is server: 0, 3, 4, 5 and 6 and no clusters which it is a client.
From this information our switch with then creates binding with clusters that it matches. For the 5 server clusters on the light, it looks to see if it is a client cluster on any of those, for the switch those are clusters 3 (identify) and 6 (on-off). So if you go to the CLI of the switch and print the binding table, you will see these new bindings, which are bound to the EUI64, not just the short ID. To print the binding table, use the following command:
option binding-table print
The output will look like this:
# type nwk loc rem clus node eui 0: UNICA 0 0x01 0x01 0x0003 0x0000 (>)000B57FFFEDEA263 1: UNICA 0 0x01 0x01 0x0006 0x0000 (>)000B57FFFEDEA263
With these bindings we can then use a bsend command to tell our device to send commands to a binding for a particular endpoint.
zcl on-off toggle bsend 1
This sends a command to our bindings on endpoint 1.
With this information, we can get to the step of making our light and switch act like a light and switch. The light will turn on or off LEDs based on attribute state, while our switch will respond to a button press instead of sending commands due to CLI entries.
First dock the Mini-Simplicity connectors onto your WSTKs are shown here:
Also connect your ribbon cable as shown. Then connect your Thunderboards on their corresponding 10 pin header. If your mini simplicity connectors do not have keyed headers, make sure to match your pin 1s of both 10 pin headers.
Since we are using Thurnderboards connected externally to our WSTKs, we must make sure our WSTKs are set to debug mode OUT. This can be done via commander. For each WSTK run the following command
commander adapter dbgmode OUT -s XXXXXXX
where XXXXXXX is the serial number of your WSTK.
This can also be performed within Studio from the Launcher perspective. Under the Debug Adapters pane near the top left, you should see the two boards/adapters show up as “J-Link Silicon Labs (4400xxxxx). Highlight each adapter and change the Debug Mode to “OUT”. If you are prompted to update the board firmware, please proceed with the update. Note that when the Debug Mode is OUT, Simplicity Studio does not know about the Thunderboard Sense 2 board anymore and this is expected. (WSTK main board is still recognized.)
Because neither of our applications will run without a bootloader, we want to create a bootloader for each. Fortunately, a default Gecko application bootloader will work for each board in this example.
To generate this bootloader:
Once your App Builder project opens, click the generate button to generate your project without any changes. Once the Generation successful window appears, you are done. Then use the Hammer icon on the toolbar to invoke your compiler and build your project. This will give you the binaries to flash onto your board. You will need to locate the file named -combined.s37, it should be located in your projects binary folder.
You should flash this application to each of your Thunderboards, making sure to erase each board as you do this. Because you are flashing an external part, it will ask you to use the device option (-d) to identify the part connected to your board, using EFR32 will be enough to proceed.
commander flash TB-app-BL-combined.s37 --masserase -s XXXXXXX -d EFR32
Once you have completed this, you will be ready to begin creating your projects.
Now it is time to build our projects for our light and switch. We will be modifying them over the course of a few steps to give them the features they require.
Our first step will be to create two blank projects, from these blank templates, we will start to add the pieces which are required for building a full Zigbee light and switch.
So, let’s get started:
After some time, Studio will display your newly created .ISC file, this will mean your project is ready for editing. Don't forget you need to create two projects, one for the light and one for the switch, so make sure to have both before you move on.
Unlike our bootloader, we will need to make some modifications to this application to build it, so let’s do this for our next step, starting with the light.
Once you have created your projects, it's time to use App Builder to configure the projects for the types of devices they are going to. As we introduce new parts of app builder, we will do our best to explain to you the pieces which you are using and hopefully educate you on making the best use of app builder.
Let's take a look at the MyLight.isc file. By default you should be on the General tab of your project. This gives some basic settings for your project, such as board, chip, and compiler. Below this is the Application configuration, which outlines the version of EmberZNet you are using and the location of the project. If you had an example project from the stack, this would give you a description of the operation of the application. And directly underneath this is multi-network configuration. This isn't something we will use today, but if you are looking for details, AN724 will outline multi-networking.
The next tab is the ZCL global tab. This is identification and versioning information for your part. You don't want to make any changes here for this project.
After this is the ZCL clusters tab, here is where we will make our first changes. On this tab you configure the ZCL elements of your device, namely your endpoints, the clusters which are enabled on your endpoints, and the attributes and commands that are supported by these clusters.
For our light device we only need a single endpoint, which is the default, but we need to pick a device type that will work for our needs. While you can build custom devices with whatever clusters and attributes you want supported, AppBuilder includes a number of ZCL device types which contain the preconfigured clusters and attributes which are normal for a particular device type. Since we are building a light, we can use a default device included with the stack, for this project find the LO On/Off Light Switch under the LO devices. This light definition has a number of default clusters for you, such as Basic, Identify, Groups, Scenes and On/Off. For this project we are going to focus on the On/Off cluster. But after you are done you can explore the other settings or even extend this light to be dimmable or color control, to add more functionality.
Moving to the Znet stack tab we will configure the Zigbee device and security level. This tab is where many of the Zigbee options are set. For the light, it will be a Coordinator/Router and utilize Zigbee 3.0 Security. These should be the default settings for this device, but if these settings aren’t correct they can be changed here. There are also some settings here for Radio configugration, ZDO and Inter-PAN settings, but they are beyond the scope of this project.
Proceeding to the Printing and CLI tab we find the configuration of Debug printing as well as the setup of the CLI. Debug printing allows you to add additional printing options beyond the ones that are supported by a standard application. The Cluster debugging includes print statements that are specific to the clusters enabled for your device. The General-purpose debug printing gives you additional printing within different aspects of your application, such as security or service discovery. You can even created your own custom messaging within this block. Along the bottom you will settings for customizing your CLI. In this section you can enable different CLI commands for your device beyond the standard ones which are included. For our needs, we are going to enable the On/off cluster printing along the top, so check box boxes next to this so that these print statements are compiled in and enabled at startup. But the normal CLI as it's built will be fine for our needs, so there are no changes needed for the bottom section.
The next tab is the HAL configuration tab. As noted, this is where some hardware settings are made. You want to be sure that your device is setup for the Application bootloader and that your part matches the board you are using (the BRD4162), but any other changes, we will make in a future step.
Finally, we need to configure the required plugins, which can be found on the corresponding tab. Plugins are the EmberZNet method to quickly enable or disable functionality supported by our application layer with a simple click of the button. For plugins, you should use all of the plugins which are included by default with the project and add the following: Network Creator, Network Creator Security, Find and Bind Target (all under ZigBee 3.0) and Security Link Keys Library (Stack Libraries).
Just to be safe, save your project to prevent anything from being lost. We aren't quite done yet, so don't hit the generate button just yet.
Now, let's open up MySwitch.isc and configure the Switch similar to the light. Since you know where to find these settings, they should be much easier to set up.
Like the light, your device will have 1 endpoint. But the ZCL device type will be an LO On/Off Light Switch.
It will utilize Zigbee 3.0 Security but will be an End Device. Don't make it a sleepy end device, you won't be able to get as much response from the CLI, and we need to be able to interact with the device as we make our settings.
For plugins, you should use all of the plugins which are included by default with the project and add the following: Find and Bind Initiator (ZigBee 3.0) and Button Interface (HAL).
Because the switch is an end device you can exchange the Zigbee PRO Stack Library Plugin for the Zigbee Pro Leaf Library. This is an optional step, but the leaf library removes many of the additional stack libraries which are only needed for routers and coordinators. The result is a smaller library which consumes less power. While we aren't using the sleepy end device, this would help you achieve a much lower current draw when your device sleeps.
Finally, located the Binding Table Library plugin. It has one option to configure – the size of the binding table, we need to make sure our table has at least 6 entries. We probably won't need this many entries, but we want to make sure we have them, just in case.
There is one final setting you need to make to both devices to make sure you can run the CLI. This involves making sure that the serial port is configured correctly.
On both mySwitch and myLight go back to the plugins tab and you want to make sure that the Serial plugin is enabled. From within the Serial plugin you need to ensure both SERIAL and USART0 are enabled (select each in the peripheral box). Finally, because the Thunderboard doesn’t support hardware flow control, we need to change the flow control type within the USART0 peripheral (in the serial plugin), make sure that Flow Control mode is set to Xon-Xoff.
Once you have configured both applications, you want to save each project.
Next, click the Generate button on each project. Just like our bootloader this will create or link to all of the files necessary to build the project. It shouldn't take too long, but you will have a few moments of waiting until the Generation successful window appears. Once you get that, click OK.
Finally, you can click the hammer icon on the toolbar
(or any other command that will begin building your application) and build your application. This will take a minute or two, depending on the speed of your computer. You can follow the progress in your Console window at the bottom. Once the files are compiled and linked, some post build scripts will run. If these run correctly you will get the following message:
Image-builder not invoked since "OTA Bootload Cluster Policy plugin" is not enabled 16:55:26 Build Finished (took 48s.142ms)
The key is the Image-builder message. Image-builder is run after your project compiles correctly. Once you see that, you know that your project has compiled successfully. Next we need to flash it to our device and test it.
If you get some sort of error during your build, return to your project .ISC file and check your work setting on your device and see if you missed any steps or have an incorrect setting.