Unfortunately, I do not have the tools nor the knowhow of David Robert. So, inspired by a lot of projects on YouTube, I took the hacker path and used an old hard drive to build my motor.

The hard drive has two mechanical elements:

  1. A brushless motor spinning the disk(s) (the spindle)
  2. An oscillating arm holding the read/write heads on one side and a coil surrounded by strong magnets on the other side. The arm is mounted on a pivot and moves when the coil is energized.

If I add a connecting rod from the oscillating arm to an off-center point on the spindle, I can mimic the mechanism of a solenoid engine.

To detect the spindle’s position, I use a hall effect sensor combined with a small magnet glued to the spindle. The sensor and magnet are set to detect when the spindle is at the top dead center (TDC http://en.wikipedia.org/wiki/Dead_centre).

To control the solenoid, I use one of the integrated H-bridges of a L293D. The advantage of an H-bridge is to be able to energize the coil in two directions, which means I can have two power strokes (push and pull on the spindle).

The sensor and the L293D are connected to an STM32F4-discovery board that will run the software.

The first version of the control software will be somewhat naive. Foremost,
I want to check that I can control the engine with the STM32F4. I will
explore advanced features later.

The hall effect sensor will be connected to an interrupt. The
interrupt will be triggered when the spindle is at TDC. By measuring the
time between two interrupts, I can compute the speed of the spindle.

-- What time is it?
Now := Clock;

-- Time since the last interrupt 
Elapsed := To_Duration (Now - Last_Trigger);

-- Store trigger time for the next interrupt
Last_Trigger := Now;

-- Compute number of revolutions per minute
RPM := 60.0 / Float (Elapsed);

Then I have to compute the best moment to energize the coil (ignition) and how long it should be energized (power phase).

Intuitively, the coil is most efficient 90 degrees after top
dead center (ATDC) which means the power phase should be fairly
distributed around that point.For the moment, we arbitrarily decide that the power phase should be 50% of the TDC to BDC time.

-- How much time will the engine take to go from Top Dead Center 
-- to Bottom Dead Center (half of a turn) based on how much time
-- it took to make the last complete rotation.
TDC_To_BDC := Elapsed / 2.0;

-- We start energizing at 25% of the TDC to BDC time
Ignition := TDC_To_BDC * 0.25;

-- We energize the coil during 50% of the TDC to BDC time
Power_Phase := TDC_To_BDC * 0.5;

-- Convert to start and stop time
Start := Now + Milliseconds (Natural (1000.0 * Ignition));
Stop := Start + Milliseconds (Natural (1000.0 * Power_Phase));

To deliver the power command, we will use timing events (the implementation is inspired by the Gem #4). Of course, a more advanced version should use the hardware timers available in the STM32F4 to reduce CPU usage. However, the engine will not exceed 3000 RPM, that’s 50 events per second and therefore not a big deal for the 168MHz micro-controller.

You can find the sources on GitHub: solenoid-engine-controller.