ADC works for measuring the battery voltage

This commit is contained in:
rbaron 2021-03-17 19:08:17 +01:00
parent b521e3f0f6
commit 25772def7e
10 changed files with 268 additions and 36 deletions

View file

@ -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

View file

@ -3361,7 +3361,7 @@
// <e> NRFX_SAADC_ENABLED - nrfx_saadc - SAADC peripheral driver
//==========================================================
#ifndef NRFX_SAADC_ENABLED
#define NRFX_SAADC_ENABLED 0
#define NRFX_SAADC_ENABLED 1
#endif
// <o> NRFX_SAADC_CONFIG_RESOLUTION - Resolution
@ -4393,7 +4393,7 @@
// <e> NRFX_UARTE_ENABLED - nrfx_uarte - UARTE peripheral driver
//==========================================================
#ifndef NRFX_UARTE_ENABLED
#define NRFX_UARTE_ENABLED 1
#define NRFX_UARTE_ENABLED 0
#endif
// <o> NRFX_UARTE0_ENABLED - Enable UARTE0 instance
#ifndef NRFX_UARTE0_ENABLED
@ -5411,7 +5411,7 @@
// <e> SAADC_ENABLED - nrf_drv_saadc - SAADC peripheral driver - legacy layer
//==========================================================
#ifndef SAADC_ENABLED
#define SAADC_ENABLED 0
#define SAADC_ENABLED 1
#endif
// <o> SAADC_CONFIG_RESOLUTION - Resolution
@ -5883,7 +5883,7 @@
// <e> UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver - legacy layer
//==========================================================
#ifndef UART_ENABLED
#define UART_ENABLED 1
#define UART_ENABLED 0
#endif
// <o> 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
// </h>
@ -7784,8 +7784,9 @@
// <i> 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
// <q> NRF_LOG_FILTERS_ENABLED - Enable dynamic filtering of logs.
@ -8479,7 +8480,7 @@
// <e> 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
// <o> PWM_CONFIG_LOG_LEVEL - Default Severity level
@ -8690,7 +8691,7 @@
// <e> 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
// <o> SAADC_CONFIG_LOG_LEVEL - Default Severity level

View file

@ -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();
}

View file

@ -0,0 +1,79 @@
#include "prst/adc.h"
#include <app_error.h>
#include <nrf_drv_saadc.h>
#include <nrf_log.h>
#include <nrf_saadc.h>
// #include <nrfx_saadc.h>
#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;
}

View file

@ -0,0 +1,18 @@
#ifndef _PRST_ADC_H_
#define _PRST_ADC_H_
#include <stdint.h>
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_

View file

@ -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(

View file

@ -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_

View file

@ -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);
}

View file

@ -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

View file

@ -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"