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

Sending the message which includes ctrl-z(0x1A) character over uart

Hi Devzone!



I'm using LM5(BG96) LTE modem to publish the mqtt message.

When I test it at PC terminal, It works very well. There is no problem.

However, when I send the message at the nRF52840 over uart, I can't publish the message. By the way, opening the server and connection don't have any problem.

I think the reason is I can't get '>' response from the modem, so the message can't be sent to AWS or 0x1A (which is ctrl-z) isn't sent normally.

Here is the whole code of our product.

/**
 * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
/**
 * @brief BLE LED Button Service central and client application main file.
 *
 * This example can be a central for up to 8 peripherals.
 * The peripheral is called ble_app_blinky and can be found in the ble_peripheral
 * folder.
 */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include "nordic_common.h"
#include "compiler_abstraction.h"
#include "nrf.h"
#include "app_error.h"
#include "app_uart.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "app_timer.h"
#include "bsp_btn_ble.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "ble_db_discovery.h"
#include "app_timer.h"
#include "app_util.h"
#include "ble_nus_c.h"
#include "ble_conn_state.h"
#include "nrf_ble_gatt.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_ble_scan.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_saadc.h"
#include "nrf_drv_timer.h"
#include "nrf_delay.h"
#include "nrf_drv_twi.h"
#include "boards.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#include "ArducamMini2MP.h"
#if defined (UART_PRESENT)
#include "nrf_uart.h"
#endif
#if defined (UARTE_PRESENT)
#include "nrf_uarte.h"
#endif


#define APP_BLE_CONN_CFG_TAG      1                                             /**< Tag that refers to the BLE stack configuration that is set with @ref sd_ble_cfg_set. The default tag is @ref APP_BLE_CONN_CFG_TAG. */
#define APP_BLE_OBSERVER_PRIO     3                                             /**< BLE observer priority of the application. There is no need to modify this value. */

#define UART_TX_BUF_SIZE        256                                             /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE        256                                             /**< UART RX buffer size. */

#define CENTRAL_SCANNING_LED      BSP_BOARD_LED_0
#define CENTRAL_CONNECTED_LED     BSP_BOARD_LED_1
#define LEDBUTTON_LED             BSP_BOARD_LED_2                               /**< LED to indicate a change of state of the Button characteristic on the peer. */

#define LEDBUTTON_BUTTON          BSP_BUTTON_0                                  /**< Button that writes to the LED characteristic of the peer. */
#define BUTTON_DETECTION_DELAY    APP_TIMER_TICKS(50)                           /**< Delay from a GPIOTE event until a button is reported as pushed (in number of timer ticks). */
#define NUS_SERVICE_UUID_TYPE   BLE_UUID_TYPE_VENDOR_BEGIN                      /**< UUID type for the Nordic UART Service (vendor specific). */
#define ECHOBACK_BLE_UART_DATA  0                                               /**< The flag whether central sends peripheral the received message again */  

#define SAMPLES_IN_BUFFER 1                                                     /**< The number of analog sensors */
#define SAADC_SAMPLE_RATE 250                                                   /**< The sampling rate of saadc */

#define BAT_PIN NRF_SAADC_INPUT_VDD                                             /**< The hadware pin for battery(vdd) */

#define BAT_CHANNEL 0                                                           /**< The saadc module channel of battery(vdd) */

#define ADC_REF_VOLTAGE_IN_MILLIVOLTS   600                                     /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
#define ADC_PRE_SCALING_COMPENSATION    6                                       /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
#define DIODE_FWD_VOLT_DROP_MILLIVOLTS  270                                     /**< Typical forward voltage drop of the diode . */
#define ADC_RES_10BIT                   1024                                    /**< Maximum digital value for 10-bit ADC conversion. */

#define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE)\
        ((((ADC_VALUE) * ADC_REF_VOLTAGE_IN_MILLIVOLTS) / ADC_RES_10BIT) * ADC_PRE_SCALING_COMPENSATION)    /**<  The mathematical expression for converting the value of saadc(vdd) as milli volts unit. */

#define NRF_POWER_EN 12
#define LM5_ONOFF_RESET

#define BAT_LIMIT 35

#define TIMECHECK                                                               /**< The flag of checking execution time. */

#define PCA10056_USE_FRONT_HEADER       1                                       /**< Use the front header (P24) for the camera module. Requires SB10-15 and SB20-25 to be soldered/cut, as described in the readme. */

NRF_BLE_GATT_DEF(m_gatt);                                                       /**< GATT module instance. */
BLE_NUS_C_ARRAY_DEF(m_ble_nus_c, NRF_SDH_BLE_TOTAL_LINK_COUNT);
BLE_DB_DISCOVERY_ARRAY_DEF(m_db_disc, NRF_SDH_BLE_TOTAL_LINK_COUNT);            /**< Database discovery module instances. */
NRF_BLE_SCAN_DEF(m_scan);                                                       /**< Scanning Module instance. */
APP_TIMER_DEF(m_repeated_timer_id);
APP_TIMER_DEF(m_psm_timer_id);

static nrf_saadc_channel_config_t ch_config_bat = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(BAT_PIN);         /**< The saadc cnannel configuration of battery(vdd). */
static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(3);               /**< The channel of used timer triver. */
static char const m_target_periph_name[] = "Nordic_Blinky";                     /**< Name of the device to try to connect to. This name is searched for in the scanning report data. */

static nrf_saadc_value_t m_buffer_pool[2][SAMPLES_IN_BUFFER];                                      /**< The storage of 4 values which are results of saadc. */
static nrf_ppi_channel_t     m_ppi_channel;                                     /**< The ppi instance for interconnecting timer and saadc. */
static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH;          /**< The maximum length of ble data. */
static uint8_t m_ble_nus_c_count;                                               /**< The instance of present connected count of ble devices. */

#ifdef TIMECHECK
static uint32_t start;                                                          /**< The time recorded when program starts. */
static uint32_t stop;                                                           /**< The time recorded when program terminates. */
static uint32_t elapsed;                                                        /**< The execution time. */
#endif

static uint8_t                          m_new_command_received = 0;
static uint8_t                          m_new_resolution, m_new_phy;
static arducam_mini_2mp_init_t          m_camera_init;

static uint8_t   saadc_counter = 0;
static uint8_t   test_counter = 0;

static uint8_t temp_array[BLE_NUS_MAX_DATA_LEN];

static bool      pwr_saving_mode         = false;
static bool      arducam_stop            = false;
static bool      lte_lock                = false;
static bool      flash_on                = false;
static bool      cam_working             = false;

static ble_uuid_t const m_nus_uuid =                                            /**< Universally unique service identifiers. */
{
    .uuid = BLE_UUID_DEVICE_INFORMATION_SERVICE,
    .type = BLE_UUID_TYPE_BLE
};

enum {APP_CMD_NOCOMMAND = 0, APP_CMD_SINGLE_CAPTURE, APP_CMD_CHANGE_RESOLUTION};

typedef enum
{
    AT_OK,
    AWS_OPEN,
    AWS_CONN,
    MQTT_SUB,
    MQTT_PUB,
    MQTT_INPUT,
    SRV_RDY
} lte_response_mode;

typedef enum
{
    DIGGING,
    FLAME,
    TILT,
    BATTERY,
    CHIPTEMP,
    FLASH,
    FLASHOFF
} pri_situation_mode;

void board_init(void)
{ 
    nrf_gpio_cfg_output(NRF_POWER_EN);
    nrf_gpio_pin_set(NRF_POWER_EN);
    nrf_gpio_cfg_output(11);
    nrf_gpio_pin_set(11);
//    nrf_gpio_cfg_output(32 + 2);
//    nrf_gpio_pin_set(32 + 2);
//    nrf_gpio_cfg_output(32 + 3);
//    nrf_gpio_pin_set(32 + 3);
//    nrf_gpio_pin_clear(32 + 2);
//    nrf_delay_ms(150);
//    nrf_gpio_pin_set(32 + 2);
}

void flash_evt_handler(int flash_evt)
{
    uint8_t control_msg[3];
    uint16_t length;
    
    switch (flash_evt)
    {
        case 1:
            if(!flash_on)
            {
                flash_on = true;
                sprintf(control_msg, "1");
            }
            break;
        case 2:
            if(flash_on)
            {
                flash_on = false;
                sprintf(control_msg, "2");
            }
            break;
        default:
            break;
    }

    for(int i=0; i<3; i++)
    {
      length = sizeof(control_msg);
      ble_nus_c_string_send(&m_ble_nus_c[i], control_msg, length);
    }
}

//needs the enlargement and battery up down / parsing / multiple uart_init in lte_psm_disable() (flag will be needed.)
void sit_evt_handler(uint8_t * msg)
{
    int situation = atoi(msg);
    
//    while(lte_lock);
//    lte_psm_disable();
//    lte_check();
//    lte_setup();
    
    switch (situation)
    {
        case DIGGING:
//            publish_mqtt("digging\r");
            printf("DIGGING\r\n");
            if (!cam_working) camera_function();
            flash_on = false;
//            flash_evt_handler(1);
            break;
        case FLAME:
            printf("FLAME\r\n");
//            publish_mqtt("flame\r");
            break;
        case TILT:
//            publish_mqtt("tilt\r");
            break;
        case BATTERY:
//            publish_mqtt("battery\r");
            break;
        case CHIPTEMP:
//            publish_mqtt("chiptemp\r");
            break;
        case FLASH:
//            printf("FLASH\r\n");
//            if (!cam_working) camera_function();
            break;
        case FLASHOFF:
            break;
        default:
            break;
    }
//    lte_psm_enable();
}

/**@brief Function for handling asserts in the SoftDevice.
 *
 * @details This function is called in case of an assert in the SoftDevice.
 *
 * @warning This handler is only an example and is not meant for the 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(0xDEADBEEF, line_num, p_file_name);
}


/**@brief Function for initializing the LEDs.
 *
 * @details Initializes all LEDs used by the application.
 */
static void leds_init(void)
{
    bsp_board_init(BSP_INIT_LEDS);
}

/**@brief Function for handling Queued Write Module errors.
 *
 * @details A pointer to this function will be passed to each service which may need to inform the
 *          application about an error.
 *
 * @param[in]   nrf_error   Error code containing information about what went wrong.
 */
static void scan_evt_handler(scan_evt_t const * p_scan_evt)
{
    ret_code_t err_code;

    switch(p_scan_evt->scan_evt_id)
    {
        case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
        {
            err_code = p_scan_evt->params.connecting_err.err_code;
            APP_ERROR_CHECK(err_code);
        } break;

        default:
            break;
    }
}


/**@brief Function for initializing the scanning and setting the filters. */
static void scan_init(void)
{
    ret_code_t          err_code;
    nrf_ble_scan_init_t init_scan;

    memset(&init_scan, 0, sizeof(init_scan));

    init_scan.connect_if_match = true;
    init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;

    err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_UUID_FILTER, &m_nus_uuid);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_UUID_FILTER, false);
    APP_ERROR_CHECK(err_code);
}

/**@brief Function for starting scanning. */
static void scan_start(void)
{
    ret_code_t ret;
    
    sd_ble_gap_scan_stop();
    NRF_LOG_INFO("Start scanning for device name %s.", (uint32_t)m_target_periph_name);
    ret = nrf_ble_scan_start(&m_scan);
    APP_ERROR_CHECK(ret);
    // Turn on the LED to signal scanning.
    bsp_board_led_on(CENTRAL_SCANNING_LED);
}

static void ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len)
{
    ret_code_t ret_val;

    NRF_LOG_DEBUG("Receiving data.");
    NRF_LOG_HEXDUMP_DEBUG(p_data, data_len);

    for (uint32_t i = 0; i < data_len; i++)
    {
        do
        {
            ret_val = app_uart_put(p_data[i]);
            if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
            {
                NRF_LOG_ERROR("app_uart_put failed for index 0x%04x.", i);
                APP_ERROR_CHECK(ret_val);
            }
        } while (ret_val == NRF_ERROR_BUSY);
    }
    if (p_data[data_len-1] == '\r')
    {
        while (app_uart_put('\n') == NRF_ERROR_BUSY);
    }
}


/**@brief   Function for handling app_uart events.
 *
 * @details This function receives a single character from the app_uart module and appends it to
 *          a string. The string is sent over BLE when the last character received is a
 *          'new line' '\n' (hex 0x0A) or if the string reaches the maximum data length.
 */
void uart_event_handle(app_uart_evt_t * p_event)
{
    static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
    static uint8_t index = 0;
    uint32_t       err_code;

    switch (p_event->evt_type)
    {
        case APP_UART_DATA_READY:

            UNUSED_VARIABLE(app_uart_get(&data_array[index]));
            index++;

            if ((data_array[index - 1] == '\n') ||
                (index >= (m_ble_nus_max_data_len)))
            {
                if(index > 1)
                {
                    NRF_LOG_INFO("%s", NRF_LOG_PUSH(data_array));
                    strcat(temp_array,data_array);

                    memset(data_array,0,BLE_NUS_MAX_DATA_LEN);
                    index = 0;
                }
            }
            break;

        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}


/**@brief Callback handling Nordic UART Service (NUS) client events.
 *
 * @details This function is called to notify the application of NUS client events.
 *
 * @param[in]   p_ble_nus_c   NUS client handle. This identifies the NUS client.
 * @param[in]   p_ble_nus_evt Pointer to the NUS client event.
 */

/**@snippet [Handling events from the ble_nus_c module] */
static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt)
{
    ret_code_t err_code;

    switch (p_ble_nus_evt->evt_type)
    {
        case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:
            NRF_LOG_INFO("Discovery complete.");
            err_code = ble_nus_c_tx_notif_enable(p_ble_nus_c);
            APP_ERROR_CHECK(err_code);
            NRF_LOG_INFO("Connected to device with Nordic UART Service.");

            if(err_code != NRF_ERROR_BUSY)
            {
                APP_ERROR_CHECK(err_code);
            }
            break;

        case BLE_NUS_C_EVT_NUS_TX_EVT:
            sit_evt_handler(p_ble_nus_evt->p_data);
//            printf(p_ble_nus_evt->p_data);
            break;

        case BLE_NUS_C_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected.");
            scan_start();
            break;
    }
}

/**
 * @brief Function for handling shutdown events.
 *
 * @param[in]   event       Shutdown type.
 */
static bool shutdown_handler(nrf_pwr_mgmt_evt_t event)
{
    ret_code_t err_code;

    err_code = bsp_indication_set(BSP_INDICATE_IDLE);
    APP_ERROR_CHECK(err_code);

    switch (event)
    {
        case NRF_PWR_MGMT_EVT_PREPARE_WAKEUP:
            // Prepare wakeup buttons.
            err_code = bsp_btn_ble_sleep_mode_prepare();
            APP_ERROR_CHECK(err_code);
            break;

        default:
            break;
    }

    return true;
}

NRF_PWR_MGMT_HANDLER_REGISTER(shutdown_handler, APP_SHUTDOWN_HANDLER_PRIORITY);

/**@brief Function for initializing nRF uart service that will be used by ble.
 */
static void nus_c_init(void)
{
    ret_code_t       err_code;
    ble_nus_c_init_t init;

    init.evt_handler = ble_nus_c_evt_handler;

    for (m_ble_nus_c_count = 0; m_ble_nus_c_count < NRF_SDH_BLE_TOTAL_LINK_COUNT; m_ble_nus_c_count++)
    {
        err_code = ble_nus_c_init(&m_ble_nus_c[m_ble_nus_c_count], &init);
        APP_ERROR_CHECK(err_code);
    }
    m_ble_nus_c_count = 0;
}

/**@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)
{
    ret_code_t err_code;

    // For readability.
    ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

    switch (p_ble_evt->header.evt_id)
    {
        // Upon connection, check which peripheral is connected, initiate DB
        // discovery, update LEDs status, and resume scanning, if necessary.
        case BLE_GAP_EVT_CONNECTED:
        {
            NRF_LOG_INFO("Connection 0x%x established, starting DB discovery.",
                         p_gap_evt->conn_handle);

            APP_ERROR_CHECK_BOOL(p_gap_evt->conn_handle < NRF_SDH_BLE_CENTRAL_LINK_COUNT);
            err_code = ble_nus_c_handles_assign(&m_ble_nus_c[p_gap_evt->conn_handle], p_gap_evt->conn_handle, NULL);
            APP_ERROR_CHECK(err_code);
            err_code = ble_db_discovery_start(&m_db_disc[p_gap_evt->conn_handle],
                                              p_gap_evt->conn_handle);
            if (err_code != NRF_ERROR_BUSY)
            {
                APP_ERROR_CHECK(err_code);
            }

            // Update LEDs status and check whether it is needed to look for more
            // peripherals to connect to.
            bsp_board_led_on(CENTRAL_CONNECTED_LED);
            if (ble_conn_state_central_conn_count() == NRF_SDH_BLE_CENTRAL_LINK_COUNT)
            {
                bsp_board_led_off(CENTRAL_SCANNING_LED);
            }
            else
            {
                // Resume scanning.
                bsp_board_led_on(CENTRAL_SCANNING_LED);
                scan_start();
            }
        } break; // BLE_GAP_EVT_CONNECTED

        // Upon disconnection, reset the connection handle of the peer that disconnected, update
        // the LEDs status and start scanning again.
        case BLE_GAP_EVT_DISCONNECTED:
        {
            NRF_LOG_INFO("LBS central link 0x%x disconnected (reason: 0x%x)",
                         p_gap_evt->conn_handle,
                         p_gap_evt->params.disconnected.reason);

            if (ble_conn_state_central_conn_count() == 0)
            {
                // Turn off the LED that indicates the connection.
                bsp_board_led_off(CENTRAL_CONNECTED_LED);
            }

            // Start scanning.
            scan_start();

            // Turn on the LED for indicating scanning.
            bsp_board_led_on(CENTRAL_SCANNING_LED);

        } break;
        
        case BLE_GAP_EVT_TIMEOUT:
        {
            // Timeout for scanning is not specified, so only the connection requests can time out.
            if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
            {
                scan_start();
                NRF_LOG_DEBUG("Connection request timed out.");
            }
        } break;

        case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
        {
            NRF_LOG_DEBUG("BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST.");
            // Accept parameters requested by peer.
            err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
                                        &p_gap_evt->params.conn_param_update_request.conn_params);
            APP_ERROR_CHECK(err_code);
        } 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_GATTC_EVT_TIMEOUT:
        {
            // Disconnect on GATT client timeout event.
            NRF_LOG_DEBUG("GATT client timeout.");
            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.
            NRF_LOG_DEBUG("GATT server timeout.");
            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;

        default:
            // No implementation needed.
            break;
    }
}


/**@brief Function for initializing the BLE stack.
 *
 * @details Initializes the SoftDevice and the BLE event interrupts.
 */
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 database discovery events.
 *
 * @details This function is a callback function to handle events from the database discovery module.
 *          Depending on the UUIDs that are discovered, this function forwards the events
 *          to their respective services.
 *
 * @param[in] p_event  Pointer to the database discovery event.
 */
static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
{
    ble_nus_c_on_db_disc_evt(&m_ble_nus_c[p_evt->conn_handle], p_evt);
}


/** @brief Database discovery initialization.
 */
static void db_discovery_init(void)
{
    ret_code_t err_code = ble_db_discovery_init(db_disc_handler);
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for initializing power management.
 */
static void power_management_init(void)
{
    ret_code_t err_code;
    err_code = nrf_pwr_mgmt_init();
    APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling the idle state (main loop).
 *
 * @details This function handles any pending log operations, then sleeps until the next event occurs.
 */
static void idle_state_handle(void)
{
    if (NRF_LOG_PROCESS() == false)
    {
        nrf_pwr_mgmt_run();
    }
}


/** @brief Function for initializing the 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 initializing the timer.
 */
static void timer_init(void)
{
    ret_code_t err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);
}

/**@brief Application main function.
 */
void timer_handler(nrf_timer_event_t event_type, void * p_context)
{

}

/**@brief Function for initializing the GATT module.
 */
void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
    if (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)
    {
        NRF_LOG_INFO("ATT MTU exchange completed.");

        m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
        NRF_LOG_INFO("Ble NUS max data length set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
    }
}

/**@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_central_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
    APP_ERROR_CHECK(err_code);
}

/**@snippet [Handling the data received over UART] */
/**@brief  Function for initializing the UART module.
 */
static void uart_init(void)
{
    ret_code_t err_code;

    app_uart_comm_params_t const comm_params =
    {
        .rx_pin_no    = RX_PIN_NUMBER,
        .tx_pin_no    = TX_PIN_NUMBER,
        .rts_pin_no   = RTS_PIN_NUMBER,
        .cts_pin_no   = CTS_PIN_NUMBER,
        .flow_control = APP_UART_FLOW_CONTROL_DISABLED,
        .use_parity   = false,
        .baud_rate    = UART_BAUDRATE_BAUDRATE_Baud115200
    };

    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_event_handle,
                       APP_IRQ_PRIORITY_LOWEST,
                       err_code);

    APP_ERROR_CHECK(err_code);
}
/**@snippet [UART Initialization] */


/**@brief Function for initializing the sampling event of saadc(Successive approximation analog-to-digital converter)
 */
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.frequency = NRF_TIMER_FREQ_31250Hz;
    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, 1000);
    nrf_drv_timer_extended_compare(&m_timer,
                                   NRF_TIMER_CC_CHANNEL2,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE2_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_CHANNEL2);
    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);
}

/**@brief Function for enabling sampling event of saadc
 */
void saadc_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);

    APP_ERROR_CHECK(err_code);
}

/**@brief Function for handling the event of saadc sampling result
 *
 * @param[in]   event   Event generated by analog-to-digital convert.
 */
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;
        nrf_saadc_value_t bat_result;
        uint16_t          batt_lvl_in_milli_volts;
        uint8_t           percentage_batt_lvl;

        saadc_counter++;
        test_counter++;

        char saadc_temp[30];
        static uint8_t nus_temp2[30];

        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);

        bat_result = p_event->data.done.p_buffer[BAT_CHANNEL];

        batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(bat_result) +
                                  DIODE_FWD_VOLT_DROP_MILLIVOLTS;
        percentage_batt_lvl = battery_level_in_percent(batt_lvl_in_milli_volts);

        if(test_counter < 30) pwr_mgmt(percentage_batt_lvl);
        else if(test_counter < 60) pwr_mgmt(30);
        else test_counter = 0;

//        sprintf(saadc_temp, "master : %d", percentage_batt_lvl);
//        NRF_LOG_INFO("%s\n", saadc_temp);

        if(saadc_counter == 10)
        {
            NRF_LOG_INFO("saadc stop\n");
            nrf_drv_ppi_channel_disable(m_ppi_channel);
            nrf_drv_timer_disable(&m_timer);
            nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
            nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
            nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
            nrf_saadc_disable();
            nrf_gpio_pin_clear(NRF_POWER_EN);
            saadc_counter = 0;
        }
   }
}

/**@brief Function for initializing the saadc
 */
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_14BIT;

    ch_config_bat.gain = NRF_SAADC_GAIN1_4;
    ch_config_bat.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(BAT_CHANNEL, &ch_config_bat);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
}

static void repeated_timer_handler(void * p_context)
{
    NRF_LOG_INFO("saadc start\n");
    nrf_gpio_pin_set(NRF_POWER_EN);
    nrf_saadc_enable();
    nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
    nrf_drv_timer_enable(&m_timer);
    nrf_drv_ppi_channel_enable(m_ppi_channel);
}

static void psm_timer_handler(void * p_context)
{
    NRF_LOG_INFO("saadc(psm) start\n");
    nrf_gpio_pin_set(NRF_POWER_EN);
    nrf_saadc_enable();
    nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
    nrf_drv_timer_enable(&m_timer);
    nrf_drv_ppi_channel_enable(m_ppi_channel);    
}

static void create_timers()
{
    ret_code_t err_code;
    err_code = app_timer_create(&m_repeated_timer_id,
                                APP_TIMER_MODE_REPEATED,
                                repeated_timer_handler);
    APP_ERROR_CHECK(err_code);

    err_code = app_timer_create(&m_psm_timer_id,
                                APP_TIMER_MODE_REPEATED,
                                psm_timer_handler);
    APP_ERROR_CHECK(err_code);
}

static void start_repeated_timer()
{
    ret_code_t err_code;
    err_code = app_timer_start(m_repeated_timer_id, APP_TIMER_TICKS(20000), NULL); //3600000
    APP_ERROR_CHECK(err_code);
}

static void start_psm_timer()
{
    ret_code_t err_code;
    err_code = app_timer_start(m_psm_timer_id, APP_TIMER_TICKS(20000), NULL); //3600000
    APP_ERROR_CHECK(err_code);
}

static bool at_send(uint8_t * data, uint8_t size)
{
    ret_code_t ret_val;

    for (uint32_t i = 0; i < size; i++)
    {
        do
        {
            ret_val = app_uart_put(data[i]);
            if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
            {
                NRF_LOG_ERROR("app_uart_put failed for index 0x%04x.", i);
                APP_ERROR_CHECK(ret_val);
            }
        } while (ret_val == NRF_ERROR_BUSY);
    }

    return true;
}

static uint8_t at_recv(uint8_t * target)
{
    uint8_t result;
    nrf_delay_ms(500);
    result = strstr(temp_array, target); // temp_array is the data_array of uart_event_handle (line 425)

    memset(temp_array,0,BLE_NUS_MAX_DATA_LEN);
    return result;
}

//static bool check_response(uint8_t * tx_msg, uint8_t size, uint8_t * rx_msg)
//{
//    bool done = false;
//    start = DWT->CYCCNT;
//    if(at_send(tx_msg, size) && at_recv("OK"))
//    {
//        do
//        {
//            done = at_recv(rx_msg);
//            stop=DWT->CYCCNT;
//            elapsed=stop-start;
//            NRF_LOG_INFO("%d", elapsed);
//        } while ((!done) && elapsed < 1161463338);
//    }
//
//    return done;
//}
//
//static void open_mqtt(void)
//{
//    uint8_t msg[] = "AT+QMTOPEN=0,\"avq1xsl5cm8b-ats.iot.us-west-2.amazonaws.com\",8883\r";
//    if(!(check_response(msg, sizeof(msg),"0,0")))
//    {
//        NRF_LOG_INFO("Failed\n");
//    }
//
//}

static void lte_reboot(void)
{
    uint8_t msg[] = "AT+CFUN=1,1\r";
    at_send(msg, sizeof(msg));
    app_uart_close();
    uart_init();
}

static void open_mqtt(void)
{
    bool done = false;

    uint8_t msg[] = "AT+QMTOPEN=0,\"avq1xsl5cm8b-ats.iot.us-west-2.amazonaws.com\",8883\r";

    start = DWT->CYCCNT;

    if(at_send(msg, sizeof(msg)) && at_recv("OK"))
    {
        do
        {
            done = at_recv("0,0");
            stop=DWT->CYCCNT;
            elapsed=stop-start;
        } while ((!done) && elapsed < 2061463338);
    }

    if (!done)
    {
//        NRF_LOG_INFO("Open Failed\n");
    }
}

static void connect_mqtt(void)
{
    bool done = false;

    uint8_t msg[] = "AT+QMTCONN=0,\"mqtttest\"\r";

    start = DWT->CYCCNT;

    if(at_send(msg, sizeof(msg)) && at_recv("OK"))
    {
        do
        {
            done = at_recv("0,0,0");
            stop=DWT->CYCCNT;
            elapsed=stop-start;
        } while ((!done) && elapsed < 3061463338);
//        NRF_LOG_INFO("enter\n");
    }
    if (!done)
    {
//        NRF_LOG_INFO("Connect Failed\n");
    }
}

void close_mqtt(void)
{
    bool done = false;

    uint8_t msg[] = "AT+QMTDISC=0\r";

    start = DWT->CYCCNT;

    if(at_send(msg, sizeof(msg)) && at_recv("OK"))
    {
        do
        {
            done = at_recv("0,0");
            stop=DWT->CYCCNT;
            elapsed=stop-start;
        } while ((!done) && elapsed < 1161463338);
    }

    if (!done)
    {
//        NRF_LOG_INFO("Failed\n");
    }
}

void publish_mqtt(uint8_t * data)
{
    uint8_t msg[] = "AT+QMTPUB=0,1,1,0,\"$aws/things/mqtttest/shadow/update/accepted\"\r";
    uint8_t mqtt_msg[] = "";

    strcpy(mqtt_msg, data); // mqtt_msg is "Hellow CEEDUP\r" (line 1515)

    bool done = false;
    
    if(at_send(msg, sizeof(msg)))
    {
        at_send(mqtt_msg, sizeof(mqtt_msg));
          app_uart_put(0x1A);
          app_uart_put('\r');
//        done = at_recv("OK");
    }

//    if (!done)
//    {
////        NRF_LOG_INFO("Publish Failed");
//    }
}

void subscribe_mqtt(void)
{
    bool done = false;

    uint8_t msg[] = "AT+QMTSUB=0,1,\"$aws/things/mqtttest/shadow/update/accepted\",1\r";

    if(at_send(msg, sizeof(msg)) && at_recv("OK"))
    {
        do
        {
            done = at_recv("0,1,0,1");
        } while (!done);
    }
}

void lte_psm_enable(void)
{
    lte_lock = false;
    uint8_t cpsms_down[] = "AT+CPSMS=1,,,\"00000100\",\"00001111\"\r";

    at_send(cpsms_down, sizeof(cpsms_down));
    at_recv("OK");
    app_uart_close();
}

void lte_psm_disable(void)
{
    lte_lock = true;
    uint8_t cpsms_up[] = "AT+CPSMS=0";
//    uart_init();
    close_mqtt();

    at_send(cpsms_up, sizeof(cpsms_up));
    at_recv("OK");
}

void lte_check(void)
{
    bool done = false;
    uint8_t qcds[] = "AT+QCDS\r";

    start = DWT->CYCCNT;
    do
    {
        at_send(qcds, sizeof(qcds));
        done = at_recv("SRV");
        stop=DWT->CYCCNT;
        elapsed=stop-start;
        nrf_delay_ms(1000);
    } while ((!done) && elapsed < 1161463338);

    if (!done)
    {
        NRF_LOG_INFO("Failed\n");
        lte_reboot();
    }
}

void lte_setup()
{
    uint8_t SSL[] = "AT+QMTCFG=\"SSL\",0,1,2\r";
    uint8_t version[] = "AT+QMTCFG=\"version\",0,4\r";
    uint8_t cacert[] = "AT+QSSLCFG=\"cacert\",2,\"UFS:root.pem\"\r";
    uint8_t clientcert[] = "AT+QSSLCFG=\"clientcert\",2,\"UFS:cert.pem\"\r";
    uint8_t clientkey[] = "AT+QSSLCFG=\"clientkey\",2,\"UFS:key.pem\"\r";
    uint8_t seclevel[] = "AT+QSSLCFG=\"seclevel\",2,2\r";
    uint8_t sslversion[] = "AT+QSSLCFG=\"sslversion\",2,4\r";
    uint8_t ciphersuite[] = "AT+QSSLCFG=\"ciphersuite\",2,0xffff\r";
    uint8_t ignorelocaltime[] = "AT+QSSLCFG=\"ignorelocaltime\",1\r";
    uint8_t aws_open[] = "AT+QMTOPEN=0,\"avq1xsl5cm8b-ats.iot.us-west-2.amazonaws.com\",8883\r";
    uint8_t aws_conn[] = "AT+QMTCONN=0,\"mqtttest\"\r";

    at_send(SSL, sizeof(SSL));
    at_recv("OK");
    nrf_delay_ms(1000);

    at_send(version, sizeof(version));
    at_recv("OK");
    nrf_delay_ms(1000);

    at_send(cacert, sizeof(cacert));
    at_recv("OK");
    nrf_delay_ms(1000);

    at_send(clientcert, sizeof(clientcert));
    at_recv("OK");
    nrf_delay_ms(1000);

    at_send(clientkey, sizeof(clientkey));
    at_recv("OK");
    nrf_delay_ms(1000);

    at_send(seclevel, sizeof(seclevel));
    at_recv("OK");
    nrf_delay_ms(1000);

    at_send(sslversion, sizeof(sslversion));
    at_recv("OK");
    nrf_delay_ms(1000);

    at_send(ciphersuite, sizeof(ciphersuite));
    at_recv("OK");
    nrf_delay_ms(1000);

    at_send(ignorelocaltime, sizeof(ignorelocaltime));
    at_recv("OK");
    nrf_delay_ms(1000);

    open_mqtt();
    nrf_delay_ms(1000);
    connect_mqtt();
}

//test is needed.
void pwr_mgmt(int16_t bat_level)
{
    NRF_LOG_INFO("bat_level : %d\n", bat_level);
    if(!pwr_saving_mode)
    {
        if(bat_level < BAT_LIMIT)
        {
            pwr_saving_mode = true;
            arducam_stop = true;
            cam_working = true;
//            nrf_gpio_pin_clear(NRF_POWER_EN);
            app_timer_stop(m_repeated_timer_id);
            start_psm_timer();
//            while(lte_lock);
//            lte_psm_disable();
//            lte_check();
//            lte_setup();
//            publish_mqtt("bat down\r");
//            lte_psm_enable();
            flash_on = true;
            flash_evt_handler(2);
            NRF_LOG_INFO("pwr_saving mode and %d\n", nrf_gpio_pin_out_read(NRF_POWER_EN));            
        }
        else if(bat_level < BAT_LIMIT +5UL)
        {
            arducam_stop = true;
        }
    }
    else
    {
        if(bat_level >= BAT_LIMIT +5UL)
        {
            arducam_stop = false;
            cam_working = false;
            pwr_saving_mode = false;
//            nrf_gpio_pin_set(NRF_POWER_EN);
            app_timer_stop(m_psm_timer_id);
            start_repeated_timer();
//            while(lte_lock);
//            lte_psm_disable();
//            lte_check();
//            lte_setup();
//            publish_mqtt("bat up\r");
//            lte_psm_enable();
            flash_on = true;
            flash_evt_handler(2);
            NRF_LOG_INFO("not pwr_saving mode and %d\n", nrf_gpio_pin_out_read(NRF_POWER_EN));
        }
    }
}

static void camera_init(void)
{
#if defined(BOARD_PCA10056)
	#if(PCA10056_USE_FRONT_HEADER == 1)
			m_camera_init.pinScl = 13;
			m_camera_init.pinSda = 15;
			m_camera_init.pinSck = 21;
			m_camera_init.pinMiso = 23;
			m_camera_init.pinMosi = 25;
			m_camera_init.pinCsn = 32 + 9;
	#else
			m_camera_init.pinScl = 27;
			m_camera_init.pinSda = 26;
			m_camera_init.pinSck = 32 + 15;
			m_camera_init.pinMiso = 32 + 14;
			m_camera_init.pinMosi = 32 + 13;
			m_camera_init.pinCsn = 32 + 12;
	#endif
#elif defined(BOARD_PCA10040)
    m_camera_init.pinScl = 27;
    m_camera_init.pinSda = 26;
    m_camera_init.pinSck = 25;
    m_camera_init.pinMiso = 24;
    m_camera_init.pinMosi = 23;
    m_camera_init.pinCsn = 22;
#else
#error Board not defined or not supported
#endif    
    arducam_mini_2mp_open(&m_camera_init);
    arducam_mini_2mp_setResolution(OV2640_1024x768);

//    arducam_set_bit(ARDUCHIP_TIM, LOW_POWER_MODE);

    arducam_wrSensorReg8_8(0xff, 0x01); //NIGHT MODE
    arducam_wrSensorReg8_8(0x11, 0x07);

//    arducam_wrSensorReg8_8(0xff, 0x00); //Saturation level 2
//    arducam_wrSensorReg8_8(0x7c, 0x00);
//    arducam_wrSensorReg8_8(0x7d, 0x02);
//    arducam_wrSensorReg8_8(0x7c, 0x03);
//    arducam_wrSensorReg8_8(0x7d, 0x58);
//    arducam_wrSensorReg8_8(0x7d, 0x58);

    nrf_delay_ms(2000);
}

void camera_function(void)
{
    if(!cam_working)
    {
        flash_evt_handler(1);
        for(int i=0; i<10; i++)
        {
      uint32_t img_data_length = 0;
      uint8_t img_data_buffer[255];
      uint8_t count = 0;
      uint32_t image_size;
      static uint8_t capture_count;
      cam_working = true;
      if(!arducam_stop)
      {
         if(m_new_command_received != APP_CMD_SINGLE_CAPTURE)
          {
              m_new_command_received = APP_CMD_SINGLE_CAPTURE;
          }

         if(m_new_command_received != APP_CMD_NOCOMMAND)
        {
            uint32_t new_command = m_new_command_received;
            m_new_command_received = APP_CMD_NOCOMMAND;
            switch(new_command)
            {
                case APP_CMD_SINGLE_CAPTURE:
                    if(arducam_mini_2mp_bytesAvailable() == 0)
                    {
                        capture_count++;
                        printf("\n\rStarting capture %i\n\r",capture_count);
                        arducam_mini_2mp_startSingleCapture(); // capture function
                        image_size = arducam_mini_2mp_bytesAvailable();
//                        flash_on = false; // after taking picture, no needs to keep turning on flash
                        printf("\n\rCapture complete: size %i bytes\n\r", (int)(image_size));
                    }
                    break;
          
  //              case APP_CMD_CHANGE_RESOLUTION:
  //                  switch(m_new_resolution)
  //                  {
  //                      case 0:
  //                          arducam_mini_2mp_setResolution(OV2640_160x120);
  ////                          lte_send("resolution is changed to 160x120");
  //                          break;
  //                  
  //                      case 1:
  //                          arducam_mini_2mp_setResolution(OV2640_320x240);
  ////                          lte_send("resolution is changed to 320x240");
  //                          break;
  //
  //                      case 2:
  //                          arducam_mini_2mp_setResolution(OV2640_640x480);
  ////                          lte_send("resolution is changed to 640x480");
  //                          break;
  //
  //                      case 3:
  //                          arducam_mini_2mp_setResolution(OV2640_800x600);
  ////                          lte_send("resolution is changed to 800x600");
  //                          break;
  //
  //                      case 4:
  //                          arducam_mini_2mp_setResolution(OV2640_1024x768);
  ////                          lte_send("resolution is changed to 1024x768");
  //                          break;
  //                  
  //                      case 5:
  //                          arducam_mini_2mp_setResolution(OV2640_1600x1200);
  ////                          lte_send("resolution is changed to 1600x1200");
  //                          break;
  //                  } 
  //                  break;
              
                default:
                    break;
            }
        }
      }
        if(img_data_length > 0 || arducam_mini_2mp_bytesAvailable() > 0)
        {
            uint32_t ret_code;
            do
            {
                if(img_data_length == 0)
                {
                    img_data_length = arducam_mini_2mp_fillBuffer(img_data_buffer, 244);
                }
                ret_code = NRF_SUCCESS;
              
                if(0 < img_data_length) 
                {
//                    printf("\n\r%i)) %s ((%i", count, img_data_buffer, img_data_length);
//                    nrf_delay_ms(10);
//                    printf("\n");
                }
                else                    
                {
                ret_code = NRF_ERROR_RESOURCES;
                }
                if(ret_code == NRF_SUCCESS)
                {
                    count++;
                    img_data_length = 0;
                }  
            }while(ret_code == NRF_SUCCESS);
                count = 0;
                cam_working = false;
        }
        if(m_new_command_received == APP_CMD_NOCOMMAND)
        {
            idle_state_handle();
        }
    }    
    }
    else
    {
      printf("cam is working\n");
    }
  flash_on = true;
  flash_evt_handler(2);
}

//#ifdef TIMECHECK
//void time_check(void)
//{
//    if(counter == 1023)
//    {
//        stop=DWT->CYCCNT;
//        elapsed=stop-start;
//        printf("%d\n", elapsed);
//        counter = 0;
//        start = DWT->CYCCNT;
//    }
//    counter++;
//}
//#endif

int main(void)
{
  int cnt = 0;
    CoreDebug->DEMCR |= 0x1000000;
    DWT->CYCCNT = 0;
    DWT->CTRL |= 0x1;
    // Initialize.
    board_init();
    log_init();
    timer_init();
    uart_init();
//    leds_init();
    power_management_init();
    ble_stack_init();
    sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);
    gatt_init();
    db_discovery_init();
//    saadc_init();
//    saadc_sampling_event_init();
    nus_c_init();
    ble_conn_state_init();
    scan_init();
    nrf_delay_ms(2000);
    lte_check();
    lte_setup();
    nrf_delay_ms(5000);
    publish_mqtt("Hellow CEEDUP\r");
//    lte_psm_enable();
//    app_uart_close();

    // Start execution.
    NRF_LOG_INFO("Multilink example started.");
    scan_start();

//    create_timers();
//    start_repeated_timer();
//    camera_init();

//    saadc_sampling_event_enable();

    // cycle counter setup
//    #ifdef TIMECHECK
//    CoreDebug->DEMCR |= 0x1000000;
//    DWT->CYCCNT = 0;
//    DWT->CTRL |= 0x1;
//    #endif


     for (;;)
    {
        idle_state_handle();
    }
}

and below figures are the function which I used to publish the message.

and as you can see, the log data is printed abnormally.

Same message is printed partially and multiple times. Also, I can't see '<' which is the response of the mqtt publish AT command.

Q1. I used app_uart_put(0x1A) to send hex character. Is it right way?

Q2. How can I print the log normally?

Best regards,

Baek

Related