One point of PWM is that the individual pulses are so short that the thing being driven only sees the average value. This certainly applies in your case too. The individual PWM pulses are irrelevant, only the duty cycle (fraction of on time to total pulse period) matters.
This concept is used a great deal in electronics, so just about every microcontroller out there comes with some hardware that can generate PWM. You don't say how fast your control loop will be, so I'll pic 1 kHz, meaning a control period of 1 ms. That's a "long" time for a modern micro.
Let's say you run the PWM at 25 kHz. That gives you 25 pulses per control iteration, so you should be able to see that individual pulses are invisible. The system will be reacting to the average duty cycle over 10s of pulses at least. Let's say you want at least 10 bit drive level resolution. That means you need a bit over 25 MHz clock into the PWM generator. That's readily available in many micros. There are some dsPICs, for example, that have a PLL built in to effectively clock a special PWM generator at nearly 1 GHz. 12 bit or more PWM resolution is available with a little digging.
The circuit is very simple:

L1 is the electromagnet, which looks to the circuit like a big fat inductor. If the power voltage and the maximum magnet current is low enough, then you can use a FET that can be driven directly from a digital output. Otherwise, use a FET driver (not shown) between the digital output and the FET gate. This will require a separate 12 V or so supply.
The diode is important and non-optional. For the best efficiency and the smoothest current, and fast reverse recovery, it should be a Schottky. It not only keeps the current circulating thru the magnet during the PWM off phase, but it also gives the inductive kickback current a place to go and keeps Q1 from getting fried when getting switched off.
Another point to consider is the non-linear response from PWM duty cycle to steel ball position. Duty cycle to magnet current will be reasonably linear, but magnet current to position will not be. This makes it impossible to tune the control loop to the right response over a range of positions since the same variation in PWM duty cycle at one end of the range produces a much smaller response than at the other end.
A good solution I've used for similar problems is to use a lookup table to roughly linearize the "plant" as seen by the control loop. Measure a bunch of points so that you can relate open loop PWM duty cycle to ball position. The control loop then adjusts the desired ball position, which gets looked up in the table to find the PWM duty cycle that will be written to the hardware that iteration. Piecewise linearly interpolate the table between points. This is a trivial operation compared to the floating point control calculations, which should still be possible in well under 1 ms.