Showing posts with label Silicon Labs. Show all posts
Showing posts with label Silicon Labs. Show all posts

Monday, April 29, 2024

Create and build Z-Wave - NCP Serial API Controller firmware for Z-Wave 800 ZGM230SA SoC

The following steps show you how to create and build Z-Wave - NCP Serial API Controller firmware for Z-Wave 800 ZGM230SA SoC.

Before you do anything, please make sure the secure firmware on your ZGM230SA is update to latest one. When I write this article, I use GSDK 4.4.1/Z-Wave SDK 7.20.2 and the latest secure firmware version for ZGM230SA is 2.2.4 for your reference.


To have Z-Wave - NCP Serial API Controller firmware working, you need to create and build Bootloader - NCP UART XMODEM first.The follow steps show you the details to create and build it.

1. Start Simplicity Studio v5 and go to Launcher perspective with your custom ZGM230SA borad connected or selecting ZGM230SAin "My Products" perspective. Create Bootloader - NCP UART XMODEM project as the following screenshot.

2. Go to "Bootloader UART Driver" and "GPIO activation" software component to configure UART TX/RX and SL_BTL_BUTTON pins according to your ZGM230SA custom board schematics.

 

3. Build and download Bootloader - NCP UART XMODEM firmware to your ZGM230SA custom board.

Then, you can create and build Z-Wave - NCP Serial API Controller firmware for your custom ZGM230SA board using the following steps:

1. Create Z-Wave - NCP Serial API Controller project as the following screenshot.

2. Go to "SerialAPI AppsHw" software component to configure UART TX/RX pins according to your ZGM230SA custom board schematics.

3. Build and download Z-Wave - NCP Serial API Controller firmware to your ZGM230SA custom board.

 After download both "Bootloader - NCP UART XMODEM" and "Z-Wave - NCP Serial API Controller firmware" firmware to your ZGM230S custom board, you can connect it with serial-to-USB convertor to your desktop and run Z-Wave PC controller to test it.

Wednesday, October 4, 2023

DIY SwitchBot using Matter Over Thread running on Silicon Labs EFR32xG24 Explorer Kit in 5 Minutes.

The following steps guide you to DIY SwitchBot using Matter Over Thread running on Silicon Labs EFR32xG24 Explorer Kit xG24-EK2703A in 5 minutes.

1. Make sure you install Silicon Labs Simplicity Studio v5 and GSDK 4.3.1 with Matter extension 2.1.0-1.1.

2.Connect your xG24-EK2703A kit to your desktop and create "Matter - SoC OnOff Plug over Thread" project as base for your DIY SwitchBot using Matter Over Thread project.

3.Install and add a "sg90" PWM instance in "SOFTWARE COMPONENTS"

4.Configure "sg90" instance to use Timer0 PA00 as PWM output with PWM frequency 50 Hz.

 

5. Replace source code in "void AppTask::ActionCompleted(OnOffPlugManager::Action_t aAction)" with the following codes (red lines), which implements on/off rotating position for SG90 to turn on/off switch.

//YK for SG90 SwitchBot
#include "sl_pwm.h"
#include "sl_pwm_init_sg90_config.h"
#include "sl_sleeptimer.h"

extern sl_pwm_instance_t sl_pwm_sg90;

void AppTask::ActionCompleted(OnOffPlugManager::Action_t aAction)
{
    // action has been completed on the outlet
    if (aAction == OnOffPlugManager::ON_ACTION)
    {
        SILABS_LOG("Outlet ON")
        sl_pwm_set_duty_cycle(&sl_pwm_sg90, 2);
        sl_pwm_start(&sl_pwm_sg90);
        sl_sleeptimer_delay_millisecond(200);
        sl_pwm_set_duty_cycle(&sl_pwm_sg90, 5);
        sl_sleeptimer_delay_millisecond(200);
        sl_pwm_stop(&sl_pwm_sg90);
    }
    else if (aAction == OnOffPlugManager::OFF_ACTION)
    {
        SILABS_LOG("Outlet OFF")
        sl_pwm_set_duty_cycle(&sl_pwm_sg90, 9);
        sl_pwm_start(&sl_pwm_sg90);
        sl_sleeptimer_delay_millisecond(200);
        sl_pwm_set_duty_cycle(&sl_pwm_sg90, 5);
        sl_sleeptimer_delay_millisecond(200);
        sl_pwm_stop(&sl_pwm_sg90);
    }
#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
    if (sAppTask.mSyncClusterToButtonAction)
    {
        chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterState, reinterpret_cast<intptr_t>(nullptr));
        sAppTask.mSyncClusterToButtonAction = false;
    }
#endif
}

6. Add the following two line to set initial SG90 position after "sl_pwm_init(&sl_pwm_sg90, &pwm_sg90_config);" in "void sl_pwm_init_instances(void)".

  //YK for SG90 SwitchBot
  sl_pwm_set_duty_cycle(&sl_pwm_sg90, 5);
  sl_pwm_start(&sl_pwm_sg90);

7. Build and download firmware into xG24-EK2703A kit(remember to dowload bootloader into the kit too)

8. Connect GND, PWR, Signal line of SG90 to GND, 3V3, and PWM pin on xG24-EK2703A kit.

9.Start RTT viewer to get QR code link for Matter Provision.


 

10. Since Apple Home supports Matter Over Thread now, we use Apple HomePod mini (iOS 17) and iPhone Home App to add our DIY SwitchBot into Apple Home.

11. Now, we can mount the DIY SwitchBot to wall switch and use Apple Home to control wall switch/light remotely.



Thursday, September 7, 2023

Adding reporting period configuration in configuration command class to Z-Wave Multilevel sensor example running on BRD2603A/ZGM230S

The following steps and codes show you how to add a reporting period configuration with configuration command class to allow changing auto report period in Z-Wave Multilevel sensor example running on BRD2603A/ZGM230S

1. Create zwave_soc_multilevel_sensor in Simplicity Studio v5 with GSDK4.3.1/Z-Wave SDK 7.20.1.0.

2. Add 3rd parameter to "configurations:" section in MultilevelSensor.cc_config and SSv5 would rebuilt parameters in parameter_pool inside cc_configuration_config.c accordingly

    - name: "auto report period"
      number: 3
      file_id: 2
      info: "sensor auto reporting period"
      size: CC_CONFIG_PARAMETER_SIZE_32_BIT
      format: CC_CONFIG_PARAMETER_FORMAT_SIGNED_INTEGER
      min_value: 1
      max_value: 3600
      default_value: 1800
      altering_capabilities: 0
      read_only: 0
      advanced: 0

3. In CC_MultilevelSensor_Support.c, revise the following codes:

#define DEBUGPRINT
#include "DebugPrint.h"
#include "CC_Configuration.h"

SSwTimer cc_multilevel_sensor_autoreport_timer;
uint32_t autoreport_time = 30;

static void cc_multilevel_sensor_init(void)
{
  cc_multilevel_sensor_config_register_instances();
  cc_multilevel_sensor_init_all_sensor();
  ZAF_nvm_read(2, &autoreport_time, 4);
  DPRINTF("configuration_pool_init[2].parameters->attributes.default_value %d\r\n", (int)autoreport_time );

  AppTimerDeepSleepPersistentRegister(&cc_multilevel_sensor_autoreport_timer, false, cc_multilevel_sensor_autoreport_callback);
  AppTimerDeepSleepPersistentStart(&cc_multilevel_sensor_autoreport_timer, autoreport_time*1000);
}

static void cc_multilevel_sensor_autoreport_callback(SSwTimer *pTimer)
{
  UNUSED(pTimer);
  cc_multilevel_sensor_send_sensor_data();
  AppTimerDeepSleepPersistentStart(&cc_multilevel_sensor_autoreport_timer, autoreport_time*1000);
}

4. In CC_Configuration.c, add the following red lines into cc_configuration_set.

#include "SwTimer.h"
extern SSwTimer cc_multilevel_sensor_autoreport_timer;
extern uint32_t autoreport_time;
static cc_config_configuration_set_return_value
cc_configuration_set(uint16_t parameter_number,  cc_config_parameter_value_t* new_value, cc_config_parameter_size_t size)
{
  cc_config_configuration_set_return_value return_value = CC_CONFIG_RETURN_CODE_OK;
  bool io_transaction_result = false;
  bool is_value_in_range = false;
  bool has_to_break = false;
  cc_config_parameter_buffer_t parameter_buffer;

  if (parameter_number==3){
    autoreport_time = new_value->as_uint32;
    ZAF_nvm_write(2, &autoreport_time, 4);
    DPRINTF("cc_configuration_set para no. %d size %d: autoreport_time %d seconds\r\n", (int)parameter_number, (int)size, (int)autoreport_time );
    AppTimerDeepSleepPersistentStart(&cc_multilevel_sensor_autoreport_timer);
    AppTimerDeepSleepPersistentStart(&cc_multilevel_sensor_autoreport_timer, autoreport_time*1000);
  }

    for(uint16_t parameter_ix = 0 ; parameter_ix < configuration_pool->numberOfParameters ; parameter_ix++)
    {
...

}

5. Build and run firmware on BRD2603A to join zwave_soc_multilevel_sensor into PC controller. You can use CONFIGURATION_SET to change auto report period with parameter 3.



Friday, September 1, 2023

Using Z-Wave Multilevel sensor example running on BRD2603A/ZGM230S to read temperature from TMP116 temperature sensor

The following example shows you how to use Z-Wave Multilevel sensor example running on BRD2603A/ZGM230S to read temperature from Texas Instrument TMP116 temperature sensor.

1. Connect Texas Instrument BOOSTXL-BASSENSORS TMP116 TMP V+, GND, and SCL/SDA to pin 20, 1, and 15(PB05)/16(PB05) on EXP-header of BRD2603A.

 

2. Install Z-Wave Debug and Z-Wave Debug Print in project software component to use  DEBUGPRINT to output data to SSv5 console 1.

3.Add the following code into MultilevelSensor_interface_sensor.c

 #define TMP116_I2C_DEVICE                (sl_i2cspm_sensor) /**< I2C device used to control the Si7021  */
#define TMP116_I2C_BUS_ADDRESS           0x48//TMP116 0x40               /**< I2C bus address                        */

static I2C_TransferReturn_TypeDef TMP116_transaction(uint16_t flag,
                                                     uint8_t *writeCmd,
                                                     size_t writeLen,
                                                     uint8_t *readCmd,
                                                     size_t readLen)
{
  I2C_TransferSeq_TypeDef seq;
  I2C_TransferReturn_TypeDef ret;

  seq.addr = TMP116_I2C_BUS_ADDRESS << 1;
  seq.flags = flag;

  switch (flag) {
    // Send the write command from writeCmd
    case I2C_FLAG_WRITE:
      seq.buf[0].data = writeCmd;
      seq.buf[0].len  = writeLen;

      break;

    // Receive data into readCmd of readLen
    case I2C_FLAG_READ:
      seq.buf[0].data = readCmd;
      seq.buf[0].len  = readLen;

      break;

    // Send the write command from writeCmd
    // and receive data into readCmd of readLen
    case I2C_FLAG_WRITE_READ:
      seq.buf[0].data = writeCmd;
      seq.buf[0].len  = writeLen;

      seq.buf[1].data = readCmd;
      seq.buf[1].len  = readLen;

      break;

    default:
      return i2cTransferUsageFault;
  }

  // Perform the transfer and return status from the transfer
  ret = I2CSPM_Transfer(TMP116_I2C_DEVICE, &seq);

  return ret;
}

uint32_t TMP116_read()
{
  I2C_TransferReturn_TypeDef ret;
  uint8_t temp[2];
  uint8_t cmdReadTemp[1]={0x00};
  int32_t temperature;

  // Wait for sensor to become ready
  //sl_sleeptimer_delay_millisecond(1000);

  // Check for device presence  and compare device ID
  ret = TMP116_transaction(I2C_FLAG_WRITE_READ, cmdReadTemp, 1, temp, 2);
  temperature=temp[0];
  temperature=(temperature<<8)|temp[1];
  //DPRINTF("Temperature = %d\r\n", (int)temperature);
  return temperature*10;
}

4. Replace "MultilevelSensor_temperature_humidity_sensor_read(&rh_data, &temp_data);" with "temp_data=(int32_t)TMP116_read();" in cc_multilevel_sensor_air_temperature_interface_read_value.

5. Build and run the firmware on BRD2603A to see the following temperature reading fromTMP116

 


P.S. If you use Texas Instrument instead of TMP117, it should work similarly. 

 

Thursday, August 31, 2023

Using Z-Wave Multilevel sensor example running on BRD2603A/ZGM230S to read temperature from DS18B20 one-wire sensor

The following example shows you how to use Z-Wave 800 Multilevel sensor example running on BRD2603A/ZGM230S to read temperature from DS18B20 one-wire sensor.

1. Connect DS18B20 Vdd, GND, and DQ (add extra 4.7K pull-high to Vdd) to pin 20, 1, and 2(PB03) on EXP-header of BRD2603A.

2. Install USTIMER, Z-Wave Debug, and Z-Wave Debug Print in project software component to use microsecond delay API USTIMER_DelayIntSafe and DEBUGPRINT to output data to SSv5 console 1.

3. Add the following code into MultilevelSensor_interface_sensor.c

#include "em_gpio.h"
#include "ustimer.h" //For microsecond delay
#include "em_core_generic.h" //For critical section

//Use PB03 on BRD2603A
#define DS_GPIO_PORT 1 //gpioPortB
#define DS_GPIO_PIN  3

#define CMD_CONVERTTEMP 0x44
#define CMD_RSCRATCHPAD 0xbe
#define CMD_WSCRATCHPAD 0x4e
#define CMD_CPYSCRATCHPAD 0x48
#define CMD_RECEEPROM 0xb8
#define CMD_RPWRSUPPLY 0xb4
#define CMD_SEARCHROM 0xf0
#define CMD_READROM 0x33
#define CMD_MATCHROM 0x55
#define CMD_SKIPROM 0xcc
#define CMD_ALARMSEARCH 0xec
#define DECIMAL_STEPS_12BIT 625 //.0625

inline void pullLineLow() {
    GPIO_PinModeSet(DS_GPIO_PORT, DS_GPIO_PIN, gpioModePushPull, 0);
}

inline void releaseLine() {
    GPIO_PinModeSet(DS_GPIO_PORT, DS_GPIO_PIN, gpioModeInputPull, 1);
}

inline void delayUs(uint16_t us) {
  USTIMER_DelayIntSafe(us);
}

inline uint32_t readLineState() {
    return GPIO_PinInGet(DS_GPIO_PORT, DS_GPIO_PIN);
}

void writeBit(uint8_t bit){
  //Pull line low for 1uS
  pullLineLow();
  delayUs(1);
  //If we want to write 1, release the line (if not will keep low)
  if(bit) {
        releaseLine();
    }
  //Wait for a while and release the line
  delayUs(20);
  releaseLine();
  delayUs(1);
}

uint8_t readBit(void){
  uint8_t bit = 0;
  //Pull line low for 1uS
  pullLineLow();
  delayUs(1);
  //Release line and wait for a while
  releaseLine();
  delayUs(8);
  //Read line value
  if(readLineState()){
        bit=1;
    }
  //Wait for a while to return read value
  delayUs(40);
  return bit;
}

uint8_t readByte(void){
  uint8_t i = 8, n = 0;
  while(i--){
    //Shift one position right and store read value
    n >>= 1;
    n |= (readBit() << 7);
  }
  return n;
}

void writeByte(uint8_t b){
  uint8_t i = 8;
  while(i--){
    //Write actual bit and shift one position right to make the next bit ready
    writeBit(b & 1);
    b >>= 1;
  }
}

uint32_t reset(){
  uint32_t i;
  pullLineLow();
  delayUs(300);
  releaseLine();
  delayUs(60);
  i = readLineState(); //(0=OK, 1=ERROR)
  delayUs(300);
  return i;
}

/*
    Returns temperature read from DS18B20
    Reading is returned mutiplied by 10000 i.e.
    for 23.4560 degrees the result will be 234560
*/
uint32_t ds18b20GetTemparature(){
  USTIMER_Init();

  //Enter cirtical section
  CORE_DECLARE_IRQ_STATE;
  CORE_ENTER_CRITICAL();

  //Reset, skip ROM and start temperature conversion
  if(reset()) {
      DPRINT("DS18B20 is not responding---reset temperature conversion\n");
        return 0;
    }
  writeByte(CMD_SKIPROM);
  writeByte(CMD_CONVERTTEMP);

  //Wait until conversion is complete
  uint16_t timeout = 0xFFFF;
  while(!readBit() && timeout > 0) {
        timeout--;
        //Feed WDG to avoid WDG reboot.
        zpal_feed_watchdog();
    }
    if(0 == timeout) {
        DPRINT("DS18B20 temperature conversion has timed out\n");
        return 0;
    }

  //Reset, skip ROM and send command to read Scratchpad
  if(reset()) {
      DPRINT("DS18B20 is not responding---reset Scratchpad\n");
        return 0;
    }
  writeByte(CMD_SKIPROM);
  writeByte(CMD_RSCRATCHPAD);

  uint8_t scratchpad[2] = {0, 0};
  //Read Scratchpad (only 2 first bytes)
  scratchpad[0] = readByte();
  scratchpad[1] = readByte();

  //Exit critial section.
  CORE_EXIT_CRITICAL();

  USTIMER_DeInit();

  int8_t digit = scratchpad[0] >> 4;
  digit |= (scratchpad[1] & 0x7) << 4;
  //Store decimal digits
  uint16_t decimal = scratchpad[0] & 0xf;
  decimal *= DECIMAL_STEPS_12BIT;

    return digit * 10000 + decimal;
}

4. Use the following two lines to replace "MultilevelSensor_temperature_humidity_sensor_read(&rh_data, &temp_data);" in cc_multilevel_sensor_air_temperature_interface_read_value.

    temp_data=ds18b20GetTemparature();
    temp_data=(int32_t)(temp_data/10);

5. Build and run the firmware on BRD2603A to see the following temperature reading from DS18B20.


 

Thursday, August 10, 2023

Using IO Stream and EXP pins on Silabs EFR32MG24+BRD4001A as second UART

The following steps show you how to create GSDK4.3.1/EmberZnet 7.3.1.0 Z3Light example with  BRD4186C+BRD4001A and use sl_iostream_write/sl_iostream_read to output/read data to/from USART1 to EXP header pin11(RX PA06)/p13(TX PA07).

1. Add exp instance from software component

圖片圖片2. Add the following code to main.c

  1. #include "sl_iostream.h"
  2. sl_iostream_t * exp_iostream = NULL;
  3. uint8_t rbuffer[128];
  4. size_t bread;
  5.  
  6. void app_init(void)
  7. {
  8. exp_iostream = sl_iostream_get_handle("exp");
  9. }
  10.  
  11. void app_process_action(void)
  12. {
  13. sl_iostream_read(exp_iostream,rbuffer,128,&bread);
  14. if(bread>0){
  15. sl_iostream_write(exp_iostream,rbuffer,bread);
  16. }
  17. }

 3. Build and run the example.

Saturday, April 15, 2023

Amazon Sidewalk Test over BLE using Silcon Labs EFR32MG24 BRD4186C

Amazon Sidewalk is broadly announced in US market. It leverage exising Amazon devices such as Echo, Ring Alarm Panel, or DoorPhone. The following steps show you how to setup Silicon Labs EFR32MG24 radio board BRD4186C to test sending and receiving packets by Amazon Sidewalk. 

1. Setup my Amazon Echo 4th generation. Most important thing is that Amazon Sidewalk is only available in US region so your IP address needs to be in US region. If not, you have to setup VPN for this.

2. Connect BRD4186C to my desktop and start Simplicity Studio v5 to create "Amazon Sidewalk - SoC Bluetooth Hello Neighbor" project, which is available in Silicon Labs GSDK 4.2.2.

3. Add and revise the following code in on_sidewalk_msg_received to receive on/off command (1 as on and 0 as off) later from AWS IoT MQTT client to toggle LED0 on BRD4001A or BRD4002A mainboard.

#include <stdlib.h>
#include "sl_simple_led.h"

extern const sl_led_t sl_led_led0;

static void on_sidewalk_msg_received(const struct sid_msg_desc *msg_desc,
                                     const struct sid_msg *msg,
                                     void *context)
{
  char cmd;
  UNUSED(context);
  app_log_info("App - received message (type: %d, id: %u, size %u)", (int)msg_desc->type, msg_desc->id, msg->size);
  app_log_info("App - %s", (char *) msg->data);
  memcpy(&cmd, msg->data,1);
  if(cmd=='1'){
    sl_led_turn_on(&sl_led_led0);
    app_log_info("from YK App - on");
  }
  else if(cmd=='0'){
      sl_led_turn_off(&sl_led_led0);
      app_log_info("from YK App - off");
    }
}

4. Revise the following code in send_counter_update to send "YK Amazon Sidewalk test %d" when press button 1 on BRD4001A or BRD4002A mainboard.

char buffer[64];

static void send_counter_update(app_context_t *app_context)
{
  if (app_context->state == STATE_SIDEWALK_READY
      || app_context->state == STATE_SIDEWALK_SECURE_CONNECTION) {
    app_log_info("App - sending counter update: %d", app_context->counter);

    sprintf(buffer,"YK Amazon Sidewalk test %d\0", app_context->counter);
    struct sid_msg msg = {
      .data = (uint8_t *)buffer,//&app_context->counter,
      .size = strlen(buffer)//sizeof(uint8_t)
    };
    struct sid_msg_desc desc = {
      .type = SID_MSG_TYPE_NOTIFY,
      .link_type = SID_LINK_TYPE_ANY,
    };

    sid_error_t ret = sid_put_msg(app_context->sidewalk_handle, &msg, &desc);
    if (ret != SID_ERROR_NONE) {
      app_log_error("App - failed queueing data: %d", (int)ret);
    } else {
      app_log_info("App - queued data message id: %u", desc.id);
    }

    app_context->counter++;
  } else {
    app_log_error("App - sidewalk is not ready yet");
  }
}

5. Build and download "Amazon Sidewalk - SoC Bluetooth Hello Neighbor" firmware into BRD4186C. Also need to download bootloader into BRD4186C to make application work.

6. Login your Amazon "Identity and Access Management (IAM)" and go to "Security credentials" to create "access key ID" and "secret access key" for provision your Amazon Sidewalk device.

7. Refer to AWS Command Line Interface (CLI) to Install AWS CLI version 1.

8. Start a Dos console to run "aws configure" to input your "Security credentials" to create "access key ID" that are created in step 6.

9. Follow steps in Provision your Amazon Sidewalk Device.

10. Disconnect and reconnect USB cable from BRD4001A/BRD4002A to restart BRD4186C, and start RTT viewer. You should able to see your "Amazon Sidewalk - SoC Bluetooth Hello Neighbor" running on BRD4186C.

10. You can press button 0 on BRD4001A or BRD4002A mainboard to get connect and button 1 to send messages. You can refer to "Send Data"section in Interacting with the Cloud to use AWS MQTT client test to check message received.


11. For sending on/off message to control LED0 on BRD4001A or BRD4002A mainboard, you can refer to "Receive Data"section in Interacting with the Cloud to start a Dos console to use the following command to send on (or off) command.

aws iotwireless send-data-to-wireless-device --id=xxxx --transmit-mode 0 --payload-data="MQ==" --wireless-metadata "Sidewalk={Seq=1}"

If the device receives command from Amazon Sidewalk, it would pops the following message on RTT viewer and LED0 would be turned on (or off).

p.s. payload-data is Base64 encoded data. "MQ==" is equal to "1" which is used for on command in my code.

12. For power consumption, it's about 132uA when device is idle and about 810 uA when device is receiving message or sending message according to Energy Profiler. These power consumption numbers are quite satisfying for battery power device.



Thursday, April 13, 2023

How to add one extra endpoint for Matter/OpenThread Light.

The following steps show you how to add one extra endpoint for Matter/OpenThread Light with Silicon Labs EFR32MG24 BRD4187C radio board. 

1. Create MatterLightOverThread with Silicon Labs EFR32MG24 BRD4187C radio board first.

2. Start ZAP tool (Zigbee Cluster Configurator) and copy endpoint 1 to create endpoint 2.

3. Enable all required client->server commands for endpoint 2 of on/off and level cluster in ZAP tool.

 

4. Make a copy of LightingManager.h to LightingManager_ep2.h and LightingManager.cpp to LightingManager_ep2.cpp.

5. Add "#include "LightingManager_ep2.h"" and the following items for endpoint 2 in AppTask.h.

    static void ActionInitiated_ep2(LightingManager_ep2::Action_t aAction, int32_t aActor);
    static void ActionCompleted_ep2(LightingManager_ep2::Action_t aAction);
    static void UpdateClusterState_ep2(intptr_t context);

6. Add led2 for endpoint by clicking "Adding New Instances" in Simple LED SOFTWARE COMPONENTS and configure led2 to use PA05 which is pin 7 on EXP header of BRD4001A/BRD4002A mainboard.

7. Add "#define LIGHT_LED_EP2 &sl_led_led2" and "LEDWidget sLightLED_ep2;" for led light of endpoint 2 in AppTask.c.

8. Add implementation of ActionInitiated_ep2, ActionCompleted_ep2, and UpdateClusterState_ep2 in AppTask.c.

void AppTask::ActionInitiated_ep2(LightingManager_ep2::Action_t aAction, int32_t aActor)
{
    // Action initiated, update the light led
    bool lightOn = aAction == LightingManager_ep2::ON_ACTION;
    EFR32_LOG("Turning _ep2 light %s", (lightOn) ? "On" : "Off")

#ifdef ENABLE_WSTK_LEDS
    sLightLED_ep2.Set(lightOn);
#endif // ENABLE_WSTK_LEDS

#ifdef DISPLAY_ENABLED
    sAppTask.GetLCD().WriteDemoUI(lightOn);
#endif
#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
    if (aActor == AppEvent::kEventType_Button)
    {
        sAppTask.mSyncClusterToButtonAction = true;
    }
#endif
}

void AppTask::ActionCompleted_ep2(LightingManager_ep2::Action_t aAction)
{
    // action has been completed bon the light
    if (aAction == LightingManager_ep2::ON_ACTION)
    {
        EFR32_LOG("EP2 Light ON")
    }
    else if (aAction == LightingManager_ep2::OFF_ACTION)
    {
        EFR32_LOG("EP2 Light OFF")
    }
#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
    if (sAppTask.mSyncClusterToButtonAction)
    {
        chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterState_ep2, reinterpret_cast<intptr_t>(nullptr));
        sAppTask.mSyncClusterToButtonAction = false;
    }
#endif
}

void AppTask::UpdateClusterState_ep2(intptr_t context)
{
    uint8_t newValue = LightMgr_ep2().IsLightOn();

    // write the new on/off value
    EmberAfStatus status = OnOffServer::Instance().setOnOffValue(2, newValue, false);

    if (status != EMBER_ZCL_STATUS_SUCCESS)
    {
        EFR32_LOG("ERR: updating ep2 on/off %x", status);
    }

9. Add kEventType_Light_ep2 enum behind kEventType_Light in AppEvent.h and use the following codes to replace original codes in LightActionEventHandler to support endpoint 2 light action.

    void AppTask::LightActionEventHandler(AppEvent * aEvent)
{
    bool initiated = false;
    LightingManager::Action_t action;
    LightingManager_ep2::Action_t action_ep2;
    int32_t actor;
    int32_t actor_ep2;
    CHIP_ERROR err = CHIP_NO_ERROR;

    if (aEvent->Type == AppEvent::kEventType_Light)
    {
        action = static_cast<LightingManager::Action_t>(aEvent->LightEvent.Action);
        actor  = aEvent->LightEvent.Actor;
    }
    else if (aEvent->Type == AppEvent::kEventType_Light_ep2)
      {
          action_ep2 = static_cast<LightingManager_ep2::Action_t>(aEvent->LightEvent.Action);
          actor_ep2  = aEvent->LightEvent.Actor;
      }
#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
    else if (aEvent->Type == AppEvent::kEventType_Button)
    {
        action = (LightMgr().IsLightOn()) ? LightingManager::OFF_ACTION : LightingManager::ON_ACTION;
        actor  = AppEvent::kEventType_Button;
    }
#endif
    else
    {
        err = APP_ERROR_UNHANDLED_EVENT;
    }

    if (err == CHIP_NO_ERROR)
    {
        if (aEvent->Type == AppEvent::kEventType_Light){
          initiated = LightMgr().InitiateAction(actor, action);

          if (!initiated)
          {
              EFR32_LOG("Action is already in progress or active.");
          }
        }
        else if (aEvent->Type == AppEvent::kEventType_Light_ep2)
        {
          initiated = LightMgr_ep2().InitiateAction(actor_ep2, action_ep2);

          if (!initiated)
          {
              EFR32_LOG("_ep2 Action is already in progress or active.");
          }
        }
    }
}

10. Add "#include "LightingManager_ep2.h"" ZclCallbacks.cpp and use the following codes in MatterPostAttributeChangeCallback function.

void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
                                       uint8_t * value)
{
    ClusterId clusterId     = attributePath.mClusterId;
    AttributeId attributeId = attributePath.mAttributeId;
    EndpointId endpoint = attributePath.mEndpointId;
    ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));

    if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
    {
        //ChipLogProgress(Zcl, "<---YK---> MatterPostAttributeChangeCallback Endpoint %d on/off value=%d", endpoint, value);
        if(endpoint==1)
          LightMgr().InitiateAction(AppEvent::kEventType_Light, *value ? LightingManager::ON_ACTION : LightingManager::OFF_ACTION);
        else if(endpoint==2)
          LightMgr_ep2().InitiateAction(AppEvent::kEventType_Light_ep2, *value ? LightingManager_ep2::ON_ACTION : LightingManager_ep2::OFF_ACTION);
    }
    else if (clusterId == LevelControl::Id)
    {
        ChipLogProgress(Zcl, "Level Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
                        ChipLogValueMEI(attributeId), type, *value, size);

        // WIP Apply attribute change to Light
    }
    else if (clusterId == ColorControl::Id)
    {
        ChipLogProgress(Zcl, "Color Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
                        ChipLogValueMEI(attributeId), type, *value, size);

        // WIP Apply attribute change to Light
    }
    else if (clusterId == OnOffSwitchConfiguration::Id)
    {
        ChipLogProgress(Zcl, "OnOff Switch Configuration attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
                        ChipLogValueMEI(attributeId), type, *value, size);

        // WIP Apply attribute change to Light
    }
    else if (clusterId == Identify::Id)
    {
        ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
                        ChipLogValueMEI(attributeId), type, *value, size);
    }
}

11. Build and download MatterLightOverThread into BRD4187C

12. Join the MatterLightOverThread device into Matter/Thread network of Apple Home mini with Hoe App and you can see two endpoints in Home App to control them separately.


 

 p.s. for your references, on/off command received flow in Matter source code is like the followings:

InteractionModelEngine::OnMessageReceived
ProcessInvokeRequest
ProcessCommandDataIB
DispatchCommand
DispatchSingleClusterCommand
DispatchServerCommand
emberAfOnOffClusterOffCallback
OnOffServer::Instance().offCommand(commandPath);
OnOffServer::setOnOffValue
Attributes::OnOff::Set
emberAfWriteServerAttribute [#define emberAfWriteServerAttribute emberAfWriteAttribute (af.h)]
emberAfWriteAttribute
emAfWriteAttribute
MatterPostAttributeChangeCallback (ZclCallbacks.cpp)

Friday, December 23, 2022

Matter/OpenThread Border Router/Gateway Reality in the field by end of 2022

It's almost in the end of 2022 and Matter/OpenThread definitely would be noted as one of biggest event in IOT. The design philosophy of Matter is the convergence of IOT so end user won't have panic selecting and using IOT appliances on the markets. Until now, there are lots of company announcing Matter Border Router/Gateway support. I try to figure out or test the reality of such event and hope can help others further understanding this topic.

1. Apple: support Matter to its devices with iOS 16.1, iPadOS 16.1, macOS Ventura, watchOS 9.1, tvOS 16.1, and HomePod 16.1 software updates on Nov. 2022.I try to build Matter/OpenThread light-app, Thermostat, and light-switch-app applications on Silicon Labs EFR32 SoC and all of them work fluently. Incredible! Don't have Matter/Wifi device to test if it work but I would guess it works since Matter/OpenThread works in my tests.

2. Google: release firmware update including the original Google Home speaker, Google Home Mini, Nest Mini, Nest Audio, Nest Hub (1st and 2nd gen), Nest Hub Max, and the new Nest Wifi Pro to support Matter on Dec. 2022. I also use Matter/OpenThread light-app, Thermostat, and light-switch-app applications on Silicon Labs EFR32 SoC to test this. However, it always stops at the end of commissioning process and I believe this is bug and compatibility issue from Google. Since Matter/OpenThread devuce cannot work, I won't expect Matter/Wifi device would work but I welcome someone provides information to prove it works.

Add on Jan. 30th 2023, you can add Matter/OpenThread light-app to Goggle Nest Hub Max by using Android 13 camera to scan QR-code on device.

3. Amazon:  rolling out Matter/Wifi support for 17 Echo devices on Dec. 2022 too and an Android phone is required for Matter setup. Amazon also says that Matter/OpenThread and iOS support will arrive sometime in 2023. Since I don't have Matter/Wifi device, I cannot prove if it works. I also welcome someone provides information to prove it works.

4. Philips: announce they will release new firmware for Hue Bridge in the first quarter of 2023.

5. Samsung: rolling out an OTA update for SmartThings v2 and v3 hubs to add Matter compatibility (via Samsung). The v2 hub will let you control Matter-compatible smart home devices over Wi-Fi and Ethernet, with Thread border router support limited to the v3 hub and SmartThings dongle. I don't have SmartThings hubs to test this and I don't see anyone reports it works by surfing/Google on Internet. I also welcome someone provides information to prove it works.

6.Aqara: users will first gain access to Matter in December 2022 via the Aqara Hub M2 through an OTA (over-the-air) update, which will allow existing Aqara Zigbee devices to become compatible with Matter. I don't have Aqara Hub M2 to test this and also don't see anyone reports this works by surfing/Google on Internet. I also welcome someone provides information to prove it works.

It seems lots of company announcing Matter support but it not actually happens in the field. Maybe it's still too early to judge anything on Matter protocol now. If you are interested in Matter device, I would suggest you to watch and monitor it for now. I would guess 2023 Q2 might be a good timing to check the Matter reality again.

By the way, you won't see much news or press from Apple Matter support but actually they integrate HomeKit with Matter/Thread seamlessly. I would give them a thumb up for solid technology to support this. If you have money, go to buy Apple stock before you buy Apple products.

Friday, October 28, 2022

Build and run Matter and OpenThread lighting-app on EFR32MG24 to work with Apple HomePod Mini and iPhone Home App.

The following steps show you how to build and run Matter and OpenThread lighting-app on EFR32MG24 to work with Apple HomePod Mini and iPhone Home App.

1. Refer to steps 1 and 2 in How to setup and build Matter/CHIP EFR32 Lighting Example on Ubuntu 20.04 to setup Ubuntu 20.04 build environment and git master Matter source codes.

2. Switch to v1.0-branch and workable commit.

    cd connectedhomeip/
    git fetch origin
    git branch -a
    git checkout -b v1.0 remotes/origin/v1.0-branch
    git submodule update --init --recursive
    git checkout 561d23d0db215a99705ff0696e73853c8edf11b2
 

3. Build lighting-app for BRD4186C

    ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32/ ./out/lighting-app BRD4186C

4. Download chip-efr32-lighting-example.hex (can be found under out/lighting-app/BRD4186C) in to BRD4186C+BRD4001A.

5. Make sure your Apple HomePod Mini and iPhone are update to OS 16.1.

6. Start Home App on your iPhone and scan the QR code on LCD of BRD4186C+BRD4001A. Following Home App wizard to complete settings.


7. You can have the Matter enable Light connecting with HomePod Mini and control it with iPhone Home App.

P.S. You can add the following code into AppTask::Init() in AppTask.c to print URL on RTT viewer output to generate QR code on browser.

PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));

P.S. You can use the following command to build lock-app SED for low power device test.

./scripts/examples/gn_efr32_example.sh ./examples/lock-app/efr32/ ./out/lock-app_SED BRD4186C --sed "chip_detail_logging=false chip_automation_logging=false chip_progress_logging=false is_debug=false show_qr_code=true chip_build_libshell=false disable_lcd=false enable_openthread_cli=false"

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;
}

Tuesday, May 31, 2022

How to use custom and increment token in Silicon Labs GSDK 4.x and EmberZnet 7.x

The following steps 2-4 show you how to use custom basic token and steps 5-7 show you how to use custom increment token in Silicon Labs GSDK 4.x and EmberZnet 7.x.

1. Turn on "Enable Custom Tokens" in Token Manager.


 

2.Add the following codes to sl_custom_token_header.h.

        #define NVM3KEY_BASICTOKEN1 (NVM3KEY_DOMAIN_USER | 0x4100)
        #define BASICTOKEN1_DEFAULT  0
        #ifdef DEFINETYPES
        typedef uint16_t tokTypeBasicToken1;
        #endif
        #ifdef DEFINETOKENS
        DEFINE_BASIC_TOKEN(BASICTOKEN1,
                                                  tokTypeBasicToken1,
                                                  BASICTOKEN1_DEFAULT)
        #endif

3. Implement counter incrementing and store to custom token TOKEN_BASICTOKEN1 when button is pressed in app.c. Add related code in sl_button_on_change.

void sl_button_on_change(const sl_button_t *handle)
{
  uint16_t cnt;
  if (sl_button_get_state(handle) == SL_SIMPLE_BUTTON_RELEASED) {
      sl_token_get_data(NVM3KEY_BASICTOKEN1, 0x7f, &cnt, sizeof(cnt));
      cnt++;
      sl_token_set_data(NVM3KEY_BASICTOKEN1, 0x7f, &cnt, sizeof(cnt));
  }
}

4. Build and download application into EFR32 to test counter read and set with increment in custom token.
 

5. Add the following codes to sl_custom_token_header.h.         

    #define NVM3KEY_COUNTERTOKEN1 (NVM3KEY_DOMAIN_USER | 0x4104)
    #define COUNTERTOKEN1_DEFAULT 0
    #ifdef DEFINETYPES
        typedef uint32_t tokTypeCounterToken1;
    #endif
    #ifdef DEFINETOKENS
        DEFINE_COUNTER_TOKEN(COUNTERTOKEN1,
                                                         tokTypeCounterToken1,
                                                         COUNTERTOKEN1_DEFAULT)
    #endif

6. Implement counter incrementing using increment token by adding related code in sl_button_on_change.

    void sl_button_on_change(const sl_button_t *handle)    
    {
      uint32_t buf;
      if (sl_button_get_state(handle) == SL_SIMPLE_BUTTON_RELEASED) {
          sl_token_get_data(NVM3KEY_COUNTERTOKEN1, 0x7f, &buf, sizeof(buf));
          sl_token_increment_counter(NVM3KEY_COUNTERTOKEN1);
          sl_token_get_data(NVM3KEY_COUNTERTOKEN1, 0x7f, &buf, sizeof(buf));
      }
    }
 7. Build and download application into EFR32 to test increment counter token when button is pressed