I am working on a project using an nRF52 Series MCU, where I am aiming to produce a sinusoidal PWM wave with a total period of approximately 6 seconds using the nRF52 SDK v.15.3.0.
I have initialized the PWM with a base clock frequency of 250kHz and a top value of 4167, and I am using an array data[360] to hold the scaled and normalized duty cycle values representing one cycle of a sine wave.
For example: 4167/250000 = 0.016668 * 360 (number of items in the array) would be approximately to 6 seconds.
However, this is where I failed to set the logic. When I check the wave effect in the logic analyzes, it takes aprox 1.2 seconds and I don't understand why.
I would appreciate some help. Thank you in advance.
Part of the code:
uint16_t data[360];
uint16_t duty_cycle;
nrf_pwm_clk_t base_clock;
const nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
nrf_pwm_values_wave_form_t seq_values_wave_form = {
.channel_0 = 0,
.counter_top = 4095,
};
nrf_pwm_values_t seq_pwm_values;
nrf_pwm_sequence_t seq_wave_form;
void pwm_init_config()
{
uint8_t prescaler_setting = 0;
switch (prescaler_setting)
{
case 0:
base_clock = NRF_PWM_CLK_250kHz;
break; // 32MHz / 128
}
nrf_drv_pwm_config_t const config0 =
{
.output_pins =
{
LED_1,
NRF_DRV_PWM_PIN_NOT_USED,
NRF_DRV_PWM_PIN_NOT_USED,
NRF_DRV_PWM_PIN_NOT_USED,
},
.irq_priority = APP_IRQ_PRIORITY_LOWEST,
.base_clock = base_clock, // Frequency
.count_mode = NRF_PWM_MODE_UP, // operating mode of the pulse generator counter
.top_value = 4167, // count, Period = top_value / Hz
.load_mode = NRF_PWM_LOAD_INDIVIDUAL, // mode of loading sequence data from RAM
.step_mode = NRF_PWM_STEP_AUTO}; // mode of advancing the active sequence
APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
}
// Initiliaze the sequence structure with values for the waveform
void initialize_basic_data()
{
int size = sizeof(data) / sizeof(data[0]);
for (int i = 0; i < size; i++)
{
double radian = i * (M_PI / 180); // Convert degree to radian as sin function in C uses radian
double sin_value = sin(radian); // get sin value which will be in range [-1, 1]
// Normalize and scale sin_value to 15-bit integer value, using only 11 upper bits for amplitude
uint16_t scaled_value = (uint16_t)((sin_value + 1) * 0x03FF); // 0x03FF = 1023, the maximum 10-bit value
data[i] = scaled_value << 4; // left shift by 4 to use the upper 11 bits
}
seq_wave_form.values.p_wave_form = data;
seq_wave_form.length = NRF_PWM_VALUES_LENGTH(data);
seq_wave_form.repeats = 0;
seq_wave_form.end_delay = 0;
}
void wave_effect()
{
initialize_basic_data(); // Inicializa os valores de data com a onda senoidal
nrf_drv_pwm_simple_playback(&m_pwm0, &seq_wave_form, 1, NRF_DRV_PWM_FLAG_LOOP);
}
The issue was uint16_t data[360]
This was required to be defined as nrf_pwm_values_individual_t data[360];
.
The PWM driver would function unexpectedly without defining the proper struct.