Wireless Connectivity Knowledge Base

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Wireless Connectivity Knowledge Base

Discussions

Sort by:
Bluetooth Low Energy offers the ability to broadcast data in format of non-connectable advertising packets while not being in a connection. This GAP Advertisement is widely known as a beacon and there are currently different beacon formats on the market.   This guide will help you to create your own beacon scanner to detect from which type of device is the beacon received from. This guide it’s based on the frdmkw41z_wireless_examples_bluetooth_temperature_collector_freertos  demo in MCUXpresso  The first thing we will do it’s to disable the low power to make the development easier in the app_preinclude.h /* Enable/Disable PowerDown functionality in PwrLib */ #define cPWR_UsePowerDownMode 0‍‍‍‍‍‍   The following changes will be all performed in the temperature_collector.c file We will disable the timer so it keeps scanning the packets received   /* Start advertising timer TMR_StartLowPowerTimer(mAppTimerId, gTmrLowPowerSecondTimer_c, TmrSeconds(gScanningTime_c), ScanningTimeoutTimerCallback, NULL); */‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍   Then we will define some of the data we want to use as a reference. static uint8_t NXPAd[3] = { /* Company Identifier*/ mAdvCompanyId, /* Beacon Identifier */ 0xBC }; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍   static uint8_t iBeaconAd[2] = { 0x4C, 0x00 };‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ static uint8_t EddyStoneUIDAd2[3] = { /* ID */ 0xAA, 0xFE, /* Frame Type */ 0x00 }; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍     static const uint8_t EddyStoneURLAd2[3] = { /* ID */ 0xAA, 0xFE, /* Frame Type */ 0x10 };‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍     static const uint8_t EddyStoneTLMAd2[3] = { /* ID */ 0xAA, 0xFE, /* Frame Type */ 0x20 };‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍   Once we have those definitions of the beacon structure of each of the types wanted we will change the function static bool_t CheckScanEvent(gapScannedDevice_t* pData) static bool_t CheckScanEvent(gapScannedDevice_t* pData) { uint8_t index = 0; bool_t foundMatch = FALSE; bool_t EddyfoundMatch = FALSE; while (index < pData->dataLength) { gapAdStructure_t adElement; adElement.length = pData->data[index]; adElement.adType = (gapAdType_t)pData->data[index + 1]; adElement.aData = &pData->data[index + 2]; /*DESIRED BEACON SCANNER PARSER CODE */ /* Move on to the next AD elemnt type */ index += adElement.length + sizeof(uint8_t); } if (foundMatch) { SHELL_NEWLINE(); shell_write("\r\Address : "); shell_writeHex(pData->aAddress, 6); } return foundMatch; }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍   As you can see, there is a comment in the function that mentions the need to add the scanner parser code, depending on the beacon you want to see  will be the code to use there  NXP if (FLib_MemCmp(NXPAD, (adElement.aData), 2)) { shell_write("\r\nFound NXP device!"); SHELL_NEWLINE(); shell_write("\r\nData Received: "); shell_writeHex(adElement.aData, adElement.length); foundMatch=TRUE; }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍   iBeacon if (FLib_MemCmp(iBeaconAd, (adElement.aData), 2)) { shell_write("\r\nFound iBeacon device!"); SHELL_NEWLINE(); shell_write("\r\nData Received: "); shell_writeHex(adElement.aData, adElement.length); foundMatch=TRUE; }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Eddystone if (FLib_MemCmp(EddyStoneUIDAd1, (adElement.aData), 2)) { shell_write("\r\nFound EddyStone device!"); if (!EddyfoundMatch) { EddyfoundMatch=TRUE; } else{ if(TRUE==EddyfoundMatch && FLib_MemCmp(EddyStoneUIDAd2, (adElement.aData), 3)) { SHELL_NEWLINE(); shell_write("\r\n[UID type] Data Received: "); shell_writeHex(adElement.aData, adElement.length); foundMatch=TRUE; EddyfoundMatch=FALSE; } else if(TRUE==EddyfoundMatch && FLib_MemCmp(EddyStoneURLAd2, (adElement.aData), 3)) { SHELL_NEWLINE(); shell_write("\r\n[URL type] Data Received: "); hell_writeHex(adElement.aData, adElement.length); foundMatch=TRUE; EddyfoundMatch=FALSE; } else if(TRUE==EddyfoundMatch && FLib_MemCmp(EddyStoneTLMAd2, (adElement.aData), 3)) { SHELL_NEWLINE(); shell_write("\r\n[TLM type] Data Received: "); shell_writeHex(adElement.aData, adElement.length); foundMatch=TRUE; EddyfoundMatch=FALSE; } else { EddyfoundMatch=TRUE; } } }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
View full article
The FRDM-KW36 comes with the OpenSDA circuit which allows users to program and debug the evaluation board. There are different solutions to support such OpenSDA circuits: 1. The J-Link (SEGGER) firmware.  2. The CMSIS-DAP (mbed) firmware. The FRDM-KW36 comes pre-programmed with the CMSIS-DAP firmware. However, if you want to update the firmware version, you need to perform the next steps.  Press and hold the Reset button (SW1 push button in the board).  Unplug and plug the FRDM-KW36 again to the PC.  The board will be enumerated as "DAPLINKBOOT" device. Drag and drop the binary file to update the OpenSDA firmware.  If the J-Link version is programmed, the board will be enumerated as "FRDM-KW36J". On the other hand, if the CMSIS-DAP version is programmed, the board will be enumerated as "FRDM-KW36". The binary for the J-link version can be downloaded from the next link: SEGGER - The Embedded Experts - Downloads - J-Link / J-Trace  The binary for the CMSIS-DAP version can be found in the next link: OpenSDA Serial and Debug Adapter|NXP    Hope this helps... 
View full article
Introduction The goal of this example is to demonstrate automatic role switching between Central and Peripheral of BLE QN9080 SIP and indicate the proximity of another BLE module using RSSI value. The automatic Role Switching feature can be used for continuously scan the presence of other BLE device and also to advertise so that other BLE device can scan it. The use case is to maintain social distancing and trigger a warning if the two devices are closer than a threshold distance. RSSI stands for Received Signal Strength Indicator which shows the power of received radio signal. Bare metal ‘Wireless_UART’ example is used from ‘SDK_2.x_QN908xCDK’ version 2.2.2 Timer Configuration As the device needs to switch its role after every particular time interval, so a timer is required to be initialized as it can be seen in below screenshot. Next step is to allocate Timer ID to the declared variable and start the timer. In this case, the timer shall go to callback function after the time(seconds) defined by the macro 'gSwitchTime'. This is done in 'BleApp_Config' function. After the specified time interval, timer stops and enters the callback function where switching of roles takes place. The main point that needs to be highlighted here is that while going into scanning mode, advertising mode should be stopped and vice versa. In advertising, the LED will be turned off. In scanning, the LED glows based on the RSSI. Central Configuration While in Central mode, device scans the presence of other bluetooth devices. Here, we need to check the RSSI value of received signals from those devices. There is a register available in QN9080 where the RSSI can be read after a received signal. RSSI is always negative, so the register stores the 2's compliment of the actual value. Below formula can be used to get the actual value of RSSI:- Actual RSSI = NOT(RSSI) + 1; This formula will give the positive value which is inversely proportional to Signal strength. In the callback function of scanning 'BleApp_ScanningCallback', filtering is applied and following decisions are taken based on filtered value:- Red LED will glow if the filtered value is lesser than a threshold value. Green LED will glow if the filtered value is greater than a threshold value. Hysteresis of 6 counts is taken to nullify the effect of fluctuation. As there is no need to make connections with the available devices, so the function requesting to make connection with the scanned device will be deleted. Peripheral Configuration Advertising interval can be changed as per requirement by making changes in the following macros:- To advertise at a fixed interval, value of minimum and maximum interval should be same. Test Setup Flash the code in two BLE EVK's. Power ON the EVK's. Red LED blinks if the EVK's are closer than a certain distance. Green LED blinks if the distance between the EVK's is greater than a threshold value. During blinking, When the LED is off, it means that the EVK is in advertising mode and when LED is ON(Red/Green), it means that EVK is in scanning mode. Note:- RSSI varies with environment, surrounding etc., so the threshold value of distance may vary with variation in testing condition. Demo code is attached for out of the box testing.
View full article
General summary MCUBOOT, fsci_bootloader and otap_bootloader are 3 different bootloader applications that can be used depending on the use case. The MCU Flashloader is a separate implementation but it's also mentioned to avoid misunderstanding.   MCUBOOT The MCU bootloader provides support for multiple communication protocols (UART, SPI, I2C, CAN) and multiple applications to interface with it. Summary: - It's a configurable flash programming utility that operates over a serial connection on several Kinetis MCUs. - Host-side command line (blhost) and GUI tools are available to communicate with the bootloader.  -  By default, application starts at address 0xa000. - MCU Bootloader|NXP website - MCU Bootloader Reference Manual - MCU Bootloader Demo Application User's Guide   fsci_bootloader Framework Serial Connectivity Interface (FSCI) is an NXP propietary protocol that allows interfacing the Kinetis protocol stack with a host system or PC tool using a serial communication interface. The FSCI bootloader enables the FSCI module to communicate with the PC and transfer the image using the FSCI protocol. Summary: - It relies on the FSCI protocol to transfer the binary from a PC connected via UART, using a python and C applications. - To enter into bootloader mode (in FRDM-KW41Z), hold SW1 (Reset) and press SW4, then release SW1 first and SW4 second. Please refer to demo user's guide to get the specific steps for your platform. - By default, application starts at 0x4000. - FSCI Bootloader Manual   otap_bootloader The Connectivity SDK contains Over-the-Air firmware upgrade examples. The OTAP bootloader loads an image obtained from wireless communication, the OTAP bootloader only enters after an image was successfully transferred to the client device (internal or external flash). Summary: - It's used by over the air programmed devices. - The bootloader mode only enters if a flag is set after reset triggered by a successful reception of an image over the air. - By default, application starts at 0x4000. - Kinetis Thread Stack Over-the-Air (OTA) Firmware Update User’s Guide   mcu_flashloader The MCU flashloader is a specific implementation of the MCU bootloader. For the flashloader implementation, the MCU bootloader command interface is packaged as an executable that is loaded from flash and executed from RAM. This configuration allows the user application to be placed at the beginning of the on-chip flash where it is automatically launched upon boot from flash. Using the MCU flashloader to program a user application to the beginning of the flash makes this implementation of the bootloader a one-time programming aid. The MCU flashloader doesn't allow to jump to a different section after a timeout or button press like the other bootloaders, it's main purpose is to flash an application without the need of an external debugger, mainly used for factory programming. Summary: - It is pre-programmed into many Kinetis flash devices during manufacturing and enables flash programming without the need for a debugger. - After the user application is programmed into flash memory, the Kinetis flashloader is no longer available. - Documentation: Getting Started with the MCU Flashloader   You can select from the MCU Bootloader, FSCI_Bootloader and OTAP Bootloader, depending on your needs. JC
View full article
Certification is the process of testing radio hardware to demonstrate that it meets the stated regulations in the country that it will operate in. A certification is needed generally when electronic hardware will be sold in a country, the certification requirements of that country must be met. If you require changes in your certificated hardware that will affects your RF performance, then you need to re-certificate the device. Most common regions and certification's institutes are (it applies for 2.4GHz & SubGHz): FCC for USA IC for Canada ETSI (CE) for Europe ARIB for Japan Other countries generally follow FCC or ETSI standars. The institute in charge of certifications depends on the region. It's the same institute to certificate your device in 2.4GHz or SubGHz in a certain region, the only difference are the articles of each institute to operate in the different frequencies. For operating in the 2.4GHZ band (worldwide): - In the U.S, CFR 47 FCC Part 15 203, 15.209 and 15.247 - In Canada, IC RSS-210 which closely follows FCC Part 15 - In EU, ETSI EN 300, 301 - In Japan, ARIB STD-T66 For SubGHz depends on the frequency you want to operate in. Taking Japan as an example: In Japan you can operate in the 920MHz band or in the 400MHz band for SubGHz. For both frequencies, ARIB is the institute in charge of the certifications but to operate in the 400MHz band the article that you will need is the ARIB STD-T67, and to operate in the 920MHz you will need to certificate your hardware with ARIB STD-T108 article. Freescale's MRB-KW019032 is certificated to operate in the following SubGHz ISM bands: The firmware used to certificate our KW products is the Radio Utility or the Connectivity Test, it allows the user in changing some RF parameters needed to pass the certification process. If you are thinking in certificate a product, contact an expert! There are Telecommunication Certification Body (TCB) companies which can give you guidance in the processes you need to follow to achieve a certification. To know more about FCC certification requirements and processes, refer to the reference manual “Freescale IEEE 802.15.4 / ZigBee Node RF Evaluation and Test Guidelines” in the Freescale's website. Best regards, Burgos. This document was generated from the following discussion: Certifications
View full article
The image below shows the different types of devices in a Thread Network. Router Routers provide routing services to network devices. Routers also provide joining and security services for devices trying to join the network. Routers are not designed to sleep. Routers can downgrade their functionality and become REEDs (Router-eligible End Devices). A Router can become a Leader and start a Thread network. Border Router A Border Router is a type of Router that provides connectivity from the 802.15.4 network to adjacent networks on other physical layers (for example, Wi-Fi and Ethernet). Border Routers provide services for devices within the 802.15.4 network, including routing services for off-network operations. There may be one or more Border Routers in a Thread Network. The Border Router also serves as an interface point for the Commissioner when the Commissioner is on a non-Thread Network; it requires a Thread interface and may be combined in any device with other Thread roles except the Joiner. Leader A Router or Border Router can assume a Leader role for certain functions in the Thread Network. This Leader is required to make decisions within the network. For example, the Leader assigns Router addresses and allows new Router requests. The Leader role is elected and if the Leader fails, another Router or Border Router assumes the Leader role. It is this autonomous operation that ensures there is no single point of failure. Router-eligible End Device REEDs have the capability to become Routers but due to the network topology or conditions these devices are not acting as Routers. These devices do not generally forward messages or provide joining or security services for other devices in the Thread Network. The Thread Network manages REEDs becoming Routers if necessary without user interaction. Sleepy End Device Sleepy end devices are host devices. They communicate only through their Parent Router and cannot forward messages for other devices References: Thread Whitepapers available at http://threadgroup.org 
View full article
In the process of practical application, customers often need the combination of ble + NFC. At present, our IOT-DK006 is the only development board with NFC module. But the NFC example is not perfect. So we porting the library of NFC reader- PN7150, to support KW series microcomputer so that KW series can handle the demand of ble + NFC function. Now I will introduce you how to port the NFC lib to KW. 1 PN7150 Introduction PN7150 is the high-performance version of PN7120, the plug’n play NFC solution for easy integration into any OS environment, reducing Bill of Material (BOM) size and cost. PN71xx controllers are ideal for home-automation applications such as gateways and work seamlessly with NFC connected tags. 2 Tools hardware:FRDM-KW36,PN7150 , some wire software:mcuxpresso11.3 package:NXP-NCI MCUXpresso example Project This package contains the nfc library and example that we need. We will refer the ‘NXPNCI-K64F_example’ firstly. Sdk version: 2.2.8, Example: frdmkw36_rtos_examples_freertos_i2c  3 Steps Hardware part:We need connect the PN7150 to KW36 like the picture. Although we can connect the PN7150 to board through the ardunio connector, the pin’s voltage is not enough to drive the PN7150. So we need a wire connected to U1 to get 3.3V.   PN7150 FRDM-KW36 VBAT/PVDD 3.3V VANT 5V GND GND IRQ PTA16 VEN PTC15 SCL PTB0,I2C0 SDA PTB1,I2C0 Software part:We should add the nfc library and directory into our project. You can check the following picture to know what file is necessary. If you want to know how to add directory into our project, you can refer this link. The red line shows what file we need. Please notice that when we add file path into the mcuxpresso configuration, we also need add the path into ‘Path and Symbols’ .   We need add some macro into ‘Preprocessor’.   We copy the NXPNCI-K64F_example’s main file content into our ‘freertos_i2c.c’. Next, we need modify the file pin_mux.c, tml.c and board.h   In file board.h,add the following macro. Don't forget to enable the pin clock. /* NXPNCI NFC related declaration */ #define BOARD_NXPNCI_I2C_INSTANCE I2C0 #define BOARD_NXPNCI_I2C_BAUDRATE (100000) #define BOARD_NXPNCI_I2C_ADDR       (0x28) #define BOARD_NXPNCI_IRQ_PORTIRQn PORTA_IRQn #define BOARD_NXPNCI_IRQ_GPIO     (GPIOA) #define BOARD_NXPNCI_IRQ_PORT     (PORTA) #define BOARD_NXPNCI_IRQ_PIN      (16U) #define BOARD_NXPNCI_VEN_GPIO     (GPIOC) #define BOARD_NXPNCI_VEN_PORT     (PORTC) #define NXPNCI_VEN_PIN            (5U)     In file pin_mux.c, add head file ‘board.h’. Add the following code in function ’ BOARD_InitPins’. The step is to configure the VEN, IRQ and I2C0. This example contains the I2C1’s code, you can comment them.     /* Initialize NXPNCI GPIO pins below */   /* IRQ and VEN PIN_MUX Configuration */   PORT_SetPinMux(BOARD_NXPNCI_IRQ_PORT, BOARD_NXPNCI_IRQ_PIN, kPORT_MuxAsGpio);   PORT_SetPinMux(BOARD_NXPNCI_VEN_PORT, NXPNCI_VEN_PIN, kPORT_MuxAsGpio);   /* IRQ interrupt Configuration */   NVIC_SetPriority(BOARD_NXPNCI_IRQ_PORTIRQn, 6);   EnableIRQ(BOARD_NXPNCI_IRQ_PORTIRQn);   PORT_SetPinInterruptConfig(BOARD_NXPNCI_IRQ_PORT, BOARD_NXPNCI_IRQ_PIN, kPORT_InterruptRisingEdge);   Finally, in file tml.c, modify PORTC_IRQHandler as PORTA_IRQHandler We finished all steps. 4 Results We use ntag to test the reading and writing operation.   When the tag is closed to the PN7150, we will get the following message.   The text recording is ‘VER=03’. Next, we will modify the text recording We need add the new macro to preprocessor.   We can modify the variable NDEF_MESSAGE in function task_nfc_reader to modify the text recording.   Then we download the program again. We will see the original text ‘VER=03’ and the text has been modified. Then we read the tag again. We will see the new text.   If we want to send the larger text, what should we do? We need modify the macro ‘ADD’. When only 4 characters are sent, ‘ADD’ is 0. And every additional character is added, the ‘ADD’ will add. We modify the tag as ‘Ver=03’, and we have two more characters. So ‘ADD’ needs to be defined as 2   It firstly shows the text ‘Test’. Then it will show the new text ‘Ver=03’. Other tags’ reading and writing operation can be enabled by defining some macro.      
View full article
This example of custom profile uses the Temperature Sensor and Temperature Collector examples as a base, so it can be easily modified. Both examples are in the SDK, so this document explains how to add the Humidity profile, and how to modify the code to get the Humidity Sensor and Collector working. Introduction Generic Attribute Profile (GATT) establishes in detail how to exchange all profile and user data over a BLE connection. GATT deals only with actual data transfer procedures and formats. All standard BLE profiles are based on GATT and must comply with it to operate correctly. This makes GATT a key section of the BLE specification, because every single item of data relevant to applications and users must be formatted, packed, and sent according to the rules. GATT defines two roles: Server and Client. The GATT server stores the data transported over the Attribute Protocol (ATT) and accepts Attribute Protocol requests, commands and confirmations from the GATT client. The GATT client accesses data on the remote GATT server via read, write, notify, or indicate operations. Notify and indicate operations are enabled by the client but initiated by the server, providing a way to push data to the client. Notifications are unacknowledged, while indications are acknowledged. Notifications are therefore faster, but less reliable.  GATT Database establishes a hierarchy to organize attributes. These are the Profile, Service, Characteristic and Descriptor. Profiles are high level definitions that define how services can be used to enable an application and Services are collections of characteristics. Descriptors defined attributes that describe a characteristic value.    To define a GATT Database several macros are provided by the GATT_DB API in the Freescale BLE Stack, which is part KW38 SDK. Server (Sensor)  First, we need to use the Temperature Sensor project as a base, to create our Humidity Custom Profile Server (Sensor). BLE SIG profiles To know if the Profile or service is already defined in the specification, you have to look for in Bluetooth SIG profiles and check in the ble_sig_defines.h file (${workspace_loc:/${ProjName}/bluetooth/host/interface) if this is already declared in the code. In our case, the service is not declared, but the characteristic of the humidity is declared in the specification. Then, we need to check if the characteristic is already included in ble_sig_defines.h. Since, the characteristic is not included, we need to define it as shown next:   /*! Humidity Charactristic UUID */ #define gBleSig_Humidity_d 0x2A6F   GATT Database The Humidity Sensor is going to have the GATT Server, because is going to be the device that has all the information for the GATT Client. On the Temperature Sensor demo have the Battery Service and Device Information, so you only have to change the Temperature Service to Humidity Service    In order to create the demo we need to define or develop a service that has to be the same as in the GATT Client, this is declared in the gatt_uuid128.h.If the new service is not the same, they will never be able to communicate each other. All macros, function or structure in SDK have a common template which helps the application to act accordingly. Hence, we need to define this service in the gatt_uuid128.h as shown next:    /* Humidity */ UUID128(uuid_service_humidity, 0xfe ,0x34 ,0x9b ,0x5f ,0x80 ,0x00 ,0x00 ,0x80 ,0x00 ,0x10 ,0x00 ,0x02 ,0x00 ,0xfa ,0x10 ,0x10)   All the Service and Characteristics is declared in gattdb.h. Descriptors are declared after the Characteristic Value declaration but before the next Characteristic declaration. In this case the permission is the CharPresFormatDescriptor that have specific description by the standard. The Units of the Humidity Characteristic is on Percentage that is 0x27AD. Client Characteristic Configuration Descriptor (CCCD) is a descriptor where clients write some of the bits to activate Server notifications and/or indications.   PRIMARY_SERVICE_UUID128(service_humidity, uuid_service_humidity) CHARACTERISTIC(char_humidity, gBleSig_Humidity_d, (gGattCharPropNotify_c)) VALUE(value_humidity, gBleSig_Humidity_d, (gPermissionNone_c), 2, 0x00, 0x25) DESCRIPTOR(desc_humidity, gBleSig_CharPresFormatDescriptor_d, (gPermissionFlagReadable_c), 7, 0x0E, 0x00, 0xAD, 0x27, 0x00, 0x00, 0x00) CCCD(cccd_humidity)   After that, create a folder humidity in the next path ${workspace_loc:/${ProjName}/bluetooth/profiles. Found the temperature folder, copy the temperature_service.c and paste inside of the humidity folder with another name (humidity_service.c). Then go back and look for the interface folder, copy temperature_interface.h and change the name (humidity_interface.h) in the same path. You need to include the path of the created folder. Project properties>C/C+ Build>Settings>Tool Settings>MCU C Compiler>Includes: Humidity Interface The humidity_interface.h file should have the following code. The Service structure has the service handle, and the initialization value.   /*! Humidity Service - Configuration */ typedef struct humsConfig_tag { uint16_t serviceHandle; int16_t initialHumidity; } humsConfig_t; /*! Humidity Client - Configuration */ typedef struct humcConfig_tag { uint16_t hService; uint16_t hHumidity; uint16_t hHumCccd; uint16_t hHumDesc; gattDbCharPresFormat_t humFormat; } humcConfig_t;   Humidity Service At minimum on humidity_service.c file, should have the following code. The service stores the device identification for the connected client. This value is changed on subscription and non-subscription events.   /*! Humidity Service - Subscribed Client*/ static deviceId_t mHums_SubscribedClientId;   The initialization of the service is made by calling the start procedure. This function is usually called when the application is initialized. In this case is on the BleApp_Config().   bleResult_t Hums_Start(humsConfig_t *pServiceConfig) { mHums_SubscribedClientId = gInvalidDeviceId_c; /* Set the initial value of the humidity characteristic */ return Hums_RecordHumidityMeasurement(pServiceConfig->serviceHandle, pServiceConfig->initialHumidity); }   On stop function, the unsubscribe function is called.   bleResult_t Hums_Stop(humsConfig_t *pServiceConfig) { /* Stop functionality by unsubscribing */ return Hums_Unsubscribe(); } bleResult_t Hums_Unsubscribe(void) { /* Unsubscribe by invalidating the client ID */ mHums_SubscribedClientId = gInvalidDeviceId_c; return gBleSuccess_c; }   The subscribe function will be used in the main file, to subscribe the GATT client to the Humidity service.   bleResult_t Hums_Subscribe(deviceId_t clientDeviceId) { /* Subscribe by saving the client ID */ mHums_SubscribedClientId = clientDeviceId; return gBleSuccess_c; }   Depending on the complexity of the service, the API will implement additional functions. For the Humidity Sensor only have a one characteristic. The measurement will be saving on the GATT database and send the notification to the client. This function will need the service handle and the new value as input parameters.   bleResult_t Hums_RecordHumidityMeasurement(uint16_t serviceHandle, int16_t humidity) { uint16_t handle; bleResult_t result; bleUuid_t uuid = Uuid16(gBleSig_Humidity_d); /* Get handle of Humidity characteristic */ result = GattDb_FindCharValueHandleInService(serviceHandle, gBleUuidType16_c, &uuid, &handle); if (result != gBleSuccess_c) return result; /* Update characteristic value */ result = GattDb_WriteAttribute(handle, sizeof(uint16_t), (uint8_t*) &humidity); if (result != gBleSuccess_c) return result; Hts_SendHumidityMeasurementNotification(handle); return gBleSuccess_c; }   After save the measurement on the GATT database with GattDb_WriteAttribute function we send the notification. To send the notification, first have to get the CCCD and after check if the notification is active, if is active send the notification.   static void Hts_SendHumidityMeasurementNotification ( uint16_t handle ) { uint16_t hCccd; bool_t isNotificationActive; /* Get handle of CCCD */ if (GattDb_FindCccdHandleForCharValueHandle(handle, &hCccd) != gBleSuccess_c) return; if (gBleSuccess_c == Gap_CheckNotificationStatus (mHums_SubscribedClientId, hCccd, &isNotificationActive) && TRUE == isNotificationActive) { GattServer_SendNotification(mHums_SubscribedClientId, handle); } }   Humidity Sensor Main file There are some modifications that have to be done, to use the new Humidity profile in our sensor example. First, we need to declare the humidity service:   static humsConfig_t humsServiceConfig = {(uint16_t)service_humidity, 0};   Then, we need to add or modify the following functions: BleApp_Start You need to modify this line:   /* Device is connected, send humidity value */ BleApp_SendHumidity();   BleApp_Config You need to start the Humidity Service, and to modify the PrintString line:   humsServiceConfig.initialHumidity = 0; (void)Hums_Start(&humsServiceConfig);     AppPrintString("\r\nHumidity sensor -> Press switch to start advertising.\r\n");   BleApp_ConnectionCallback There are some modifications required in two Connection Events. gConnEvtConnected_c   (void)Hums_Subscribe(peerDeviceId); gConnEvtDisconnected_c   gConnEvtDisconnected_c   (void)Hums_Unsubscribe();   BleApp_GattServerCallback   /* Notify the humidity value when CCCD is written */ BleApp_SendHumidity()   BleApp_SendHumidity And, we need to add this function:   static void BleApp_SendHumidity(void) { (void)TMR_StopTimer(appTimerId); /* Update with initial humidity */ (void)Hums_RecordHumidityMeasurement((uint16_t)service_humidity, (int16_t)(BOARD_GetTemperature())); #if defined(cPWR_UsePowerDownMode) && (cPWR_UsePowerDownMode) /* Start Sleep After Data timer */ (void)TMR_StartLowPowerTimer(appTimerId, gTmrLowPowerSecondTimer_c, TmrSeconds(gGoToSleepAfterDataTime_c), DisconnectTimerCallback, NULL); #endif }   In this example, the Record Humidity uses the BOARD_GetTemperature, to use the example without any external sensor and to be able to see a change in the collector, but, in this section would be a GetHumidity function. Client (Collector)  First, we need to use the Temperature Collector project as a base, to create our Humidity Custom Profile Client (Collector). BLE SIG profiles The same applies for the Client. To know if the Profile or service is already defined in the specification, you have to look for in Bluetooth SIG profiles and check in the ble_sig_defines.h file (${workspace_loc:/${ProjName}/bluetooth/host/interface) if this is already declared in the code. In our case, the service is not declared, but the characteristic of the humidity is declared in the specification. Then, we need to check if the characteristic is already included in ble_sig_defines.h. Since, the characteristic is not included, we need to define it as shown next:   /*! Humidity Charactristic UUID */ #define gBleSig_Humidity_d 0x2A6F   GATT Database The Humidity Collector is going to have the GATT client; this is the device that will receive all information from  the GATT server. Demo provided in this post works like the Temperature Collector. When the Collector enables the notifications from the sensor, received notifications will be printed in the serial terminal. In order to create the demo we need to define or develop a service that has to be the same as in the GATT Server, this is declared in the gatt_uuid128.h.If the new service is not the same, they will never be able to communicate each other. All macros, function or structure in SDK have a common template which helps the application to act accordingly. Hence, we need to define this service in the gatt_uuid128.h as shown next:   /* Humidity */ UUID128(uuid_service_humidity, 0xfe ,0x34 ,0x9b ,0x5f ,0x80 ,0x00 ,0x00 ,0x80 ,0x00 ,0x10 ,0x00 ,0x02 ,0x00 ,0xfa ,0x10 ,0x10)   After that, copy the humidity profile folder from the Sensor project, to the Collector project ${workspace_loc:/${ProjName}/bluetooth/profiles. And also for this project, include the path of the new folder. Project properties>C/C+ Build>Settings>Tool Settings>MCU C Compiler>Includes: Humidity Collector Main file In the Collector source file, we need to do also some modifications, to use the Humidity Profile. First, we need to modify the Custom Information of the Peer device:   humcConfig_t humsClientConfig;   BleApp_StoreServiceHandles   static void BleApp_StoreServiceHandles ( gattService_t *pService ) { uint8_t i,j; if ((pService->uuidType == gBleUuidType128_c) && FLib_MemCmp(pService->uuid.uuid128, uuid_service_humidity, 16)) { /* Found Humidity Service */ mPeerInformation.customInfo.humsClientConfig.hService = pService->startHandle; for (i = 0; i < pService->cNumCharacteristics; i++) { if ((pService->aCharacteristics[i].value.uuidType == gBleUuidType16_c) && (pService->aCharacteristics[i].value.uuid.uuid16 == gBleSig_Humidity_d)) { /* Found Humudity Char */ mPeerInformation.customInfo.humsClientConfig.hHumidity = pService->aCharacteristics[i].value.handle; for (j = 0; j < pService->aCharacteristics[i].cNumDescriptors; j++) { if (pService->aCharacteristics[i].aDescriptors[j].uuidType == gBleUuidType16_c) { switch (pService->aCharacteristics[i].aDescriptors[j].uuid.uuid16) { /* Found Humidity Char Presentation Format Descriptor */ case gBleSig_CharPresFormatDescriptor_d: { mPeerInformation.customInfo.humsClientConfig.hHumDesc = pService->aCharacteristics[i].aDescriptors[j].handle; break; } /* Found Humidity Char CCCD */ case gBleSig_CCCD_d: { mPeerInformation.customInfo.humsClientConfig.hHumCccd = pService->aCharacteristics[i].aDescriptors[j].handle; break; } default: ; /* No action required */ break; } } } } } } }   BleApp_StoreDescValues   if (pDesc->handle == mPeerInformation.customInfo.humsClientConfig.hHumDesc) { /* Store Humidity format*/ FLib_MemCpy(&mPeerInformation.customInfo.humsClientConfig.humFormat, pDesc->paValue, pDesc->valueLength); }   BleApp_PrintHumidity   /*www.bluetooth.com/specifications/assigned-numbers/units */ if (mPeerInformation.customInfo.humsClientConfig.humFormat.unitUuid16 == 0x27ADU) { AppPrintString(" %\r\n"); } else { AppPrintString("\r\n"); }   BleApp_GattNotificationCallback   if (characteristicValueHandle == mPeerInformation.customInfo.humsClientConfig.hHumidity) { BleApp_PrintHumidity(Utils_ExtractTwoByteValue(aValue)); }    CheckScanEvent   foundMatch = MatchDataInAdvElementList(&adElement, &uuid_service_humidity, 16);   BleApp_StateMachineHandler mAppIdle_c   if (mPeerInformation.customInfo.humsClientConfig.hHumidity != gGattDbInvalidHandle_d)   mAppServiceDisc_c   if (mPeerInformation.customInfo.humsClientConfig.hHumDesc != 0U) mpCharProcBuffer->handle = mPeerInformation.customInfo.humsClientConfig.hHumDesc;   mAppReadDescriptor_c   if (mPeerInformation.customInfo.humsClientConfig.hHumCccd != 0U)   BleApp_ConfigureNotifications   mpCharProcBuffer->handle = mPeerInformation.customInfo.humsClientConfig.hHumCccd;   Demonstration Now, after connection, every time that you press the SW3 on KW38 Humidity Sensor is going to send the value to KW38 Humidity Collector.  
View full article
QTool is a PC software tool that works with QN9080 USB dongle to assist in the development of BLE projects with the QN9080. You control the dongle via the QTool software, which issues and receives FSCI (Framework Serial Communication Interface) formatted commands over a virtual COM port. The dongle can then act either as a master or a slave to a QN9080DK board over BLE.  Before using the BLE dongle with QTool though, the firmware on the QN9080 Dongle must be updated. The updated firmware can be found inside the QTool installation directory, and you will need to put the dongle into bootloader mode to drag-and-drop new firmware on it. Updating the Firmware on the QN9080 Dongle. 1. Install QTool: https://www.nxp.com/webapp/sps/download/license.jsp?colCode=Connectivity-QTool-Setup   2. Plug the QN9080 Dongle into a USB port on your computer 3. Using a wire, connect TP5 to ground. You can use either TP4 or the USB shield for GND. 4. While that wire is connected, press the reset button on the dongle. This will now put the dongle into bootloader mode. 5. A drive will enumerate on your computer named “CRP_DISABLD”     6. You can now remove the wire 7. Delete the firmware.bin file found in that drive 8. Drag-and-drop the firmware.bin file found in C:\NXP\Connectivity QTool\bin files into that enumerated drive. 9. Once done copying, unplug and replug in the USB Dongle, and the new firmware will now be running.  Installing the QN9080 Dongle Driver The dongle will enumerate as a USB CDC COM device. If the CDC driver is not automatically detected, you will need to manually install the driver. 1. Right-click Computer and choose Properties, the System Management window appears. 2. Click Device Manager and navigate to MCU VIRTUAL COM DEMO      3. Right-click the device MCU VIRTUAL COM DEMO and choose Update Driver Software 4. Click the  Browse my computer for driver software option in the window. 5. Click Browse button to go to the folder  C:\NXP\Connectivity QTool\drivers 6. Click the Next button at the bottom to install the driver.  7. After the driver is installed you will see the Virtual Com Port device under the Ports category    Using QTool: Now that the QN9080 dongle has the updated firmware and has the correct driver installed, you can follow the instructions in the QTool documentation found at C:\NXP\Connectivity QTool\UM11085.pdf Related documentation: QN908x Quick Start Guide QN908x DK User's Guide
View full article
Introduction   This post explains how to create a BLE GATT database using FSCI commands sent to the BLE Server device. Additionally, this document explains how to set up the fields of each FSCI command used to create the BLE GATT database for the BLE Server.   Main FSCI commands to create the BLE GATT DB in the BLE Server device   The following, are the main commands to create, write and read the GATT DB from the BLE Server perspective. The purpose of this post is to serve as a reference and summary of the most important commands. The full list of commands FSCI commands can be found in the Framework Serial Connectivity Interface (FSCI) for Bluetooth Low Energy Host Stack documentation within your SDK package. GATT-InitRequest This command is used to initialize the GATT database at runtime, and it must be sent before any other command to declare a database in your BLE Server device. GATTServer-RegisterCallback.Request This command installs an application callback for the GATT Server module, enabling the device to respond to the FSCI request from the CPU application through an FSCI indication. GATTDBDynamic-AddPrimaryServiceDeclaration.Request It adds a primary service to the database. It has 3 parameters that should be configured, the desired handle, the UUID type (16 bits, 32 bits, 128 bits), and the UUID value. Usually, the desired handle should be set to zero and the stack will assign the handle of the primary service automatically.   If the GATT application callback was installed through the GATTServer-RegisterCallback.Request command, the GATT Server responds to the GATTDBDynamic-AddPrimaryServiceDeclaration.Request command with a GATTDBDynamic-AddPrimaryServiceDeclaration.Indication that contains the handle assigned to the primary service. The following example shows how to prepare this command to define the battery service in the database. GATTDBDynamic-AddCharacteristicDeclarationAndValue.Request It adds a characteristic and its value to the database. It has 7 parameters that should be configured, the UUID type (16 bits, 32 bits, 128 bits), the UUID value, characteristic properties, the maximum length of the value (only for variable-length values), the initial length of the value, the initial value of the characteristic and value access permissions. The characteristic declared using this command, belongs to the last primary service declared in the database. For values with a fixed length, the maximum length parameter should be set to 0, and the length is obtained from the initial length of the value parameter.   If the GATT application callback was installed, the response of this command is indicated by the GATTDBDynamic-AddCharacteristicDeclarationAndValue.Indication command. The following example shows how to prepare this command to define the battery level characteristic in the database with a fixed length of 1 byte and an initial value of 90%. GATTDBDynamic-AddCharacteristicDescriptor.Request It adds a characteristic descriptor to the database. It has 5 parameters that should be configured, the UUID type (16 bits, 32 bits, 128 bits), UUID value, length of the descriptor value, descriptor’s value, and descriptor access permissions. The descriptor declared using this command, belongs to the last characteristic declared in the database.   If the GATT application callback was installed, the response of this command is indicated by the GATTDBDynamic-AddCharacteristicDescriptor.Indication command. The following example shows how to prepare this command to add the characteristic presentation format descriptor of the battery level characteristic in the database.   GATTDBDynamic-AddCccd.Request It adds a CCDD into the database. This command does not have parameters. The CCCD declared using this command, belongs to the last characteristic declared in the database. The response of this command is indicated by GATTDBDynamic-AddCccd.Indication.   GATTDB-FindServiceHandle.Request This command is used to find the handle of a service previously declared in the database. It has 3 parameters that should be configured, the handle to start the search (should be 1 on the first call), the UUID type of the service to find (16 bits, 32 bits, 128 bits), and the UUID value of the service that you are searching.   If the GATT application callback was installed, the response of this command is indicated by the GATTDB-FindServiceHandle.Indication command, which contains the handle of the found service. The following example shows how to prepare this command to find the handle of the battery service declared in the previous examples. Notice that the result of the search corresponds to the handle returned by the GATTDBDynamic-AddPrimaryServiceDeclaration.Indication as expected.   GATTDB-FindCharValueHandleInService It finds the characteristic´s handle of a given service previously declared in the database. It has 3 parameters that should be configured, the handle of the service that contains the characteristic, the UUID type of the characteristic to find (16 bits, 32 bits, 128 bits), and the UUID value of the characteristic that you are searching for.   If the GATT application callback was installed, the response of this command is indicated by the GATTDB-FindCharValueHandleInService.Indication command, which contains the handle of the found characteristic’s value. The following example shows how to prepare this command to find the handle of the battery level value. Notice that the result of the search corresponds to the handle returned by the GATTDBDynamic-AddCharacteristicDeclarationAndValue.Indication plus one, because the AddCharacteristicDeclarationAndValueIndication command returns the handle of the characteristic and, on the other hand, FindCharValueHandleInService returns the handle of the characteristic’s value. GATTDB-FindDescriptorHandleForcharValueHandle.Request It finds the descriptor´s handle of a given characteristic previously declared in the database. It has 3 parameters that should be configured, the handle of the characteristic’s value that contains the descriptor, the UUID type of the descriptor to find (16 bits, 32 bits, 128 bits), and the UUID value of the descriptor that you are searching.   If the GATT application callback was installed, the response of this command is indicated by the GATTDB-FindDescriptorHandleForCharValueHandle.Indication command, which contains the handle of the found descriptor. The following example shows how to prepare this command to find the handle of the characteristic presentation format descriptor. The result corresponds to the handle returned by the GATTDBDynamic-AddCharacteristicDescriptor.Indication   GATTDB-FindCccdHandleForCharValueHandle.Request It finds the CCCD’s handle of a given characteristic previously declared in the database. It has only one parameter, the handle of the characteristic’s value that contains the CCCD.   If the GATT application callback was installed, the response of this command is indicated by the GATTDB-FindCccdHandleForCharValueHandle.Indication command, which contains the handle of the found CCCD. The following example shows how to prepare this command to find the handle of CCCD. The result corresponds to the handle returned by the GATTDBDynamic-AddCccd.Indication.   GATTDB-WriteAttribute.Request It writes the value of a given attribute from the application level. It has 3 parameters that should be configured, the handle of the attribute that you want to write, the length of the value in bytes, and the new value.   In the following example, we will modify the battery level characteristic’s value from 90% to 80%.   GATTDB-ReadAttribute.Request   It reads the value of a given attribute from the application level. It has 2 parameters that should be configured, the handle of the attribute that you want to read, and the maximum bytes that you want to read. The GATT application callback must be installed, since the response of this command indicated by the GATTDB-ReadAttribute.Indication command contains the value read from the database. In the following example, we will read the battery level characteristic’s value, the result is 80%.      
View full article
The KW40Z connectivity software stack has several demo application available, and one of them is the OTAP client. This application allows the user to reprogram the device in a wireless fashion. This can be done by both using another device with an OTAP server application, or with the Kinetis BLE Toolbox mobile application, using the OTAP tool. To create a binary file for the KW40Z, follow these next steps: Using IAR Embedded Workbench, open the application you want to send through OTAP. Right click the main project, and open the Options... menu.                                                                                                                                              In the options menu, go to the Output Converter submenu. In the Output Converter submenu, check the "Generate additional output" box, and choose Motorola as the Output format.                                                                                                                                                                            In the options menu, go to the Linker submenu. Now, in the Config tab, replace the symbols in the Configuration file symbol definitions box with these: gUseNVMLink_d=1 gUseBootloaderLink_d=1 gUseInternalStorageLink_d=0 __ram_vector_table__=1                                                                                                                                                                                              In the Linker submenu, go to the Input tab. In the Keep symbols box, add the symbol 'bootloader' (without the quotes). In the Input tab, in the Raw binary image box, in the File option, add the following path: $PROJ_DIR$\..\..\..\..\..\..\..\framework\Bootloader\Bin\BootloaderOTAP_KW40Z4.bin In the Raw binary image box, add the following options to the Symbol, Section and Align boxes: Symbol: bootloader Section: .bootloader Align: 4                                                                                                                                                                                                                         Press OK. Compile the project. The output file (*.srec) should be in the main project folder, inside the debug folder.                                                      You can now use this binary file to reprogram your device with OTAP.
View full article
The KW41Z has support for an external 26 MHz or 32 MHz reference oscillator. This oscillator is used, among other things, as the clock for the RF operation. This means that the oscillator plays an important role in the RF operation and must be tuned properly to meet wireless protocol standards. The KW41Z has adjustable internal load capacitors to support crystals with different load capacitance needs. For proper oscillator function, it is important that these load capacitors be adjusted such that the oscillator frequency is as close to the center frequency of the connected crystal (either 26 MHz or 32 MHz in this case). The load capacitance is adjusted via the BB_XTAL_TRIM bit field in the ANA_TRIM register of the Radio block. The KW41Z comes preprogrammed with a default load capacitance value. However, since there is variance in devices due to device tolerances, the correct load capacitance should be verified by verifying that the optimal central frequency is attained.  You will need a spectrum analyzer to verify the central frequency. To find the most accurate value for the load capacitance, it is recommended to use the Connectivity Test demo application. This post is aimed at showing you just how to do that.   In this case, the Agilent Technologies N9020A MXA Signal Analyzer was used to measure, configured with the following parameters: FREQ (central frequency): 2405 MHz (test will be conducted on channel 11) SPAN (x-axis): 100 KHz AMPTD (amplitude, y-axis): 5 dBm To perform the test, program the KW41Z with the Connectivity Test application. The project, for both IAR and KDS, for this demo application can be found in the following folder: <KW41Z_connSw_1.0.2_install_dir>\boards\frdmkw41z\wireless_examples\smac\connectivity_test\FreeRTOS NOTE:  If you need help programming this application onto your board, consult your Getting Started material for the SMAC applications.  For the FRDM-KW41Z, it is located here. Once the device is programmed, make sure the device is connected to a terminal application in your PC. When you start the application, you're greeted by this screen: Press 'ENTER' to start the application. Press '1' to select the continuous tests mode. Press '4' to start a continuous unmodulated transmission. Once the test is running, you should be able to see the unmodulated signal in the spectrum analyzer. Press 'd' and 'f' to change the XTAL trim value, thus changing the central frequency. Now, considering the test in this example is being performed in 802.15.4 channel 11, the central frequency should be centered exactly in 2.405 GHz, but on this board, it is slightly above (2.4050259 GHz) by default. In order to fix this, the XTAL trim value was adjusted to a value that moves the frequency to where it should be centered. Once the adequate XTAL trim value is found, it can be programmed to be used by default. This other post explains how to do this process.
View full article
What is a BLE Beacon? A BLE Beacon is a hardware including a MCU, a BLE radio, an antenna and a power source. Things like Freescale Beacon, iBeacon, AltBeacon or Eddystone are software protocols with their own characteristics. How it works? A BLE Beacon is a non-connectable device that uses Bluetooth Low Energy (BLE or Bluetooth Smart) to broadcast packets that include identifying information and each packet receives the name of Advertising Packet. The packet structure and the information broadcasted by a Beacon depend on the protocol, but, the basic structure is conformed by: UUID. This is a unique identifier that allows identifying a beacon or a group of beacons from other ones. Major number. Used to identify a group of beacons that share a UUID. Minor number. Used to identify a specific beacon that share UUID and Major number. Example UUID Major Minor AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA 1 1 These Beacons share the same UUID and Major number, and are differentiated by Minor number. AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA 1 2 AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA 2 1 This Beacon shares the same UUID as the previous ones, but has a different Major number, so it belongs to a different group. BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB 1 1 This Beacon is completely different from the previous ones, since it doesn’t share the same UUID. These packets need to be translated or interpreted in order to provide the beacon a utility. There are applications that can interact with beacons, usually developed to be used with smartphones and/or tablets. These applications require being compliant with the protocol used by the beacon in order to be able to perform an action when a beacon is found. Use Cases Beacons can be used on different places to display different content or perform different actions, like: Restaurants, Coffee Shops, Bars Virtual Menu Detailed information Food source Suggested wine pairings Museums Contextual information. Analytics Venue check-in (entry tickets) Self-guided tours. Educational excursions Event Management and Trade Shows Frictionless Registration Improved Networking Sponsorship Navigation and Heat Mapping Content Delivery Auto Check-in Stadiums Seat finding and seat upgrading Knowing the crowded locations Promotions, offers and loyalty programs Sell Merchandise Future implementations Retail and Malls Shopping with digital treasure hunts Gather digital up-votes and down-votes from visitors Allow retailers to join forces when it comes to geo-targeted offers Use time-sensitive deal to entice new shoppers to walk in Help in navigation Engage your customers with a unified mall experience.
View full article
Introduction The FRDM-KW36 includes an RTC module with a 32 kHz crystal oscillator. This module generates a 32 kHz clock source for the MCU whilst running on very low power mode. This oscillator includes a set of programmable capacitors used as the C LOAD . Changing the value of these capacitors can modify the frequency the oscillator provides. This configurable capacitance ranges from 0 pF (capacitor bank disabled) to 30 pF in steps of 2 pF. These values are obtained by combining the enabled capacitors. The values available are 2 pF, 4 pF, 8 pF, and 16 pF. Any combination of these four can be done. It is recommended that these internal capacitors are disabled if the external capacitors are available (clearing SC2P, SC4P, SCS8, and SC16 bits in RTC Control Register SFR). To adjust the frequency provided by the oscillator, you must first be able to measure the frequency. Using a frequency counter would be ideal, as it provides a more precise measurement than an oscilloscope. You will also need to output the oscillator frequency. To output the oscillator frequency, using any of the Bluetooth demo applications as an example, you should do the following: Adjusting Frequency Example This example will make use of the Heart Rate Sensor demo (freertos version) from the Connectivity Software Stack and assumes that the developer has the knowledge of import or open projects from the SDK to IDE. Open or clone the Heart Rate Sensor project from your SDK. Find the board.c and board.h files in the board folder at the workspace.                                                                                Declare a void function on the board.h file as shown below. This function will be in order to mux the RTC clock out to the PTB3 and be able to measure the frequency.  /* Function to mux PTB3 to RTC_CLKOUT */ void BOARD_EnableRtcClkOut (void);‍‍ Develop the BOARD_EnableRtcClkOut function inside the board.c file as below. void BOARD_EnableRtcClkOut(void) { /* Enable PORTB clock gating */ CLOCK_EnableClock(kCLOCK_PortB); /* Mux the RTC_CLKOUT to PTB3 */ PORT_SetPinMux(PORTB, 3u, kPORT_MuxAlt7); /* Select the 32kHz reference for RTC_CLKOUT signal */ SIM->SOPT1 |= SIM_SOPT1_OSC32KOUT(1); } Call the BOARD_EnableRtcClkOut function in hardware_init function just after BOARD_BootClockRUN (board.c file). Find clock_config.c file in the board folder at the workspace. Add the following defines at the top of the file. #define RTC_OSC_CAP_LOAD_0 0x0U /*!< RTC oscillator, capacitance 0pF */ #define RTC_OSC_CAP_LOAD_2 0x2000U /*!< RTC oscillator, capacitance 2pF */ #define RTC_OSC_CAP_LOAD_4 0x1000U /*!< RTC oscillator, capacitance 4pF */ #define RTC_OSC_CAP_LOAD_6 0x3000U /*!< RTC oscillator, capacitance 6pF */ #define RTC_OSC_CAP_LOAD_8 0x800U /*!< RTC oscillator, capacitance 8pF */ #define RTC_OSC_CAP_LOAD_10 0x2800U /*!< RTC oscillator, capacitance 10pF */ #define RTC_OSC_CAP_LOAD_12 0x1800U /*!< RTC oscillator, capacitance 12pF */ #define RTC_OSC_CAP_LOAD_14 0x3800U /*!< RTC oscillator, capacitance 14pF */ #define RTC_OSC_CAP_LOAD_16 0x400U /*!< RTC oscillator, capacitance 16pF */ #define RTC_OSC_CAP_LOAD_18 0x2400U /*!< RTC oscillator, capacitance 18pF */ #define RTC_OSC_CAP_LOAD_20 0x1400U /*!< RTC oscillator, capacitance 20pF */ #define RTC_OSC_CAP_LOAD_22 0x3400U /*!< RTC oscillator, capacitance 22pF */ #define RTC_OSC_CAP_LOAD_24 0xC00U /*!< RTC oscillator, capacitance 24pF */ #define RTC_OSC_CAP_LOAD_26 0x2C00U /*!< RTC oscillator, capacitance 26pF */ #define RTC_OSC_CAP_LOAD_28 0x1C00U /*!< RTC oscillator, capacitance 28pF */ #define RTC_OSC_CAP_LOAD_30 0x3C00U /*!< RTC oscillator, capacitance 30pF */ Search the CLOCK_CONFIG_EnableRtcOsc call to a function inside the BOARD_BootClockRUN function (also in the clock_config.c file), and edit the argument by any of the defines above. Finally, disable the low power options and led support in the "preinclude.h" file located in the source folder of the project: #define cPWR_UsePowerDownMode 0 #define gLEDSupported_d 0 At this point, you can measure in PTB3 and play with the frequency adjust using your frequency counter. Each time that the board is programmed, you need to perform a POR to get the correct measure. The following table was obtained from an FRDM-KW36 board rev B and it can be used as a reference to adjust the frequency. Please note that the capacitance is not only composed of the enabled internal capacitance, but also the parasitic capacitances found in the package, bond wires, bond pad, and the PCB traces. So, while the reference measurements given below should be close to the actual value, you should also make measurements with your board, to ensure that the frequency is trimmed specifically to your board and layout.   Enabled Capacitors CLOAD Capacitance Definition Frequency - 0pF RTC_OSC_CAP_LOAD_0 (bank disabled) 32772.980Hz SC2P 2pF RTC_OSC_CAP_LOAD_2 32771.330Hz SC4P 4pF RTC_OSC_CAP_LOAD_4 32770.050Hz SC2P, SC4P 6pF RTC_OSC_CAP_LOAD_6 32769.122Hz SC8P 8pF RTC_OSC_CAP_LOAD_8 32768.289Hz SC2P, SC8P 10pF RTC_OSC_CAP_LOAD_10 32767.701Hz SC4P, SC8P 12pF RTC_OSC_CAP_LOAD_12 32767.182Hz SC2P, SC4P, SC8P 14pF RTC_OSC_CAP_LOAD_14 32766.766Hz SC16P 16pF RTC_OSC_CAP_LOAD_16 32766.338Hz SC2P, SC16P 18pF RTC_OSC_CAP_LOAD_18 32766.038Hz SC4P, SC16P 20pF RTC_OSC_CAP_LOAD_20 32765.762Hz SC2P, SC4P, SC16P 22pF RTC_OSC_CAP_LOAD_22 32765.532Hz SC8P, SC16P 24pF RTC_OSC_CAP_LOAD_24 32765.297Hz SC2P, SC8P, SC16P 26pF RTC_OSC_CAP_LOAD_26 32765.117Hz SC4P, SC8P, SC16P 28pF RTC_OSC_CAP_LOAD_28 32764.940Hz SC2P, SC4P, SC8P, SC16P 30pF RTC_OSC_CAP_LOAD_30 32764.764Hz
View full article
Hello community, This time I bring to you a document which explains how easy is to add a new endpoint and a new cluster to a ZigBee device in the BeeStack in BeeKit. This document is based in the MC1323x MCUs but the procedure applies to the Kinetis devices. Before to start you need to install the BeeKit Wireless Connectivity Toolkit​. If you are interested about what an endpoint is, the document ZigBee Endpoints Reserved could be useful for you. I hope you find this guide useful. Enjoy this guide, enjoy ZigBee! Any feedback is welcome. Best regards, Earl Orlando Ramírez-Sánchez Technical Support Engineer NXP Semiconductors
View full article
简介: 当 OTAP 客户端(接收软件更新的设备,通常为 Bluetooth LE 外围设备)从 OTAP 服务器 (发送软件更新的设备,通常为 Bluetooth LE Central)请求软件更新时,您可能希望保留一 些数据,例如绑定信息,系统振荡器的匹配值或您的应用程序的 FlexNVM 非易失数据。 本 文档指导您在执行 OTAP 更新时, 如何保留您感兴趣的闪存数据内容。 本文档适用于熟悉 OTAP 定制 Bluetooth LE 服务的开发人员,有关更多基础信息,您可以阅读以下文章: 使用 OTAP 客户端软件对 KW36 设备进行重新编程。 OTAP 标头和子元素 OTAP 协议为软件更新实现了一种格式,该格式由标题和定义数量的子元素组成。 OTAP 标 头描述了有关软件更新的一般信息,并且其定义的格式如下图所示。 有关标题字段的更多 信息,请转至 SDK 中的<SDK_2.2.X_FRDM-KW36_Download_Path> \ docs \ wireless \ Bluetooth 中的《 Bluetooth Low Energy Application Developer's Guide》文档的 11.4.1 Bluetooth Low Energy OTAP 标头一章。   每个子元素都包含用于特定目的的信息。 您可以为您的应用程序实现专有字段(有关子元 素字段的更多信息, 请转至 SDK 中的<SDK_2.2.X_FRDM-KW36_Download_Path> \ docs \ wireless \ Bluetooth 中的《 Bluetooth Low Energy Application Developer's Guide》文档的 11.4.1 Bluetooth Low Energy OTAP 标头一章。 OTAP 包含以下子元素: 镜像文件子元素 值字段长度(字节) 描述 升级镜像 变化 该子元素包含实际的二进制可执行镜像,该镜像将被复制到 OTAP 客户端设备的闪存中。 该子元素的最 大大小取决于目标硬件。 扇区位图 32 该子元素包含目标设备闪存的扇区位图,该位图告诉引导加载程序哪些扇区应被覆盖,哪些扇区保持完 整。 该字段的格式是每个字节的最低有效位在前,最低有效字节和位代表闪存的最低存储部分。 镜像文件CRC 2 是在镜像文件的所有元素(此字段本身除外)上计算的 16 位 CRC。 该元素必须是通过空中发送的镜像文件中的最后一个子元素。   OTAP 扇区位图子元素 KW36 闪存分为: 一个 256 KB 程序闪存( P-Flash)阵列, 最小单元为 2 KB 扇区,闪存地址范围为 0x0000_0000 至 0x0003_FFFF。 一个 256 KB FlexNVM 阵列, 最小单元为 2 KB 扇区,闪存地址范围为 0x1000_0000 至 0x1003_FFFF, 同时它也会被映射到地址范围为 0x0004_0000 至 0x0007_FFFF 的空间。 位图子元素的长度为 256 位,就 KW36 闪存而言,每个位代表 2KB 扇区,覆盖从 0x0- 0x0007_FFFF 的地址范围(P-Flash 到 FlexNVM 映射地址范围),其中 1 表示该扇区应 被擦 除, 0 表示应保留该扇区。 OTAP 引导加载程序使用位图字段来获取在使用软件更新对 KW36 进行编程之前应擦除的地址范围,因此必须在发送软件更新之前对其进行配置,以使包含您 的数据的内存的地址范围保持不变。仅擦除将被软件更新覆盖的地址范围。 例如:假设开发人员想要保留 0x7D800-0x7FFFF 之间的地址范围和 0x0-0x1FFF 之间的地址 范围,并且必须擦除剩余的存储器。 0x7D800-0x7FFFF 之间的地址范围对应于前 5 个闪存 扇区, 0x0-0x1FFF 之间的地址范围是最低的 4 个扇区。 因此,这意味着应将 256 和 252 之间的位(256、 255、 254、 253 和 252)以及 4 和 1 之间 的位(4、 3、 2 和 1)设置为 0,这样本示例的 OTAP 位图为 : 0x07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 使用 NXP 测试工具配置 OTAP 位图以保护地址范围 在恩智浦网站上下载并安装用于连接产品的测试工具   在 PC 上打开 NXP Test Tool 12 软件。 转到“ OTA 更新-> OTAP 蓝牙 LE”,然后单击“浏 览...”按钮加载用于软件更新的映像文件(NXP 测试工具仅接受.bin 和.srec 文件)。 您 可以配置 OTAP 位图,选择“覆盖扇区位图”复选框,并通过新的位图值更改默认值。 配 置位图后,选择“保存...”。   然后,将显示一个窗口,用于选择保存.bleota 文件的目的地,保存文件可以自行取名。 您可以将此文件与 Android 和 iOS 的 IoT Toolbox App 一起使用,以使用 OTAP 更新软 件。 这个新的.bleota 文件包含位图,该位图告诉 OTAP 引导加载程序哪些扇区将被擦 除,哪些扇区将被保留。    
View full article
Introduction The FRDM-KW36 includes an RSIM (Radio System Integration Module) module with an external 32 MHz crystal oscillator. This clock source reference is mainly intended to supply the Bluetooth LE Radio peripheral, but it can be used as the main clock source of the MCU as well. This oscillator includes a set of programmable capacitors to support crystals with different load capacitance needs. Changing the value of these capacitors can modify the frequency the oscillator provides, that way, the central frequency can be tuned to meet the wireless protocol standards. This configurable capacitance range is from C1: 5.7pF - C2: 7.1pF to C1: 22.6pF - C2: 28.2pF and it is configured through the BB_XTAL_TRIM field at the ANA_TRIM. The KW36 comes preprogrammed with a default load capacitance value. However, since there is variance in devices due to tolerances and parasite effects, the correct load capacitance should be checked by verifying that the optimal central frequency is attained.  You will need a spectrum analyzer to measure the central frequency. To find the most accurate value for the load capacitance, it is recommended to use the Connectivity Test demo application. Adjusting Frequency Example Program the KW36 Connectivity Test software on the device. This example can be found in wireless_examples -> genfsk -> conn_test folder from your SDK package. Baremetal and FreeRTOS versions are available. In case that FRDM-KW36 board is being used to perform the test, you should move the 10pF capacitor populated in C55 to C57, to direct the RF signal on the SMA connector. Connect the board to a serial terminal software. When you start the application, you will be greeted by the NXP logo screen:  Press the enter key to start the test. Then press "1" to select "Continuous tests": Finally, select "6" to start a continuous unmodulated RF test. At this point, you should be able to measure the signal in the spectrum analyzer. You can change the RF channel from 0 to 127 ("q" Ch+ and "w" Ch- keys), which represents the bandwidth from 2.360GHz to 2.487GHz, stepping of 1MHz between two consecutive channels. To demonstrate the trimming procedure, this document will make use of channel 42 (2.402GHz) which corresponds to the Bluetooth LE channel 37. In this case, with the default capacitance value, our oscillator is not exactly placed at the center of the 2.402GHz, instead, it is slightly deflected to 2.40200155 GHz, as depicted in the following figure: The capacitance can be adjusted with the "d" XtalTrim+ and "f" XtalTrim- keys. Increasing the capacitance bank means a lower frequency. In our case, we need to increase the capacitance to decrease the frequency. The nearest frequency of 2.402 GHz was 2.40199940 GHz  Once the appropriate XTAL trim value has been found, it can be programmed as default in any Bluetooth LE example, changing the mXtalTrimDefault constant located in the board.c file: static const uint8_t mXtalTrimDefault‍ = 0x36;‍‍‍
View full article
Overview The Bluetooth specification defines 4 Generic Access Profile (GAP) roles for devices operating over a Low Energy physical transport [1]: Peripheral Central Broadcaster Observer The Bluetooth Low Energy Host Stack implementation on the Kinetis KW40Z offers devices the possibility to change between any of the 4 roles at run time. This article will present the interaction with the Bluetooth Low Energy Host API needed to implement a GAP multiple role device. General Procedure instructions Running the GAP roles requires the application to go through the following 3 steps: Configuration - Stack configuration for the desired GAP role The application needs to configure the stack parameters, e.g. advertising parameters, advertising data, scan parameters, callbacks. Note that configuration of the advertising parameters or scanning response and advertising data can be done only once if the values don’t change at runtime. The configuration is always made in the Link Layer Standby state. Start - Running the role The application needs to start advertising, scanning or initiate connection. Stop - Return to Standby state When changing between roles, the Link layer must always go through the Link Layer Standby state. Running as a GAP Broadcaster or GAP Peripheral The GAP Broadcaster or Peripheral sends advertising events. Additionally, the GAP Peripheral will accept the establishment of a LE link. This is why the GAP Observer will only support the Non Connectable Advertising mode (gAdvNonConnectable_c). Both roles requires configuration of advertising data, advertising parameters. The configuration (gAppAdvertisingData, gAppScanRspData and gAdvParams) usually resides in app_config.c. The confirmation events for setting these parameters is received in BleApp_GenericCallback. The confirmation event for the changing state of advertising is received in BleApp_AdvertisingCallback. Configuration /* Setup Advertising and scanning data */ Gap_SetAdvertisingData(&gAppAdvertisingData, &gAppScanRspData); /* Setting only for GAP Broadcaster role */ gAdvParams. advertisingType = gAdvNonConnectable_c; /* Set advertising parameters*/ Gap_SetAdvertisingParameters(&gAdvParams); Start App_StartAdvertising(BleApp_AdvertisingCallback, BleApp_ConnectionCallback); Stop Gap_StopAdvertising(); Running as a GAP Observer The GAP Observer receives advertising events. Unlike the GAP Peripheral or Broadcaster, it does not need to set scanning parameters separately. It passes the configuration with the start procedure. The configuration (gAppScanParams) usually resides in app_config.c. The confirmation event for the changing state of scanning is received in BleApp_ScanningCallback. Configuration and Start App_StartScanning(&gAppScanParams, BleApp_ScanningCallback); Stop Gap_StopScanning (); Running as a GAP Central The GAP Central initiates the establishment of the LE link. Like the GAP Observer, it passes the configuration with the start procedure. The configuration (gConnReqParams) usually resides in app_config.c. The confirmation event for the changing state of link is received in BleApp_ConnectionCallback. Configuration and Start Gap_Connect(&gConnReqParams, BleApp_ConnectionCallback); Stop Gap_Disconnect(deviceId); Example An out-of-the box example for multiple role is attached. The application named blood_pressure_multi_role implements a Blood Pressure GATT client and server and can switch between the following GAP roles: Peripheral, Observer and Central. The contents of the archive needs to be copied to the following location: <Installer Path>\KW40Z_Connectivity_Software_1.0.1\ConnSw\examples\bluetooth\ The application can be found at: <Install Path specified>\KW40Z_Connectivity_Software_1.0.1\ConnSw\examples\bluetooth\blood_pressure_multi_role\frdmkw40z\bare_metal\build\iar\blood_pressure_multi_role.eww Running as GAP Peripheral Press SW4. LED1 will start flashing and the console will show that the Link Layer enters Advertising. If the Link Layer was in a previous state, it will go through Standby. static void BleApp_Advertise(void) {     /* Ensure Link Layer is in Standby */     BleApp_GoToStandby();         shell_write(" GAP Role: Peripheral\n\r");     mGapRole = gGapPeripheral_c;         /* Start GAP Peripheral */     App_StartAdvertising(BleApp_AdvertisingCallback, BleApp_ConnectionCallback); } Running as GAP Observer Press SW3. A chasing LED pattern will start and the console will show that the Link Layer enters Scanning. If the Link Layer was in a previous state, it will go through Standby. static void BleApp_Scan(void) {     /* Ensure Link Layer is in Standby */     BleApp_GoToStandby();         shell_write(" GAP Role: Observer\n\r");     mGapRole = gGapObserver_c;         /* Start GAP Observer */     App_StartScanning(&gAppScanParams, BleApp_ScanningCallback); } Running as GAP Central If the Link Layer is in scanning and finds a Blood Pressure Sensor, it will go through Standby and initiate connection. static void BleApp_Connect(void) {     /* Ensure Link Layer is in Standby */     BleApp_GoToStandby();         shell_write(" GAP Role: Central\n\r");     mGapRole = gGapCentral_c;         /* Start GAP Central */     Gap_Connect(&gConnReqParams, BleApp_ConnectionCallback); } Returning to Standby Pressing SW3 for more than 2 seconds, brings the Link Layer back in Standby. static void BleApp_GoToStandby(void) {     /* Check if connection is on */     if (mPeerInformation.deviceId != gInvalidDeviceId_c)     {         /* Stop GAP Central or Peripheral */         Gap_Disconnect(mPeerInformation.deviceId);     }     if (mAdvOn)     {         /* Stop GAP Peripheral or Bradcaster */         Gap_StopAdvertising();     }         if (mScanningOn)     {         /* Stop GAP Observer */         Gap_StopScanning();     } } References [1] BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C], 2.2 PROFILE ROLES
View full article
This article will describe in detailed steps how to generate, build and test a Bluetooth low energy Heart Rate Sensor project on the FRDM-KW41Z evaluation board by using the Bluetooth Developer Studio (BDS) and the NXP Kinetis BDS Plug-in. Getting Started To use this plug-in and test its output, the following programs are required:  - Bluetooth Developer Studio v1.1.306 or newer: Bluetooth Developer Studio & Plugins | Bluetooth Technology Website   - NXP Semiconductors Kinetis Plug-in v1.0.0: Link  - Kinetis SDK 2.0 with support for MKW41Z and Bluetooth Stack version 1.2.2: Link  - Kinetis SDK 2.0 add-on for BDS (found in the same package as the plug-in)  - Kinetis BLE Toolbox Android or iOS mobile application To enable the NXP Kinetis BDS Plug-in in the Bluetooth Developer Studio, follow please the installation details in the readme.txt document included in the downloaded plug-in archive. Creating the project with BDS Create a new project by clicking FILE-> NEW PROJECT. Add project location, name and namespace as detailed below: Drag and drop an adopted Heart Rate Profile from the right hand side list. Your device should import the following services:   Next step will be to configure the GAP layer. Click on the GAP button. First tab will be the Advertising Data. Enter desired values and check which AD types you want to include in the advertising packets. A bar below will show you how much bytes your data uses. Make sure you do not use more than the 32 bytes available. Next step is to configure the GAP properties. Make sure you check at least one advertising channel and a reasonable advertising interval range, as presented below:     Click TOOLS->GENERATE CODE. Select Server as GATT side to be generated and NXP Semiconductors Kinetis v1.0.0 as the plug-in. BDS will prompt you to enter a location for the exported files. After generating the files, another window with the results log will appear. If no error messages appear, the generation is successful. Check the “Open output location when finished” box and hit the “Finish” button. A folder with the following content will open: Using the generated code Copy the contents inside the following folder:  "<SDK 2.0 installation folder>\middleware\wireless\bluetooth_1.2.2\examples\bds_template_app". To generate the “bds_template_app” embedded project and test it, follow the instructions detailed in the Bluetooth Quick Start Guide document from the SDK. Seeing the application in action Before compiling the application add the following code snippet in app.c inside BleApp_HandleKeys:         case gKBD_EventPressPB2_c:         {             mUserData.cRrIntervals = 0;             mUserData.expendedEnergy = 100;             Hrs_RecordHeartRateMeasurement(service_heart_rate, 120, &mUserData);             break;         } This will allow the board to send heart rate data of 120 bpm while in a connection and when pressing button SW3 on the FRDM-KW41Z board. The value can be seen when using Kinetis BLE Toolbox, as shown below:
View full article