Hi,
I want to read the ADC value and send it over BLE to mobile app at every 5sec, which BLE peripheral code i need to use , Please suggest asp.
Thanks in Advance
Pavan S K
Hi Pavan,Thank you for posting your question online.Please refer on this Tutorial:1. Introduction — DA145XX Tutorial SDK peripherals (renesas.com)This tutorial is based on the empty_peripheral_template example and on chapter 9 you can find information regarding the ADC on SDK6.Since you want to send the data every 5sec over BLE, you should implement an app_easy_timer as well. Keep in mind that if you have implemented Extended Sleep Mode during your connection you will have to sample the ADC when the BLE core is active.Kind Regards,OV_Renesas
Hi ,
Its only peripheral example, How to send the ADC value over BLE to mobile app. Which BLE peripheral program to use and how to add adc peripheral there. Please help to share the example program.
T
Hi Pavan,I worked on the ble_app_peripheral example.The ble_app_peripheral example has by default 3 custom services with multiple custom characteristics.If you want more information on how you can achieve that please check this tutorial: DA145XX Tutorial Create a Custom GATT Profile — DA145XX Tutorial Create a Custom GATT Profile (renesas.com)In the 1st custom service, there is a characteristic with a Characteristic User Description: "Control Point" and another characteristic with a Characteristic User Description: "ADC Value 1". If you write any value other than 0 on the Control Point characteristic, then a timer starts and updates the ADC Value 1 characteristic every second with an incrementing value.On user_custs1_impl.c For the Control Point Characteristic:
void user_svc1_ctrl_wr_ind_handler(ke_msg_id_t const msgid, struct custs1_val_write_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { uint8_t val = 0; memcpy(&val, ¶m->value[0], param->length); if (val != CUSTS1_CP_ADC_VAL1_DISABLE) { timer_used = app_easy_timer(APP_PERIPHERAL_CTRL_TIMER_DELAY, app_adcval1_timer_cb_handler); } else { if (timer_used != EASY_TIMER_INVALID_TIMER) { app_easy_timer_cancel(timer_used); timer_used = EASY_TIMER_INVALID_TIMER; } } }
void app_adcval1_timer_cb_handler() { struct custs1_val_ntf_ind_req *req = KE_MSG_ALLOC_DYN(CUSTS1_VAL_NTF_REQ, prf_get_task_from_id(TASK_ID_CUSTS1), TASK_APP, custs1_val_ntf_ind_req, DEF_SVC1_ADC_VAL_1_CHAR_LEN); // ADC value to be sampled static uint16_t sample __SECTION_ZERO("retention_mem_area0"); sample = (sample <= 0xffff) ? (sample + 1) : 0; //req->conhdl = app_env->conhdl; req->handle = SVC1_IDX_ADC_VAL_1_VAL; req->length = DEF_SVC1_ADC_VAL_1_CHAR_LEN; req->notification = true; /*Change the value updated with adc_val_mv */ memcpy(req->value, &sample, DEF_SVC1_ADC_VAL_1_CHAR_LEN); ke_msg_send(req); if (ke_state_get(TASK_APP) == APP_CONNECTED) { // Set it once again until Stop command is received in Control Characteristic timer_used = app_easy_timer(APP_PERIPHERAL_CTRL_TIMER_DELAY, app_adcval1_timer_cb_handler); } }
/****************************************************************************************/ /* UART2 configuration */ /****************************************************************************************/ // Define UART2 Tx Pad #if defined (__DA14531__) #define UART2_TX_PORT GPIO_PORT_0 #define UART2_TX_PIN GPIO_PIN_5 #else #define UART2_TX_PORT GPIO_PORT_0 #define UART2_TX_PIN GPIO_PIN_4 #endif #define ADC_INPUT_PORT GPIO_PORT_0 #define ADC_INPUT_PIN GPIO_PIN_6
void GPIO_reservations(void) { /* i.e. to reserve P0_1 as Generic Purpose I/O: RESERVE_GPIO(DESCRIPTIVE_NAME, GPIO_PORT_0, GPIO_PIN_1, PID_GPIO); */ #if defined (CFG_PRINTF_UART2) RESERVE_GPIO(UART2_TX, UART2_TX_PORT, UART2_TX_PIN, PID_UART2_TX); #endif RESERVE_GPIO(LED, GPIO_LED_PORT, GPIO_LED_PIN, PID_GPIO); #if !defined (__DA14586__) RESERVE_GPIO(SPI_EN, SPI_EN_PORT, SPI_EN_PIN, PID_SPI_EN); #endif RESERVE_GPIO(ADC_INPUT, ADC_INPUT_PORT, ADC_INPUT_PIN, PID_ADC); } void set_pad_functions(void) { /* i.e. to set P0_1 as Generic purpose Output: GPIO_ConfigurePin(GPIO_PORT_0, GPIO_PIN_1, OUTPUT, PID_GPIO, false); */ #if defined (__DA14586__) // Disallow spontaneous DA14586 SPI Flash wake-up GPIO_ConfigurePin(GPIO_PORT_2, GPIO_PIN_3, OUTPUT, PID_GPIO, true); #else // Disallow spontaneous SPI Flash wake-up GPIO_ConfigurePin(SPI_EN_PORT, SPI_EN_PIN, OUTPUT, PID_SPI_EN, true); #endif #if defined (CFG_PRINTF_UART2) // Configure UART2 TX Pad GPIO_ConfigurePin(UART2_TX_PORT, UART2_TX_PIN, OUTPUT, PID_UART2_TX, false); #endif GPIO_ConfigurePin(ADC_INPUT_PORT, ADC_INPUT_PIN, INPUT, PID_ADC, false); GPIO_ConfigurePin(GPIO_LED_PORT, GPIO_LED_PIN, OUTPUT, PID_GPIO, false); }
#include "adc.h" #include "adc_531.h" #include "arch_console.h" /* According to SDK6 Peripheral Drivers Tutorial http://lpccs-docs.renesas.com/da145xx_tutorial_sdk6_peripherals/da14531_adc.html */ static uint16_t gpadc_read(void); static uint16_t gpadc_sample_to_mv(uint16_t sample); static uint16_t gpadc_read(void) { /* Initialize the ADC */ adc_config_t adc_cfg = { .input_mode = ADC_INPUT_MODE_SINGLE_ENDED, .input = ADC_INPUT_SE_P0_6, .smpl_time_mult = 2, .continuous = false, .interval_mult = 0, .input_attenuator = ADC_INPUT_ATTN_4X, .chopping = false, .oversampling = 0, }; adc_init(&adc_cfg); /* Perform offset calibration of the ADC */ adc_offset_calibrate(ADC_INPUT_MODE_SINGLE_ENDED); adc_start(); uint16_t result = adc_correct_sample(adc_get_sample()); adc_disable(); return (result); } static uint16_t gpadc_sample_to_mv(uint16_t sample) { /* Resolution of ADC sample depends on oversampling rate */ uint32_t adc_res = 10 + ((6 < adc_get_oversampling()) ? 6 : adc_get_oversampling()); /* Reference voltage is 900mv but scale based in input attenation */ uint32_t ref_mv = 900 * (GetBits16(GP_ADC_CTRL2_REG, GP_ADC_ATTN) + 1); return (uint16_t)((((uint32_t)sample) * ref_mv) >> adc_res); }
void app_adcval1_timer_cb_handler() { struct custs1_val_ntf_ind_req *req = KE_MSG_ALLOC_DYN(CUSTS1_VAL_NTF_REQ, prf_get_task_from_id(TASK_ID_CUSTS1), TASK_APP, custs1_val_ntf_ind_req, DEF_SVC1_ADC_VAL_1_CHAR_LEN); // ADC value to be sampled static uint16_t sample __SECTION_ZERO("retention_mem_area0"); sample = (sample <= 0xffff) ? (sample + 1) : 0; /* Perform single ADC conversion */ uint16_t result = gpadc_read(); /* Print the Adc Result */ arch_printf("\n\radc result: %dmv", gpadc_sample_to_mv(result)); /* Save the ADC Result in a variable in order to update the characteristic */ uint16_t adc_val_mv = gpadc_sample_to_mv(result); //req->conhdl = app_env->conhdl; req->handle = SVC1_IDX_ADC_VAL_1_VAL; req->length = DEF_SVC1_ADC_VAL_1_CHAR_LEN; req->notification = true; /*Change the value updated with adc_val_mv */ memcpy(req->value, &adc_val_mv, DEF_SVC1_ADC_VAL_1_CHAR_LEN); ke_msg_send(req); if (ke_state_get(TASK_APP) == APP_CONNECTED) { // Set it once again until Stop command is received in Control Characteristic timer_used = app_easy_timer(APP_PERIPHERAL_CTRL_TIMER_DELAY, app_adcval1_timer_cb_handler); } }