Friday, August 5, 2022

How to create periodic timer event and use iADC for EFR32 series 2 to do battery voltage monitor in GSDK 4.x and EmberZnet 7.x

How to create periodic timer event and use iADC for EFR32 series 2 to do battery voltage monitor in GSDK 4.x and EmberZnet 7.x

1. Add the following code in app.c

#define _IADC_

#ifdef _IADC_
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_iadc.h"
#include "em_gpio.h"
#endif //#ifdef _IADC_

#ifdef _IADC_
#define CLK_SRC_ADC_FREQ          20000000 // CLK_SRC_ADC
#define CLK_ADC_FREQ              10000000 // CLK_ADC - 10MHz max in normal mode
/*
 * Specify the IADC input using the IADC_PosInput_t typedef.  This
 * must be paired with a corresponding macro definition that allocates
 * the corresponding ABUS to the IADC.  These are...
 *
 * GPIO->ABUSALLOC |= GPIO_ABUSALLOC_AEVEN0_ADC0
 * GPIO->ABUSALLOC |= GPIO_ABUSALLOC_AODD0_ADC0
 * GPIO->BBUSALLOC |= GPIO_BBUSALLOC_BEVEN0_ADC0
 * GPIO->BBUSALLOC |= GPIO_BBUSALLOC_BODD0_ADC0
 * GPIO->CDBUSALLOC |= GPIO_CDBUSALLOC_CDEVEN0_ADC0
 * GPIO->CDBUSALLOC |= GPIO_CDBUSALLOC_CDODD0_ADC0
 *
 * ...for port A, port B, and port C/D pins, even and odd, respectively.
 */
#define IADC_INPUT_0_PORT_PIN     iadcPosInputAvdd;
#define IADC_INPUT_1_PORT_PIN     iadcNegInputGnd;

#define IADC_INPUT_0_BUS          BBUSALLOC
#define IADC_INPUT_0_BUSALLOC     GPIO_BBUSALLOC_BEVEN0_ADC0
#define IADC_INPUT_1_BUS          BBUSALLOC
#define IADC_INPUT_1_BUSALLOC     GPIO_BBUSALLOC_BODD0_ADC0

/*******************************************************************************
 ***************************   GLOBAL VARIABLES   *******************************
 ******************************************************************************/

static volatile int32_t sample;
static volatile double singleResult; // Volts

static sl_sleeptimer_timer_handle_t bat_volt_read_periodic_timer;
static void bat_volt_read_periodic_timer_callback(sl_sleeptimer_timer_handle_t *handle, void *data)
{
  (void)handle;
  (void)data;
  // Start IADC conversion
  IADC_command(IADC0, iadcCmdStartSingle);

  // Wait for conversion to be complete
  while((IADC0->STATUS & (_IADC_STATUS_CONVERTING_MASK
              | _IADC_STATUS_SINGLEFIFODV_MASK)) != IADC_STATUS_SINGLEFIFODV); //while combined status bits 8 & 6 don't equal 1 and 0 respectively

  // Get ADC result
  sample = IADC_pullSingleFifoResult(IADC0).data;

  // Calculate input voltage:
  // For differential inputs, the resultant range is from -Vref to +Vref, i.e.,
  // for Vref = VBGR = 2.42V, and with analog gain = 0.5, 12 bits represents
  // 4.84V full scale IADC range.
  singleResult = (sample * 4.84) / 0xFFF;

}
/**************************************************************************//**
 * @brief  Initialize IADC function
 *****************************************************************************/
void initIADC (void)
{
  // Declare init structs
  IADC_Init_t init = IADC_INIT_DEFAULT;
  IADC_AllConfigs_t initAllConfigs = IADC_ALLCONFIGS_DEFAULT;
  IADC_InitSingle_t initSingle = IADC_INITSINGLE_DEFAULT;
  IADC_SingleInput_t initSingleInput = IADC_SINGLEINPUT_DEFAULT;

  // Enable IADC0 and GPIO clock branches

  /* Note: For EFR32xG21 radio devices, library function calls to
   * CMU_ClockEnable() have no effect as oscillators are automatically turned
   * on/off based on demand from the peripherals; CMU_ClockEnable() is a dummy
   * function for EFR32xG21 for library consistency/compatibility.
   */
  CMU_ClockEnable(cmuClock_IADC0, true);
  CMU_ClockEnable(cmuClock_GPIO, true);

  // Reset IADC to reset configuration in case it has been modified by
  // other code
  IADC_reset(IADC0);

  // Select clock for IADC
  CMU_ClockSelectSet(cmuClock_IADCCLK, cmuSelect_FSRCO);  // FSRCO - 20MHz

  // Modify init structs and initialize
  init.warmup = iadcWarmupKeepWarm;

  // Set the HFSCLK prescale value here
  init.srcClkPrescale = IADC_calcSrcClkPrescale(IADC0, CLK_SRC_ADC_FREQ, 0);

  // Configuration 0 is used by both scan and single conversions by default
  // Use internal bandgap (supply voltage in mV) as reference
  initAllConfigs.configs[0].reference = iadcCfgReferenceInt1V2;
  initAllConfigs.configs[0].vRef = 1210;
  initAllConfigs.configs[0].analogGain = iadcCfgAnalogGain1x;

  // Divides CLK_SRC_ADC to set the CLK_ADC frequency
  initAllConfigs.configs[0].adcClkPrescale = IADC_calcAdcClkPrescale(IADC0,
                                             CLK_ADC_FREQ,
                                             0,
                                             iadcCfgModeNormal,
                                             init.srcClkPrescale);

  // Assign pins to positive and negative inputs in differential mode
  initSingleInput.posInput   = IADC_INPUT_0_PORT_PIN;
  initSingleInput.negInput   = IADC_INPUT_1_PORT_PIN;

  // Initialize the IADC
  IADC_init(IADC0, &init, &initAllConfigs);

  // Initialize the Single conversion inputs
  IADC_initSingle(IADC0, &initSingle, &initSingleInput);

  // Allocate the analog bus for ADC0 inputs
  GPIO->IADC_INPUT_0_BUS |= IADC_INPUT_0_BUSALLOC;
  GPIO->IADC_INPUT_1_BUS |= IADC_INPUT_1_BUSALLOC;
}
#endif//#ifdef _IADC_

2. Add the following codes in emberAfMainInitCallback

#ifdef _IADC_
  initIADC();
  sl_sleeptimer_start_periodic_timer(&bat_volt_read_periodic_timer, 1000, bat_volt_read_periodic_timer_callback, NULL, 0, 0);
#endif //#ifdef _IADC_

3. Battery voltage input to AVDD would be read to singleResult in bat_volt_read_periodic_timer_callback every second.

Thursday, August 4, 2022

How to setup and build Matter/CHIP EFR32 Lighting Example on Ubuntu 20.04.

The following steps show you how to setup and build Matter/CHIP EFR32 Lighting Example on Ubuntu 20.04.

1. Install necessary packages.

sudo apt-get install -y git gcc g++ pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev
 
2. Get Matter/CHIP source codes.

git clone --recurse-submodules https://github.com/project-chip/connectedhomeip
 

3. Enter Matter/CHIP source folder and build Matter/CHIP EFR32 Lighting Example


    3.1 run "cd connectedhomeip/"
 
    3.2 run "source scripts/activate.sh"
 
    3.3 run "./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32/ ./out/lighting-app BRD4161A"

 

4. Get chip-efr32-lighting-example.s37 under /connectedhomeip/out/lighting-app/BRD4161A to program it via Simplicity Flash Programmer or Commander.


5. You can see QR code on BRD4001A LCD and execute CLI command on serial console.

Tuesday, July 26, 2022

How to build EmberZnet 7.1.0.0 Z3Gateway on Raspberry Pi.

 The following steps show you how to build EmberZnet 7.1.0.0 Z3Gateway on Raspberry Pi.

 

1. Install Simplicity Studio v5 and GSDK 4.1.0 on Ubuntu 20.04LTS. For example, GSDK 4.1.0 is installed at "~/SimplicityStudio/SDKs/gecko_sdk_2" in my test.

2. Start Simplicity Studio File->New->Silicon Labs Project Wizard... and set "Target Device" as "Linux 32 Bit" to click NEXT button.

 

3. Select "Zigbee - Host Gateway" and click NEXT button.

 

4. Make sure you set project location to under your GSDK 4.1.0 folder such as my example "/home/yk/SimplicityStudio/SDKs/gecko_sdk_2/Z3Gateway" and select "Copy contents" to click FINISH button.


5. Download and setup 2022-04-04-raspios-bullseye-armhf-lite.img for your Raspberry Pi.

6. Use sftp to copy the whole "/home/yk/SimplicityStudio" folder contents to your Raspberry Pi home folder.

7. Change direct to "~/SimplicityStudio/SDKs/gecko_sdk_2/Z3Gateway" on your Raspberry Pi and run "make -f Z3Gateway.Makefile" to build Z3Gateway

8. After build successfully, you will get Z3Gateway binary under "~/SimplicityStudio/SDKs/gecko_sdk_2/Z3Gatewaybuild/debug/". You can run Z3Gateway by "Z3Gateway -p /dev/ttyACM0" under this folder.



Friday, June 17, 2022

How to intercept ZDO leave request in EmberZnet.

The following steps show you how to intercept ZDO leave request in EmberZnet.

1. Enable Packet Handoff plugin.

2. Use emberAfIncomingPacketFilterCallback in project callbacks.

3. Add the following code to intercept ZDO leave request.

uint8_t* cmd;
EmberPacketAction emberAfIncomingPacketFilterCallback(EmberZigbeePacketType packetType, uint8_t* packetData, uint8_t* size_p, void* data)
{
  if(packetType == EMBER_ZIGBEE_PACKET_TYPE_ZDO){

      emberAfZdoPrintln("Receive EMBER_ZIGBEE_PACKET_TYPE_ZDO");
      emberAfZdoPrintBuffer(data,sizeof(data), true);
      cmd=(uint8_t*)data;
      if((cmd[2])==0x34 && (cmd[3])==0x00)
        emberAfZdoPrintln("-----------Receive ZDO Leave Request------------------------");
   }
  return EMBER_ACCEPT_PACKET;
}