본문 바로가기

[ST_MICRO]/STM32WB

STM32WB55 SSM - Zigbee 데이터 송수신 테스트

STM32WB55는 무선 관련 스텍이 별도의 코어에서 수행되고 필요에 따라서 원하는 무선 프로파일을 다운로드 해서 사용할 수 있는 구조이다. nRF5시리즈의 SoftStack과 유사한 구조 이다. 차이점이라면 별도의 코어로 동작하기 때문에 장단점이 있을 수 있겠다.

 

 

Zigbee 스택을 이용해서 무선으로 데이터 전송하는 테스트를 해 보자.

우선  Zigbee중 FFD(풀스택)을 다운로드 해서 테스트 해보면 좋을것 같다.

 

 

 

무선 스텍은 STM32WB_Copro_Wireless_Binaries 폴더에 있다.

 

 

소프트에어 스택 다운로드 방법은 STM32CubeProgrammer 를 이용하여 다운로드 하면 된다. 아래 그림과 같은 순서로 다운로드 하면된다. 주의 사항으로는 Start address 를 스택별, STM32WB 메모리 사양별로 다르게 지정해 주어야 한다.

 

 

Zigbee 예제를 이용해서 프로그램을 작성하려면  ST에서 제공하는 STM32_WPAN 라이브러리 폴더를 추가 해야 한다.

그리고 APP쪽에서 각 어플리케이션에 맞는 app_zigbee.c 를 추가해서 수정하면 된다.

 

 

 


 

Zigbee네트웍 연결

app_zigbee.c  코드에 Zigbee관련 처리 함수가 제공된다.

Zigbee 데이터 송수신을 위해 Zigbee 네트웍에 조인 해야 하는 APP_ZIGBEE_NwkFrom() 함수에서 처리 할 수 있다.

static void APP_ZIGBEE_NwkForm(void)
{
  if ((zigbee_app_info.join_status != ZB_STATUS_SUCCESS) && (HAL_GetTick() >= zigbee_app_info.join_delay))
  {
    struct ZbStartupT config;
    enum ZbStatusCodeT status;

    /* Configure Zigbee Logging */
    ZbSetLogging(zigbee_app_info.zb, ZB_LOG_MASK_LEVEL_5, NULL);

    /* Attempt to join a zigbee network */
    ZbStartupConfigGetProDefaults(&config);

    /* Set the centralized network */
    APP_DBG("Network config : APP_STARTUP_CENTRALIZED_END_DEVICE");
    config.startupControl = zigbee_app_info.startupControl;

    /* Using the default HA preconfigured Link Key */
    memcpy(config.security.preconfiguredLinkKey, sec_key_ha, ZB_SEC_KEYSIZE);

    config.channelList.count = 1;
    config.channelList.list[0].page = 0;
    config.channelList.list[0].channelMask = 1 << CHANNEL; /*Channel in use */

    /* Add End device configuration */
    config.capability &= ~(MCP_ASSOC_CAP_RXONIDLE | MCP_ASSOC_CAP_DEV_TYPE | MCP_ASSOC_CAP_ALT_COORD);
    config.endDeviceTimeout=ZED_SLEEP_TIME_30S;

    /* Using ZbStartupWait (blocking) */
    status = ZbStartupWait(zigbee_app_info.zb, &config);

    APP_DBG("ZbStartup Callback (status = 0x%02x)", status);
    zigbee_app_info.join_status = status;

    if (status == ZB_STATUS_SUCCESS) {
      /* Enabling Stop mode */
      UTIL_LPM_SetStopMode(1U << CFG_LPM_APP, UTIL_LPM_ENABLE);
      UTIL_LPM_SetOffMode(1U << CFG_LPM_APP, UTIL_LPM_DISABLE);

      /* USER CODE BEGIN 0 */
      zigbee_app_info.join_delay = 0U;
      zigbee_app_info.init_after_join = true;

      gZigbeeStatus = 1;

      //Led1Off();
      Led1Toggle();
      //BSP_LED_On(LED_BLUE);
    }

 

 

 

데이터 수신 콜백 함수

app_zigbee.c 에서 콜백 함수로 등록 하면 된다.

zigbee로 데이터를 받느면 custom_ls_set_cb() 함수가 수행되고 여기서 받은 데이터를 처리 하면 된다. 

static void APP_ZIGBEE_ConfigEndpoints(void)
{
  struct ZbApsmeAddEndpointReqT req;
  struct ZbApsmeAddEndpointConfT conf;

  APP_DBG("APP_ZIGBEE_ConfigEndpoints");
  memset(&req, 0, sizeof(req));
  req.profileId = ZCL_PROFILE_HOME_AUTOMATION;
  req.deviceId = ZCL_DEVICE_ONOFF_SWITCH;

  /* Endpoint: SW1_ENDPOINT */
  req.endpoint = SW1_ENDPOINT;
 
  ZbZclAddEndpoint(zigbee_app_info.zb, &req, &conf);
  assert(conf.status == ZB_STATUS_SUCCESS);

  /* Custom long string cluster server */
   zigbee_app_info.custom_ls_server = ZbZcl_custom_ls_ServerAlloc(zigbee_app_info.zb, \
          SW1_ENDPOINT, &custom_ls_server_cb, &zigbee_app_info);
   ZbZclClusterEndpointRegister(zigbee_app_info.custom_ls_server);
  
} /* config_endpoints */

static enum ZclStatusCodeT custom_ls_set_cb(struct ZbZclClusterT *clusterPtr, \
        struct set_custom_ls_command_req_t *cmd_req, \
        struct ZbZclAddrInfoT *src_info, void *arg)
{
	//char buf[64];
      char *msg = "";
      /* We display the message received here */
      //수신 데이터 처리
      printf(cmd_req->string);
      printf("\r\n");

#if 1
      if(memcmp((char*)&cmd_req->string[0],(char*)&msg[0],30)!=0)
      {
        rsp.one = ZCL_CUSTOM_LS_MISMATCH;
      }
      else
      {
        rsp.one = ZCL_CUSTOM_LS_MATCH;
      }
      
      /* Send the response */
      ZbZcl_custom_ls_ServerSendCommandRsp(clusterPtr, src_info, &rsp);
#endif
      BSP_LED_Toggle(LED_RED);
      return ZCL_STATUS_SUCCESS;
}

 

 

 

데이터 송신

ZbZclSet_custom_ls_ClientCommand() 함수를 이용하여 데이터를 전송할 수 있다.

int SendSensorMsg(char *msg)
{
    struct ZbApsAddrT dst;

    memset(&dst, 0, sizeof(dst));
    dst.mode = ZB_APSDE_ADDRMODE_SHORT; /* for unicast */
    dst.endpoint = SW1_ENDPOINT;
    dst.nwkAddr = 0x0000; /* Coordinator short address */

    Led1Toggle();

    if (ZbZclSet_custom_ls_ClientCommand(zigbee_app_info.custom_ls_client,
                                         &dst,msg, custom_ls_client_cb, NULL) != ZCL_STATUS_SUCCESS)
    {
    	APP_DBG("Error, ZbZclSet_custom_ls_ClientCommand failed (SW1_ENDPOINT)");

    	Led1Toggle();
    	return 3;
    }
    else
    {
    	gSendCount++;


    }
    return 0;
}

 

 

APP에서 사용자 인터페이스 처리는 app_entry.c 파일에 설정 할 수 있다.

스위치 입력에 따른 인터럽시 Zigbee 데이터 전송하는 코드를 작성했다.

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	  switch (GPIO_Pin) 
      {
	  case GPIO_PIN_4:
	  	SendSensorMsg("STM32WB55 Zigbee Data");
		break;
        
	  default:
	    break;
	  }
}
반응형