Magnetic Levitation – The Digital Way

Magnetic-Levitation-Object with only …IMG_7101

  • an ESP32Pico M5Stack „ATOM LITE“ or „ATOM MATRIX“
  • a modified simple 5V-relais and
  • a HALL-sensor A1302/A1308.
  • The wooden carrier is made of an embroidery frame.

IMG_7105

After I had successfully built up a „Magnetic Levitation Object“ in conventional analog design and described that in article „Magnetic Levitation – The Easy Way“ , I now wanted to replace the technology of the 1980s with modern digital components. The object should also get  a little smaller, and  -as I hope – more beautiful.

In this video you can see the result:  Magnetic Levitation – The Digital Way

Instead of the analog comparator, an ESP32 SoC module from M5Stack is now used. The ATOM LITE or also the ATOM MATRIX are extremely small (24mm*24mm*10mm or 15mm) and still offer all the appreciated features of the ESP32.
So especially a quite fast 12Bit-ADC is available.

Schematic

The Hall sensor A1302 is now operated with 3V3 so that the level is suitable for the ESP32 ADC. This is a bit below its data sheet specification, but works very well.

Furthermore a modified 5V relay is used as electromagnet – so no winding of coils etc is necessary and the result is predictable and reproducible. The modification of the relay is described in detail HERE. It can be controlled directly with 3V3 from the ESP32. As the former relais coil is now switched on/off very fast and has a high inductance, it is important to replace  the diode D1 ( parallel to the coil) by an LED with a serial resistor. This limits the flyback voltage/current and  preserves T1 against  the resulting very high induction voltage. The three original connector pins (GND,+,S) are still used to connect the electromagnet.

Attention: The HALL-sensor is now powered with 3V3 at the former „NO“-relais-contact, but the former relais has to be powered with 5V at pin „+“.  Both share the same GND at contacts „NC“ and „-“ ( so I connected them on the board).

I placed the ATOM LITE at a piece of PCB with 4+5 pins and used two flat band cables  at the inner wall of the wooden ring  to make the  five connections to the board with the electromagnet. M5stack’s ATOM LITE with an ESP32 pico and an USB-C interface is ideal for this, as it is very small and well protected in its housing.

The ATOMs can be powered from USB-C or the grove-port (G and 5V) or via the downside-plugs (G and 5V).

CODE:  The small minimalistic ARDUINO IDE program makes sure that the ADC of the ESP32 behaves like the comparator LM311 of the analog version – including the hysteresis, which stabilizes the behavior of the control very much. This is extremely simple to program, but works very well once you have experimentally determined the correct value for the TRIGGER variable. This value is very dependent on the magnets and the payload weight, as there is only a range of a few mm where the electromagnet can control the flightlevel  of the magnetic object..

ATTENTION: It turned out that the quality of the 5V supply is very important. At first I had problems with the stability of the flight altitude as long as I used the 5V of my notebook via the USB port. This supply was too unstable and unclean. Only when I connected a USB hub with its own power supply in between it worked very well. 

With a future extension of the program this value could be determined in the program and stored in the permanent memory of ESP32. This will make it e.g. more easy to change the payload without code-changing/compiling/uploading again.

At fist I wrote the necessary code in MicroPython, but that turned out to be a bit to slow. So here you see my simple program-code for the ARDUINO IDE and an M5Stack’s ATOM LITE:

/**************************************
Magnetic Levitation object:
Lets a LEGO man, glued together with a neobodymium magnet, float under a modified 5V relay 
- SoC:            ESP32, very good: M5Stack's ATOM LITE or ATOM MATRIX
- Electromagnet:  Modified 5V-Relais HW-482 with 3V3/5V transistor input 
- Sensor:         HALL-sensor A1302 or A1308
***************************************/
// int TRIGGER     = 2740; // Triggerlevel is set to a level where weight of payload is equal to the force between magnet and electromagnet  
int TRIGGER     = 2740; // good for payload = 2 Neobdym-Magnets  and a LEGO-Man  
int HYST        = 35;   // Hysterese for trigger level

int HALL_PIN    = 33;   // analog Signal from HALL-sensor at GPIO33
int HALL_VAL    = 0;    //
int RELAIS_PIN  = 23;   // GPIO23 to drive the transistor input of the modified 5V-relais  that is used as electromagnet
int X           = 0;    //


void setup(){
  Serial.begin(115200);
  pinMode(RELAIS_PIN, OUTPUT);
  Serial.print("Magnetic Levitation:   START " );
}


void loop(){
  HALL_VAL =analogRead(HALL_PIN);       //read HALL-Sensor with default 0-3.9V input >> 12bit

  if (HALL_VAL < (TRIGGER + X) ){
    digitalWrite(RELAIS_PIN, HIGH);     // lift the payload
    X = HYST;
  }
  else{
    digitalWrite(RELAIS_PIN, LOW);      // drop the payload
    X = 0 - HYST;
  }
// no delay is best
//  delay (1);     
}



UPDATE:

The next step was to  enlarge the ARDUINO code:

  • Use the built in button of the ATOM LITE and ATOM MATRIX to determine the right value  for the variable TRIGGER by decreasing the preset value with each button press and then show  the new value via the serial interface
  • Use the NeoPixel-LEDs of ATOM MATRIX for a limited animation
DA2E12A0-7D0D-4DA7-9CCB-6C8EB4EE826D

… with M5Stack’s ATOM MATRIX

So this is the enlarged code for M5Stack’s ATOM LITE and MATRIX:

/**************************************
Magnetic Levitation object:
Lets a LEGO man, glued together with a neobodymium magnet, float under a modified 5V relay
– SoC: ESP32, very good: M5Stack’s ATOM LITE or ATOM MATRIX
– Electromagnet: Modified 5V-Relais HW-482 with 3V3/5V transistor input
– Sensor: HALL-sensor A1302 or A1308
***************************************/

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 27
#define NUMPIXELS 25

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
//Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

// int TRIGGER = 2740; // Triggerlevel is set to a level where weight of payload is equal to the force between magnet and electromagnet
//int TRIGGER = 2740; // ATOM LITE with 2 Neobdym-Magnets and a LEGO-Man
int TRIGGER = 2672; // ATOM MATRIX with 2 Neobdym-Magnets and a LEGO-Man

int HYST = 35; // Hysterese for trigger level

int BUTTON = 39; // PushButton of M5-ATOM
int HALL_PIN = 33; // analog Signal from HALL-sensor at GPIO33
int HALL_VAL = 0; //
int RELAIS_PIN = 23; // GPIO23 to drive the transistor input of the modified 5V-relais that is used as electromagnet
int X = 0; //
int II = 0;
int CNT = 0;

void setup(){
Serial.begin(115200);
pinMode(RELAIS_PIN, OUTPUT);
pinMode(BUTTON, INPUT_PULLUP);
Serial.println(„Magnetic Levitation: START “ );

pixels.begin();

}
void loop(){
HALL_VAL =analogRead(HALL_PIN); //read HALL-Sensor with default 0-3.9V input >> 12bit

if (HALL_VAL < (TRIGGER + X) ){
digitalWrite(RELAIS_PIN, HIGH); // lift the payload
X = HYST;
}
else{
digitalWrite(RELAIS_PIN, LOW); // drop the payload
X = 0 – HYST;
}
II = ++II;

switch (II) {

case 1000:
if (digitalRead(BUTTON) == 0){
TRIGGER–;
Serial.print(„Trigger ist:\t“);
Serial.println(TRIGGER );
}
break;
case 33000:
NEO_ANIMATION();
break;

case 99000:
delay(1); //delay disables the interrupts!!!
pixels.show(); // why here?
// Schreibt erst jetzt den neopixel-Puffer,
// wegen flicker-Problem bei ESP32, wenn show() ohne delay DIREKT nach dem setpixelcolor() kommt.
II = 0;
break;
}
// no delay is best
// delay (1);
}

void NEO_ANIMATION(){
// xxxxxxxxxx

CNT = ++CNT;
switch (CNT) {
case 1:
pixels.clear();
pixels.setPixelColor(12, pixels.Color(0, 10, 0));
break;
case 2:
//do something when var equals 2
pixels.clear();
pixels.setPixelColor(6, pixels.Color(0, 10, 0));
pixels.setPixelColor(7, pixels.Color(0, 10, 0));
pixels.setPixelColor(8, pixels.Color(0, 10, 0));
pixels.setPixelColor(11, pixels.Color(0, 10, 0));
pixels.setPixelColor(13, pixels.Color(0, 10, 0));
pixels.setPixelColor(16, pixels.Color(0, 10, 0));
pixels.setPixelColor(17, pixels.Color(0, 10, 0));
pixels.setPixelColor(18, pixels.Color(0, 10, 0));
break;
case 3:
pixels.clear();
pixels.setPixelColor(0, pixels.Color(0, 10, 0));
pixels.setPixelColor(1, pixels.Color(0, 10, 0));
pixels.setPixelColor(2, pixels.Color(0, 10, 0));
pixels.setPixelColor(3, pixels.Color(0, 10, 0));
pixels.setPixelColor(4, pixels.Color(0, 10, 0));
pixels.setPixelColor(5, pixels.Color(0, 10, 0));
pixels.setPixelColor(9, pixels.Color(0, 10, 0));
pixels.setPixelColor(10, pixels.Color(0, 10, 0));
pixels.setPixelColor(14, pixels.Color(0, 10, 0));
pixels.setPixelColor(15, pixels.Color(0, 10, 0));
pixels.setPixelColor(19, pixels.Color(0, 10, 0));
pixels.setPixelColor(20, pixels.Color(0, 10, 0));
pixels.setPixelColor(21, pixels.Color(0, 10, 0));
pixels.setPixelColor(22, pixels.Color(0, 10, 0));
pixels.setPixelColor(23, pixels.Color(0, 10, 0));
pixels.setPixelColor(24, pixels.Color(0, 10, 0));
break;
case 4:
pixels.clear();
pixels.setPixelColor(12, pixels.Color(0, 0, 5));
CNT = 0;
break;
}
//delay(1);
// delay(1) ist bei esp32 vor pixels-show nötig!!
//pixels.show();

}

 

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Google Foto

Du kommentierst mit Deinem Google-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s

%d Bloggern gefällt das: