Arduino PID Magnetic Levitation

Hello,

I have made a magnetic levitation device using an Arduino Nano, L298N, Neodymium Magnets and 4 of these coils. It uses 2 Hall effect sensors to determine the position of the floating magnet. In addition, an op amp is used to amplify the signal coming from the sensors, and to set the reference value.

However, I'm facing some problems as well. The less annoying one is the coil whine that the PWM creates in the coils. I tried to change the PWM pins from 6 and 5 to 9 and 10, but that didn't work.
The most annoying is that the coils are unable to stabilize the magnet and the whole thing can not achieve the levitating.

Here is the code that I used in this project. It uses the PID_v1 library. I would like to know where the problem might be. I nearly tried everything with the hardware. The reference values were almost perfect. Is it the software's or the hardware's fault, that the magnet can not stay above the coils?

#include <PID_v1.h>
#define IN1 4
#define IN2 3
#define IN3 7
#define IN4 8
#define ENA 9
#define ENB 10
#define BL 2

double Setpoint_X, Input_X, Output_X,X_plus;
double p_X = 1,i_X = 0,d_X = 0.01;
double Setpoint_Y, Input_Y, Output_Y,Y_plus;
double p_Y = 1,i_Y = 0,d_Y = 0.01;

int i,on_put=1;

unsigned long time;

PID PID_X(&Input_X, &Output_X, &Setpoint_X,p_X,i_X,d_X, DIRECT);
PID PID_Y(&Input_Y, &Output_Y, &Setpoint_Y,p_Y,i_Y,d_Y, DIRECT);

char inByte='9',nullByte,run_flag,run_dirict;
float go_step;

void turn_X(int a)
{
  if(a>=0)
  {
    digitalWrite(IN1,1);
    digitalWrite(IN2,0);
    analogWrite(ENA,a);
  }
  else
  {
    a=-a;
    digitalWrite(IN1,0);
    digitalWrite(IN2,1);
    analogWrite(ENA,a);
  }
}

void turn_Y(int a)
{
  if(a>=0)
  {
    digitalWrite(IN3,0);
    digitalWrite(IN4,1);
    analogWrite(ENB,a);
  }
  else
  {
    a=-a;
    digitalWrite(IN3,1);
    digitalWrite(IN4,0);
    analogWrite(ENB,a);
  }
}

void setup()
{
  Serial.begin(9600);
  pinMode(IN1,OUTPUT);
  pinMode(IN2,OUTPUT);
  pinMode(IN3,OUTPUT);
  pinMode(IN4,OUTPUT);
  pinMode(ENA,OUTPUT);
  pinMode(ENB,OUTPUT);
  pinMode(BL,OUTPUT);
  digitalWrite(IN1,0);
  digitalWrite(IN2,0);
  digitalWrite(IN3,0);
  digitalWrite(IN4,0);
  analogWrite(ENA,0);
  analogWrite(ENB,0);
  Setpoint_X = 560;//560;
  Setpoint_Y = 560;//560;
  PID_X.SetTunings(p_X,i_X,d_X);
  PID_Y.SetTunings(p_Y,i_Y,d_Y);
  PID_X.SetOutputLimits(-255,255);
  PID_Y.SetOutputLimits(-255,255);
  PID_X.SetSampleTime(5);
  PID_Y.SetSampleTime(5);
  PID_X.SetMode(AUTOMATIC);
  PID_Y.SetMode(AUTOMATIC);
}

void loop()
{  
  Input_X = analogRead(A1);
  Input_Y = analogRead(A0);
  PID_X.Compute();
  PID_Y.Compute();
  turn_X(Output_X);
  turn_Y(Output_Y);
  

  
}

The code makes no sense without a complete circuit diagram, a drawing or photo of the setup and some explanation of how it should work. For example, why do you need four coils? What are X and Y?

All PID projects require careful tuning of the three parameters in order to function correctly.

Oh, my mistake! I have provided too little information. The schematic is here:

The working principle is that the 2 hall sensors are in the middle perpendicular to each other. The X sensor is in line with the X unit, and the Y sensor with Y unit. There are 2 pairs of coils, the L2 and L3 make up the X unit, and the L1 and L4 the Y unit.

I hold the magnet in the centre of the 4 coils, and I calibrate the reference values for both X and Y sensor. 560 is the best value as the code suggested. For example: The magnet comes closer to L2, the X sensor senses it and the software makes the L2 inductor to repel the magnet, and the L3 to attract it just a little. This is also the principle when the opposite happens. The same thing happens with the Y unit.

Interesting idea!

If the Hall sensors are intended to detect the magnet position, how do the varying magnetic fields from the coils affect the position measurements?

What were the results when you tried to tune the PID parameters?

Are you trying to replicate one of these things?

Well, the sensors readings seem clean. Unfortunately I'm a newbie with PID controllers, and I'm still learning them, but it is a bit difficult to understand them in this operating situation.

Yes, my levitator has a similar principle.

At idle (no magnet): the Output_X bounces around 38.00 plus or minus 2.00
the Output_Y shows around 245.00 plus or minus 4.00
Both of them should be zero when the magnet is floating on top of the coils.

1 Like

I imagine that the ring of magnets on the outer rim of the commercial example (photo in post #4) are really important.

What did you base the PID values on?
If you don't have any experience with PID controllers, I suggest learning about them with some simple examples on the internet. They are very logical once you understand them, but it may take a couple of hours. (good example: https://sites.google.com/site/fpgaandco/pid , read up on what the values do and then play around with them, see if you understand why a system can become stable or unstable due to the controller)

Realize that your application is very non-linear, while a PID controller is actually most suited for linear systems (maybe good to read up on this as well).
It's not impossible to use a PID controller for this application, but your 'stable operating region' will not be very large. (i.e. there is only a small region above the coils in which you are able to balance the magnet using the controller, outside of this region the controller wont be able to balance it, and the magnet will fall.)

Also, the output measurements you state in post #5, are those taken with the coils activated (albeit via the PID controller)

Agree with @chris_abc. If you just want to learn PID principles that project is not a good place to start.

A much simpler, much easier to build PID levitator is shown here.

You might find it useful to read an article on the K & J Magnetics website which discusses just the system you are trying to achieve. It does however use a ring of neodymium magnets outside of the electromagnets, so these might be an essential part of the system.
As far a tuning the PID parameters is concerned, might I suggest you temporarily add a potentiometer for each of them, and scale initially for gains of 0 to 1 for the "I" and "D" terms, and 0 to 10 for the "P" term. You can always tweak these later to obtain good stability and response times before hard coding them.

1 Like

I have understood the working principle and how to achieve this levitation. The point where I had problems is the PID implementation. Thank you so much for the help, I'll definitely try it. How precise should the increments be? 2 or 3 decimals?

That's relatively easy, you can set the PWM frequency higher (ultrasonic), using either a library, or direct register manipulation (the datasheet for the processor details it all). Given the size of you electromagnets (and lack of closed magnetic circuit), a higher PWM frequency may be required anyway. You want the current variations to be less than the magnitude of the typical currents, ie smoothed out,
and 500Hz or 1kHz is a bit low for that.

1 Like

Once you get the PID parameters in the right ball park, a change of +- 20% will make very little observable difference to the system response to a step input. Up till that point, your guess is probably better than mine!!
Not wishing to be a doom monger, but there must be a very good reason why commercial levitation products use a ring of high strength magnets surrounding the control solenoids. These magnets aren't cheap, and the Chinese will use every trick in the book to reduce material costs in a product.

1 Like

Been doing a little searching for information on PID controllers and found this article on levitation. Go to "Step3" - there is an animated response plot showing the effect of variations in the three terms. Quite fascinating and instructive.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.