Back in 2003, out of boredom, I decided to build a rudimentary laser projector using a laser pointer, small mirrors, cardboard, a dc motor, and a PIC16 microcontroller. The results weren't precisely optically appealing, but that was all I could achieve with what I had at hand.
Fast forward 22 years, I gave it another try at building a laser projector, but this time, using modern technologies. Now older and (allegedly) wiser, and having accumulated a lot of electronic components over the years, plus having a 3D printer, and easy access to cheap Chinese electronic modules, and PCB manufacturing services, I would have thought the task would be much easier this time. However, I had to go through several iterations to get to the final prototype, and yet, it is far from perfect. Anyway, the important lesson here is, to have learnt why each of these attempts didn't work. As Thomas Edison once said: "I didn't fail one thousand times, I found one thousand ways it wouldn't work". So, lets cover the failed attempts.
First attemptMy first idea was to have a single mirror instead several spinning mirrors. The disadvantage of the spinning mirrors is that the number of horizontal lines is limited to the number of mirrors, or alternatively, it needs a second set of spinning mirrors, rotating around a different axis, and the synchronization between these two axes could be somewhat challenging. So, I built a prototype consisting of a square mirror suspended against a 3D printed frame, held by four springs on each corner, and four magnets on each side, each magnet had an electromagnet behind, the idea was to control the movement of the mirror by electromagnetic means, the two horizontal electromagnets would deflect the incoming laser beam in the horizontal axis, and the two vertical magnets would do the same in the vertical axis.
The problem with this system is that the inertia of the moving parts is so large, that it doesn't allow for controlled precision movements, and on top of that, the resonance due to the springs introduces instability. This prototype could only display circles or random garbled ellipses.
Second attemptThen I though about having two mirrors, one mirror deflecting the laser beam on the horizontal axis, and another on the vertical, like a pair of galvos. This time, I built the frame holding the mirror as light as possible to reduce inertia, and I got rid of the springs, the back and forth movement was going the be driven purely by magnetic force.
The problem with this DIY setup is that is doesn't produce sufficient deflection for the laser beam at the intended speed.
Third attemptNext, I decided that I needed a more sophisticated motion mechanism, my DIY builds felt too clumsy, then I thought about using a stepper motor, but I was going to apply a back and forth movement, instead of making it rotate. That is possible with a stepper if I alternate the activation two consecutive steps, avoiding the activation of the other steps, so that the motor appears to shake.
The problem again seems to be the inertia, the built is too heavy to move back and forth quickly, resulting in a poor deflection of the laser beam.
Fourth attemptAt this point it became clear that there are two options: declare defeat and get an expensive galvo, or go for a rotating mirror. Getting a pair of galvos would completely defeat the purpose of making something DIY, affordable, and innovative. So, in order to use the inertia to my advantage, instead of being a limitation, I had to resort to rotating objects. But this time, the idea was to shine the laser beam through a crystal cube. By rotating the cube on one axis, the outgoing beam is always parallel to the incoming beam, however there is a displacement that depends on the angle of incidence between the beam and the crystal surface. Then I would use two rotating crystal cubes, one for each axis, producing a beam scanning a square surface, then I could use a projector lens, to amplify the aforementioned square surface.
The rotating crystal cube concept is an interesting one, unlike mirrors, which create a diverging beam reflection, a crystal cube produces a projection that doesn't diverge with increasing distance.
The problem with this build is that the horizontal deflection cube must spin so fast, that a powerful motor must be used, making a lot of noise, consuming a lot of power, and producing a lot of vibrations. The fastest rotation I could achieve was 3000rpm, this would have produced an image of less that 10 horizontal lines, at a refresh rate of 30Hz.
Fifth attemptAt this point, it is fair to say that for the horizontal deflection, using a cube is cumbersome, it couldn't be rotated fast enough, mainly because of its weight. Then I thought replacing the horizontal deflection mechanism with a simple rotating mirror (back to square one) but keeping the vertical deflection cube, given that there is not such a tight constraint on the vertical deflection regarding the rotation speed. This will produce an image that diverges on the horizontal axis (becomes larger with increasing distance), but keeps its size on the vertical axis.
Then I looked at fast spinning motors. I found out that core-less dc motors can spin very fast, up to 60000rpm. Then I built a very light setup of four spinning mirrors, driven by two coreless dc motors.
The problem now is that the mirrors are very difficult to align, a tiny misalignment is very visible at 15cm. At 1 meter away, the four laser beams produced by each mirror are clearly visible. In theory, such misalignment could be corrected in software, but it would be a headache, and each new build must be individually corrected.
Sixth attemptAfter watching YouTube videos of other people building laser projectors, I decided that the best way to produce a fast horizontal deflection with reasonable accuracy, was to use a polygon mirror. Polygon mirrors are typically used inside laser printers, and laser scanners. I already had a couple hanging around, extracted from defunct laser printers. Although, it feels like cheating using a non-DIY system for the horizontal deflection, it isn't a big deal, a polygon mirror can be bought on Aliexpress for less that $20. Not ultra cheap, but not as expensive as a galvo.
Driving a polygon mirror is fairly easy, it needs a power supply, powerful enough to spin the mirror at the desired speed, it also needs a start signal, and a clock signal. The driver of the polygon mirror synchronizes the mirror rotation so that a full rotation takes the clock period multiplied by the number of faces of the polygon. For example, if the polygon has 6 faces (a hexagon) then a full rotation takes 6 times the clock period. This is important to keep in mind, because it allows us to synchronize the laser activation without using an angle position detector.
Then I proceeded to build a frame with my 3D printer, to hold the polygon mirror and the rotating cube for the laser beam vertical deflection. As said before, the vertical deflection mechanism doesn't need to rotate at fast speeds, for example, each side of the cube is a frame, to aim at a refresh rate of 30 frames per second, the cube must rotate at 450rpm, perfectly achievable with a low power stepper motor, or so I thought. I first used a 1503 stepper motor, but this proved too weak, then I used a larger bipolar motor.
With this approach I was finally able to produce an image with the laser, however the motor couldn't reach 30Hz frame rate, 25Hz was the top speed, and the image was notably shaky, lowering the frame rate to 12Hz produced a more stable image, but introduced a noticeable flickering. And also the motor required a long ramp up to reach the desired speed, and sometimes it went out of sync, not to mention it overheated after a few minutes of continuous operation. This is clear evidence that this motor wasn't powerful enough. Then, I decided to bring in the heavy artillery: a NEMA motor.
This design used a NEMA motor to spin the crystal cube, with the help of a coupler. The cube was held in place by a 3D printed cage, and it was supported on the rotation axis by two ball-bearings. There is a slotted optical switch at the top to measure the rotation speed. The shakiness improved, but it was still unacceptable at 30Hz. I tried several software tricks to compensate this inconvenience, but then I gave up, and decided to build a sturdier frame, I got rid of the coupler, the motor was brought closer to the cube, and the bearings were replaced with ones having a larger internal radius.
This final version had an acceptable shakiness. The cube rotates at 450 rpm, to provide a frame rate of 30Hz. The polygon mirror spins at 15000 rpm, to provide 50 lines per frame, although some lines are unusable because they are too close to the cube's edges. Realistically speaking, 42 to 45 lines are usable. As said before, with this arrangement, the projection on the horizontal axis stretches out with increasing distance, but that is not the case for the vertical axis, the net effect is that a text that is completely legible at short distance, is not at longer distance.
The main idea is to switch the laser on and off according to the desired pattern. The polygon mirror creates a laser beam that scans the horizontal axis, and the rotating cube takes this horizontally deflected beam, and adds a deflection on the vertical axis, creating a 2D projection of the desired pattern. Both mechanical deflectors operate at a fixed rotational speed, so that the laser must be turned on at a specific time to display a pixel.
The polygon mirror has an interface consisting of 5 wires, power, ground, clock, start, and lock detect. I used a 19V laptop power supply in this project, the polygon mirror can accept between 12V to 28V, consult with the manufacturer of the specific polygon mirror you got. The clock signal is a 50% duty cycle signal that the polygon mirror controller uses to generate its internal clock. I used a polygon mirror with six sides, so the polygon mirror controller tries to spin the mirror so that the hexagon rotates 60 degrees (360/6) in a single clock period. If your polygon mirror has more than six sides, lets say N, then a whole revolution takes: N x (clock period). The start signal must be pulled low after providing a clock source. This enables the polygon mirror rotation. Lock detect is an output signal, telling you that the polygon mirror has reached the desired rotational speed based on the provided clock source.
The NEMA stepper motor moving the crystal cube is driven by a stepper motor driver, I used the TMC2209, but you could use the ubiquitous A4988, or any other of your liking. The only constraint is to rotate the cube fast enough to produce 30Hz frame rate (each side of the cube is a whole frame), doing so eliminates flickering. Flickering is barely noticeable at 25Hz, and more so as you reduce the frame rate. To reach a frame rate of 30Hz, the cube must spin at 450rpm. To reach 50 horizontal lines per frame, the polygon mirror must reach the speed of 15000rpm (30Hz x 50 lines x 1/6 x 60 = 15000 rpm). Adjust the clock drivers to both the polygon mirror and the stepper motor to reach these speeds. These clock sources must be stable.
See the picture below to understand how the cube deflects an incoming laser beam without introducing divergence. The important point here is that any beam exiting the cube is always parallel to the incident beam, this is guaranteed by the cube's geometry, as long as the cube has parallel sides.
Keep in mind that the cube surface will reflect something around 2% of the laser beam back, keep the cube clean to minimize the loses due to reflected light. The cubes I bought on Aliexpress hadn't the same length per side, I found with a caliper, that some cubes had a mismatch of up to 1mm, so choose the two axes of the cube that are closer in length for the laser operation, and use the third one as the rotation axis.
Implementation detailsI used a GigaDevice GD32F303 microcontroller. The laser is driven by the SPI unit, this allows me to have an accurate time base for the switching on and off. The MOSI wire is connected to the input of a circuitry that acts as constant current supply, based on the MCP6022, which is a good choice because it is fast enough to display a single pixel, but not so fast as to introduce oscillations. See the picture below. D1 acts as a voltage limiter to the opamp, hence the current flowing through the laser is limited as well, which in this case is 0.62V/25Ω=24.8mA, this is because my laser is rated at 25mA max. If you use a more powerful laser diode, then R4, R5 and Q2 must be adapted accordingly to dissipate sufficient power.
I used the general purpose timers inside the GD32F303 to generate the clocks for the polygon mirror and the stepper driver. The device operates at its max frequency, which is 120MHz. I used the DMA unit to feed the SPI with pixel data while running, because in this way possible data starvation situations can be avoided. I used another channel of the same timer driving the polygon mirror clock, to implement a counter, that counts a specific amount of horizontal lines before start displaying pixel data, this is because, as said before, some horizontal lines are unusable, due to the laser hitting the cube's edges. For the NEMA stepper motor driver it is necessary to ramp it up in small steps, from 0 rpm to 450rpm, 10 to 15 seconds ramp up time should be sufficient. Always synchronize the start of the laser output with the horizontal clock. I used a timer to count up to a specific time after a horizontal clock positive edge, and then the laser output started.
As for the CAD files, I created a parametric design script in python. You can just copy and paste the script content on the Freecad command line console. Make sure to update the variable cwd in the script before running it. Once you get the STEP files, configure your slicer to 3 wall loops for those parts requiring brass inserts.
Advice for the PCB: use "Hand solder" footprints if you are going to solder SMD components by hand. I normally use 1206 size for SMD resistors, capacitors, diodes, etc.
To generate a text pattern, I used an utility called pbmtextps.
pbmtextps -font=Times-Roman -fontsize=22 -topmargin=0 -bottommargin=0 -leftmargin=0 -rightmargin=50 "Your text here" > text.pbm
Executing the line above produces an image with 42 horizontal lines, in pbm format. Then this image needs to be converted to actual C code you can embed in your microcontroller application. For that purpose I created a small python script called create_pattern.py. This script automatically takes text.pbm and creates a header file called lorem_ipsum.h which can be included in your project. It is important that the number of horizontal lines does not exceed the max capacity, which in this case is 50 minus the unused lines. This build could theoretically reach 100 horizontal lines, this only requires the polygon mirror to reach 30000rpm, which is completely feasible for these kind of devices, but I haven't tested that yet because I don't see any advantage in doing that. Even more, by using interlacing it could be possible to double that, and reach 200 horizontal lines. The number of pixels per horizontal line in this project is 255, but could easily reach 511. Your text image can be as long as you desire, however be mindful not to exceed the microcontroller flash capacity.
This laser projector does not feature grayscale, but a simple modification could make it capable of displaying grayscales, for example, by using the SPI in QUAD mode, and using a DAC to convert the output of the SPI to an analog voltage level to feed into the constant current source with modulation.
Comments