Arduino-Controlled Decor
A spinning globe of the Earth is a common enough piece of home décor. But Herwig decided to kick things up a notch and build a magnetically levitating, spinning globe. Based on the Arduino Nano, the system is designed to hang in a stable state of levitation while spinning at a constant controllable speed.
Oh yes, a wooden lantern with a burning candle in it. It feels so cozy! Nevertheless, I decided to replace the candle with something more ambitious: A floating, rotating and illuminated earth globe. While admitting that this item has no functional use at all—it doesn’t switch on the lights when I come home, and it doesn’t open the garage door either—I feel that what I crafted is an amazing artifact—combining technology with beauty and earning a center place in my living room
The basic project objective was clear: Make an object float. That said, the realization of the project took me quite some time, more than a year. That’s because I had to factor in some requirements. On the technical side, I wanted a well-designed PCB, well-structured and documented code and an Arduino Nano at the heart of the whole thing. Meanwhile, I wanted an object of a certain size and weight (the globe’s diameter is 11cm and it weighs 140g) with a “considerable” distance between globe and lifting electromagnet (actually, it’s 3.5cm).
In addition to all that, I of course wanted stability—no jitter, no oscillations. To the human eye, the globe should appear to “hang” there without any visible movement—no swinging, no moving up and down. I also wanted the globe to be able to rotate at a constant, controllable speed. And I wanted it illuminated by digitally controlled LED strips. I wanted the item to be “didactic” to a certain extent—everything visible, nothing hidden inside an enclosure. And did I mention safety? The main electromagnet has a 24V and 25W rating, producing quite some heat. I didn’t want to risk a fire, so a few safety measures had to be built in. Finally, (I almost forgot), the resulting object had to look nice.
All this led to a rather long prototyping phase. I used a large breadboard holding the electronic components and a mechanical construction for electromagnet, rotation coils and sensors. When I was sure about what electronics I was going to use, only then did I start designing the two-layer PCB. When it came back from the manufacturer it took me a day or two to place all components and test it with the current code version. It worked perfectly!
In the meantime, I continued refining the code, until I felt happy that it was working as it should. When all this was done, I started building everything in the wooden lantern that I had received for my birthday a couple of years ago. With all that in mind, let’s first take a step back now and explain a little bit more in detail about the principle of operation.
MAGNETIC LEVITATION PRINCIPLE
One way to achieve magnetic levitation is to position an electromagnet above an object—in this case, an earth globe—which contains a very strong magnet. By constantly measuring the vertical position of the object, we can vary the magnetic force exerted by the electromagnet on the object’s magnet to keep the object in place. This happens much in the same way as driving a car on the highway. By constantly measuring whether the car drifts to the left or to the right, the driver can stay in his/her lane by applying small corrections only. This mechanism is called a “control system” or “feedback system.”
— ADVERTISMENT—
—Advertise Here—
This magnetic levitation control system is not a “linear” system at all. For instance, the relationship between current applied to the electromagnet and force exerted (on the globe’s magnet) is quadratic. Moreover, this force varies with the distance between electromagnet and magnet—which seems logical. But this relationship also is quadratic!
That means that the “parameters” (we’ll talk about that in a moment) used to keep the globe’s position stable are critical. Any change to the globe’s weight, the magnet, the electromagnet or the position of the sensor will probably result in a highly unstable globe, and you will have a hard time finding the correct parameters (which will be trial and error, I’m afraid) to obtain stable operation again. Indeed, this non-linearity also makes it difficult to apply mathematical methods to calculate these parameters.
GLOBE LIFTING CONTROL
So, how does it work? Well, I’ll try to explain it in an easy way. And, in the meantime, please keep an eye on the drawing in Figure 1. First, we need to determine the globe’s vertical position. This position is measured by a Hall effect sensor, a tiny device that measures the strength of the magnetic field (produced by the magnet mounted inside the globe), converting it to an electrical voltage. If the globe comes closer to the sensor, the magnetic field strength will increase and the output voltage will change. In our case, because of the way the magnet’s north and south poles and the Hall effect sensor are positioned, this voltage will decrease. Voltage will increase again if the globe moves further away from the sensor. So, the sensor effectively converts a position to a voltage!
This (small) voltage (typically between 100mV and 300mV at the operating point, depending on settings) is amplified before it is converted to a 10-bit number by the Arduino ADC (analog-to-digital converter). Welcome to the digital world! This amplification is a necessary step, considering the very small voltage variations to be captured (less than a millivolt at the Hall detector output) and the 10-bit Arduino ADC resolution.
Note that, from a control systems perspective, the ADC conversion can be considered a second “amplification” step. The ADC scales an input voltage to a number from 0 to 1,023. It is perfectly fine to consider this number as the digital representation of a (scaled) voltage. Or you can use “ADC steps” as a unit. Doesn’t matter, as long as you are consistent.
As a next step, the program will subtract this number (representing a position but expressed in millivolts—or ADC steps if you prefer) from the desired position (called “setpoint”), which should also be expressed in millivolts—or ADC units—and appropriately scaled. We can only subtract values expressed in same units. The subtraction gives us the deviation from the desired globe position. We call it “error signal,” because it is zero when there is no deviation. This deviation is (again) expressed in millivolts.
THIRD STEP
Forgetting for a while about the “integrator” and “differentiator” boxes in the Figure 1 drawing (I’ll come to that in a moment), we have a third amplification step that is performed digitally this time. The amplification factor (“gain”) is stored as a constant in the Arduino program.
Note that the total gain delivered by these three amplification steps is simply the product of the three individual gains. Whether these steps happen in the analog or digital world is not relevant at all! And this total gain is important, because a higher gain makes that a same (small) controller input (here: deviation in position) produces a higher output (here: a pulse with a higher duty cycle—we’ll come to that). Imagine if this total gain would be very small. Not a lot would happen, right? More in general, with the gain too low or too high, the system risks to become highly unstable, so we need to choose it carefully.
Anyway, the amplified error signal is then fed to 16-bit Arduino Nano Timer 1 to generate a pulse with a specific duty cycle (PWM—pulse width modulation). If it’s zero, then the duty cycle will be zero as well. If it’s 999, the duty cycle will be 100%. The pulse duration is fixed at exactly one millisecond. This can be seen in the oscilloscope screen capture in Figure 2.
— ADVERTISMENT—
—Advertise Here—
The pulse produced will determine the “ON” time of the electromagnet (using power transistor Q1—we’re back in the analog world now) within that single millisecond. This will increase or decrease the “average” force exerted by the electromagnet on the globe’s magnet within that millisecond and as a result the globe’s position will change.
REPEATING PROCESS
As you might have guessed, this whole process is repeated every millisecond (interrupt driven). Every cycle is started by reading the ADC output to obtain the Hall sensor voltage. If the globe is in a stable, floating position, this voltage will be close to the setpoint voltage (in this example: around 1,000mV). As with any control system, this voltage will fluctuate a little. If it didn’t, we wouldn’t need a controller. Think about that! Figure 2 shows that every millisecond the globe is falling to the ground for approximately 500µs and then moving upward again toward the electromagnet. “Up” is actually “down” on the oscilloscope and vice versa. Sorry for that.
And what about those integrator and differentiator boxes? Well … differentiating the error signal with respect to time and adding this term to the error signal provides a faster reaction to quickly changing globe positions. The effect of this term will be smaller for slower changing globe positions. The differentiator time constant Τd (which is also a parameter in the Arduino program) controls the weight of this term. It is a critical parameter and must be carefully chosen to obtain stability.
And why do we integrate the error signal (with respect to time)? Well, imagine the system is at rest and the actual globe position corresponds to the setpoint. This reduces the error signal to zero, as well as the PWM output (pulse with zero duty cycle) and the electromagnet’s force exerted on the globe. But this situation is impossible—because of the globe’s weight, it needs a counterforce.
So, the globe’s position at rest will be a little lower than indicated by the setpoint, which leaves us with a non-zero error signal and, consequently, a non-zero PWM signal and a counterforce. This is called “static error.” Now, if we integrate the remaining error signal, the controller (PWM) output will slowly increase, the globe position will approach the desired position, the error signal will become zero and integration will stop … exactly when the globe is where we want it to be. The integrator time constant Τi is, as you will have guessed, another parameter in the Arduino program. It is less critical than Τd.
Conclusion: Four parameters are important here: Setpoint, gain, integration time constant and differentiation time constant. You’ll find these constants defined in the Arduino program (available for download on my GitHub repository [3]). And why is the sampling time 1ms? Why not 10ms? In free fall, an object initially at rest will fall about 5µm in 1ms. In 10ms, this increases to 0.5mm (×100). Not exactly a stable situation as perceived by the human eye. And it’s probably a lot more difficult to keep the system stable from a control system perspective. That answers that!
ELECTROMAGNET ASSEMBLY
This assembly contains everything we need, except for the coils used for globe rotation and the LED strips (Figure 3). The electromagnet is quite powerful and produces a fair amount of heat. To keep everything safe, a quite large heatsink is placed on top of it. Additionally, a temperature sensor is fixed to the heatsink. It will be used to continuously control temperature.
Above the heatsink comes a wooden plank—used to “hang” the assembly in the wooden lantern without the need for any nuts or bolts. Just underneath, notice an aluminum corner profile to keep the plank in position. Threaded (non-magnetic) spacers connect the plank with the base of the heatsink.
Underneath the heatsink, we have another set of threaded spacers arriving at a plexiglass plate, holding the sensor we use for vertical position measuring (Hall effect sensor) and the 3D assembly with the globe rotation Hall effect sensor. We’ll discuss this later. The plexiglass also serves as a protection, preventing the globe with its strong magnet from smashing against the electromagnet.
SENSORS IN ACTION
Several ways exist to accurately measure the distance between globe and electromagnet—more correctly, to measure the deviation between desired position (“set point”) and actual position. A common method is to use a light source at one side of the globe and a light detector at the other side. But in our case, as said, we use a Hall effect sensor measuring the strength of a magnetic field (which depends on the globe position) and converting this to an electrical voltage.
Actually, this sensor (Figure 4) will not control the position of the globe with reference to the electromagnet, but with reference to the sensor itself. But because this sensor is fixed in position, this will ultimately determine the position of the globe with reference to the electromagnet. The vertical distance between electromagnet and sensor (or plexiglass plate) is critical because it determines the electromagnet duty cycle required.
With the electromagnet I used (height 40mm), the plexiglass plate is 58mm away from the heatsink, which can be obtained by stacking 15mm and 40mm threaded spacers, adding a nut in the middle. This results in a “gap” of 18mm between electromagnet and Hall effect sensor (Figure 3). A question you might ask: Doesn’t the magnetic field of the electromagnet influence the sensor reading? Well, yes… but this is not a problem, because while we read out the sensor value (every millisecond), the electromagnet is always in the same (“ON”) condition. You can verify this by looking at the scope screenshot in Figure 2. So, its attribution is constant and can be discarded.
The Hall effect sensor needs to be placed exactly beneath the center point of the magnet. If not, you will introduce oscillations in the system and the globe will start to “swing” in a horizontal direction, which is something the electromagnet cannot control. When visually figuring out that position, a thing called “parallax” must be taken into account. Once I determined that spot, I put a small dot on the bottom side of the plexiglass as an aid to position the Hall sensor.
The sensor leads are then placed into a receptacle with precision contacts, glued to the plexiglass plate (I used Loctite superglue). This allows for easy fine tuning of the sensor position. Assuming we’re using a SS495A Hall effect sensor from Honeywell, the stamped side must be facing down (the Arduino program assumes it). When gluing the receptacle, the plexiglass plate needs to be clean and dry. We’ll deal with the PCB connection later.
The system also uses a temperature sensor. The temperature sensor (Figure 5) continuously measures the heatsink temperature. When it passes a set threshold, electromagnet, coils and LED strips will be shut off as part of the safety features built in. When the temperature drops again (applying a small hysteresis), the system can be enabled again. The sensor should be mounted so that it makes good mechanical contact with the heatsink.
— ADVERTISMENT—
—Advertise Here—
THE GLOBE
Let’s now talk about the globe itself for a moment. I was able to find a globe for use as piggy bank. This has the advantage that there’s a big opening at the bottom (and the disadvantage there’s a slot for throwing in money, too). In this case we’ll use this opening to position a strong permanent magnet—neodymium, 20mm × 20mm × 20mm—inside, near the globe’s geographic north pole. I used double-sided adhesive tape to do the trick. Some chirurgical skills and good thinking are needed to finish the job without having to open (and possibly damage) the globe, but… it’s possible (Figure 6).
The lifting magnet must be positioned with its north pole facing upward. A cube has six sides, so this requires some experimenting. If the magnet is placed upside down, it won’t work! Best to use a compass to determine the magnet’s north pole. A magnet’s north pole attracts a compass needle’s south pole. This is the needle pointing in the direction of the earth’s geographic South. This looks strange, but the earth’s magnetic North is located close to the earth’s geographical South and vice versa. Later on, we will have to reverse the electromagnet wires if the force exerted on the globe’s magnet proves to be repelling instead of attracting. But let’s not worry about that for now.
But we also want the globe to rotate, right? This will require placement of two additional (smaller) magnets inside the globe. Also, these magnets are of the neodymium type. And again, I was lucky—the globe I used is made of two plastic halves with an inside border (in red) used to glue them together (I guess). This border is the ideal place to position these two magnets: one at the Greenwich meridian, and the other—at the opposite side, of course (the Greenwich anti-meridian). Also, here I used double-sided adhesive tape.
Important: The magnet at the Greenwich meridian must be positioned with its north pole facing up, the other one with its north pole facing down. The magnets will generate a (very small) torque, keeping the globe rotating—but that comes later.
GLOBE ROTATION COILS
To create a globe rotation torque, we need a rotating magnetic field. The six coils placed below the globe will serve that purpose. I made these coils myself, out of empty spools (I found these on the Internet) and 500 turns of enamel-coated copper wire (0.28mm diameter). This produces a coil resistance around 20Ω, which is just fine. The coils are held in place by a 3D-printed spider with six knobs, providing a tight fit with the center holes in the spools. The spider itself is fixed to a plexiglass plate by two screws (Figure 7). The STL files to print the spider yourself is available for download from the link provided in RESOURCES at the end of the article [1].
A two-pin header is soldered to each coil, these headers are all connected to a larger 15-pin receptacle (with 3 unused pins) glued to the spider, right in the middle. The coils are numbered from 1 to 6 (Figure 8) and coil terminals are labeled A and B (Figure 9). If, looking down at a coil from the top, the winding direction (from first to last turn) is clockwise, we define terminal A as the start of the first turn of the copper winding (close to the center of the spool) and terminal B as the end of the last turn of the copper winding. If the winding direction is counterclockwise, then we designate the start of the first turn as terminal B and the end of the last turn as terminal A.
The coils will work together in 3 pairs: Coil 1 and 4, 2 and 5, 3 and 6. Therefore, we connect the 2-pin headers (coil terminals) to the receptacle as indicated in Figure 9. The coils “B” terminals are simply interconnected for each coil pair. The Receptacle pins for the coil’s “A” terminals are soldered to the flat cable (6 wires). At the other end of the flat cable, we will solder a receptacle later. The plexiglass plate, of course, will have to be cut to the desired dimensions, depending on the lantern chosen.
If everything is correctly connected, at any given moment the vertical magnetic field orientation of three adjacent coils will be opposite to the magnetic field of the other three coils. At regular intervals, this field will rotate by 60 degrees, counterclockwise (looking at the coils from the top). This will create a torque on the globe’s two side magnets. Moreover, this rotation will be in phase with what the Arduino program expects.
To obtain a nicer visual effect, the coils are positioned 13cm under the two globe rotation magnets. Because we don’t need much torque, even with this distance we will be able to keep the globe rotating.
ROTATION SENSOR ASSEMBLY
This assembly consists of six 3D-printed parts (Figure 10). Its purpose is to position the globe rotation Hall effect sensor in such a way that it can pick up the passage of the globe rotation magnets mounted inside the globe. Therefore, it allows the Hall effect sensor to be moved horizontally (by moving the “vertical connector” part forward or backward) and vertically (by sliding the Hall effect sensor housing up or down in its slot). Once in position, two nuts keep the Hall effect sensor firmly in place.

The Hall effect sensor itself is placed inside the small tube at the lower end of the Hall effect sensor housing. A precision-contact receptacle is glued to the back side of it (I used Loctite superglue) to receive the three Hall effect sensor leads.
Mounting the Hall effect sensor is a simple task. Just bend the three leads in a 90-degree position, slide the sensor inside the small tube (from back to front) and, using tweezers, place the three sensor leads in the receptacles with precision-contacts. Assuming we’re using an SS495A sensor, the stamped side must be facing up (the Arduino program assumes it). The STL file to print these parts yourself is available for download from a link provided in RESOURCES.
GLOBE ROTATION CONTROL
As explained earlier, the rotation coils beneath the globe will exert a tiny torque on the globe (because of the two small magnets mounted inside the globe). This torque is so small, that it will only keep the globe’s rotation synced with (locked to) the rotating magnetic field (caused by the six coils) if the two speeds (of magnetic field and globe) are not too far apart.
As a side note, it is certainly not helping that we also have the Earth magnetic field trying to turn the globe into a compass. Indeed, if the coils are switched off, the globe will always position itself with its two magnets pointing to the Earth’s magnetic North and South Pole. The fact that the rotation magnets are positioned with their poles facing up and down does not prevent that, because the Earth magnetic field lines do not run horizontally. In most geographical areas, they have a vertical component! Anyway, we need some type of control system, but nothing like the lifting control system described earlier—which is based on pure control theory.
First, the controller needs to have knowledge about the globe’s rotation speed. We won’t measure this speed directly (although methods exist to do that) but we will measure the time of each globe rotation. As you will have guessed, the rotation Hall effect sensor provides this input. This signal is shaped into a position sync pulse indicating the passage of the “Greenwich anti-meridian” magnet (Figure 11)—the other magnet passes quietly. After further shaping by a Schmitt trigger (not shown), the pulse is sampled and, to avoid glitches, “debounced” by the Arduino Nano for use as controller input.
If the globe’s rotation speed is currently too low (lower than the desired speed), the rotating magnetic field speed will be set to a speed slightly higher than the globe’s current rotation speed (and vice versa). This accelerating or decelerating process is repeated at each full turn of the globe, until the globe’s rotation speed reaches a small band around the desired rotation speed. Within that band, the control system is switched off: globe’s rotation is now “synced” with (locked to) the rotating magnetic field. The control system described here will only work if the phase of the rotating magnetic field is set correctly (with reference to the rotating globe). The program takes care of that.
LED STRIPS
Because a globe floating and spinning in the dark is not much of an attraction, two digital LED strips are added as a final touch (Figure 12). Each RGB LED is individually controllable and only four wires are needed: Ground, 5V, data and clock.
These LED strips are sold “by the meter” and can easily be cut to the desired length. In this case, each LED strip contains eight LEDs. The type I used also has a very convenient adhesive tape at the back side, making it quite easy to position the LED strips and fix them in place. You’ll probably need a few small wooden rails as well.
The clock lines will be tied together later, and the data lines as well. We will send the same data to the two LED strips. For now, we just solder a 4-wire flat cable of sufficient length to the input side of each LED strip. The data flow is clearly indicated by arrows, as you can see in Figure 12. As a strain relief and to keep the flat cables in place, it’s easiest to glue them to the lantern. We’ll deal with the other end of these two flat cables later.
Important: To keep current consumption low, only 8 of the 16 LEDs will be used and not even at full power. This is quite sufficient to obtain nice visual effects. If each RGB led (rated at 60mA) would be switched on simultaneously and at full power, this would draw almost 1A. We will use a fraction of that. Note: The l293D half bridge chip providing power to the LED strips has a maximum rating of 600mA.
ARDUINO NANO CODE
The code is available for download on my GitHub repository [3]. The program is fairly well documented so I will not elaborate too much on it. The program has been designed for speed. For instance, the interrupt service routines (ISRs) do not make use of floating-point numbers. This means that, for instance, the lifting controller calculations are done with (long) integers, increasing accuracy by adding extra “binary fraction” digits and removing them at the end of the calculation—shifting values left or right by a number of bits.
Note that, because of this, care must be taken, if specific constants are changed, that no under- or overflow situations occur. Also, because divisions take much longer than multiplications (no processor instruction for division), there are none in the ISRs. For example, dividing a value by a constant “5” can be performed by multiplying that value with an integer constant “51” and then shifting right 8 bits (51 = 1/5 × 28). If more accuracy is needed, use more than 8 bits. This results in an average processor load of about 20%, which is measured by the program and can be verified with the Serial Monitor.
MAIN LOOP
The main loop is short—everything happens in dedicated procedures—but clearly shows the general structure (Listing 1).
LISTING 1 - Arduino main loop
void loop() {
getEventOrUserCommand(); // get ONE event or assembled user command if
// available
processEvent(); // process event, if available
processCommand(); // process command, if available
checkSwitches(); // if SW3 to SW0 to be interpreted as switches
// only
writeStatus(); // print status to Serial (and LCD if connected)
writeParamLabelAndValue(); // print label and value to Serial (and LCD if
// connected)
writeLedStrip(); // write led strip data
myEvents.removeOldestChunk(ISRevent != eNoEvent); // remove event from queue
wdt_reset(); // reset watchdog timer
resetHWwatchDog = true; // allow next ISR to reset hardware watchdog
idleLoop(); // return if still something to do or ISR occurred
}
Here’s some key notes about the main loop:
• If a user command or an event is available, it will be processed. If not, the program moves on. Events are generated by Interrupt Service Routines (ISRs). User commands are assembled from the Serial Interface or the (optional) hardware buttons.
• Switch states (read and debounced within the ISR) are used to adapt settings if needed.
• Information (if any) is sent to the serial interface and to the optional LCD.
• If the LED strip’s brightness needs to change (indicated by the occurrence of a specific “LED strip” event), serial data will be sent to the LED strip.
• As long as there’s nothing to do, control will stay in the idle loop. If there are still events to process (event queue not empty), the key buffer is not empty or an interrupt occurs (“Timer 1 overflow” or “ADC complete interrupt”) the idle loop will exit, starting a new main loop.
As a general rule, data is written or read within the ISRs, with two exceptions. LED strip data is sent serially, which takes a few milliseconds—400 bits sent each time the LED strip needs to be refreshed). Therefore, the main program loop takes care of sending LED strip data. The program ensures there are no “collisions” when sending of LED strip data is interrupted by an ISR sending or receiving data using the same data bus (port D). The optional LCD is accessed from within the main program loop as well.
Timer 1 overflow interrupt:
• Executes every millisecond
• Provides time base (timer 0 is not used by the program, but it is not disabled)
• Resets hardware watchdog (see “SCHEMATIC AND PCB” section)
• Initiates lifting Hall sensor ADC conversion and enables “ADC complete” interrupt
• Polls globe rotation Hall effect sensor
• Reads and debounces switches/buttons and produces keycodes for pressed/released buttons (if connected)
ADC complete interrupt:
• Sometimes executed twice every millisecond: at completion of lifting Hall sensor ADC conversion (every millisecond) and et completion of temperature sensor ADC conversion (every 128ms)
• Reads converted ADC value. If this was a lifting Hall effect sensor value, proceeds. If it was a temperature sensor conversion, it stores the temperature and exits.
• Performs calculations related to lifting control, rotation control, safety
• Sets Timer 1 register controlling pulse duty cycle for electromagnet (PWM)
• Outputs data for the coils, the LEDs and so forth
• Calculates LED strip brightness levels. Note that serial data will be sent to the LED strips in the main program loop (because time consuming).
• Sends information to the main loop by using “events”: data is stored in dynamic memory, indicating the nature of the event (e.g., the globe’s rotation speed has now obtained the set value) along with some extra information. The main loop will process events and remove them again from dynamic memory (see class MyEvents
).
• Every 128ms: initiates a temperature ADC conversion (which will trigger a second, but very short, occurrence of this ISR)
SCHEMATIC AND PCB
A two-layer PCB (Figure 13) hosts all electronics, except the sensors, the electromagnet, the coils and the LED strips. The PCB has been designed with great care, trying to observe good practices like making adequate use of power planes and separating as much as possible analog and digital component areas. This includes minimizing noise introduced by digital logic presented to the analog circuits—especially the stability of the floating globe will depend on signal variations of less than 0.5mV. The board contains a few extra connectors, making available most of the Arduino Nano pins as well as a few other signals. This facilitates using the board for prototyping activities beyond the scope of this project.

Because the schematic for this project is large, it is not included in these pages, but it is available for download from Circuit Cellar’s article code and files webpage [1]. The files (“Gerber files”) needed to order this PCB (I ordered mine from Seeed Studio [2]) are available for download on my GitHub repository [3].
The board uses Arduino Nano port D (6 bits wide) as a data bus, providing the data for the coils, the LEDs, the LED strip, the optional LCD and for reading the switch and button states. IC10 decodes the 3-bit hardware address provided by Arduino port B bits 0, 4 and 5 into 8 I/O selection lines. Four of these selection lines will select either IC2 flip flops to write data to (to control coils), IC3 flip flops (to control LEDs and so forth), IC4 buffers (to read switches and buttons) or the LED strip. Unused selection lines are wired to expansion connector SV5. Note that the (optional) LCD chip select is not connected to one of these selection lines but to an Arduino Nano pin (check the code), because it is accessed via the LiquidCrystal library which does, of course, not use a decoder chip to select the LCD.
IC5 and IC6 each contain 4 half-bridges, which we use to drive the six coils, to supply voltage to the LED strips (these are not directly connected to Vcc) and to control the red LED. Op amps IC9A and IC9D form a “hardware watchdog.” If the software fails to regularly switch the signal at its input from high to low and vice versa, its output will come low, signaling an error condition, effectively shutting down electromagnet, coils and LED strip and switching on the red LED. Op amp IC8B amplifies the lifting Hall sensor by a factor of 10. Changing the values of resistors R10 and R12 from 100kΩ to 150kΩ increases the amplification to 15 for a greater ADC accuracy. The corresponding #define
statement in the Arduino program must then be changed accordingly (this adapts a few constants).
#define highAnalogGain 1
Op amps IC8A, C and D are used to shape the signal coming from the rotation Hall effect sensor. Op amp IC9B is used as an inverter and IC9C is not used at all.
COMPONENT PLACEMENT
Parts are clearly indicated on the schematic drawing, the PCB silk screen and in Figure 14. I used IC sockets for all chips (female headers for the Arduino Nano) potentially saving me a lot of trouble in case a chip must be replaced. I used 74HCT logic chips because of the low power consumption, but 74LS chips will work as well (IC1 to 4, IC10).
The VMA404 step down converter is mounted vertically, components facing outward (Figure 15). The terminals are clearly labelled on the main board and on the step-down converter board. Before connecting terminal Out+, the converter’s trimpot must be adjusted to obtain an output voltage of 7V—temporarily plugging in the external 24V wall power supply). This voltage setting will guarantee proper functioning of the board without dissipating excess power. When terminal Out+ is connected but before placing the actual chips in their sockets, it is good to use a multimeter or oscilloscope to run a few tests verifying that 5V is obtained where expected across the board.
We will need a connection to the three sensors (temperature and two Hall effect sensors), the electromagnet, the coils and the LED strip—and we’ll need power, of course. Power is supplied by an external 24V wall power adapter, plugged into the PCB DC connector. It’s a good idea to check the polarity first: 24V(+) is to be delivered to the center pin. The polarity of the two wires to the electromagnet will be determined later (during testing). If the force exerted will be repelling rather than attracting—the wires need to be switched.
Sensor connectors (J3, J4 and J5 on the schematic) each expect 5V, sensor signal output and GND wires to be connected to the same respective connector pins (Figure 15). So, if a sensor is connected to a wrong connector, nothing will breakdown—although the board won’t function, of course. For the lifting Hall effect sensor (connector J3) I did not use a connector at all but soldered the wires directly to the board, not making them longer than needed, because the voltage variations measured are small (less than 0.5mV).

For connection to the rotation coils (10-pin header—only 6 pins used), corresponding signal names are clearly indicated on Figure 9 (globe’s rotation coils connections) and Figure 15 (PCB connections). The PCB LED strip connector has 5 pins. The pin closest to the DC power jack, pin 1, delivers 5V. Pin 2 and pin 3 are data lines for lower and upper LED strip (currently supplying the same data). Pin 4 delivers the clock signal and pin 5 is GND.
TESTING AND TUNING
The roadmap I used for testing is divided into several separate tests:
Test 1: Verify communication (over USB) with the serial monitor on your PC. Make sure all DIP switches are in the OFF position and verify that the serial monitor’s baud rate corresponds to the baud rate set by the Arduino program (standard 1000000 baud— preferably do not change it). Plug in the USB cable (no need to power on the PCB board yet and no need to make any other connections for now) and verify that the Arduino responds with a message starting with “Type + or – to change parameter shown, E to edit value…” after reset.
Setup: In the serial monitor, type “A” + ENTER. Arduino will respond with a list of parameters and values (Figure 16). Check that the rotation time set (“rot time”) is 12 seconds and the vertical globe position (“vert pos”) is set to 1000mV (or 1500mV, if the analog gain was changed to 15—see section “SCHEMATIC AND PCB”). If needed, refer to the procedure outlined on my GitHub repository [3] to set these values.

Test 2: For this test, forget about globe’s rotation and LED strips for a while. Just connect the temperature sensor (otherwise, the board will detect a “high temperature” and will switch off the electromagnet). Connect the lifting Hall sensor and the electromagnet wires as well. Power on. The PCB LED should start flashing green. Wait 5 seconds. The PCB LED should start blinking blue (a complete explanation about LED colors and meaning is given further on). Now, move the globe (with the lifting magnet inside) slowly upward, in the direction of the lifting hall sensor (and the electromagnet) until it touches the plexiglass plate. Then move it away from the sensor, in a downward direction. This enables the electromagnet and the lifting control system. Bringing the globe closer to the magnet again, you should now observe an attracting force between electromagnet and lifting magnet. In case the force seems to be repelling, the two electromagnet’s wires need to be switched.
Test 3: Try “hanging” the globe into position (procedure explained in next section).
Test 4: Power off, connect the rotation hall-effect sensor as well and power on. Hang the globe into position again and give it a slight turn (counterclockwise). Connect an oscilloscope to IC8A pin 9 (Schmitt trigger input) and verify that the waveform looks like the yellow waveform in Figure 11. If it’s not, then try to obtain this waveform by adjusting the horizontal and vertical position of the rotation hall sensor (loosening the two nuts —see section “ROTATION SENSOR ASSEMBLY”).
Tune Schmitt trigger output: Connect the oscilloscope channel 2 to IC8C pin 8 (Schmitt trigger output). By adjusting trimpot R8 (see the schematic [1]), set the input threshold voltage (scope channel 1) close to 0.8V. Supposing the initial globe rotation speed is somewhere between 10 and 15 seconds, this should produce a pulse between 0.5 and 1 second, each time the 180-degree meridian passes the rotation hall sensor.
Test 5: Power off, connect the coils as well and power on. Hang the globe into position again and give it a slight turn (counterclockwise). The rotation control system should now kick in. After some 30 seconds, the PCB led should go out, indicating that the set rotation speed is obtained.
Test 6: Now, connect the LED strips. Then, use serial monitor commands (explained in a next section) to set LED strip cycle 5 (cycle through all colors) and LED strip timing 1 (fastest). Verify that the LED strips function properly (remember that not all LEDs are used).
In the next section, we’ll focus on detailed info on how to handle the globe, the status LEDs and serial communication.
GLOBE, LEDS AND COMMS
After power up, you can immediately “hang” the globe in position—some 35mm below the electromagnet, or approximately 15mm below the plexiglass plate holding the lifting Hall effect sensor. Make sure that you watch the RGB status LED mounted on the PCB. If it lights up steady green, you’re at the correct height. If it blinks (green), you’re either too high or too low. This takes some practice, but it should be fairly easy. Once the globe floats, give it a slight turn (counterclockwise) and wait. Depending on the initial rotation speed given (which is not critical), after some time, the globe will attain its set rotation time (standard 12 seconds).
Now let’s discuss the status LED. When the LED is off the globe is floating and globe rotation is either locked (synced with the rotating magnetic field created by the coils) or rotation is switched off. When the LED is ON (green or blue), these are different statuses:
Green LED flashes around four times a second: Globe is not within a narrow vertical “floating” range. Very helpful while positioning the globe
Green LED is on continuously: Globe is floating but no Greenwich position sync (passage of Greenwich anti-meridian magnet) detected yet. Rotation coils switched off.
Green LED is flashing rapidly (around 16 times per second): Globe is floating; a first rotation time measurement is underway. Rotation coils switched off.
Blue LED is on continuously, but with brighter (green) flashes: Globe is floating but globe rotation is not yet locked. A blue flash indicates the direction of the rotating magnetic field just changed. A green flash indicates the Greenwich magnet is currently passing the rotation Hall effect sensor.
LED is blinking blue: Lifting magnet and coils are currently switched off because of an error condition. The number of consecutive 1-second blinks (followed by a pause) indicates what caused the error condition:
• 1 blink: Dropped globe for more than 5 seconds (globe probably fell down or was taken away, or no globe detected yet after power on).
• 2 blinks: Sticky globe: globe position too high for more than 5 seconds (globe was probably sticking to the plexiglass plate).
• 3 blinks: Average lifting magnet duty cycle was higher than 80% for the last few minutes (a situation that is highly unlikely to occur, but as this concerns safety).
• 4 flashes: Smoothed temperature reading is higher than 65°C.
To enable the system again, bring the globe close to the plexiglass plate holding the lifting sensor (in an upward movement), then move it away from the plexiglass plate again (downward movement). The LED will now turn green again and you’ll have (again) 5 seconds to bring the globe back into its floating position.
LED is red: If, because of a malfunction or program error, the program stops producing pulses on the input of the circuit around op amps IC9A and IC9D (acting as a hardware watchdog), lifting magnet, coils and LED strips will be disabled and the LED will turn red.
By using the Arduino serial monitor (or other properly configured “terminal” software) via USB, you can print certain information and change a few settings (Figure 16). The following information (“parameters”) can be printed: currently selected and actual rotation time; rotation time sync error; the accumulated globe rotation time error (when locked); “globe is floating” time and “globe rotation is locked” time; smoothed temperature and lifting magnet average duty cycle (%); globe vertical position reference (setpoint) and smoothed globe vertical position error in millivolts; current value of the PID controller integration term; phase between rotating magnetic field and rotating globe (used for rotation controller calibration); and smoothed duration of the “ADC conversion complete” ISR routine and processor load.
In addition, each status change will be printed (for example, when the selected rotation time is reached, status ‘”locked” will be displayed). A number of commands are available to change settings (rotation time, vertical position reference (setpoint) and LED strip color cycle and timing. A detailed command reference is available on GitHub [3], so I won’t get into detail here.
An interesting command is available to apply a “step” change (less than a millimeter) to the vertical position reference (Figure 17) and measure the reaction of the globe (“step response”). This is most useful while fine-tuning the PID controller parameters (see earlier in this article) to check changes in stability (number of oscillations, damping). For 20 seconds, the measured step response (actual globe vertical position) and controller output (PWM duty cycle) is sent to the serial monitor where it can be logged for evaluation in Excel and so forth (one sample per millisecond—baud rate must be high enough to accommodate this).
BUTTONS AND SWITCHES
It is possible to connect four (make contact) buttons directly to the Spinning Globe board PCB (buttons connector SV2), as well as a 16×2 character, Arduino compatible LCD display (general-purpose connector SV5). This allows you to review the same live values and change the same settings as by using the serial monitor.
The LCD displays status information on the top line (for example, “E! dropped globe”) and the currently selected parameter (see section “GLOBE, LEDS AND COMMS”) on the bottom line (Figure 16). To use buttons, DIP switches 2 to 5 need to be in the OFF position. Detailed connection instructions are beyond the scope of this article, they are available on GitHub [3].
You can use the DIP switches to change settings (program mode). In program mode, the same four DIP switches (2 to 5) are used to set the globe rotation time, vertical position setpoint and LED strip color cycle—without the need for serial communication or buttons/LCD.
The procedure is simple: While power is OFF, indicate which parameter to change with DIP switches 2 to 5 and then power ON again. The system is now in program mode and the selected parameter can now be changed by setting the DIP switches accordingly. When done, power OFF again and (while power is OFF) set switches 2 to 5 to “OFF” again. Now, power ON again. The new setting for the selected parameter is in effect. Detailed instructions and switch settings are available on my GitHub repository [3].
THAT’S ALL FOLKS
With this article, I tried to give you an insight into the project that consumed most of my free time during the last year. During this endeavor, I had to answer a lot of design questions that popped up, one by one. But it paid off and I’m really happy with the result. I would encourage you to build a floating and spinning globe of your own! Feel free to contact me with questions, suggestions. I would love to hear from you.
RESOURCES
The links for the STL files are as follows:
– Spider STL file: https://skfb.ly/6YZRD
– Globe rotation sensor assembly STL file: https://skfb.ly/6YZSP
References:
[1] The schematic for this project is available for download from Circuit Cellar’s article code and files webpage
[2] https://www.seeedstudio.com
[3] GitHub repository
https://github.com/Herwig9820/spinning_globe
YouTube video of the Spinning Globe:
Arduino | www.arduino.cc
Honeywell | www.honeywell.com
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • JUNE 2021 #371 – Get a PDF of the issue
Sponsor this ArticleHerwig Taveirne graduated as an engineer in electronics and became a developer of digital hardware and software before moving on to the world of functional consulting in the ERP domain. For some time now, he's been working as a program and project manager. Herwig has a lively interest in science and technology in general and likes thinking about theoretical concepts and inventing things, making use of electronics and software. Email him with remarks or questions at Herwig.taveirne@gmail.com