I'm using a NRF52810 to control an LED load and need to ramp up PWM frequency over the span of 6 seconds, like 0-1s : 6Hz, 1-2s : 7Hz, 2-3s : 8Hz, 4-5s : 9Hz, 5-6s : 10Hz.
At the moment, this is how I do PWM with fixed frequency:
#include "nrf.h"
#include "nrf_gpio.h"
#include "nrf_drv_gpiote.h"
#include "nrf_drv_rtc.h"
#include "nrf_drv_clock.h"
#include "nrf_delay.h"
#include "nrfx_rtc.h"
#include "app_timer.h"
#include "low_power_pwm.h"
#include "boards.h"
#include <stdint.h>
#include <stdbool.h>
#include "nrf_mtx.h"
#include "math.h"
int ch1_period;
int ch1_ontime;
float ch1_frequency;
float ch1_dutycycle;
float ch1_offset;
int ch1_int_offset;
int ch1_period_tmr; // keeps track of flash period
int ch1_ontime_tmr; // keeps track of LED on-time
bool ch1_on_flag = false;
bool ch1_enable = false;
const nrfx_rtc_t rtc1 = NRF_DRV_RTC_INSTANCE(1); // Create a handle that will point to the RTC1 of nrf device
void gpio_init(){
nrf_gpio_cfg_input(switch_mode1, NRF_GPIO_PIN_PULLUP); // configure the mode switch input, with pin pullup
nrf_gpio_cfg_output(pwm_1); // configure the CH1 PWM output pin
nrf_gpio_pin_clear(pwm_1); // init pin to low which disables the LED driver
}
void init_group1_flash_patterns(){
ch1_enable = true;
ch1_frequency = 6; //specify in Hertz. Decimals are OK.
ch1_dutycycle = 25; // specify in "% positive duty cycle". Example: 45 = 45% On, 55% Off
}
void calc_flash_parameters(){
float z;
//determine channel flash pattern periods and flash duty cycles ("ontimes")
ch1_period = round((1/ch1_frequency)/.001); // period = frequency X .01sec
ch1_ontime = round(1/ch1_frequency/.001 * ch1_dutycycle/100);
// reset timers
ch1_ontime_tmr = 0;
ch1_period_tmr = 0;
}
// Initialize the low frequency clock which drives the real time counter
void lfclk_config(void){
nrf_drv_clock_init(); // Initialize the low frequency clock
nrf_drv_clock_lfclk_request(NULL); // Request the clock to not generate events
}
// RTC1 interrupt handler which will be used to maintain the flash period and duty cycle for the led channel
void rtc1_handler(nrfx_rtc_int_type_t int_type){
if(ch1_enable == true){ // Channel 1 handling
ch1_period_tmr = ch1_period_tmr + 1; // increment the period timer
if(ch1_period_tmr == ch1_period && nrf_gpio_pin_out_read(pwm_1) == false ){ //turn on LED at start of each period
nrf_gpio_pin_set(pwm_1); // turn on the LED
ch1_ontime_tmr = 0;
}
ch1_ontime_tmr = ch1_ontime_tmr + 1;
if(ch1_ontime_tmr == ch1_ontime && nrf_gpio_pin_out_read(pwm_1) == true){
nrf_gpio_pin_clear(pwm_1);
}
}
}
// A function to configure and intialize the RTC1 which is used for generating the interrupt
void rtc1_config(void){
nrfx_rtc_config_t rtc1_config = NRFX_RTC_DEFAULT_CONFIG; // Create a struct of type nrfx_rtc_config_t and assign it default values
rtc1_config.prescaler = 32; // tick = 32768 / (32 + 1) = 16384Hz = 61usec (all approximate).
nrfx_rtc_init(&rtc1, &rtc1_config, rtc1_handler); // Initialize the rtc and pass the configurations along with the interrupt handler
nrfx_rtc_tick_enable(&rtc1, true); // Enable a tick interrupt on each tick
nrfx_rtc_overflow_disable(&rtc1); // don't know if this is necessary
nrfx_rtc_enable(&rtc1); // start the rtc
}
int main(void){
gpio_init(); // Initialize the gpio
if(nrf_gpio_pin_read(switch_mode1) == 0){ //if mode 1 selected on the mode switch
init_group1_flash_patterns(); //initialize the flash patterns
}
max_parameter_violation_check();
lfclk_config(); // low frequency low power clock configuration
nrfx_clock_lfclk_start();
rtc1_config(); // rtc1 configuration
}
I'm stuck on how to implement this dynamic frequency, a way I think it could be implemented: to reset the timer every 1000ms, and adjusting parameters for the next frequency. Hence, using another timer as that counter?
I can't seem to wrap my head around how to implement this.