How to combine USB CDC ACM and MODEL

Hello,

I would like to enter simple commands such as on, off to the USB CDC ACM, and then set the parameters in the model through string comparing.

(now i'm trying Generic onoff model, but in the end, I want to pass the data through the vendor model) 

following is my idea.

case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
    {
        ret_code_t ret;
        static uint8_t index = 0;
        static char StrTrue[] = "begin is ok\r\r\n";
        static char StrFalse[] = "end is ok\r\r\n";
        static char cmp[] = "on\r\r\n";
        index++;

        do
        {
            if ((m_cdc_data_array[index - 1] == '\n') ||
                (m_cdc_data_array[index - 1] == '\r') ||
                (index >= (244)))
            {
                if (index > 1)
                {   
                    generic_onoff_set_params_t set_params;
                    model_transition_t transition_params;
                    uint32_t status = NRF_SUCCESS;
                    static uint8_t tid = 0;

                    nrf_gpio_pin_toggle(BSP_LED_0);
                    uint16_t length = (uint16_t)index;
                    if (length + sizeof(ENDLINE_STRING) < 244)
                    {
                        memcpy(m_cdc_data_array + length, ENDLINE_STRING, sizeof(ENDLINE_STRING));
                        length += sizeof(ENDLINE_STRING);
                    }
                    
                    if (strcmp(m_cdc_data_array, cmp) == 0) 
                        set_params.on_off = APP_STATE_ON;
                    else
                        set_params.on_off = APP_STATE_OFF;

                    set_params.tid = tid++;
                    transition_params.delay_ms = APP_ONOFF_DELAY_MS;
                    transition_params.transition_time_ms = APP_ONOFF_TRANSITION_TIME_MS;
                    
                    //(void)access_model_reliable_cancel(m_clients[0].model_handle);
                    app_usbd_cdc_acm_write(&m_app_cdc_acm, StrTrue, sizeof(StrTrue) / sizeof(StrTrue[0]));
                    status = generic_onoff_client_set_unack(&m_clients[1], &set_params,
                                                &transition_params, APP_UNACK_MSG_REPEAT_COUNT);
                    app_usbd_cdc_acm_write(&m_app_cdc_acm, StrFalse, sizeof(StrFalse) / sizeof(StrFalse[0]));
                }

                index = 0;
            }

            /*Get amount of data transferred*/
            //size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
            //NRF_LOG_DEBUG("RX: size: %lu char: %c", size, m_cdc_data_array[index - 1]);

            /* Fetch data until internal buffer is empty */
            ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                        &m_cdc_data_array[index],
                                        1);
            if (ret == NRF_SUCCESS)
            {
                index++;
            }
        }
        while (ret == NRF_SUCCESS);

        break;
    }

However, it doesn't work well when it passes GENERIC ONOFF OPCODE through generic_onoff_client_set_unack().

it will get stuck with four leds always on.

Any ideas? Thanks!

  • Hello!

    All four leds on would indicate you have run into some kind of error. Do you have any log output with error messages, or an error code?

    You are running into an error inside generic_onoff_client_set_unack()?

    Br,
    Joakim

  • Hi!

    Joakim,Thanks for your reply.

    Now I have solved this problem by using a timer.

    APP_TIMER_DEF(zqaking_timer_id);
    
    static void zqaking_app_timer_handler(void * p_unused)
    {   
        if (DataChange)
        {
            DataChange = false;
            uint32_t status;
    
            app_usbd_cdc_acm_write(&m_app_cdc_acm, my_data_buffer, my_data_buffer_lenght);
            status = hx_model_client_opcode_tx_unreliable(&m_hx_model_client[0], my_data_buffer, my_data_buffer_lenght, APP_UNACK_MSG_REPEAT_COUNT);
        }
    }
    
    static void start(void)
    {
        ···
        ERROR_CHECK(app_timer_create(&zqaking_timer_id, APP_TIMER_MODE_REPEATED, zqaking_app_timer_handler));
        ERROR_CHECK(app_timer_start(zqaking_timer_id, 6000, NULL));
        ···
    }

    following is USB CDC ACM rx event:
    case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
            {
                ret_code_t ret;
                static uint8_t index = 0;
                index++;
    
                do
                {
                    if ((m_cdc_data_array[index - 1] == '\n') ||
                        (m_cdc_data_array[index - 1] == '\r') ||
                        (index >= (244)))
                    {
                        if (index > 1)
                        {   
                            nrf_gpio_pin_toggle(BSP_LED_0);
                            uint16_t length = (uint16_t)index;
                            if (length + sizeof(ENDLINE_STRING) < 244)
                            {
                                memcpy(m_cdc_data_array + length, ENDLINE_STRING, sizeof(ENDLINE_STRING));
                                length += sizeof(ENDLINE_STRING);
                            }
                            memcpy(my_data_buffer, m_cdc_data_array, length);
                            my_data_buffer_lenght = length;
                            DataChange = true;
                        }
    
                        index = 0;
                    }
                    /* Fetch data until internal buffer is empty */
                    ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                &m_cdc_data_array[index],
                                                1);
                    if (ret == NRF_SUCCESS)
                    {
                        index++;
                    }
                }
                while (ret == NRF_SUCCESS);
    
                break;
            }


    I add a timer to check for changes in variable DATACHANGE, and this makes my program works well.
    Although I don't know the reason yet, I think there should be some kind of conflict between MESH and USB CDC ACM.

  • Thanks for sharing the solution.

    You are welcome to post a new ticket if you have any further questions.

    Br,
    Joakim

Related