This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

multiple adc +multiple pwm

Hi, i am using nrf52840 development kit , four servo motor . using 15.2 sdk version

here i am controlling the angle using adc values , i am done with one servo motor . pwm+adc. Now i need to control the angle for all the four motors , how to do that ? how can  i add the four adc channels . 

  • In order to add an ADC channel, you only need to change the pin, and change the channel number:

    void saadc_init(void)
    {
        ret_code_t err_code;
        nrf_saadc_channel_config_t channel_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    
        err_code = nrf_drv_saadc_init(NULL, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_channel_init(0, &channel_config);
        APP_ERROR_CHECK(err_code);
        
        channel_config.pin_p = NRF_SAADC_INPUT_AIN1;
        err_code = nrf_drv_saadc_channel_init(1, &channel_config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    
    }

    Then I recommend setting the "SAMPLES_IN_BUFFER" = n*number of channels, where n=1,2,3,4,...

    If you do this to the saadc example from the SDK, you will get 2 channels in the ADC. Just keep adding these until you have 4.

    It is quite similar to the PWM. I don't know if you used the pwm_library or the pwm_driver example/libraries, but it should be possible to add channels in either one of them. In the PWM_library, you may need to add a second instance of PWM in order to control 4 channels.

    BR,

    Edvin

  • what about the timer ? static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0); , i need to change?

  • Only if you intend to use the Softdevice (the bluetooth low energy stack). In that case you can change it to 1. If not, you can use the same timer instance for all the channels.

    This is the timer that is used to trigger the ADC measurements. It is sufficient with one timer. The reason you need to change it if you use the softdevice is that the softdevice always will claim TIMER0 (and RTC0). 

  • while running i am getting this in debug terminal ,

    but i couldn't able to connect to the device , i switched to timer 3 for adc and timer 1 for one pwm . It is advertising continuously even i can't able to connect 

    here is my code

    #include <stdint.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf.h"
    #include "ble_hci.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_conn_params.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "nrf_ble_gatt.h"
    #include "app_timer.h"
    #include "ble_nus.h"
    #include "app_uart.h"
    #include "app_util_platform.h"
    #include "bsp_btn_ble.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "nrf_drv_usbd.h"
    #include "nrf_drv_clock.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    #include "nrf_drv_power.h"
    
    #include "app_error.h"
    #include "app_util.h"
    #include "app_usbd_core.h"
    #include "app_usbd.h"
    #include "app_usbd_string_desc.h"
    #include "app_usbd_cdc_acm.h"
    #include "app_usbd_serial_num.h"
    
    #include "pca10056.h"
    #include "boards.h"
    
    #include "C:\nRF5_SDK_15.2.0_9412b96\nRF5_SDK_15.2.0_9412b96\components\libraries\pwm\app_pwm.h"
    #include "nrf_drv_saadc.h"
    #include "nrf_drv_ppi.h"
    #include "nrf_drv_timer.h"
    
    #define LED_BLE_NUS_CONN (BSP_BOARD_LED_0)
    #define LED_BLE_NUS_RX   (BSP_BOARD_LED_1)
    #define LED_CDC_ACM_CONN (BSP_BOARD_LED_2)
    #define LED_CDC_ACM_RX   (BSP_BOARD_LED_3)
    
    
    #define SAMPLES_IN_BUFFER 4
    volatile uint8_t state = 1;
    
    static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(3);
    //static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];
    static nrf_saadc_value_t       m_buffer_pool[2][SAMPLES_IN_BUFFER];
    static nrf_ppi_channel_t     m_ppi_channel;
    static uint32_t              m_adc_evt_counter;
    #define LED_BLINK_INTERVAL 800
    
     uint16_t adc_value1,adc_value2,adc_value3,adc_value4,adc_value;
    
    
    APP_TIMER_DEF(m_blink_ble);
    APP_TIMER_DEF(m_blink_cdc);
    
    
    
    static volatile bool ready_flag; 
     uint16_t adc_value1,adc_value2,adc_value3,adc_value4,adc_value;
    APP_PWM_INSTANCE(PWM1,1);  // Create the instance "PWM1" using TIMER1.  Enable the TIMER1 
    
    //APP_PWM_INSTANCE(PWM2,2);  //  Create the instance "PWM2" using TIMER2. Enable the Timer2
    
    int val;
    
    /**
     * @brief App timer handler for blinking the LEDs.
     *
     * @param p_context LED to blink.
     */
    void blink_handler(void * p_context)
    {
        bsp_board_led_invert((uint32_t) p_context);
    }
    
    #define ENDLINE_STRING "\r\n"
    
    
    // USB DEFINES START
    static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                        app_usbd_cdc_acm_user_event_t event);
    
    #define CDC_ACM_COMM_INTERFACE  0
    #define CDC_ACM_COMM_EPIN       NRF_DRV_USBD_EPIN2
    
    #define CDC_ACM_DATA_INTERFACE  1
    #define CDC_ACM_DATA_EPIN       NRF_DRV_USBD_EPIN1
    #define CDC_ACM_DATA_EPOUT      NRF_DRV_USBD_EPOUT1
    
    static char m_cdc_data_array[BLE_NUS_MAX_DATA_LEN];
    
    /** @brief CDC_ACM class instance */
    APP_USBD_CDC_ACM_GLOBAL_DEF(m_app_cdc_acm,
                                cdc_acm_user_ev_handler,
                                CDC_ACM_COMM_INTERFACE,
                                CDC_ACM_DATA_INTERFACE,
                                CDC_ACM_COMM_EPIN,
                                CDC_ACM_DATA_EPIN,
                                CDC_ACM_DATA_EPOUT,
                                APP_USBD_CDC_COMM_PROTOCOL_AT_V250);
    
    // USB DEFINES END
    
    // BLE DEFINES START
    #define APP_BLE_CONN_CFG_TAG            1                                           /**< A tag identifying the SoftDevice BLE configuration. */
    
    #define APP_FEATURE_NOT_SUPPORTED       BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2        /**< Reply when unsupported features are requested. */
    
    #define DEVICE_NAME                     "Nordic_USBD_BLE_UART"                      /**< Name of device. Will be included in the advertising data. */
    #define NUS_SERVICE_UUID_TYPE           BLE_UUID_TYPE_VENDOR_BEGIN                  /**< UUID type for the Nordic UART Service (vendor specific). */
    
    #define APP_BLE_OBSERVER_PRIO           3                                           /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    
    #define APP_ADV_INTERVAL                64                                          /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
    #define APP_ADV_DURATION                18000                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    
    
    #define MIN_CONN_INTERVAL               MSEC_TO_UNITS(20, UNIT_1_25_MS)             /**< Minimum acceptable connection interval (20 ms). Connection interval uses 1.25 ms units. */
    #define MAX_CONN_INTERVAL               MSEC_TO_UNITS(75, UNIT_1_25_MS)             /**< Maximum acceptable connection interval (75 ms). Connection interval uses 1.25 ms units. */
    #define SLAVE_LATENCY                   0                                           /**< Slave latency. */
    #define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)             /**< Connection supervisory timeout (4 seconds). Supervision Timeout uses 10 ms units. */
    #define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)                       /**< Time from initiating an event (connect or start of notification) to the first time sd_ble_gap_conn_param_update is called (5 seconds). */
    #define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)                      /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
    #define MAX_CONN_PARAMS_UPDATE_COUNT    3                                           /**< Number of attempts before giving up the connection parameter negotiation. */
    
    #define DEAD_BEEF                       0xDEADBEEF                                  /**< Value used as error code on stack dump. Can be used to identify stack location on stack unwind. */
    
    #define UART_TX_BUF_SIZE                256                                         /**< UART TX buffer size. */
    #define UART_RX_BUF_SIZE                256                                         /**< UART RX buffer size. */
    
    
    BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT);                                   /**< BLE NUS service instance. */
    NRF_BLE_GATT_DEF(m_gatt);                                                           /**< GATT module instance. */
    BLE_ADVERTISING_DEF(m_advertising);                                                 /**< Advertising module instance. */
    
    uint8_t ble_val[];
    uint32_t i;
    static uint16_t   m_conn_handle          = BLE_CONN_HANDLE_INVALID;                 /**< Handle of the current connection. */
    static uint16_t   m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3;            /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
    static ble_uuid_t m_adv_uuids[]          =                                          /**< Universally unique service identifier. */
    {
        {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
    };
    static char m_nus_data_array[BLE_NUS_MAX_DATA_LEN];
    
    // BLE DEFINES END
    
    /**
     * @brief Function for assert macro callback.
     *
     * @details This function will be called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and does not fit a final product. You need to analyze
     *          how your product is supposed to react in case of an assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in] line_num    Line number of the failing ASSERT call.
     * @param[in] p_file_name File name of the failing ASSERT call.
     */
    void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(DEAD_BEEF, line_num, p_file_name);
    }
    
    /** @brief Function for initializing the timer module. */
    static void timers_init(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
        err_code = app_timer_create(&m_blink_ble, APP_TIMER_MODE_REPEATED, blink_handler);
        APP_ERROR_CHECK(err_code);
        err_code = app_timer_create(&m_blink_cdc, APP_TIMER_MODE_REPEATED, blink_handler);
        APP_ERROR_CHECK(err_code);
    }
    
    /**
     * @brief Function for the GAP initialization.
     *
     * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of
     *          the device. It also sets the permissions and appearance.
     */
    static void gap_params_init(void)
    {
        uint32_t                err_code;
        ble_gap_conn_params_t   gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *) DEVICE_NAME,
                                              strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
        gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
        gap_conn_params.slave_latency     = SLAVE_LATENCY;
        gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**
     * @brief Function for handling the data from the Nordic UART Service.
     *
     * @details This function processes the data received from the Nordic UART BLE Service and sends
     *          it to the USBD CDC ACM module.
     *
     * @param[in] p_evt Nordic UART Service event.
     */
    static void nus_data_handler(ble_nus_evt_t * p_evt)
    {
        
        if (p_evt->type == BLE_NUS_EVT_RX_DATA)
        {
            uint32_t err_code;
            
       
            NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART.");
            NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
       
                for ( i = 0; i < p_evt->params.rx_data.length; i++)
                {
                     ble_val[i] = p_evt->params.rx_data.p_data[i];
                }
       /*    if(ble_val[0] == '1')
           {
                    nrf_gpio_pin_set(ARDUINO_8_PIN);
                    
            }
             if(ble_val[0] == '0')
           {
                    nrf_gpio_pin_clear(ARDUINO_8_PIN);
                    
            }*/
    
            if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == '\r')
            {
                while (app_uart_put('\n') == NRF_ERROR_BUSY);
          
            }
        }
    
    }
    
    
    /** @brief Function for initializing services that will be used by the application. */
    static void services_init(void)
    {
        uint32_t       err_code;
        ble_nus_init_t nus_init;
    
        memset(&nus_init, 0, sizeof(nus_init));
    
        nus_init.data_handler = nus_data_handler;
    
        err_code = ble_nus_init(&m_nus, &nus_init);
        APP_ERROR_CHECK(err_code);
    }
    
    /**
     * @brief Function for handling errors from the Connection Parameters module.
     *
     * @param[in] nrf_error  Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    /** @brief Function for initializing the Connection Parameters module. */
    static void conn_params_init(void)
    {
        uint32_t               err_code;
        ble_conn_params_init_t cp_init;
    
        memset(&cp_init, 0, sizeof(cp_init));
    
        cp_init.p_conn_params                  = NULL;
        cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
        cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
        cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
        cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
        cp_init.disconnect_on_fail             = true;
        cp_init.evt_handler                    = NULL;
        cp_init.error_handler                  = conn_params_error_handler;
    
        err_code = ble_conn_params_init(&cp_init);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**
     * @brief Function for putting the chip into sleep mode.
     *
     * @note This function does not return.
     */
    static void sleep_mode_enter(void)
    {
        uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE);
        APP_ERROR_CHECK(err_code);
    
        // Prepare wakeup buttons.
        err_code = bsp_btn_ble_sleep_mode_prepare();
        APP_ERROR_CHECK(err_code);
    
        // Go to system-off mode (this function will not return; wakeup will cause a reset).
        err_code = sd_power_system_off();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /** @brief Function for starting advertising. */
    static void advertising_start(void)
    {
        uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
        APP_ERROR_CHECK(err_code);
    }
    
    /**
     * @brief Function for handling advertising events.
     *
     * @details This function is called for advertising events which are passed to the application.
     *
     * @param[in] ble_adv_evt  Advertising event.
     */
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
    {
        uint32_t err_code;
    
        switch (ble_adv_evt)
        {
            case BLE_ADV_EVT_FAST:
                err_code = app_timer_start(m_blink_ble,
                                           APP_TIMER_TICKS(LED_BLINK_INTERVAL),
                                           (void *) LED_BLE_NUS_CONN);
                APP_ERROR_CHECK(err_code);
                break;
            case BLE_ADV_EVT_IDLE:
                NRF_LOG_INFO("Advertising timeout, restarting.")
                advertising_start();
                break;
            default:
                break;
        }
    }
    
    
    /**
     * @brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        uint32_t err_code;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("BLE NUS connected");
                err_code = app_timer_stop(m_blink_ble);
                APP_ERROR_CHECK(err_code);
                bsp_board_led_on(LED_BLE_NUS_CONN);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("BLE NUS disconnected");
                // LED indication will be changed when advertising starts.
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                // Pairing not supported.
                err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
            {
                ble_gap_data_length_params_t dl_params;
    
                // Clearing the struct will effectively set members to @ref BLE_GAP_DATA_LENGTH_AUTO.
                memset(&dl_params, 0, sizeof(ble_gap_data_length_params_t));
                err_code = sd_ble_gap_data_length_update(p_ble_evt->evt.gap_evt.conn_handle, &dl_params, NULL);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                // No system attributes have been stored.
                err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_EVT_USER_MEM_REQUEST:
                err_code = sd_ble_user_mem_reply(p_ble_evt->evt.gattc_evt.conn_handle, NULL);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
            {
                ble_gatts_evt_rw_authorize_request_t  req;
                ble_gatts_rw_authorize_reply_params_t auth_reply;
    
                req = p_ble_evt->evt.gatts_evt.params.authorize_request;
    
                if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID)
                {
                    if ((req.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ)     ||
                        (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) ||
                        (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL))
                    {
                        if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
                        {
                            auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
                        }
                        else
                        {
                            auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
                        }
                        auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED;
                        err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle,
                                                                   &auth_reply);
                        APP_ERROR_CHECK(err_code);
                    }
                }
            } break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**
     * @brief Function for the SoftDevice initialization.
     *
     * @details This function initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    
    /** @brief Function for handling events from the GATT library. */
    void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
    {
        if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
        {
            m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
            NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
        }
        NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
                      p_gatt->att_mtu_desired_central,
                      p_gatt->att_mtu_desired_periph);
    }
    
    
    /** @brief Function for initializing the GATT library. */
    void gatt_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, 64);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**
     * @brief Function for handling events from the BSP module.
     *
     * @param[in]   event   Event generated by button press.
     */
    void bsp_event_handler(bsp_event_t event)
    {
        uint32_t err_code;
        switch (event)
        {
            case BSP_EVENT_SLEEP:
                sleep_mode_enter();
                break;
    
            case BSP_EVENT_DISCONNECT:
                err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                if (err_code != NRF_ERROR_INVALID_STATE)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
    
            case BSP_EVENT_WHITELIST_OFF:
                if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
                {
                    err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                    if (err_code != NRF_ERROR_INVALID_STATE)
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                }
                break;
    
            default:
                break;
        }
    }
    
    /** @brief Function for initializing the Advertising functionality. */
    static void advertising_init(void)
    {
        uint32_t               err_code;
        ble_advertising_init_t init;
    
        memset(&init, 0, sizeof(init));
    
        init.advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        init.advdata.include_appearance = false;
        init.advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
    
        init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.srdata.uuids_complete.p_uuids  = m_adv_uuids;
    
        init.config.ble_adv_fast_enabled  = true;
        init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
        init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    
        init.evt_handler = on_adv_evt;
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    
    
    /** @brief Function for initializing buttons and LEDs. */
    static void buttons_leds_init(void)
    {
        uint32_t err_code = bsp_init(BSP_INIT_LEDS, bsp_event_handler);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /** @brief Function for initializing the nrf_log module. */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    
    /** @brief Function for placing the application in low power state while waiting for events. */
    static void power_manage(void)
    {
        uint32_t err_code = sd_app_evt_wait();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**
     * @brief Function for handling the idle state (main loop).
     *
     * @details If there is no pending log operation, then sleep until next the next event occurs.
     */
    static void idle_state_handle(void)
    {
        UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
        power_manage();
    }
    
    
    // USB CODE START
    static bool m_usb_connected = false;
    
    
    /** @brief User event handler @ref app_usbd_cdc_acm_user_ev_handler_t */
    static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                        app_usbd_cdc_acm_user_event_t event)
    {
        app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);
    
        switch (event)
        {
            case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
            {
                /*Set up the first transfer*/
                ret_code_t ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                       m_cdc_data_array,
                                                       1);
                UNUSED_VARIABLE(ret);
                ret = app_timer_stop(m_blink_cdc);
                APP_ERROR_CHECK(ret);
                bsp_board_led_on(LED_CDC_ACM_CONN);
                NRF_LOG_INFO("CDC ACM port opened");
                break;
            }
    
            case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
                NRF_LOG_INFO("CDC ACM port closed");
                if (m_usb_connected)
                {
                    ret_code_t ret = app_timer_start(m_blink_cdc,
                                                     APP_TIMER_TICKS(LED_BLINK_INTERVAL),
                                                     (void *) LED_CDC_ACM_CONN);
                    APP_ERROR_CHECK(ret);
                }
                break;
    
            case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
                break;
    
            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 >= (m_ble_nus_max_data_len)))
                    {
                        if (index > 1)
                        {
                            bsp_board_led_invert(LED_CDC_ACM_RX);
                            NRF_LOG_DEBUG("Ready to send data over BLE NUS");
                            NRF_LOG_HEXDUMP_DEBUG(m_cdc_data_array, index);
    
                            do
                            {
                                uint16_t length = (uint16_t)index;
                                if (length + sizeof(ENDLINE_STRING) < BLE_NUS_MAX_DATA_LEN)
                                {
                                    memcpy(m_cdc_data_array + length, ENDLINE_STRING, sizeof(ENDLINE_STRING));
                                    length += sizeof(ENDLINE_STRING);
                                }
    
                                ret = ble_nus_data_send(&m_nus,
                                                        (uint8_t *) m_cdc_data_array,
                                                        &length,
                                                        m_conn_handle);
    
                                if (ret == NRF_ERROR_NOT_FOUND)
                                {
                                    NRF_LOG_INFO("BLE NUS unavailable, data received: %s", m_cdc_data_array);
                                    break;
                                }
    
                                if (ret == NRF_ERROR_RESOURCES)
                                {
                                    NRF_LOG_ERROR("BLE NUS Too many notifications queued.");
                                    break;
                                }
    
                                if ((ret != NRF_ERROR_INVALID_STATE) && (ret != NRF_ERROR_BUSY))
                                {
                                    APP_ERROR_CHECK(ret);
                                }
                            }
                            while (ret == NRF_ERROR_BUSY);
                        }
    
                        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;
            }
            default:
                break;
        }
    }
    
    static void usbd_user_ev_handler(app_usbd_event_type_t event)
    {
        switch (event)
        {
            case APP_USBD_EVT_DRV_SUSPEND:
                break;
    
            case APP_USBD_EVT_DRV_RESUME:
                break;
    
            case APP_USBD_EVT_STARTED:
                break;
    
            case APP_USBD_EVT_STOPPED:
                app_usbd_disable();
                break;
    
            case APP_USBD_EVT_POWER_DETECTED:
                NRF_LOG_INFO("USB power detected");
    
                if (!nrf_drv_usbd_is_enabled())
                {
                    app_usbd_enable();
                }
                break;
    
            case APP_USBD_EVT_POWER_REMOVED:
            {
                NRF_LOG_INFO("USB power removed");
                ret_code_t err_code = app_timer_stop(m_blink_cdc);
                APP_ERROR_CHECK(err_code);
                bsp_board_led_off(LED_CDC_ACM_CONN);
                m_usb_connected = false;
                app_usbd_stop();
            }
                break;
    
            case APP_USBD_EVT_POWER_READY:
            {
                NRF_LOG_INFO("USB ready");
                ret_code_t err_code = app_timer_start(m_blink_cdc,
                                                      APP_TIMER_TICKS(LED_BLINK_INTERVAL),
                                                      (void *) LED_CDC_ACM_CONN);
                APP_ERROR_CHECK(err_code);
                m_usb_connected = true;
                app_usbd_start();
            }
                break;
    
            default:
                break;
        }
    }
    
    // USB CODE END
    
    void pwm_ready_callback(uint32_t pwm_id)    // PWM callback function
    {
        ready_flag = true;
    }
    
    void timer_handler(nrf_timer_event_t event_type, void * p_context)
    {
    
    }
    
    
    void saadc_sampling_event_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        /* setup m_timer for compare event every 400ms */
        uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 400);
        nrf_drv_timer_extended_compare(&m_timer,
                                       NRF_TIMER_CC_CHANNEL0,
                                       ticks,
                                       NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                       false);
        nrf_drv_timer_enable(&m_timer);
    
        uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                    NRF_TIMER_CC_CHANNEL0);
        uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                              timer_compare_event_addr,
                                              saadc_sample_task_addr);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void saadc_sampling_event_enable(void)
    {
        ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    
        APP_ERROR_CHECK(err_code);
    }
    
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            
           
    		ret_code_t err_code;
            uint16_t adc_value1,adc_value2,adc_value3,adc_value4,adc_value;
           uint8_t value[SAMPLES_IN_BUFFER];
            uint8_t bytes_to_send;
         
            // set buffers
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
            APP_ERROR_CHECK(err_code);
    						
            // print samples on hardware UART and parse data for BLE transmission
            printf("ADC event number: %d\r\n",(int)m_adc_evt_counter);
            adc_value1= p_event->data.done.p_buffer[0];
            adc_value2= p_event->data.done.p_buffer[1];
            adc_value3= p_event->data.done.p_buffer[2];
            adc_value4= p_event->data.done.p_buffer[3];
            for (int i = 0; i < SAMPLES_IN_BUFFER; i++)
            {
                
                adc_value = p_event->data.done.p_buffer[i];
                value[i*2] = adc_value;
                value[(i*2)+1] = adc_value >> 8;
                 m_adc_evt_counter++;
               
            }
             printf("adc_value 1:%d \r\n", p_event->data.done.p_buffer[0]);
         printf("adc_value 2:%d \r\n", p_event->data.done.p_buffer[1]);
              printf("adc_value 3:%d\r\n", p_event->data.done.p_buffer[2]);
               printf("adc_value 4:%d\r\n", p_event->data.done.p_buffer[3]);  
                                    
      nrf_delay_ms(1000);
        }
        
    }
    
    
    void saadc_init(void)
    {
        ret_code_t err_code;
    	
        nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
        saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
    	
        nrf_saadc_channel_config_t channel_0_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
        channel_0_config.gain = NRF_SAADC_GAIN1_4;
        channel_0_config.reference = NRF_SAADC_REFERENCE_VDD4;
    	
        nrf_saadc_channel_config_t channel_1_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
        channel_1_config.gain = NRF_SAADC_GAIN1_4;
        channel_1_config.reference = NRF_SAADC_REFERENCE_VDD4;
    	
        nrf_saadc_channel_config_t channel_2_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
        channel_2_config.gain = NRF_SAADC_GAIN1_4;
        channel_2_config.reference = NRF_SAADC_REFERENCE_VDD4;
    	
        nrf_saadc_channel_config_t channel_3_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);
        channel_3_config.gain = NRF_SAADC_GAIN1_4;
        channel_3_config.reference = NRF_SAADC_REFERENCE_VDD4;				
    	
        err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_channel_init(0, &channel_0_config);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_saadc_channel_init(1, &channel_1_config);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_saadc_channel_init(2, &channel_2_config);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_saadc_channel_init(3, &channel_3_config);
        APP_ERROR_CHECK(err_code);	
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);   
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    }
    
    
    
    
    /** @brief Application main function. */
    int main(void)
    {
        ret_code_t ret;
        ret_code_t err_code_p;
    
        static const app_usbd_config_t usbd_config = {
            .ev_state_proc = usbd_user_ev_handler
        };
        // Initialize.
          log_init();
        timers_init();
    
        buttons_leds_init();
    
        app_usbd_serial_num_generate();
    
        ret = nrf_drv_clock_init();
        APP_ERROR_CHECK(ret);
    
        NRF_LOG_INFO("USBD BLE UART example started.");
    
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(ret);
    
        app_usbd_class_inst_t const * class_cdc_acm = app_usbd_cdc_acm_class_inst_get(&m_app_cdc_acm);
        ret = app_usbd_class_append(class_cdc_acm);
        APP_ERROR_CHECK(ret);
    
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
       saadc_sampling_event_init();
        saadc_init();
        saadc_sampling_event_enable();
               
        // Start execution.
        advertising_start();
    
        ret = app_usbd_power_events_enable();
        APP_ERROR_CHECK(ret);
    
      
               
        app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_2CH(5000L, BSP_LED_0, ARDUINO_13_PIN);  //2-channel PWM, 200Hz, output on DK LED pins.
    
     // 2-channel PWM, 200Hz, output on DK LED pins.
    
        pwm1_cfg.pin_polarity[1] = APP_PWM_POLARITY_ACTIVE_HIGH; //Switch the polarity of the second channel.
    
    
      
        NRF_LOG_INFO("SAADC HAL simple example started."); 
        
        err_code_p = app_pwm_init(&PWM1,&pwm1_cfg,pwm_ready_callback);
        APP_ERROR_CHECK(err_code_p);
    
      app_pwm_enable(&PWM1);
         
        
        // Enter main loop. 
              
                                                      
     while (1)
            {
      while (app_pwm_channel_duty_set(&PWM1, 1, 30));
        //CLOCK
        if(ble_val[0]=='1' && ble_val[2] == '1') //90  
        //if(ble_val[0] == '1')
        {
      // nrf_gpio_pin_toggle(15);
           if(!(adc_value2>=500 && adc_value2<=600))
           {
             while (app_pwm_channel_duty_set(&PWM1, 1, 35));
          //  nrf_gpio_pin_toggle(16);
             
            }
        }
       
        if(ble_val[0]=='1' && ble_val[2] == '2') //180 
        // if(ble_val[0] == '2')
        {
           if(!(adc_value2>=300 && adc_value2<=400))
           {
             while (app_pwm_channel_duty_set(&PWM1, 0, 35));
             
            }
        }
        if(ble_val[0]=='1' && ble_val[2] == '3') //270
         //if(ble_val[0] == '3')
        {
           if(!(val>=30 && val<=100))
           {
             while (app_pwm_channel_duty_set(&PWM1, 1, 35));
             
            }
        }
         if(ble_val[0]=='1' && ble_val[2] == '4') //360 
         // if(ble_val[0] == '4')
        {
           if(!(val>=200 && val<=300))
           {
             while (app_pwm_channel_duty_set(&PWM1, 1, 35));
            
            }
        } //COUNTER-CLOCK
         //if(ble_val[0] == '5')
         if(ble_val[0]=='1' && ble_val[2] == '5') //90  
        {
           if(!(adc_value2>=500 && adc_value2<=600))
           {
             while (app_pwm_channel_duty_set(&PWM1, 1, 25));
             
            }
        }
         if(ble_val[0]=='1' && ble_val[2] == '6') //180  
          //if(ble_val[0] == '6')
        {
           if(!(adc_value2>=300 && adc_value2<=400))
           {
             while (app_pwm_channel_duty_set(&PWM1, 1, 25));
            
            }
        }
         //if(ble_val[0] == '7')
          if(ble_val[0]=='1' && ble_val[2] == '7') //270 
        {
           if(!(adc_value2>=30 && adc_value2<=100))
           {
             while (app_pwm_channel_duty_set(&PWM1, 1, 25));
            }
        }
          //if(ble_val[0]=='1' && ble_val[2] == '8') //360  
          }
            
            
            
        }
    
     
           
          
     
    
    /**
     * @}
     */
    

  • What happens when you try to connect? Does it say something in the log?

Related