Manufacturing experience and stepping pit of pull-up maglev ~ (based on stm32f103, Arduino and 51, but it should be similar)

I've been doing pull-up maglev recently, but I searched csdn and arduino Chinese community. It seems that there is nothing similar. Just record my experience after I finish it. Maybe I can avoid lightning for you.

First, put a picture of several common and uncommon schemes. The picture is from amo forum, The third kind in the picture is unscientific (the magnetic field generated by the electromagnet will interfere with the hall, and the second kind of upper and lower hall can counteract this effect. I stepped on this pit at the beginning). The fourth kind is too rare and not well understood. The first and second kinds are most often seen. Another kind is to put a magnet on the top of 2 to "pull" the lower magnet to counteract gravity (refer to the principle of push down)
I myself use the second one, because it can realize integration (the first one needs upper and lower parts).

Stepping pit:

Let's talk about stepping on the pit first; First of all, to make a pull-up maglev, we need a shelf. The key point is that the shelf must be strong and reliable, otherwise it will be extremely psychological (don't ask me how I know 555)
Let me show you my shelf. I bought 5 pieces of wood for 6 yuan on Taobao, and then put them together with hot-melt glue:

2. We must share the land!
3. There is AD on the board. Generally, I don't need to buy a signal amplifier. I bought an LM358 module. I found it useless when I bought it. (32 seems to have a 12 bit ADC. The conversion accuracy of 8-bit ADC is uncertain. It is recommended to see the hardware manual.)
4. DuPont line, hole board, hot melt adhesive and so on. Buy more. It's cheap anyway and can be used in the future. Save waiting time for express delivery
5. The coil will generate heat. If it is a Hall element fixed with hot melt adhesive, pay attention to heat insulation (I padded a layer of wood)

Process:
Then start the processing process. My simple practical experience tells me that such a system needs five parts,

  1. Control part (MCU, 32Mini development board of punctual atom I use);
  2. Sensing part (the linear Hall 503 I use is directly connected to the ADC on the board and filtered by software. Note that the ADC access voltage of 32 should not exceed 3.3v);
  3. Driving part (L298N finished module used by me);
  4. Power supply part (I use a 12v to 3.3v, 5v power supply module, and the external 12v power supply is a 3-24v adjustable power supply)
  5. Moving part (here is the electromagnet, I use the finished coil I bought before, with iron core)

Then fix the hardware to the hole board, and lead out the two hall elements with wires (the wires should be longer) without fixing. Then fix the hole board to the shelf, power on and debug first, and then write code to read the sensor indication:

I basically use the official code base of punctual atom. If you don't understand, you can leave a message and return when you see it.

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "adc.h"
#include "pwm.h"
#include "key.h"

u16 PID_Cal(PID *pp,u16 adc_2,u16 adc_1);
u16 pwm_next_val=0;
   	
 int main(void)
 { 
	u8 t=0;
	u16 adcx,adcx2;
	u32 ERR;
	pp.SetPoint=500; pp.P=12.2;	pp.I=0;	pp.D=29;	 	//This parameter is not very good	
	pp.LastError=0; 
	//float temp;
	delay_init();	    	 //Delay function initialization	  
	uart_init(9600);	 	//The serial port is initialized to 9600
	LED_Init();		  		//Initialize the hardware interface to the LED
 	Adc_Init();		  		//ADC initialization	  
  KEY_Init(); 	 
	//TIM1_PWM_Init(899,0);// No frequency division. PWM frequency = 72000/(899+1)=80Khz 
	LED0=0;
	while(1)
	{
		adcx=Get_Adc_Average(ADC_Channel_1,3);
		adcx2=Get_Adc_Average(ADC_Channel_2,3);
		printf("display ADC Value of%d\n",adcx);
		printf(" \r\n");
		printf("display ADC22 Value of%d\n",adcx2);
		printf(" \r\n");
		ERR = adcx2-adcx;
		printf("Difference--Up and down%d\n",ERR);
		printf(" \r\n\r\n\r\n\r\n");
		
		delay_ms(200);
		ERR += 1;
		
	}											    
}	

After that, connect the two halls and put them next to each other. Normally, the two should be very close (the difference is one or two at most). My previous hall may be due to the problem of welding, and the indication of the two is dozens of different.
Then energize the coil and install two hall when it is energized (with magnetic force). It is required that the difference between the two after installation and fixation should be as small as possible (no more than ten at most), and then cut off the power to see how the difference between the two after power failure is. If it is still within ten, there is no problem.

Then write the control code. The common is PD control in PID control, without integral term. On the PID control algorithm can baidu other articles, I have been in vain as an automation student 55

For example:
https://www.arduino.cn/forum.php?mod=viewthread&tid=12813&highlight=PID
https://blog.csdn.net/qq_39200996/article/details/81477223
http://openedv.com/forum.php?mod=viewthread&tid=309084&highlight=pid

Let's see a code from the Internet (pull-up is really rare):

#include<iom16v.h>
#include<macros.h>
#include"12864.h"
#include"INIT.h"
#include"ADC.h"
#define uint unsigned int
#define uchar unsigned char
int ads,m;
int kp=139;ki=0,kd=260;
int temp=0;
int pid(int input)
{
 	  //Input range:
	  //Output range:
 	  static int n1,n2,n3,res;  
	  n1=176-input;
	  res=22+kp*n1/64+kd*(n1-n2);
	  n3=n2;
	  n2=n1;
	  return res;
}

void main(void)
{	
static int shur,diandwn,dianup;
  ADC_init();
  IO_init();
  LCD_init();
  PORTB&=~0x01;
  PORTB|=0x02;
  Delay_ms(200);
  //display_map(QQ);
//  Delay_ms(20000);
  LCD_Clr_All();
  
  while(1)
  {
   		  getdata();
  		 DDRD|=0X30;
		 TCCR1A=0X63;
		 TCCR1B=0X1B;
		 OCR1A=99;
		 shur=AD[1]+AD[2]-129;
		 temp=pid(shur);
		 if(shur<=131)temp=0;
		if(temp>99)temp=99;
		 if(temp<0)temp=0;
		 OCR1B=temp;
	//QF;
  }
}

Let me show you my code again. The parameters are not adjusted well and are not very stable:

typedef struct PID {
	float SetPoint;
	float P;        //
	float I;        // 
	float D;        // 
	int LastError;
	int sumERROR;
} PID;

PID pp;

u16 PID_Cal(PID *pp,u16 adc_2,u16 adc_1);
u16 pwm_next_val=0;
   	
 int main(void)
 { 
	u8 t=0;
	u16 adcx,adcx2;
	u32 ERR;
	pp.SetPoint=500; pp.P=12.2;	pp.I=0;	pp.D=29;	 pp.LastError=0; //2.7,70.1.1,10 pp.SetPoint=500; pp.P=3.1;	pp.I=0;	pp.D=126;
	 //SetPoint=500; pp.P=12.3;	pp.I=0;	pp.D=27
	//float temp;
	delay_init();	    	 //Delay function initialization	  
	uart_init(9600);	 	//The serial port is initialized to 9600
	LED_Init();		  		//Initialize the hardware interface to the LED
 	Adc_Init();		  		//ADC initialization	  
  KEY_Init(); 	 
	TIM1_PWM_Init(899,0);//No frequency division. PWM frequency = 72000/(899+1)=80Khz 

	while(1)
	{
		adcx=Get_Adc_Average(ADC_Channel_1,3);
		adcx2=Get_Adc_Average(ADC_Channel_2,3);

		if(adcx<1900){
			pwm_next_val=PID_Cal(&pp,adcx2,adcx);
			TIM_SetCompare1(TIM1,pwm_next_val);
		}
		else{
			pwm_next_val = 899;
			TIM_SetCompare1(TIM1,pwm_next_val);
		}
		delay_us(200);
		ERR += 1;
		
		t=KEY_Scan(0);		//Get key value
		switch(t)
		{				 
			case KEY0_PRES:
				LED1 = !LED1;
				printf("display yixiliePWM Value of%d\n",pwm_next_val);
			  printf(" \r\n");
				break;
			case KEY1_PRES:
				break;
			case WKUP_PRES:				
				
				break;
			default:
				break;
		}
	}											    
}	
 
u16 PID_Cal(PID *pp, u16 adc_2, u16 adc_1)
 {
	 
	 int dERROR=0, ERROR=0,mid_pid_val=0;
	 ERROR=pp->SetPoint-(adc_2-adc_1);//Current error for scale calculation
	 //pp->sumERROR+=ERROR;            // Error sum for integral calculation
	 dERROR=ERROR-pp->LastError;     //Error deviation, for differential operation
	 pp->LastError=ERROR;

	 mid_pid_val=300+pp->P*ERROR+pp->D*dERROR;//Calculate PID value
	 
	 if(mid_pid_val>0){
		 //GP7 = 0;
		 if(mid_pid_val>899)
		 {
			 mid_pid_val=899;
		 }
	 }
	 
	 else if(mid_pid_val<0){
		 //GP7 = 1;
		 mid_pid_val = 0;
	 }
	 mid_pid_val = 899-mid_pid_val;  //In fact, it is a threshold value. It is not output before the threshold value
	 return mid_pid_val;
 }
 

Then it's time to adjust the pid parameters. Everyone's hardware is different, so the parameters are different, and mine is hard to say. It's not a lesson. The only experience is to adjust to jitter (similar to self-control equal amplitude oscillation), and then slowly increase Kd and reduce Kp. If there is something wrong, please point it out. Thank you.

If you think of anything else, you'll add it later~

In addition, a few pictures are attached for reference, and I will also post links to others I feel worthy of reference:

The other two links feel that they are doing very well:
https://www.amobbs.com/thread-4552606-1-1.html
https://arduino.ncnynl.com/archives/201603/374.html

Keywords: stm32

Added by rix on Tue, 21 Dec 2021 08:13:11 +0200