After the driving problems with sound cards, the project has been reboot. The solution was quite obvious : use a sound card which can be used as precise DAC, integrate it within the laser projector, and stream data to it.
A while ago, I started to play with Pure Data, a visual programming software intended to manipulate audio. It has powerful yet easy to use tools, and can process real time audio with ease. It also provides tools for reading file, managing serial connection, and there are lot of external libraries for more specific things. Like data and audio streaming.
So after having worked on some audio project, I decided to give it a try !
The user interface has been broken into several modules, each one being a dedicated basic function.
The first thing needed is to know, given distance and max travel angle of the galvos, what is the max size that can be reach by the projector. The first module therefore computes the ratio there is between a given dimension and the resulting angle the mirror should move to project the laser to this point. At first this module was doing elementary trigonometric calculus, using tangent to compute the right position, and exporting each angle in tables. Viewing the table the line was quite straight, so I wonder if tangent could be replaced by a coefficient that would enable fastest realtime computation. A spreadsheet with graphics shows that for angles bellow 10°, a line can be used to approximate tangent, with an error that stays under 0.4%. So no more trigonometry, an angle per mm ratio is sufficient ! This module is given the max travel angle, distance from projector to wall, and then output angle per distance ratio for both axis, as well as max distance, max angle, and other parameters used by other modules. It is also used to set DPI, even if this is not directly linked to the projector, and more to pictures.
The second important module is the send module. It connects to the laser using TCP protocol to send control data, like turning DSP (digital signal processing) or laser diode, on or off. And it also sends the position data (managed as audio) using UDP protocol.
On laser side, Pure Data is used as well, it runs on a headless Rapsberry Pi Zero that lauches the program as soon as it boots. Pure Data can turn the laser on or off using a library which interface WiringPi digital pin.
Then the files... GEM is a librarie used to process real time image. It can be used to generate particles, manipulate 3D objects, and for the laser it's only used to open an image and read its pixel values. It has something great : pixel values that are read from the picture are resampled, so any file can be output with any resolution or size, without tiling or pixelised effect. That's great because it would be something demanding time and coding otherwise.
The image opened with GEM is parsed according to desired DPI (default DPI is computed on file opening), desired projection size, a scanning angle ranging from -90 to 90°, and a parameter which enables to skip lines during parsing. It can also apply a threshold on the picture to set any pixel to black or white, given its value. For each output pixel, both X and Y coordinate are output, and the corresponding pixel value is output too.
There is another module which job is to generate audio stream to project the picture. The idea while spliting image parsing and data computing is that one image can be interpreted several way. One is to simply project shades like the original picture, but it could also use sinusoid lines which amplitude varies after shades of the original file. Data computing could also be made on the projector.
When this module receives data from the image, for each X,Y couple it computes the vector length from the current position to the new one. It then attributes it a travel time, which is computed using length, pixel value, and a parameter that gives a correct exposure value for black. Each value is then store to a table.
When the image is to be sent, the table are read one value at a time, and a simple ramp is simply generated for each X,Y position, using the travel time associated with it.