• In Which I Declare Victory, and Have Parting Thoughts

    Alan Green10/05/2019 at 05:46 3 comments

    Here are pictures of my old and new clock. The new one has larger, greener hands.

    Two pictures, show both old and new clocks
    Before and After

    A close up of the clock face:

    Laser path tracing out a clock on wall. You can see the screw that held the old clock up.
    Close up of new clock face

    I’m really pleased with the curvy style of the minute and hour hands. The data passed to the DACs traces a more polygonal shape, but the specified movements are so quick that inertia and the analog power circuitry conspire to bend the line segments smoothly into each other. 

    The way the hands are each not quite joined on one side of the base is also unintentional. It's because the mirrors haven’t quite steered back to the bottom of the hand before the laser is turned off. But it looks artistic and I’ll keep it for now.

    The clock image is difficult to capture on camera - it’s drawn at about 60Hz, which means cell phone cameras mostly just catch one or two of the three hands. For still pictures, I used my fancy Olympus OM-D EM-10II on a tripod and with a long exposure.  I've post processed the images to get the color closer to what the eye sees, but it's still not quite there. The single wavelength doesn't play nicely with the camera sensors. Sadly, no camera I own does a job of capturing video of the clock, so I don't have one to show.

    Overall the project came out according to The Plan:

    Laser clock's place in the kitchen
    My kitchen, now with Laser Clock and tidied fridge magnets

    The transparent casing shows more mess than I'd like, but it makes my smile to see all the individual components in there, working hard:

    Close up of Laser Clock projector unit, on ceiling
    Projector, on the ceiling

    Since Last Post

    It's been more than a month since my last post. In addition to the physical cutting of the parts, assembly, realization that I’d glued something together in mirror image, re-cutting those parts, reassembly, realization that I’d glued something else together in mirror image, re-cutting those part, reassembly, and fixing everything into the ceiling, I wrote a lot of Python on the Raspberry Pi.

    The Pi has two daemon processes. The first, clock_gen produces XY coordinates that the frame driver will output to the DAC. It packages these into a byte array, in a format suitable for the frame driver and writes the byte array to a file.

    The second daemon, clock_push, takes that file, sends its contents to the frame driver, and tells the frame driver to display it.

    The code is just good enough to work reliably.

    What I Could Do Better

    When I look at my clock, I see plenty of potential projects:

    • Turn the frame driver into a Raspberry Pi hat: get a circuit board made.
    • Use the laser beam analog control to dim the laser at night.
    • Presence detection: turn the clock off when no one is around to look at it. I’m thinking of setting up several WiFi connected sensors communicating with the RPi via MQTT.
    • Cooling: It would be useful to have a fan blowing air into the case to carry away heat from the CPU, galvos and laser. Because of higher-than-ideal temperatures inside the case, I’ve decided to back off both the frame generation rate and image size.
    • Perspective: because of the geometry of the projection, the clock’s hands get longer when they point down compared to when they point up. There are several ways to fix this. One would be to carefully work thought the math of the projection, also taking into account refraction through the perspex case. Another would be to measure the relationship between DAC outputs and laser dot position over the projection area, and adjust outputs accordingly.
    • Rewrite in C or Go: Python has been brilliant for getting something up and going, but it’s pretty clear that a rewrite in a more efficient language will result in cooler Pi and better, smoother animations. It would also avoid issues with the RPi's old version of Python SPI dev, which is limited to 4kB transfers.
    • Electrical shielding: I live near an electrified rail line. Sometimes when the trains go past, the clock image wobbles. When it’s really bad, the communications between the RPi and frame driver get messed up, and the RPi resets the frame driver.
    • Understanding the behavior of the...
    Read more »

  • 5 Lines, Lessons From

    Alan Green08/24/2019 at 20:39 0 comments

    With the PIC32 firmware largely done, I've started working on the Python code running on the Raspberry Pi.

    Here's my attempt at drawing five horizontal lines:

    Five green, horizontal lines

    This was generated in much the same way as the diamond pattern I had working last month, but with some refactoring of the code, I was able to show what happens when the laser is only turned on for part of the drawing. 

    5 horizontal lines in a pyramid

    For these lines, the laser was on for 120us for the top line, then 240, 360, 480 and finally 600us for the bottom line. The laser is tracing those lines at approximately 0.5mm per us. It's possible to see that the mirror starts slow, then accelerates, before decelerating toward the end.  

    Note that I've used slightly different movement speed parameters for the second picture compared to the first picture - you can see this most clearly in the starting position for the first of the five lines. In this second picture, the starting line is just about in a the right place, where as in first, it is shifted to the right somewhat.

    I wanted to explore the this a little better, so I left the laser light on while the mirrors were moving between the start and end of lines. I got this:

    I also X-Y plotted the op-amp X and Y outputs:

    This is interesting.  The galvo struggles to keep up with some of the movements in the signal. There is definitely something weird happening at the top left, with the X galvo most definitely not tracking the same signal the op-amp is outputting. There might be some weirdness in the differential signal and it definitely bears further investigation.

    Surprising to me is that the op-amp signal is not moving as linearly as I thought it would be. I wonder how much of the galvo's curved path is due to this non linearity in signal. 

    And Also...

    I've been doing more on the mounting and case. Here's the latest prototype of the mounting board. I have a new design coming that is slightly slimmer, and has provision for some cable management, but the overall layout will be the same.

  • 5x Faster Output

    Alan Green08/24/2019 at 07:55 0 comments

    Microchip's PIC32 toolchain strongly encourages the use of their framework, Harmony. Harmony does a lot of things well, but it isn't appropriate for every situation, and the Laser Galvo clock had one of those situations.

    The PIC32 periodically drives a DAC via SPI. In the following oscilloscope screenshot, the yellow pulse shows the time taken to handle an interrupt. The blue lines show the SPI clock, and indicate when the transfers are taking place.

    In total, it was taking about 32us, even though much SPI output was taking about 3us in total.

    I changed the code to output via the lower level PLIB, and got this:

    It's now taking less than 6us in total. 

    Because it is taking less time to output DAC changes, that means we can output them more frequently and perhaps draw smoother figures.

  • 3D Models and Physical Layout

    Alan Green07/28/2019 at 21:39 0 comments

    I'm going to need some way to mount all these components to my kitchen ceiling. The current plan is to have a base board to which to attach the components. I'll flip the base board upside-down, and mount the back side to the ceiling. I'll also need a lid for it all.

    Laser and Galvo

    The only really critical alignment required is between the laser and the galvo. I modelled them both in Fusion 360 and then laser cut a tiny prototype base plate to verify that I had the relative locations correct.

    Laser galvo and module on a laser cut table.

    Both modules screw into the base plate, and there are two scraps of PCB under the laser module to raise it about 3mm.

    I then modeled and printed a 3D table with a small back angle so that the laser galvo's center will be aimed at the center of the wall, rather than up near the ceiling. Here is the model:

    And it came out just like that, but not as pretty:

    Despite the rough look, it feels fine in the hand and works exactly as required:

    I'm not happy with every detail - it's taller and bulkier than it needs to be, the laser module part has a cut out on one side but not the other, and there's a weird join between the table for the module and the table for the galvo. All that said, it is the first 3D print I designed myself, and it will work just fine. It's a keeper. 

    A funny story for those of you who have read this far: I noticed that the laser was not hitting in the center of the mirrors. For the x-axis (lower) galvo, the light was partly on the blob of glue that holds the mirror. To fix this, I loosened the bolt that holds the galvo into the block and moved the galvo back a little. At this point I realized the galvo can not only move further in and out of the block, it can also rotate. Doh. I had spent a day modeling that table in order to move the Y axis by 6.8 degrees. I could have just rotated the galvo by 3.4 degrees. 

    The table is a better solution, but I don't know that it was worth the time.

    Prototype Base Plate

    I had a first attempt at a base plate. I modeled at least the outlines of each of the electronic components, then threw the whole lot onto a rectangular base. Here's what it looked like in Fusion 360:

    The Raspberry Pi is a model I found in Autodesk's library. It looks beautiful, with each cap, resistor, header pin and sheet metal fold individually modeled. However, it does push Fusion 360 quite hard. I think I should maybe just use the PCB in future layouts. The BlueBoard#01 in the middle has a decal in the model, but that decal just fails to appear in the render. No idea why.

    And here it is on my bench:

    Mostly successful. The general layout is OK. I'll need some kind of cable management in the final version. The biggest issue was with mounting the RPi. It has M2.5 mounting holes, and I had eyeballed them as M3. According to the forums, it is possible to safely drill the holes out to M3, but I've ordered the M2.5 mounting hardware anyway.

    It's early days. I will also need to mount a 4-way mains power board on this base board and make a transparent, openable lid. Oh yeah - also figure out how to attach it to the ceiling in some removable way. 

  • A New Laser and Laser Control

    Alan Green07/16/2019 at 08:33 0 comments

    Two exciting developments today. 

    A New Laser

    In comments on a previous log, [Stefan Kruger] reminded me that common, cheap, poorly designed 532nm laser pointers also emit a surprising amount of infrared light, which is a potential danger. He  referenced this great paper from NIST, which features a laser pointer very similar to the one that donated my previous green laser.

    After a bit of research, I ended up buying a 50mW 505nm laser, which does not have the same problem. 

    Photo from the eBay listing

    The driver board I received looks a little different, and it has both "TTL" and analog inputs. 

    Laser Control

    I hooked up the "TTL" input to my PIC32 and it Pretty Much Just Worked. Here's a cross-in-a-square test pattern, which demonstrates the laser can be turned off between drawing the square and drawing the cross.

    Same pattern as before, but without the excess lines
    Look ma! No unwanted lines!

    One change I made: I moved the laser control to a 5V tolerant pin since the input is marked "TTL" and it wouldn't be unreasonable to find 5V their at some point. However, the input pin seems to float at around 1.8V, and connecting the pin to ground turns the laser off. Therefore, I set the PIC's output to use an open drain.

    Next

    I'm working on plans to mount all this hardware on the ceiling of my kitchen. I'm using Fusion 360 to model all the components so I can figure out how to place them and where all the holes need to go. It's taking a while, but I did make this blocky but dimensionally accurate laser galvo model.

    Another thing that needs doing is to rewrite the PIC32's DAC output loop. It has two problems. First, it's too slow to output 20,000 points per second to the galvos. Second, there's a bug in there because it seems to stop working from time to time. A rewrite will fix both.

  • Python Generated Shapes, Traced By Laser

    Alan Green07/12/2019 at 08:21 0 comments

    More progress: I now have a Python program, running on the RPi to send data to the PIC32 Frame Driver. It was about 500 lines of new C code, plus 100-odd lines of Python, but I can now dynamically update frames. 

    It projected this little thing onto my notebook.

    This is what success looks like

    As predicted, the communications protocol was tricky. I wrote a 4 page document to describe it. The main complication is that the PIC32+MP Harmony approach to the SPI chip select (aka CS, aka Slave Select aka SS) line doesn't conveniently allow it to be used to define the end of packet, which makes handling variable-sized packets difficult.

     As a result, the protocol I ended up with has fixed size command packets, and one of the commands says 'hey! there's data coming and it has length N'. The PIC32 then goes into a special mode where it waits for exactly that much data.

    Here's the state diagram from the PIC32's point of view:

    Abridged communications protocol state diagram
    Not shown: error handling transitions

    Also, inspired by Ben Eater's recent video about CRCs, I use 16 bit CRCs on all requests and responses. I used pycrc to both calculate CRCs in Python and to generate the C code for the PIC32. The PIC32 actually has built in facilities for CRC calculation, but I'm not clear on how to use it in conjunction with the MP Harmony SPI drivers. 

    Speaking of MP Harmony, I now have a whole rant about MP Harmony which I might polish up and publish.

    The Frame Driver is now Almost Finished Enough that I could start building the clock daemon that will run on the Raspberry Pi. However, I think my next task will be to integrate the new, 505nm 50mW laser that is due to be delivered mid-next week.

  • Mini update: power hungry lasers

    Alan Green07/06/2019 at 01:37 2 comments

    So far, my experiments have used the cat's battery powered laser pointer. Today, I disassembled a few laser pointers and powered laser modules directly from my bench power supply. 

    The green laser module was the brightest and looked the best. Also, I know it will be visible in the day time. According to the sticker that was on it, it is a "class III"  and "<5mW", which I believe makes it a class 3R laser, which I'm happy with from a safety point of view.

    However, it also draws between 250mA and 350mA, which is much more load than I want to put on the RPi's supply, especially since that load will be switched rapidly and repeatedly. 

    So, instead of using the output of the 3.3V LDO to supply the laser, I'll use a 12V wall adapter, along with an eBay buck converter module.

  • Test Pattern

    Alan Green07/01/2019 at 11:49 3 comments

    Progress! Here's a pattern generated by the PIC32, sent to the DAC, turned into twin differential signals by the op-amp and sent to the galvo:

    Pattern projected onto the window blind

    It is a cross inside a square. However, I have not yet hooked up the FET to control the laser, so the laser doesn't turn off while moving between the ends of the cross and the bottom left of the square.

    Apart from that, there are several noteworthy artifacts in this image:

    1. At three of the square corners, there is a spike where the mirror has - despite the closed loop control - overshot its destination and then walked back. It looks as though the Y galvo might have more problems than the X galvo.
    2. The end points of motion are very bright because the laser dwells on them for some time.  
    3. The path traced to and from the cross is quite curved.  I'm not entirely sure why.

    I plan to address all of these problems later in the build, after I have a basic clock showing.

    What's Happening With the Electrons

    Here's a scope screenshot showing SPI data being sent to the DAC. The DAC output we're following is channel 3, the magenta line.  The SPI command 0xBFFF causes to the output to transition from 0x000 to 0xFFF. The transition from min to max value takes about 6uS

    Channel 2 (light blue) is the signal inverted and amplified, then channel 1 (yellow) inverts the signal again.

    Over a longer period, we can see the differential output on channels 1 and 2 following the DAC output on channel 3:

    Notice that the op-amp output tends to drift toward 0V over the course of a few milliseconds. That's interesting.

    Conclusions

    One thing I learned: the output pattern is reasonably stable despite not having a separate 3.3V supply for the analog circuitry. 

    Things to do next:

    1. Start sending patterns from the RPi to the PIC32.
    2. Solder up the laser fet to a laser so the dot can be turned on and off.

    Questions to answer some day:

    1. Measure the +/- 8 V and +/-15V rails while the galvos are operating. Is it noisy? Could the op-amps work directly with the 15V?
    2. How much of the overshoot is due to the settling of the op-amp output?
    3. Is the Y-galvo's overshoot problem specific to (a) the galvo, (b) the driver/amplifier board or (c) the output from the Frame Driver?

  • Another look at the Galvos - Closed Loops!

    Alan Green06/26/2019 at 09:28 0 comments

    It turns out that the galvos I bought are closed loop devices. When a signal is applied to them, the move to a new position, and they also give feedback about their position to their controller. This feedback "closes the loop".

    Taking the rear cover off one of the galvos shows the position sensor. It consists of an LED, two photodiodes, and a plate attached to the galvanometer shaft. As the shaft rotates, it allows more or less light to shine on each photodiode, which provides the feedback.

    I had been wondering why the galvo needed a six-wire connector. Now it seems obvious that two of the wires are for the galvanometer itself, and four of the wires are for the position sensor - V+, V- and two photodiode signals.

    This complexity also explains why each galvo control board has 4 quad op-amps: the board is an analog computer, trying to calculate how to accelerate and deaccelerate in order to bring the mirror smoothly to its new position with no over or undershoot. 

    I learned about the galvo position sensor from zenodilodon's Youtube channel, in particular the video "Inside the Closed Loop Laser Beam Stearing Galvanometer" in which Zeno shows several galvanometers that look like bigger versions of my cheapy.

    Yes, the production is a bit rough. Yes, those dead pixels are on Zeno's camera sensor, not on your screen. Yes, I too find the paint flecks on his hands distracting. Despite all that, it's a pleasure to watch a gifted professional dispensing the kind of helpful information and tips that can only come from experience. I am totally subscribed.

    Another one of Zeno's videos, "Complete Build of a 4 Watt Analog Modulated ILDA Show Laser" was also helpful. I'm building a just-good-enough for home single color, 5mW , digital version of the professional RGB, 4 Watt, four laser analog rig that Zeno puts together here. Plenty of good tips. My build will be simpler and involve less swarf.

  • Frame Driver Construction: MCU

    Alan Green06/25/2019 at 11:14 0 comments

    I spent the past few days soldering up the PIC32 MCU and getting it to work with the Raspberry Pi. 

    It's Going To Work. Hooray! There were a couple of tweaks to the schematic, one dead PIC32, and a couple of moments of utter confusion with Microchip's MPLAB Harmony, but we're now in a good place.

    Goals

    I did this first since the PIC32 is an unknown for me - hence something that might go wrong. If it wasn't going to work, I needed to know early.

    As a proof of concept, I had the PIC32 use a timer to blink an LED in a pattern. It also acted an SPI slave, ready to accept data from the RPi that it would use to change the LED blinking pattern.

    Planning and Construction

    Initial Planning SheetThe picture to the right is a scan of my first planning sheet. While constructing it, I made a few changes, which you can see in the larger image, below.

    One of the nice things about working on a Blueboard#01 is that one can almost always try a new configuration if something doesn't work. It also lends itself to constructing a circuit in stages.

    The picture below is me getting excited about soldering up my first PIC32. Flux is on the footprint, and moving the chip into position.

    My First PIC32, Ready to solder
    Ready to solder

    The end result was fairly neat, with only a few solder blots. Most of the wiring is hidden on the back of the board.

    And the final planning sheet:

    Planning sheet, after further iteration
    Planning sheet, after further iteration

    Software and Testing

    The PIC32 sets up one timer peripheral and one SPI slave peripheral. It has a buffer containing a pattern.

    • When the timer times out, it turns the LED on or off according to the pattern.
    • When it receives data from the SPI peripheral, it updates the pattern.

    I used the MPLAB Harmony framework, the MPLAB IDE and the the MPLAB Snap programming tool. Microchip should send me a T-shirt.

    On the RPi side, I used Python and spidev. Spidev appears to be installed by default, which is great. It's pretty straight forward to send a bunch of bytes to an SPI slave.

    Here it is, all together. The laptop has a window open to the RPi, the RPi is wired to the PIC on the Blueboard#01, and the Blueboard#01 is being probed by the oscilloscope. 

    Everything working nicely

    There are a lot of wires. I did this because the PIC32 is highly configurable, and I wanted to make sure I had the connections right, so I used 0.1" header pins pressed into the Blueboard#01, with dupont wires to make temporary connections. I'll solder in permanent connections, behind the board now that I know it works.

    The oscilloscope is probing via a row of 0.1" header pins pushed into the Blueboard#01. With SPI running a 1 MHz clock, there were no problems at all. Channel 3 (magenta) is the clock:

    Oscilloscope trace at 1MHz
    No problems at 1MHz

    It also works at 20MHz. This is suprising to me, given all the dupont wires going everywhere. At 20MHz, the waveforms are less well defined:

    Lessons Learned

    • Power is hard, as always: I had intended to power the MCU from the RPi's 3.3V supply. Not a great idea as it turns out. The RPi's 3.3V supply seems pretty marginal, and the PIC's 30mA seemed to bring it close to failure. I watched the voltage dip 0.1V as the MCU turned an LED on and off. Instead, I chose to power it from the 3V3Ref linear regulator. I may need a second linear regulator later if it turns out the PIC makes this one too noisy.
    • Polarity is easy ... to get wrong. I blew up one PIC by connecting my bench power supply the wrong way around to GND and 3V3. They say that experience is what you get when you didn't get get what you wanted, and this was definitely an experience. The AVR chips I'm used to would have put up with that kind of abuse, but the PIC32 appears to be a different, more fragile class of device.
    • MPLAB Harmony is complex. The PIC's default programming environment uses the MPLAB Harmony framework. It took me several days to wrap my head around it. I made peace with it for now - Most Things Just Work Once You Know How.
    • Protocols require attention. The...
    Read more »