Maglev based on stm32f103

I saw a lot of information about magnetic levitation on the Internet, but most of them were about Arduino. I happened to have an stm32 minimum system on hand, so I just wanted to make one using stm32. But in fact, I found out that there are really many pitfalls when I started it. I only realized it after referring to the blog of Power Old Boy and other related information.

Fundamental

The principle is to use four coils to adjust the position of the float in the front, back, left, and right. The position of the float is detected by a linear Hall element. After being converted into voltage, the ADC is collected by the microcontroller. The microcontroller performs the pid of the x and y axes on the collected position data
Insert image description here
. Algorithm processing, output pwm to control the magnetic force of the electromagnetic coil to control the position of the float.

Hall output processing

Insert image description here
The a3144 used for the linear Hall element has an output of only a few hundred mv and needs to be amplified by an op amp. If the op amp is connected to 5v, its maximum output is about 4v. Two resistors need to be used to limit it below 3.3v to protect the microcontroller. You can also Use two diodes to form a clamping circuit for limitation. Originally, I looked at information on the Internet and said that you can just use the Ah49e linear Hall element without the need for an amplification circuit. During actual operation, I found that the noise of the Hall sensor itself masks the position information of the float. It seems that there are successes that depend on your own technology. . It is recommended that linear Hall elements must be used, and an amplifier circuit must be connected to amplify the output of the Hall element, and the amplified output must be limited to avoid burning out the stm32 microcontroller.

After connecting the Hall element, op amp, and potential limiting circuit, you need to adjust the potentiometer to stabilize the output voltage around 1.7v.

pid algorithm and adjustment

There are many pid algorithms on the Internet, so I won’t explain them here. I’ll post a few links https://blog.csdn.net/qq_25352981/article/details/81007075 https://blog.csdn.net/sdkdlwk/article/details/107759435

The following uses the position pid algorithm. When adjusting the pid parameter, the x and y axes can be adjusted together. First adjust kp, which is the proportion coefficient, and then adjust the kd differential coefficient.
You can also refer to https://blog.csdn.net/qq_39200996/article/details/81477223

#include<stdio.h>
#include<math.h
#include<stdlib.h>
#define Max_Cycle 290//限制幅度
#define Min_Cycle -290

typedef struct//结构体
{
    
     
   int targetValue;//设定值
   int Error;//误差
   int prevError;//上次误差
   int Integral;//误差积分
   float Kp;//比例系数
   float Ki;//没用
   float Kd;//微分系数
}PID;
PID xPID,yPID;//X和Y的结构体

    intCalc_PID(PID*pid,intPos)//位置PID
    {
    
    
    intoutput;
    intDifferential;//微分变量
    pid->Error=(pid->targetValue-Pos);     //误差有正负
    pid->Integral+=pid->Error;          //  误差累计
    Differential=pid->Error-pid->prevError;//微分部分本次误差减去上次误差
    output=(pid->Kp*pid->Error+pid->Integral*pid->Ki+pid->Kd*Differential);//通过比例积分微分参数算出输出控制量可省略积分部分
    pid->prevError=pid->Error;          //本次误差赋值为上次
    if(output>Max_Cycle)//超过上限则输出恒定值
    output=Max_Cycle;
     
     if(output<Min_Cycle)
      output=Min_Cycle;
    returnoutput;
    }
    voidInit_PID_Parameter(void)
    {
    
    
    xPID.targetValue=2300;//
    yPID.targetValue=2300;
     xPID.Error=0;
     yPID.Error=0;
    xPID.prevError=0;
     yPID.prevError=0;
     
    xPID.Ki=0.0f;
    yPID.Ki=0.0f;
    xPID.Kp=0.3f;
    yPID.Kp=0.3f;
    xPID.Kd=0.60f;
    yPID.Kd=0.60f;
    }
    

PWM mainly controls the magnetic force of the electromagnetic coil, thereby controlling the position of the float. Use the output of the pid algorithm as the input of pwm to control the on and off of 4-way pwm

The l298n accepts the PWM output of the microcontroller and then outputs the voltage to the electromagnetic coil.

    voidTIM3_GPIO_Config(void)
    {
    
    
    GPIO_InitTypeDefGPIO_InitStructure;
     /*设置TIM3CLK为72MHZ*/
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    /*GPIOAandGPIOBclockenable*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
    /*GPIOAConfiguration:TIM3channel1and2asalternatefunctionpush-pull*/
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;  //复用推挽输出
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    /*GPIOBConfiguration:TIM3channel3and4asalternatefunctionpush-pull*/
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    }
        voidTIM3_Mode_Config(void)
    {
    
    
     TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
     TIM_OCInitTypeDefTIM_OCInitStructure;
    TIM_TimeBaseStructure.TIM_Period=299;//当定时器从0计数到999,即为1000次,为一个定时周期
    TIM_TimeBaseStructure.TIM_Prescaler=11; //设置预分频:不预分频,即为72MHz
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //设置时钟分频系数:不分频(这里用不到)
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
    /*PWM1Modeconfiguration:Channel1*/
    TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //配置为PWM模式1
    TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; 
     TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//当定时器计数值小于CCR1_Val时为高电平
    TIM_OCInitStructure.TIM_Pulse=10; //设置跳变值,当计数器计数到这个值时,电平发生跳变可不设置
    TIM_OC1Init(TIM3,&TIM_OCInitStructure); //使能通道1
    TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
    /*PWM1Modeconfiguration:Channel2*/
    TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse=10; //设置通道2的电平跳变值,输出另外一个占空比的PWM
    TIM_OC2Init(TIM3,&TIM_OCInitStructure); //使能通道2
    TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
     
     /*TIM3的通道3*/
     TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse=10; //设置通道2的电平跳变值,输出另外一个占空比的PWM
    TIM_OC3Init(TIM3,&TIM_OCInitStructure); //使能通道2
    TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);
     
     /*TIM通道4*/
     TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse=10; //设置通道2的电平跳变值,输出另外一个占空比的PWM
    TIM_OC4Init(TIM3,&TIM_OCInitStructure); //使能通道2
    TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
    /*TIM3enablecounter*/
    TIM_Cmd(TIM3,ENABLE);//使能定时器3 
    }
    voidTIM3_PWM_Init(void)
    {
    
    
     TIM3_GPIO_Config();
     TIM3_Mode_Config(); 
    }
    //x轴pwm通断函数,读取pid的返回值
    voidTIM3_OutSequence1zhuoyou(intShuzhi){
    
    
     if(Shuzhi>0){
    
    
      TIM_SetCompare1(TIM3,0);
      TIM_SetCompare2(TIM3,Shuzhi);
     
     }
     else{
    
    
      TIM_SetCompare1(TIM3,Shuzhi*(-1));
      TIM_SetCompare2(TIM3,0);
     
     }
    }
    //y轴pwm通断函数
    voidTIM3_OutSequence1shangxia(intShuzhi){
    
    
     if(Shuzhi>0){
    
    
      TIM_SetCompare3(TIM3,0);
      TIM_SetCompare4(TIM3,Shuzhi);
     
     }
     else{
    
    
      TIM_SetCompare3(TIM3,Shuzhi*(-1));
      TIM_SetCompare4(TIM3,0);
     }
    }

When all the circuits are connected, place the powerful magnet in the middle of the four coils, and then move it left and right. If you feel a repulsive force to limit the float to the middle, the circuit connection is correct. Otherwise, the circuit connection needs to be adjusted.

The position of the big magnet (which provides the main support for the float) is very important. Place the float above the middle of the big magnet to feel the repulsive force. It is best to place the large magnet under the board, that is, under the electromagnetic coil, otherwise the control force of the electromagnetic coil is not enough to control the attitude of the float. Or you can increase the voltage of the input electromagnetic coil.

final effect

Insert image description here

keil5 project files, circuit schematics, and bill of materials
https://download.csdn.net/download/sijianwuxian/14975830

Guess you like

Origin blog.csdn.net/sijianwuxian/article/details/113457805