Modifying Main PWM Output Channels (STM32 - Crazyflie)

Greetings all,

I am currently working on a new build config based on the existing crazyflie config, which uses the Big Quad expansion deck. This requires that the PWM output channels for the motors are changed in the board driver.

The original crazyflie used pins PA0, PB11, PA15, and PB9, to drive the motors. However, the Big Quad deck uses pins PA2, PA3, PB4, and PB5 for this function.

I attempted to implement this functionality by modifying the PWM timer defines in board_config.h, and I also changed the struct tables in crazyflie_timer_config.c, to use the correct timer channels. Lastly, I enabled the new timers, and disabled the old ones, in the nuttx-config defconfig.

Unfortunately, the PWM is still being output on the old pins, and not the ones that I need. Why is this happening? Why are the old PWM channels being used, despite the fact that the timers for those channels are no longer configured, and presumably should not even be enabled?

I am happy to share my code with you all! When I have things working and tested, I intend to contribute my board configuration back to the PX4/Firmware repository.

Regards,
Joseph

EDIT: it appears that the old PWM pins are outputing 1Hz, 50% duty signals. Further, this waveform is not modified by changing the PWM parameters in qgroundcontrol, so I assume that this behavior is not caused by the servo driver.

Bump and example code. I determined the constants by referencing the following documents:

  1. Big Quad Deck Schematic

  2. Crazyflie 2.0 schematic

  3. STM32f4 Datasheet (section on pin mapping

  4. STM32F4 reference manual (section on timers)

I’m confident in the pin and timer channel mapping. But this seems to not be enough to configure the stm32 servo driver.

From board_config.h

/* PWM

* Four PWM motor outputs are configured.
*
* Pins:
*
* M1 : PA2 : pin 16 : TIM2_CH3
* M2 : PB4 : pin 56 : TIM3_CH1
* M3 : PB5 : pin 57 : TIM3_CH2
* M4 : PA3 : pin 17 : TIM2_CH4
*/


#define GPIO_TIM2_CH3OUT GPIO_TIM2_CH3OUT_1
#define GPIO_TIM3_CH1OUT GPIO_TIM3_CH1OUT_2
#define GPIO_TIM3_CH2OUT GPIO_TIM3_CH2OUT_2
#define GPIO_TIM2_CH4OUT GPIO_TIM2_CH4OUT_1

#define DIRECT_PWM_OUTPUT_CHANNELS	4

From crazyflie_timer_config.h:

__EXPORT const io_timers_t io_timers[MAX_IO_TIMERS] = {
{
	.base = STM32_TIM2_BASE,
	.clock_register = STM32_RCC_APB1ENR,
	.clock_bit = RCC_APB1ENR_TIM2EN,
	.clock_freq = STM32_APB1_TIM2_CLKIN,
	.first_channel_index = 0,
	.last_channel_index = 1,
	.handler = io_timer_handler0,
	.vectorno =  STM32_IRQ_TIM2,
},
{
	.base = STM32_TIM3_BASE,
	.clock_register = STM32_RCC_APB1ENR,
	.clock_bit = RCC_APB1ENR_TIM3EN,
	.clock_freq = STM32_APB1_TIM3_CLKIN,
	.first_channel_index = 2,
	.last_channel_index = 3,
	.handler = io_timer_handler1,
	.vectorno =  STM32_IRQ_TIM3,
}

};

__EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
	{
		// M1
		.gpio_out = GPIO_TIM2_CH3OUT,
		.gpio_in = GPIO_TIM2_CH3IN,
		.timer_index = 1,
		.timer_channel = 3,
		.ccr_offset = STM32_GTIM_CCR3_OFFSET,
		.masks  = GTIM_SR_CC3IF | GTIM_SR_CC3OF
	},
	{
			// M4
			.gpio_out = GPIO_TIM2_CH4OUT,
			.gpio_in = GPIO_TIM2_CH4IN,
			.timer_index = 1,
			.timer_channel = 4,
			.ccr_offset = STM32_GTIM_CCR4_OFFSET,
			.masks  = GTIM_SR_CC4IF | GTIM_SR_CC4OF
	},

	{
		// M2
		.gpio_out = GPIO_TIM3_CH1OUT,
		.gpio_in = GPIO_TIM3_CH1IN,
		.timer_index = 2,
		.timer_channel = 1,
		.ccr_offset = STM32_GTIM_CCR1_OFFSET,
		.masks  = GTIM_SR_CC1IF | GTIM_SR_CC1OF
	},

	{
		// M3
		.gpio_out = GPIO_TIM3_CH2OUT,
		.gpio_in = GPIO_TIM3_CH2IN,
		.timer_index = 2,
		.timer_channel = 2,
		.ccr_offset = STM32_GTIM_CCR2_OFFSET,
		.masks  = GTIM_SR_CC2IF | GTIM_SR_CC2OF
	},

};