To be different from other articles explaining PWM modules, this article does not intend to spend a lot of space to explain the various registers of the PWM module in detail, because those things are everywhere on the Internet and in bookstores. If you are good at English, you can refer to the datasheet, a 762-page PDF document, but it's a pity for my poor English level...
This article will write something about the actual control of the smart car, and write more about the control strategy.
If you have any questions about the register, you can leave a message and I will do my best to answer them.
First, the PWM code on my electromagnetic car:
//PWM.C
void Steering_PWM_Init(void)
{
PWMCTL_CON67 = 1; //PWM channel 67 cascade, B or SB as clock source
PWME_PWME7 = 0;
PWMPRCLK_PCKB = 0x3; //Prescaler B 8-divide 10MHz
PWMSCLB = 0x01; //SB_CLK = B_CLK / (2*1) == 5MHz
PWMPOL_PPOL7 = 1; //Start high level
PWMCLK_PCLK7 = 1; //PWM module clock selection SB
PWMCNT6 = 0x00; //PWMCNTx: channel count register
PWMCNT7 = 0x00;
PWMPER67 = 50000; // Period == (1/5M) * (50000) = 10ms;
PWMCAE_CAE7 = 0; //Left alignment
}
void Motor_PWM_Init(void)
{
PWMCTL_CON01 = 1; //PWM channel 01, 45 cascade, A or SA as clock source
PWMCTL_CON45 = 1;
PWMPRCLK_PCKA = 0x2; //Prescaler A 4-division 20MHz
PWMSCLA = 0x01; //SB_CLK = B_CLK / (2*1) == 10MHz
PWMPOL_PPOL1 = 1;
PWMPOL_PPOL5 = 1;
PWMCLK_PCLK1 = 1;
PWMCLK_PCLK5 = 1;
PWMCNT0 = 0x00;
PWMCNT1 = 0x00;
PWMCNT4 = 0x00;
PWMCNT5 = 0x00;
PWMPER01 = 10000; // 1ms ; 1KHz
PWMPER45 = 10000; // 1ms :1KHz
PWMCAE_CAE1 = 0;
PWMCAE_CAE5 = 0;
}
//Control the servo
void Set_PWM67(uint16 duty, uint16 period)
{
if(duty <= period)
{
PWMPER67 = period;
PWMDTY67 = duty;
}
}
//Control the motor
void Set_PWM01(uint16 duty, uint16 period)
{
if(duty <= period)
{
PWMPER01 = period;
PWMDTY01 = duty;
}
}
void Set_PWM45(uint16 duty, uint16 period)
{
if(duty <= period)
{
PWMPER45 = period;
PWMDTY45 = duty;
}
}
//PWM.h
/**********************************************************************************
* PWM module
***********************************************************************************/
void Steering_PWM_Init(void);
void Motor_PWM_Init(void);
void Set_PWM01(uint16 duty, uint16 period);
void Set_PWM67(uint16 duty, uint16 period);
void Set_PWM45(uint16 duty, uint16 period);
#define Start_PWM01() {PWME_PWME1 = 1;}
#define Stop_PWM01() {PWME_PWME1 = 0;}
#define Start_PWM67() {PWME_PWME7 = 1;}
#define Stop_PWM67() {PWME_PWME7 = 0;}
#define Start_PWM45() {PWME_PWME5 = 1;}
#define Stop_PWM45() {PWME_PWME5 = 0;}
First of all, the above code defaults to the PWM channel being closed, so when using it, you need to use the defined macro to turn on the PWM module first.
Servo part:
PWM controls nothing more than servos and motors. Let's talk about the servos first. Use the macro Start_PWM67(); to turn on the 67-channel cascaded PWM module, and then you can actually operate the servos' turning angles.
The control of the turning angle generally includes table lookup open-loop control and PD closed-loop control. Table lookup is to first list an array according to the position quantity, which corresponds to the turning angle parameters at each position quantity.
like:
The left and right extreme values and the center value are: 2120/5380/3750
const uint16 steer_arr[253] = {
2120, 2132, 2145, 2158, 2171, 2184, 2197, 2210,
2223, 2236, 2249, 2262, 2275, 2288, 2301, 2314,
2326, 2339, 2352, 2365, 2378, 2391, 2404, 2417,
2430, 2443, 2456, 2469, 2482, 2495, 2508, 2521,
2533, 2546, 2559, 2572, 2585, 2598, 2611, 2624,
2637, 2650, 2663, 2676, 2689, 2702, 2715, 2728,
2740, 2753, 2766, 2779, 2792, 2805, 2818, 2831,
2844, 2857, 2870, 2883, 2896, 2909, 2922, 2935,
2947, 2960, 2973, 2986, 2999, 3012, 3025, 3038,
3051, 3064, 3077, 3090, 3103, 3116, 3129, 3141,
3154, 3167, 3180, 3193, 3206, 3219, 3232, 3245,
3258, 3271, 3284, 3297, 3310, 3323, 3336, 3348,
3361, 3374, 3387, 3400, 3413, 3426, 3439, 3452,
3465, 3478, 3491, 3504, 3517, 3530, 3543, 3555,
3568, 3581, 3594, 3607, 3620, 3633, 3646, 3659,
3672, 3685, 3698, 3711, 3724, 3737, 3750, 3762,
3775, 3788, 3801, 3814, 3827, 3840, 3853, 3866,
3879, 3892, 3905, 3918, 3931, 3944, 3956, 3969,
3982, 3995, 4008, 4021, 4034, 4047, 4060, 4073,
4086, 4099, 4112, 4125, 4138, 4151, 4163, 4176,
4189, 4202, 4215, 4228, 4241, 4254, 4267, 4280,
4293, 4306, 4319, 4332, 4345, 4358, 4370, 4383,
4396, 4409, 4422, 4435, 4448, 4461, 4474, 4487,
4500, 4513, 4526, 4539, 4552, 4565, 4577, 4590,
4603, 4616, 4629, 4642, 4655, 4668, 4681, 4694,
4707, 4720, 4733, 4746, 4759, 4771, 4784, 4797,
4810, 4823, 4836, 4849, 4862, 4875, 4888, 4901,
4914, 4927, 4940, 4953, 4966, 4978, 4991, 5004,
5017, 5030, 5043, 5056, 5069, 5082, 5095, 5108,
5121, 5134, 5147, 5160, 5173, 5185, 5198, 5211,
5224, 5237, 5250, 5263, 5276, 5289, 5302, 5315,
5328, 5341, 5354, 5367, 5380
};
This is my electromagnetic car. At the beginning, I also used the open loop table lookup method. Some people may ask, why are there so many? Isn't it dizzy to arrange them manually? In fact, this is because the sensor is an analog quantity, and generally there are not so many. Well, if you are as lazy as me, we can actually write another program to help us build the table.
like:
#include #include #define min 2120 #define max 5380 #define count 253 using namespace std; int main(int argc, char *argv[]) { int i = 0; cout << "const uint16 steering_arr[count] = {"; for(i = 0;i <= count - 1;i++) { if(i) cout << ", "; if(!(i%8)) cout << endl << "/t"; cout << min + (max - min) * i / (count - 1); } cout<<",/n"; cout << endl << "};" << endl; return 0; } #define KP_steering_ 8 #define KD_steering_ 3 #define KP_steering 16 #define KD_steering 6 uint16 temp; sint16 error; pre_pos_ = pos_; error = pos_ - pre_pos_; if(pos_ <= 30 && pos_ >= -30) { temp = Steer_Angle_Center + KP_steering_ * ~pos_ - KD_steering_ * error; if(temp < 2120) { Set_PWM67(2120, 50000); test_steering = 2120; } else if(temp > 5380) { Set_PWM67(5300, 50000); test_steering = 5380; } else { Set_PWM67(temp, 50000); test_steering = temp; } } else if(pos_ > 30 || pos_ < -30) { temp = Steer_Angle_Center + KP_steering * ~pos_ - KD_steering * error; if(temp < 2120) { Set_PWM67(2120, 50000); test_steering = 2120; } else if(temp > 5380) { Set_PWM67(5380, 50000); test_steering = 5380; } else { Set_PWM67(temp, 50000); test_steering = temp; } } else { _asm(nop); } Motor part: When talking about motors, we must first talk about motor drivers. Most teams in previous sessions used 33886 as the motor driver chip for smart cars, but I personally think that the driving capability of 33886 is limited, and the heat generated is more than half. Also, due to the Freescale competition, this chip is hard to come by, and its price has risen. It is quite expensive. In fact, it is better to use 4 power MOS tubes to build an H-bridge circuit for motor driving. I don't intend to explain the specific method and how to connect the wires (how to connect the wires is related to whether reverse braking can be performed) in detail here. I will write an article to discuss this when I have time. Let's get back to the topic, or talk about motor control. Motor control is nothing more than giving it a speed to run from the beginning. like: //Assume that the motor is driven by PWM, and the other one is set to low level by IO port Start_PWM01(); Set_PWM01(5000,10000); This open-loop control is definitely not the best due to reasons such as battery voltage and actual road conditions. The introduction of PID control can solve this problem well. I adopted the method of combining PID and BANG-BANG control, where PID is the control accuracy and BANG-BANG is the control strength, achieving a relatively good effect. Here we briefly talk about BANG-BANG control. For a servo system with a wide speed regulation range, small static error and fast dynamic response, a single closed-loop control cannot meet the requirements, so the servo system uses a current loop, a speed loop and a position loop to complete the control. In the control of the servo system, PID control has the characteristics of simple structure and can achieve effective control even when the object model is uncertain, but its adaptability to model parameter changes and interference is poor. BANG-BANG control can increase the control strength of the system and improve the rapidity of the system when the system deviation is large. Therefore, BANG-BANG control is an indispensable control method in the servo system. To put it more clearly, each component u (t) of the time optimal control is a piecewise constant function of time t, and jumps from one constant value to another constant value in the switching time. And the so-called one constant value to another constant value mapped to the smart car is the minimum to maximum speed.
Previous article:MC9S12G128 memory map (local address, logical address, global address)
Next article:Freescale XS128 Series (III) PIT
Recommended ReadingLatest update time:2024-11-16 18:02
- Popular Resources
- Popular amplifiers
- Practical Development of Automotive FlexRay Bus System (Written by Wu Baoxin, Guo Yonghong, Cao Yi, Zhao Dongyang, etc.)
- Automotive Electronics KEA Series Microcontrollers——Based on ARM Cortex-M0+ Core
- Automotive integrated circuits and their applications
- ADS2008 RF Circuit Design and Simulation Examples (Edited by Xu Xingfu)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Experts make their own temperature and humidity clock, let's take a look~
- About the 1ms delay program for STC89C52 microcontroller?
- Exploration of RTOS and Linux controller cycloneDDS communication and encryption protection
- Qorvo to Acquire Active-Semi International
- Need a stereo audio amplifier circuit to replace TI's LM4666
- [Modelsim FAQ] Error loading design
- Principle of oscillometric blood pressure signal detection (a common method of measuring blood pressure)
- LDO problems found in AD2S1210 application
- German electrician VS Indian electrician, one has obsessive-compulsive disorder, the other drives the obsessive-compulsive disorder to death
- Newbies to power supplies, look here! Everything you want to know is here, and you will definitely gain something after reading this