CH32V003 : Howto use PWM and driving Sg90 Servo Motors - Page 1
Forum section: electronics / general

author: jlsilicon
author_rank: Contributor
timestamp: April 28, 2024, 03:22:00 am
content: I am looking to drive SG90 Servor Motors - using PWM on Ch32v003 / Sg32v103 .Any ideas ?I pulled some Ch32v103 PWM MG996 driving code off of foreign sites.But it does not give functional examples.-- End notes are from the site - not me.Code:/*- Compiles*//**@NoteUSART Print debugging routine:USART1_Tx(PA9).This example demonstrates using USART1(PA9) as a print debug port output.*/#include "debug.h"///// CH32V103_MG996R servo driver// ch32v103 tim_pwmout_init(tim3_ch1);// CH32V103_MG996R servo driver// TIM PWM initialization#define PWM_MODE PWM_MODE2#define ARR 60000 //60000#define TIM3_CH4 0x34#define TIM3_CH3 0x33#define TIM3_CH2 0x32#define TIM3_CH1 0x31#define TIM2_CH3 0x23#define TIM2_CH4 0x24#define PWM_MODE1 0#define PWM_MODE2 1void TIM_PWMOut_Init(uint8_t type){GPIO_InitTypeDef GPIO_InitStructure;TIM_OCInitTypeDef TIM_OCInitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;switch(type){case TIM3_CH4:RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE ); //Enable GPIO peripherals and AFIO multiplexing function module clock enableGPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init( GPIOC, &GPIO_InitStructure );RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE );break;case TIM3_CH3:RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE ); //Enable GPIO peripherals and AFIO multiplexing function module clock EnableGPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init( GPIOC, &GPIO_InitStructure );RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE );break;case TIM3_CH2:RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE ); //Enable GPIO peripherals and AFIO multiplexing function module clock enableGPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init( GPIOC, &GPIO_InitStructure );RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE );break;case TIM3_CH1:RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE ); //Enable GPIO peripherals and AFIO multiplexing function module clock enableGPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init( GPIOC, &GPIO_InitStructure );RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE );break;case TIM2_CH3:RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE ); //Enable GPIO peripherals and AFIO multiplexing function module clock enableGPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init( GPIOB , &GPIO_InitStructure );RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE );break;case TIM2_CH4:RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE );//Enable GPIO peripherals and AFIO multiplexing function module clock enableGPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init( GPIOB, &GPIO_InitStructure );RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE );break;default:break;}TIM_TimeBaseInitStructure.TIM_Period = ARR; //Specify the period value to be loaded into the active automatic reload register the next time the event is updated.TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1 ; // PSC; //Specify the prescaler value used to divide the TIM clock.TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;if( type > TIM2_CH4 )TIM_TimeBaseInit( TIM3, &TIM_TimeBaseInitStructure);elseTIM_TimeBaseInit( TIM2, &TIM_TimeBaseInitStructure);#if (PWM_MODE == PWM_MODE1)TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;#elif (PWM_MODE == PWM_MODE2)TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;#endifTIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = 0.5/20.0*ARR; //Specify the pulse value to be loaded into the capture compare register.TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;switch(type){case TIM3_CH4:TIM_OC4Init( TIM3, &TIM_OCInitStructure );TIM_CtrlPWMOutputs(TIM3, ENABLE );TIM_OC4PreloadConfig( TIM3, TIM_OCPreload_Disable );//TIM_OCPreload_Enable TIM_OCPreload_DisableTIM_ARRPreloadConfig( TIM3, ENABLE );TIM_Cmd( TIM3, ENABLE );break;case TIM3_CH3:TIM_OC3Init( TIM3, &TIM_OCInitStructure );TIM_CtrlPWMOutputs(TIM3, ENABLE );TIM_OC3PreloadConfig( TIM3, TIM_OCPreload_Disable );//TIM_OCPreload_Enable TIM_OCPreload_DisableTIM_ARRPreloadConfig( TIM3, ENABLE );TIM_Cmd( TIM3, ENABLE );//TIM_SetCompare3(TIM3,1600);break;case TIM3_CH2:TIM_OC2Init( TIM3, &TIM_OCInitStructure );TIM_CtrlPWMOutputs(TIM3, ENABLE );TIM_OC2PreloadConfig( TIM3, TIM_OCPreload_Disable );//TIM_OCPreload_Enable TIM_OCPreload_DisableTIM_ARRPreloadConfig( TIM3, ENABLE );TIM_Cmd( TIM3, ENABLE );break;case TIM3_CH1:TIM_OC1Init( TIM3, &TIM_OCInitStructure );TIM_CtrlPWMOutputs(TIM3, ENABLE );TIM_OC1PreloadConfig( TIM3, TIM_OCPreload_Disable );//TIM_OCPreload_Enable TIM_OCPreload_DisableTIM_ARRPreloadConfig( TIM3, ENABLE );TIM_Cmd( TIM3, ENABLE );break;case TIM2_CH3:TIM_OC3Init( TIM2, &TIM_OCInitStructure );TIM_CtrlPWMOutputs(TIM2, ENABLE );TIM_OC3PreloadConfig( TIM2, TIM_OCPreload_Disable );//TIM_OCPreload_Enable TIM_OCPreload_DisableTIM_ARRPreloadConfig( TIM2, ENABLE );TIM_Cmd( TIM2, ENABLE );break;case TIM2_CH4:TIM_OC4Init( TIM2, &TIM_OCInitStructure );TIM_CtrlPWMOutputs(TIM2, ENABLE );TIM_OC4PreloadConfig( TIM2, TIM_OCPreload_Disable );//TIM_OCPreload_Enable TIM_OCPreload_DisableTIM_ARRPreloadConfig( TIM2, ENABLE );TIM_Cmd( TIM2, ENABLE );break;}}void Set_PWM_Dutycycle(uint16_t dutycycle,uint8_t type){switch(type){case TIM3_CH4:TIM_SetCompare4(TIM3,dutycycle); //Set the TIM3 capture comparison 1 register value, which is used to modify the duty cyclebreak;case TIM3_CH3:TIM_SetCompare3(TIM3,dutycycle); //Set the TIM3 capture Compare 1 register value, used to modify the duty cyclebreak;case TIM3_CH2:TIM_SetCompare2(TIM3,dutycycle); //Set the TIM3 capture compare 1 register value, used to modify the duty cyclebreak;case TIM3_CH1:TIM_SetCompare1(TIM3, dutycycle); //Set the TIM3 capture compare 1 register value, used to modify the duty cyclebreak;case TIM2_CH3:TIM_SetCompare3(TIM2,dutycycle); //Set the TIM3 capture compare 1 register value, used to modify the duty cyclebreak ;case TIM2_CH4:TIM_SetCompare4(TIM2,dutycycle); //Set the TIM3 capture comparison 1 register value, used to modify the duty cyclebreak;}}/*Introduction The CH32V103 series is a 32-bit general-purpose MCU with the QingdaoV3A processor as the core. The processor is designed based on the RISC-V open source instruction set. The clock safety mechanism, multi-level power management, and universal DMA controller are integrated on the chip. This series has rich peripheral resources such as 1-channel USB2.0 host/device interface, multi-channel 12-bit ADC conversion module, multi-channel TouchKey, multiple groups of timers, and multiple IIC/USART/SPI interfaces. This tutorial uses timer 1 channel 1 (PA8) to generate PWM through the PA8 pin to control the brightness of the LED light LED1. 1. Introduction to PWM and related functions Pulse width modulation ( PWM ) is an analog control method that uses microprocessorsQinheng CH32V103 Play and Learn 1-Development Environment and GPIO Project4-21However, the library functions it uses are basically the same as STM32, and there is no difference in the core structure. You can quickly get started with library function development through this board and understand some simple concepts, such as GPIO ADC/DAC, watchdog timer interrupt, PWM and other core knowledge points. , it will be easier to convert to STM32 later. CH32V103 C8T6 has not yet received Qin...RISC-V MCU application tutorial timer interrupt_risk-v systick4-201.5. void TIM _ PWM IConfig ( TIM _TypeDef* TIM x, TIM _IC Init TypeDef* TIM _IC Init Struct) Function: Configure TIM peripherals according to the specified parameters in the TIM structure to measure external PWM signals. Input: TIM x: where x can be 1 to 4 to select the TIM peripheral; TIM _IC Init Struct: points to TIM _IC...Qinheng CH32V307 usage record: using TIM to output PWM signalUsing TIM to output PWM signals is a commonly used function in microcontrollers. This article will explain the relevant content in CH32V307.STM32 TIM3 outputs PWM signal to drive MG996R servo (button control)3-30timer_pwm_init(PWM3_CH1_C6,50,740);// //D2 gpio_init(D2,GPI,0,IN_PULLUP); // error=0; error_last=0; //4-8#include"ch32v10x.h" intw =0; volatileu8 flag=0; voidTIM3_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0}; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); ...05-22You can drive two MG996R servos by using one PWM output pin , but you need to pay attention to some issues:1. The maximum operating frequency of each MG996R servo is 50Hz, that is, each cycle is 20ms, so it needs to be within one cycle Complete the PWM signal output of the two servos ;2. The operating voltage of the MG996R servo is 4.8V~7.2V, so it is necessary to ensure that the supply voltage and current are sufficient to drive the two servos ;3. If connected on the same pin For multiple servos , a signal distributor (such as a crystal oscillator) needs to be used to distribute the PWM signal to ensure that each servo can receive the correct PWM signal;4. The appropriate PWM signal should be calculated based on the load characteristics of the servo . PWM duty cycle to ensure the stability and accuracy of the servo movement.*/////* Global Variable *//********************************************************************** @fn main** @brief Main program.** @return none*/int main(void){NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);Delay_Init();USART_Printf_Init(115200);printf("SystemClk:%d\r\n", SystemCoreClock);TIM_PWMOut_Init( TIM3_CH1 );Set_PWM_Dutycycle( 1000 , TIM3_CH1 );while(1){}}///

author: Cuchi
author_rank: Newbie
timestamp: May 07, 2024, 10:24:13 am
content: Hello,I am a new member of this site and a beginner in the subject. I don't know how to navigate it yet but I came across your post while doing a search and I'm telling you my problem thinking that you might be able to help me find the solution or tell me where to ask my question more effectivelyI purchased a controller as specified belowan PWM type single channel H-Bridge DC brushed motor driver for automotive useThe pin assignment is as follow:an Output high-side current monitoring function (OCM pin):+VIN; GND and M+;M-A Microcontroller(inputs):PWM1: Driver control signal input pin 1PWM2: Driver control signal input pin 2ENGBD+12V OUTI plan to use it to vary the speed of a 12 volt electric motor (a motorcycle starter) connected to a 12 volt motorcycle battery as well.The problem is that when I connect the throttle to the controller inputs (+12v pin; Gnd pin and signal pin) the output signal of the throttle connected to the PWM1 input of the controller, I obtain an inverted effect, i.e. the motor spins when the throttle is closed and at rest and the motor stops when the throttle is opened with the lever pushed all the way. If I connect the throttle signal pin to the PWM2 of the controller nothing happensMy question is how to reverse things, i.e. make the motor spin as the throttle is applied towards more gas and not the other way around.Thanks