Electromagnetic levitation in Arduino

I saw this post and thought that electromagnetic levitation (magnetic levitation) is amazing, so I struggled to make it with the familiar Arduino.

Electromagnetic levitation is very cool, isn't it? The unseen power is fascinating to me. It's also in Pokémon's Skill, but for all the coolness of its name, it's not used much in games.

About this article

I want to make the magnetic levitation of like this a reality using an electromagnet!

The actual results look like this. https://twitter.com/AceZeami/status/1231863911109951488

Here's the article I referenced.

What to prepare

In this article, I used Arduino-compatible Teensy3.2, but anything is OK. I also used an electromagnet because I had a large surplus of hand-wound electromagnets that I had used in another case before. If you want to make one, please prepare bolts, nuts, and enamel wire accordingly. I want a lot of current to flow through the motor driver, so I'm using a 10A motor driver, but I think anything is fine. As for the neodymium magnet, use one without a hole in the middle. If there is a hole in the center, the magnetic field near the center is not constant (the direction of the magnetic field is reversed from the center), so the levitation is not stable. (This bothered me for about an hour.)

Development Environment

  • MacOS Mojave 10.14.6
  • Arduino 1.8.11
  • Platformio 4.2.1

How to make things float

Simply put, if the repulsive force of the magnet and the gravity on the floating object are balanced, the object can be made to float in the air. However, it has been shown by [Earnshaw's theorem] (https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%BC%E3%81%AE%E5%AE%9A%E7%90%86) that magnetic levitation is not stable in a permanent magnet (static magnetic field) alone. In order to make an object float, it is necessary to sense the current state (how far the object to be floated is from the magnet) and change the magnitude of the magnetic force accordingly.

This time, a Hall sensor (a sensor that senses magnetism) is used for sensing the state, and an electromagnet is used to change the magnitude of the magnetic force.

Hardware Implementation

Attach the Hall sensor to the end of the electromagnet. IMG_2833のコピー.png

It is better to cover the hole sensor part with cushioning or curing tape as shown in the image. (When the neodymium magnet sticks to the Hall sensor, it will have a huge impact and break the Hall sensor.) IMG_2828のコピー.png Hang it up on a suitable stand. IMG_2832のコピー.png Once the electromagnet, motor driver, and Arduino are properly connected, the hardware setup is complete.

Software Implementation

Read more at repository on Github. Only the main Magnet class is listed here.

It is written in various ways, but all we are doing is keeping the value of the Hall sensor constant with PID control. The value of the target Hall sensor depends on the weight of the object to be floated, so adjust it accordingly. If the magnets are placed too close together, the repulsive force of the electromagnet will be insufficient and the neodymium magnet will stick to the electromagnet. Conversely, if the magnets are too far apart, the force of attraction between them will be insufficient and the neodymium magnet will fall off. Therefore, it is important to adjust the target values.

Magnet Class

#ifndef   MAGNET_HPP
#define   MAGNET_HPP

class Magnet {
        int pwm_pin, sensor_pin, dir_pin;
        Magnet(int dir, int pwm, int sensor) {
            pwm_pin = pwm_pin;
            sensor_pin = sensor_pin;
            dir_pin = dir_pin;
        void setup() {
        void update() {
            sensor_val = analogRead(sensor_pin);
        bool getIsGenerating() {return isGenerating;}
        void setIsGenerating(bool isGen) {isGenerating = isGen;}
        int getPWM() {return pwm_val;}
        int getSensorVal() { return sensor_val; }
        void handleMagnet(int target) {
            if (isGenerating) {
                pwm_val = pwmfunc(sensor_val,target);
            } else {
                pwm_val = 0;
            pwm_val = constrain(PWM_CORR * pwm_val, -MAX_PWM_VAL, MAX_PWM_VAL);
        void reset() {
            pwm_val = 0;
            error_i = 0;
            error_prev = 0;
        float pwm_val;
        int sensor_val = 0;
        float KP=0.005,KI=0.002,KD=0.00001;
        float PWM_CORR = 0.5;
        float error_i;
        float error_prev;
        int last_updated_time;
        int MAX_PWM_VAL = 150;
        int THRESHOULD_UPPER = 210;
        int range = 100;
        bool isGenerating = false;
        int pwmfunc(int val, int target) {
            // pid 
            float error = target - val;
            error_i += error;
            float error_d = (error - error_prev) / (float)(micros() - last_updated_time) * 1000000.0;
            pwm_val += error * KP + error_i * KI + error_d * KD;
            last_updated_time = micros();
            error_prev = error;
            Serial.println("pwm : " + (String)pwm_val + " error : " + error + " error_i : " + error_i);
            return pwm_val;


Next Step

Electromagnetic levitation, do you want to do it from above? You want to do it from the bottom? This time, we were able to levitate by lifting the object from above, but we would like to try to levitate by using an electromagnet installed underneath the floating object.

Ph.D. Student of the University of Tokyo

My research interests include Human-Computer Interaction and virtual reality.