Hello,
I started to work in a recen project with previous code developed and I want to use the current code to play 2 PWM pulses but each pulse with different duty cycle. For example, the 1st pulse at 100% 1000ms ON / 1000ms OFF and the 2nd pattern sequence at 25% duty cycle with the same 1000ms / 1000ms OFF.
Current code was able to play a pulse at one duty cycle and now I extended their usability to 2 pattern sequence, but as far as I try to modify the duty cycle independently, I ended with two pulses with the same duty cycle...
For this I wanted to implement the nrfx_pwm_complex_playback() function.
But after testing the behavior of the code, it seems that the dutycle is set by a line of code when I implement the 2nd sequence definition. specially in
// Write pattern to memory p_mem2 = p_instance->p_mem;
nrfx_pwm_complex_playback(p_instance->p_drv_instance, &pwm_sequence, &pwm_sequence2, pattern_rep, NRFX_PWM_FLAG_STOP );
/**@brief Motor instance data
@details Contains pointer to PWM pattern array, pointer to nrfx_pwm instance data,
energy of current pattern being played, to be taken into account when the repetition is over
and bool indicating if instance is enabled, if patterns are accepted
*/
typedef struct
{
uint16_t *p_mem;
nrfx_pwm_t const *p_drv_instance;
uint32_t last_pat_energy;
bool is_pat_playing;
bool motor_is_enabled;
} motor_data_t;
/**@brief Plays the passed motor pattern
@details If the instance is enabled, decodes the passed pattern and executes it.
Overwrites any motor pattern that was being played, if any. Calls the handler notifying
that the motor module is ON.
@param[in] p_pattern New pattern to be played.
@param[in] p_instance Struct where information related to the instance is stored.
*/
void motor_play(const motor_pat_t *p_pattern, motor_data_t *p_instance)
{
motor_evt_t evt_data = {0};
nrf_pwm_sequence_t pwm_sequence = {0};
uint16_t pwm_value = 0;
uint32_t duration_on = 0;
uint32_t duration_off = 0;
uint32_t pattern_rep = 0;
uint32_t i = 0;
uint16_t *p_mem = 0;
uint32_t int_scaler = 0;
// Decode pattern
int_scaler = motor_int_scaler[p_pattern->intensity];
if (int_scaler > 25)
{
int_scaler -= 25;
}
pwm_value = MOTOR_TOP_VALUE * int_scaler / 100;
duration_on = 200UL*MOTOR_FREQ/1000UL;
duration_off = 50UL*MOTOR_FREQ/1000UL;
pattern_rep = motor_pat_rep[p_pattern->repetitions];
// Write pattern to memory
p_mem = p_instance->p_mem;
// Turn on at 100% for 20ms
for(i=0;i<(20UL*MOTOR_FREQ/1000UL);i++)
{
p_mem[MOTOR_CH] = 0; // 0 -> 100% duty cycle
p_mem += MOTOR_N_CH;
}
duration_on = duration_on - (20UL*MOTOR_FREQ/1000UL);
for(i=0;i<duration_on;i++)
{
p_mem[MOTOR_CH] = MOTOR_TOP_VALUE-pwm_value;
p_mem += MOTOR_N_CH;
}
for(i=0;i<duration_off;i++)
{
p_mem[MOTOR_CH] = MOTOR_TOP_VALUE-0;
p_mem += MOTOR_N_CH;
}
pwm_sequence.values.p_raw = p_instance->p_mem;
pwm_sequence.repeats = 0;
pwm_sequence.end_delay = 0;
pwm_sequence.length = (20UL*MOTOR_FREQ/1000UL + duration_on + duration_off) * MOTOR_N_CH; // Add turn on + active + inactive times to determine length
// Execute pattern
nrf_pwm_sequence_t pwm_sequence2 = {0};
uint16_t pwm_value2 = 0;
uint32_t duration_on2 = 0;
uint32_t duration_off2 = 0;
uint32_t pattern_rep2 = 0;
uint32_t i2 = 0;
uint16_t *p_mem2 = 0;
uint32_t int_scaler2 = 0;
// Decode pattern
int_scaler2 = motor_int_scaler[p_pattern->intensity];
pwm_value2 = MOTOR_TOP_VALUE * int_scaler2 / 100;
duration_on2 = 200UL*MOTOR_FREQ/1000UL;
duration_off2 = 50UL*MOTOR_FREQ/1000UL;
pattern_rep2 = motor_pat_rep[p_pattern->repetitions];
// Write pattern to memory
// if the intensity duty cycle was 50% and modified to 25%, this will set it back to 50% for all the patterns
p_mem2 = p_instance->p_mem; // ---> duty cycle is modified here with the previous pattern command
// Turn on at 100% for 20ms
for(i=0;i<(20UL*MOTOR_FREQ/1000UL);i++)
{
p_mem2[MOTOR_CH] = 0; // 0 -> 100% duty cycle
p_mem2 += MOTOR_N_CH;
}
duration_on2 = duration_on2 - (20UL*MOTOR_FREQ/1000UL);
for(i=0;i<duration_on2;i++)
{
p_mem2[MOTOR_CH] = MOTOR_TOP_VALUE-pwm_value2;
p_mem2 += MOTOR_N_CH;
}
for(i=0;i<duration_off2;i++)
{
p_mem2[MOTOR_CH] = MOTOR_TOP_VALUE-0;
p_mem2 += MOTOR_N_CH;
}
pwm_sequence2.values.p_raw = p_instance->p_mem;
pwm_sequence2.repeats = 0;
pwm_sequence2.end_delay = 0;
pwm_sequence2.length = (20UL*MOTOR_FREQ/1000UL + duration_on2 + duration_off2) * MOTOR_N_CH; // Add turn on + active + inactive times to determine length
// play two patterns here..
nrfx_pwm_complex_playback(p_instance->p_drv_instance, &pwm_sequence, &pwm_sequence2, 2*pattern_rep,
NRFX_PWM_FLAG_STOP );
}
