From 25772def7e9cbfcfec1e3c87235b85eeab24f865 Mon Sep 17 00:00:00 2001 From: rbaron Date: Wed, 17 Mar 2021 19:08:17 +0100 Subject: [PATCH] ADC works for measuring the battery voltage --- code/b-parasite/Makefile | 8 +- code/b-parasite/config/sdk_config.h | 17 ++-- code/b-parasite/src/main.c | 24 +++--- code/b-parasite/src/prst/adc.c | 79 +++++++++++++++++++ code/b-parasite/src/prst/adc.h | 18 +++++ code/b-parasite/src/prst/ble.c | 5 +- code/b-parasite/src/prst/ble.h | 2 +- code/b-parasite/src/prst/pwm.c | 5 +- .../saadc-vcc-nrf52832/saadc_gcc_nrf52.ld | 76 ++++++++++++++++-- .../saadc-vcc-nrf52832/saadc_gcc_nrf52832.ld | 70 ++++++++++++++++ 10 files changed, 268 insertions(+), 36 deletions(-) create mode 100644 code/b-parasite/src/prst/adc.c create mode 100644 code/b-parasite/src/prst/adc.h create mode 100644 code/playground/nrf_sdk/saadc-vcc-nrf52832/saadc_gcc_nrf52832.ld diff --git a/code/b-parasite/Makefile b/code/b-parasite/Makefile index 1608e39..9947a86 100644 --- a/code/b-parasite/Makefile +++ b/code/b-parasite/Makefile @@ -43,16 +43,14 @@ SRC_FILES += \ $(SDK_ROOT)/components/boards/boards.c \ $(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_clock.c \ $(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_twi.c \ - $(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_uart.c \ $(SDK_ROOT)/modules/nrfx/soc/nrfx_atomic.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_clock.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_gpiote.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_rtc.c \ + $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_saadc.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_twi.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/prs/nrfx_prs.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_pwm.c \ - $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_uart.c \ - $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_uarte.c \ $(SDK_ROOT)/components/libraries/bsp/bsp.c \ $(PROJ_DIR)/main.c \ $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c \ @@ -64,6 +62,7 @@ SRC_FILES += \ $(SDK_ROOT)/components/softdevice/common/nrf_sdh.c \ $(SDK_ROOT)/components/softdevice/common/nrf_sdh_ble.c \ $(SDK_ROOT)/components/softdevice/common/nrf_sdh_soc.c \ + $(PROJ_DIR)/prst/adc.c \ $(PROJ_DIR)/prst/ble.c \ $(PROJ_DIR)/prst/pwm.c \ $(PROJ_DIR)/prst/rtc.c \ @@ -220,6 +219,9 @@ CFLAGS += -DNRF_SD_BLE_API_VERSION=7 CFLAGS += -DS140 CFLAGS += -DSOFTDEVICE_PRESENT CFLAGS += -DEBUG +# Setting -DDEBUG prints info via JLkinkRTTLogger, but hides the stack trace +# when debugging with VSCode's Cortex Debug extension. +# CFLAGS += -DDEBUG CFLAGS += -mcpu=cortex-m4 CFLAGS += -mthumb -mabi=aapcs CFLAGS += -Wall -Werror diff --git a/code/b-parasite/config/sdk_config.h b/code/b-parasite/config/sdk_config.h index 2fe59ca..d2d980b 100644 --- a/code/b-parasite/config/sdk_config.h +++ b/code/b-parasite/config/sdk_config.h @@ -3361,7 +3361,7 @@ // NRFX_SAADC_ENABLED - nrfx_saadc - SAADC peripheral driver //========================================================== #ifndef NRFX_SAADC_ENABLED -#define NRFX_SAADC_ENABLED 0 +#define NRFX_SAADC_ENABLED 1 #endif // NRFX_SAADC_CONFIG_RESOLUTION - Resolution @@ -4393,7 +4393,7 @@ // NRFX_UARTE_ENABLED - nrfx_uarte - UARTE peripheral driver //========================================================== #ifndef NRFX_UARTE_ENABLED -#define NRFX_UARTE_ENABLED 1 +#define NRFX_UARTE_ENABLED 0 #endif // NRFX_UARTE0_ENABLED - Enable UARTE0 instance #ifndef NRFX_UARTE0_ENABLED @@ -5411,7 +5411,7 @@ // SAADC_ENABLED - nrf_drv_saadc - SAADC peripheral driver - legacy layer //========================================================== #ifndef SAADC_ENABLED -#define SAADC_ENABLED 0 +#define SAADC_ENABLED 1 #endif // SAADC_CONFIG_RESOLUTION - Resolution @@ -5883,7 +5883,7 @@ // UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver - legacy layer //========================================================== #ifndef UART_ENABLED -#define UART_ENABLED 1 +#define UART_ENABLED 0 #endif // UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control @@ -7611,7 +7611,7 @@ #ifndef NRF_FPRINTF_DOUBLE_ENABLED -#define NRF_FPRINTF_DOUBLE_ENABLED 0 +#define NRF_FPRINTF_DOUBLE_ENABLED 1 #endif // @@ -7784,8 +7784,9 @@ // Log data is buffered and can be processed in idle. +// TODO(rbaron): optimize. #ifndef NRF_LOG_DEFERRED -#define NRF_LOG_DEFERRED 1 +#define NRF_LOG_DEFERRED 0 #endif // NRF_LOG_FILTERS_ENABLED - Enable dynamic filtering of logs. @@ -8479,7 +8480,7 @@ // PWM_CONFIG_LOG_ENABLED - Enables logging in the module. //========================================================== #ifndef PWM_CONFIG_LOG_ENABLED -#define PWM_CONFIG_LOG_ENABLED 0 +#define PWM_CONFIG_LOG_ENABLED 1 #endif // PWM_CONFIG_LOG_LEVEL - Default Severity level @@ -8690,7 +8691,7 @@ // SAADC_CONFIG_LOG_ENABLED - Enables logging in the module. //========================================================== #ifndef SAADC_CONFIG_LOG_ENABLED -#define SAADC_CONFIG_LOG_ENABLED 0 +#define SAADC_CONFIG_LOG_ENABLED 1 #endif // SAADC_CONFIG_LOG_LEVEL - Default Severity level diff --git a/code/b-parasite/src/main.c b/code/b-parasite/src/main.c index 059d5b7..e5fd175 100644 --- a/code/b-parasite/src/main.c +++ b/code/b-parasite/src/main.c @@ -15,6 +15,7 @@ #include "nrf_sdh.h" #include "nrf_sdh_ble.h" #include "nrf_soc.h" +#include "prst/adc.h" #include "prst/ble.h" #include "prst/pwm.h" #include "prst/rtc.h" @@ -54,28 +55,28 @@ static void power_manage(void) { nrf_pwr_mgmt_run(); } -static uint8_t data; - // Here we need to be extra careful with what operations we do. This callback // has to return fast-ish, otherwise we hit some hard exceptions. static void rtc_callback() { - NRF_LOG_INFO("rtc callback running...\n"); + NRF_LOG_INFO("Batt raw "); NRF_LOG_FLUSH(); nrf_gpio_pin_set(PRST_LED_PIN); prst_shtc3_read_t temp_humi = prst_shtc3_read(); - NRF_LOG_INFO("Read temp: " NRF_LOG_FLOAT_MARKER " oC", - NRF_LOG_FLOAT(temp_humi.temp_c)); prst_pwm_init(); prst_pwm_start(); - // TODO: ADC. - nrf_delay_ms(500); - // TODO: PWM pin seems to be stuch on high after stop. + prst_adc_batt_read_t batt_read = prst_adc_batt_read(); prst_pwm_stop(); - prst_ble_update_adv_data(++data); + prst_ble_update_adv_data(batt_read.millivolts); prst_adv_start(); - nrf_delay_ms(300); + nrf_delay_ms(200); prst_adv_stop(); nrf_gpio_pin_clear(PRST_LED_PIN); + UNUSED_VARIABLE(batt_read); + UNUSED_VARIABLE(temp_humi); + NRF_LOG_INFO("Read batt: " NRF_LOG_FLOAT_MARKER " V (%d), %u mV", + NRF_LOG_FLOAT(batt_read.voltage), batt_read.raw, batt_read.millivolts); + NRF_LOG_INFO("Read temp: " NRF_LOG_FLOAT_MARKER " oC", + NRF_LOG_FLOAT(temp_humi.temp_c)); NRF_LOG_FLUSH(); } @@ -84,10 +85,13 @@ int main(void) { leds_init(); power_management_init(); prst_ble_init(); + prst_adc_init(); prst_shtc3_init(); prst_rtc_set_callback(rtc_callback); prst_rtc_init(); + nrf_delay_ms(100); + for (;;) { power_manage(); } diff --git a/code/b-parasite/src/prst/adc.c b/code/b-parasite/src/prst/adc.c new file mode 100644 index 0000000..1a1303c --- /dev/null +++ b/code/b-parasite/src/prst/adc.c @@ -0,0 +1,79 @@ +#include "prst/adc.h" + +#include +#include +#include +#include +// #include + +#include "prst_config.h" + +// 10 bits resoltuion. +#define PRST_ADC_RESOLUTION 10 + +// #define PRST_ADC_BATT_INPUT NRF_SAADC_INPUT_VDD +#define PRST_ADC_BATT_INPUT NRF_SAADC_INPUT_VDD +#define PRST_ADC_BATT_CHANNEL 0 + +// #define PRST_ADC_SOIL_INPUT NRF_SAADC_INPUT_AIN1 +// #define PRST_ADC_SOIL_CHANNEL 1 + +// Unused, since we'll call the SAADC synchronously for now. +// void saadc_callback(nrfx_saadc_evt_t const* p_event) { +// NRF_LOG_INFO("CB!", p_event->type) +// } +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 size = p_event->data.done.size; + + err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, size); + APP_ERROR_CHECK(err_code); + + int i; + NRF_LOG_INFO("ADC event!"); + + for (i = 0; i < size; i++) { + NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]); + } + } +} + +void prst_adc_init() { + nrf_saadc_channel_config_t batt_channel_config = + NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PRST_ADC_BATT_INPUT); + + APP_ERROR_CHECK(nrf_drv_saadc_init(NULL, saadc_callback)); + + APP_ERROR_CHECK( + nrf_drv_saadc_channel_init(PRST_ADC_BATT_CHANNEL, &batt_channel_config)); + + // nrf_saadc_channel_config_t soil_channel_config = + // NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PRST_ADC_SOIL_INPUT); + // soil_channel_config.reference = NRF_SAADC_REFERENCE_VDD4; + + // APP_ERROR_CHECK( + // nrf_drv_saadc_channel_init(PRST_ADC_SOIL_CHANNEL, + // &soil_channel_config)); +} + +prst_adc_batt_read_t prst_adc_batt_read() { + nrf_saadc_value_t result; + // *WARNING* this function is blocking, which is ot ideal but okay, but it + // *does not work* when oversampling is set! I had to manually disable + // SAADC_CONFIG_OVERSAMPLE in sdk_config.h. + APP_ERROR_CHECK(nrf_drv_saadc_sample_convert(PRST_ADC_BATT_CHANNEL, &result)); + NRF_LOG_INFO("Read batt: here %d", result); + prst_adc_batt_read_t ret; + ret.raw = (uint16_t) result; + ret.voltage = (3.6 * result) / (1 << PRST_ADC_RESOLUTION); + ret.millivolts = ret.voltage * 1000; + return ret; +} + +int16_t prst_adc_soil_read() { + nrf_saadc_value_t result = 0; + // APP_ERROR_CHECK(nrf_drv_saadc_sample_convert(PRST_ADC_SOIL_CHANNEL, + // &result)); + return result; +} \ No newline at end of file diff --git a/code/b-parasite/src/prst/adc.h b/code/b-parasite/src/prst/adc.h new file mode 100644 index 0000000..6f1a459 --- /dev/null +++ b/code/b-parasite/src/prst/adc.h @@ -0,0 +1,18 @@ +#ifndef _PRST_ADC_H_ +#define _PRST_ADC_H_ + +#include + +typedef struct prst_adc_batt_val { + int16_t raw; + uint16_t millivolts; + double voltage; +} prst_adc_batt_read_t; + +void prst_adc_init(); + +prst_adc_batt_read_t prst_adc_batt_read(); + +int16_t prst_adc_soil_read(); + +#endif // _PRST_ADC_H_ \ No newline at end of file diff --git a/code/b-parasite/src/prst/ble.c b/code/b-parasite/src/prst/ble.c index 7c13f2d..7a5e481 100644 --- a/code/b-parasite/src/prst/ble.c +++ b/code/b-parasite/src/prst/ble.c @@ -98,8 +98,9 @@ void prst_ble_init() { init_advertisement_data(); } -void prst_ble_update_adv_data(uint8_t n) { - service_data[0] = n; +void prst_ble_update_adv_data(uint16_t batt_millivolts) { + service_data[0] = batt_millivolts >> 8; + service_data[1] = batt_millivolts & 0xff; // Encodes adv_data_ into .gap_adv_data_. uint32_t err_code = ble_advdata_encode( diff --git a/code/b-parasite/src/prst/ble.h b/code/b-parasite/src/prst/ble.h index bb6e1f9..382550a 100644 --- a/code/b-parasite/src/prst/ble.h +++ b/code/b-parasite/src/prst/ble.h @@ -11,6 +11,6 @@ void prst_adv_start(); void prst_adv_stop(); -void prst_ble_update_adv_data(uint8_t n); +void prst_ble_update_adv_data(uint16_t batt_millivolts); #endif // _PRST_BLE_H_ \ No newline at end of file diff --git a/code/b-parasite/src/prst/pwm.c b/code/b-parasite/src/prst/pwm.c index 2d97238..d7731ca 100644 --- a/code/b-parasite/src/prst/pwm.c +++ b/code/b-parasite/src/prst/pwm.c @@ -62,10 +62,7 @@ void prst_pwm_start() { } void prst_pwm_stop() { - // Careful when using wait_until_stopped! When calling this from within the - // RTC callback, somtimes I'm hitting a hard exception. I haven't figured it - // out yet, but probably some race condition for waiting + rtc? - APP_ERROR_CHECK(nrf_drv_pwm_stop(&m_pwm0, /*wait_until_stopped=*/false)); + nrf_drv_pwm_stop(&m_pwm0, /*wait_until_stopped=*/true); nrf_drv_pwm_uninit(&m_pwm0); nrf_gpio_pin_clear(PRST_PWM_PIN); } \ No newline at end of file diff --git a/code/playground/nrf_sdk/saadc-vcc-nrf52832/saadc_gcc_nrf52.ld b/code/playground/nrf_sdk/saadc-vcc-nrf52832/saadc_gcc_nrf52.ld index dd4c500..c6e70fb 100644 --- a/code/playground/nrf_sdk/saadc-vcc-nrf52832/saadc_gcc_nrf52.ld +++ b/code/playground/nrf_sdk/saadc-vcc-nrf52832/saadc_gcc_nrf52.ld @@ -5,8 +5,8 @@ GROUP(-lgcc -lc -lnosys) MEMORY { - FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x80000 - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000 + FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xd9000 + RAM (rwx) : ORIGIN = 0x20002300, LENGTH = 0x3dd00 } SECTIONS @@ -19,6 +19,18 @@ SECTIONS .mem_section_dummy_ram : { } + .cli_sorted_cmd_ptrs : + { + PROVIDE(__start_cli_sorted_cmd_ptrs = .); + KEEP(*(.cli_sorted_cmd_ptrs)) + PROVIDE(__stop_cli_sorted_cmd_ptrs = .); + } > RAM + .fs_data : + { + PROVIDE(__start_fs_data = .); + KEEP(*(.fs_data)) + PROVIDE(__stop_fs_data = .); + } > RAM .log_dynamic_data : { PROVIDE(__start_log_dynamic_data = .); @@ -39,12 +51,66 @@ SECTIONS .mem_section_dummy_rom : { } + .sdh_soc_observers : + { + PROVIDE(__start_sdh_soc_observers = .); + KEEP(*(SORT(.sdh_soc_observers*))) + PROVIDE(__stop_sdh_soc_observers = .); + } > FLASH + .sdh_ble_observers : + { + PROVIDE(__start_sdh_ble_observers = .); + KEEP(*(SORT(.sdh_ble_observers*))) + PROVIDE(__stop_sdh_ble_observers = .); + } > FLASH .pwr_mgmt_data : { PROVIDE(__start_pwr_mgmt_data = .); KEEP(*(SORT(.pwr_mgmt_data*))) PROVIDE(__stop_pwr_mgmt_data = .); } > FLASH + .sdh_req_observers : + { + PROVIDE(__start_sdh_req_observers = .); + KEEP(*(SORT(.sdh_req_observers*))) + PROVIDE(__stop_sdh_req_observers = .); + } > FLASH + .sdh_state_observers : + { + PROVIDE(__start_sdh_state_observers = .); + KEEP(*(SORT(.sdh_state_observers*))) + PROVIDE(__stop_sdh_state_observers = .); + } > FLASH + .sdh_stack_observers : + { + PROVIDE(__start_sdh_stack_observers = .); + KEEP(*(SORT(.sdh_stack_observers*))) + PROVIDE(__stop_sdh_stack_observers = .); + } > FLASH + .nrf_queue : + { + PROVIDE(__start_nrf_queue = .); + KEEP(*(.nrf_queue)) + PROVIDE(__stop_nrf_queue = .); + } > FLASH + .nrf_balloc : + { + PROVIDE(__start_nrf_balloc = .); + KEEP(*(.nrf_balloc)) + PROVIDE(__stop_nrf_balloc = .); + } > FLASH + .cli_command : + { + PROVIDE(__start_cli_command = .); + KEEP(*(.cli_command)) + PROVIDE(__stop_cli_command = .); + } > FLASH + .crypto_data : + { + PROVIDE(__start_crypto_data = .); + KEEP(*(SORT(.crypto_data*))) + PROVIDE(__stop_crypto_data = .); + } > FLASH .log_const_data : { PROVIDE(__start_log_const_data = .); @@ -57,12 +123,6 @@ SECTIONS KEEP(*(SORT(.log_backends*))) PROVIDE(__stop_log_backends = .); } > FLASH - .nrf_balloc : - { - PROVIDE(__start_nrf_balloc = .); - KEEP(*(.nrf_balloc)) - PROVIDE(__stop_nrf_balloc = .); - } > FLASH } INSERT AFTER .text diff --git a/code/playground/nrf_sdk/saadc-vcc-nrf52832/saadc_gcc_nrf52832.ld b/code/playground/nrf_sdk/saadc-vcc-nrf52832/saadc_gcc_nrf52832.ld new file mode 100644 index 0000000..dd4c500 --- /dev/null +++ b/code/playground/nrf_sdk/saadc-vcc-nrf52832/saadc_gcc_nrf52832.ld @@ -0,0 +1,70 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x80000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000 +} + +SECTIONS +{ +} + +SECTIONS +{ + . = ALIGN(4); + .mem_section_dummy_ram : + { + } + .log_dynamic_data : + { + PROVIDE(__start_log_dynamic_data = .); + KEEP(*(SORT(.log_dynamic_data*))) + PROVIDE(__stop_log_dynamic_data = .); + } > RAM + .log_filter_data : + { + PROVIDE(__start_log_filter_data = .); + KEEP(*(SORT(.log_filter_data*))) + PROVIDE(__stop_log_filter_data = .); + } > RAM + +} INSERT AFTER .data; + +SECTIONS +{ + .mem_section_dummy_rom : + { + } + .pwr_mgmt_data : + { + PROVIDE(__start_pwr_mgmt_data = .); + KEEP(*(SORT(.pwr_mgmt_data*))) + PROVIDE(__stop_pwr_mgmt_data = .); + } > FLASH + .log_const_data : + { + PROVIDE(__start_log_const_data = .); + KEEP(*(SORT(.log_const_data*))) + PROVIDE(__stop_log_const_data = .); + } > FLASH + .log_backends : + { + PROVIDE(__start_log_backends = .); + KEEP(*(SORT(.log_backends*))) + PROVIDE(__stop_log_backends = .); + } > FLASH + .nrf_balloc : + { + PROVIDE(__start_nrf_balloc = .); + KEEP(*(.nrf_balloc)) + PROVIDE(__stop_nrf_balloc = .); + } > FLASH + +} INSERT AFTER .text + + +INCLUDE "nrf_common.ld"