This rubidium frequency reference came up as a project after trying, for some time, to get a pair of Symmetricom TimeSource 3500s up and running, but eventually finding that the external IF converter really was required for the unit to receive the GPS signal from an antenna. Since it would have been more costly and more work to do and the interface with the TimeSource 3500 was a little awkward without the correct software (which seems to be unavailable), I ended up salvaging the units and building my own rubidium 10MHz reference. The important part to pull was the rubidium oscillator module, a Stanford Research Systems unit marked with a sticker TSD11, but which seems to match the PRS10 in every way.
The PRS10 module is a nicely compact and easy to deal with device – you give it 24V and it does its thing, but if you give it a 1 PPS signal, a standard output for GPS timing receivers, it will automatically discipline the rubidium oscillator to GPS time, making a complete GPSDO with only a GPS receiver and a PRS10. The PRS10 also uses that rubidium source to discipline an internal OCXO, giving a very clean 10MHz sine wave output that has the low phase noise you would expect from a good oscillator as well as the low drift you'd expect from a rubidium reference.
I wanted as stable of a reference as I could put together, so I looked at available GPS timing receivers. The PPS variation is specified on datasheets in several ways and it's difficult to say exactly which performs best (though I have plans to test some in a direct comparison), but because of a low 15ns RMS specification, a fairly cheap price, and a compact size, I decided on using a Trimble Resolution SMT. Between the Resolution SMT and the PRS10, the GPSDO was effectively complete, so I set about designing a board to power things appropriately, the provide a little feedback on the status of the unit, and to incorporate a distribution amplifier to keep from needing an external one.
What I ended up with was a fairly simple board crammed with BNC connectors. Using two quad op amps, I got seven individually buffered 10MHZ sine outputs, then one PPS output coming from the PRS10. I mounted the Resolution SMT directly to the underside of the board to save space and to link it to the PRS10, and I built in an Arduino Pro Micro to handle basic monitoring of the unit and report information back on a USB serial port. In addition to monitoring the PPS outputs for overall system health, it also monitors three temperature sensors to make sure things are operating in the right temperature range. The board also uses a couple of regulators to supply everything appropriately, with fairly liberal usage of ferrites and inductors to help reduce noise on particularly sensitive supply lines, like the power for the GPS. The main 5V for the Arduino is supplied by a switching regulator because the 24V input to the PRS10 would mean a huge power dissipation in a linear regulator, so some extra filtering was required.
Combining everything, I used a fairly inexpensive aluminum box, mounted the PRS10 and a MeanWell LRS-75-24 (a couple amps is required during the initial heating phase of the PRS10) and cut notches for the BNC connectors on the back. A few holes and a small vent hole later, the relatively crude aluminum chassis was ready to accept all the parts. The vent may not be required, and is entirely passive, but since the rubidium module runs fairly warm, I figured I would give a little escape for hot air just because most of the other parts on the board aren't designed for prolonged high temperature use. I hope they are sufficient, the boards generally stay below 60C and the electrolytic capacitors, probably the most sensitive to heat, are 105C rated.
Evaluating performance of the unit has been difficult, if simply because I don't have access to a more accurate reference for a direct comparison (partly because the next step up would be a Cesium beam standard). I have, however, at least been able to demonstrate that it has almost no drift in checking it against another (much 'noisier') GPSDO. Not only do the two converge towards exactly 10MHz mean over time, but I've tested covering the rubidium reference with plastic (bubble wrap bag), and the increased heat, about 5C on the internal sensors, made no difference in the output frequency, both when increasing and when decreasing back to normal temperatures. Since the PRS10 has its own heater for the rubidium lamp, runs fairly warm, and still has an oven for the output oscillator, it effectively has both a wide functional range in terms of temperature and has two ovens on the part most susceptible to drift, so the thin case I put it in hasn't made it vulnerable to changes in ambient temperature.
In tests, I've been able to demonstrate down to 1x10^-11 or so of accuracy when compared against a standard GPSDO with a mediocre GPS module for timing purposes, but the PRS10 datasheet claims performance to be about twice as good as that, at minimum, and coupled with a fairly stable GPS input signal, I think it's probably performing in the low 10^-12 region for both stability and accuracy. Hopefully I'll devise some ways to actually test it, but for now, I am satisfied that it seems to be entirely under the noise floor of my previous reference. Almost all the variation in this was digital adjustment steps of the lower performance GPSDO compared against this reference, but it's clearly disciplined to the right frequency.
Since there aren't many sine wave distribution amplifiers designed for 50 ohm, 10MHz reference use, I took the circuit from this board and broke it off into a separate, standalone board. It is somewhat limited – because of the overhead of the input to the op amp chosen, the maximum signal can be only about 2.5Vpp, which going through a 100 ohm output resistor and into a 50 ohm load can only be about 0.8Vpp (+2dBm). This could be increased if instead of using buffer amp configurations on the output, they were also a gain stage, but that would require more parts and when using quad op amp packages, there is a limit on how much power you want to supply. Cooking a chip outright is unlikely, but since they'll be always on, the extra heat can shorten its lifetime.
I expect that this is about as good of a time reference a home lab can have, given the price and complexity of better references, but it's been a fun project to put together and it gives me an extremely precise base to measure against. If my later investigation into PPS signal accuracy shows a clear leader that is not the Resolution SMT, I may swap that into the design in place of it.
September 13, 2017
A Cheap 10MHz Reference Distribution Amplifier
I got a GPSDO time reference for my home lab a few months ago and while I've been happy with the inexpensive model, I've wanted a few available outputs to go off to various instruments. There are commercial amplifiers available and many video distribution amps can be repurposed for reference frequency distribution, the overall design seemed simple and there was some extra space in my small GPSDO's case, so I decided I'd design one to fit in the case and be as unobtrusive as possible. This page documents the design and gives you all the information you need to make one of your own, including a guide to finding the signals you need to tap off of when installing it. Of course, I cannot be held liable for building it up, modifying your GPSDO, or damaging anything in the process of it, but for people like me, it's a fun, low risk project with a useful result.
The design:
The point of the project was to fit into the case my BG7TBL 2016-05-31 was already in, and since the extruded aluminum case had a matching board groove on the top as well as the bottom, I had a bit of clearance over the heatsink on the primary regulator and some open space on the front panel to drill holes for more BNCs. I could easily fit 4 BNCs, a 5th may be possible, but it would be quite a squeeze without moving the antenna cable. While my unit is configured for square wave output and I haven't come across an instrument that needs a sine reference specifically, I wanted the flexibility to have both options as outputs. My initial attempt at laying out a board was similar to what I ended up with, but included an opamp for the sine wave output and a header with a jumper for selecting the output.
This design worked alright, but it had some disadvantages. Because it was laid out as a simple follower amp without feedback resistors, the input needed to be connected to keep the opamp from drawing tons of current and the signal was small - it would work fine if you added a 2-3x gain, but after an output resistor to limit current, the resulting output signal wasn't very high in amplitude. Fixable problems, but as it turned out, not worth the effort. A decent, low noise opamp was going to cost a few dollars, not an expensive part, but much more than the other parts on the board (except the connectors), and the same functionality could be achieved with a square wave and a filter, so I set out to design one. It turned out that two capacitors and an inductor in standard values did a great job of smoothing the signal out, and while it's a bit lumpy with a high impedance input, it's a great looking sine wave on a 50 ohm load.
I also did away with the selectors for sine and square, since the board was going to be inside a box where things weren't accessible, and I was able to remove some other headers for alternative signal inputs. Because of the way the GPSDO is designed, the OCXO produces a sine wave which is squared up and fed into the CPLD for timing measurement, then out to a driver and the BNC, but the sine wave output variants of the GPSDO do a similar filtering technique for the output, so the input signals were there for either option and the output was going to be a filtered square wave even in the original design.
The second version was the final one, with fewer parts and expense and essentially the same performance. It even includes some mounting holes for structural support if used in a different housing than the BG7TBL GPSDO case. I opted for local regulation to be sure it would not load down the main regulator on the GPSDO board since it ran warm and already had a heatsink, but the finished unit only needs about 40mA in operation.
Building the distribution amplifier:
This project is fully documented, the PCB layout files and schematic can be found here and were made in CircuitMaker, which is a free PCB design tool (not without its faults, but powerful for free software). I've also included the schematic here for reference.
The bill of materials is small and consists of:
The PCB (10cm x 4cm double sided)
4x BNC connectors, I used a Molex 0731385033 but the footprint seems fairly standard - get decent quality ones so they last!
2x 74LVC14 14 pin SOIC hex Schmitt triggers or comparable TTL level inverter
1x AZ1117 series 5V regulator in a SOT-223 package
2x Radial electrolytic filter capacitors with a 5mm lead spacing and less than 20mm height, I used 330uF 50V 105C rated Nichicon caps, must be rated to above input voltage
2x 4.7uF 0805 ceramic capacitors
2x .1uF 0603 ceramic capacitors (for bypassing)
2x 1nF 0603 ceramic capacitors (for bypassing)
4x 75 ohm 0603 resistors
1x 1 Megaohm 0603 resistors
2x 2 pin 2.54mm male headers, I used one straight and one right angle
Those parts will build you a board with four square wave outputs, then for each one you want with a sine wave output instead, add:
1x 1uH 0603 inductor
1x 680pF 0603 capacitor (NP0 as it is for a filter)
1x 470pF 0603 capacitor (NP0 as it is for a filter)
1x 1nF 0603 capacitor for AC coupling the output
Assembly of the board is fairly straight forward for most parts, and the pads are left large for hand soldering (large enough for 0805s to fit on the 0603 pads). The only complicated part is the output filtering: each channel can be configured for square or sine wave output, for a square wave, populate R1, 2, 3, or 4 (whichever corresponds to the channel), then put a solder bridge in place of L1, 2, 3, or 4 (matching the number of the channel again), and bridge C9, 10, 11, or 12 that corresponds to the channel you are configuring. For sine wave output, populate all of those passives on the channel you want - the two capacitors which are part of the filter, the inductor, and the capacitor on the output to AC couple it.
Installation:
This section assumes you are installing the board in a BG7TBL 2016-05-31 model GPSDO, the one it was designed for. Several other dated BG7TBL GPSDOs will be nearly identical, but very early ones using branded GPSDO modules may not physically accommodate the board. The amplifier could realistically work in almost any chassis, but I obviously can't provide installation instructions for all of those. When your board is built up, you need to locate and tap off the input signals. A list of parts needed are as follows:
1x 2 pin 2.54mm male straight header
1x length of shielded single conductor wire
1x short two pin to two pin female header cable
1x female two pin housing and crimp pins
Electronic safe silicone or other glue to give a little strain relief to your mod
The first is easy, solder a 2 pin straight header to the terminals marked DC In next to the DC input jack - this is where your board will be powered from. Then you need to tap off a signal source, and I've highlighted a few good sources for square waves in light blue on this image of the bottom of my board. You'll want to use a single conductor shielded cable to run the signal up to the amplifier, and luckily they can be found very cheaply in small quantities - I got a one meter length from Digikey for just over a dollar. If you have any doubt about which pin the source is, measure it with your scope - it's not a very square looking wave on mine, but it certainly is not a sine wave. Near the signal source, find a grounding point for the shield of your cable, some good choices are marked in purple on the image. Terminate one end of the cable in the two pin female housing, this will connect to your amplifier board, then cut to length and attach to the points you've located for your square wave source and ground shield - I went through the holes on the board to solder on the underside and then used some electronic safe silicone adhesive (does not smell like vinegar when curing) to stick it in place and provide a little mechanical strength to the mod. As you can see, since I did this mod for the first design versions, I had two tap off points - the orange boxes are around potential sine wave sources.
The yellow box is unrelated and just shows where the sine wave and square wave variants of the GPSDO differ, the filtering section for the 10MHz output. After the electrical part of the mod is done, you just need to drill the holes for the BNCs in the front PCB plate. They are tough to measure, but you can get exact BNC spacing from the PCB design files, then just remember that the board will be installed on the PCB ridge in the chassis directly opposite of the one for the main board, so it will be installed upside down. I ended up measuring a bit and eyeballing a bit, and it worked out fine enough. Then you thread in the BNCs through the newly cut holes, screw their nuts down, and connect up the power and signal connectors. Then you should be able to just slide the thing into the case, and when the screws are back in the front plate, you are finished!
Performance
Performance seems perfectly usable and generally decent. There is a little ringing on the square wave output and both outputs should be terminated with 50 ohm impedances (1M impedance will work, but the waveforms look bad), but they are consistent. With a 75 ohm limiting resistor, as listed in the schematic, you get a 2Vpp output on the square wave and just over a 1Vpp output with the sine wave configuration. The board used about 38mA without any outputs connected and just over 39mA with two connected, so power consumption is quite low. The image below is after a couple minutes of running with infinite persistence on. The yellow trace is the built in square wave output, the pink sine wave is the sine configuration output from the distribution amp, and the blue square wave is the square output from the distribution amp.
The whole mod costs around $12 in parts, with close to $10 of that in BNC connectors, the board was another $10 but only because I had to order several to get it made. Given that it effectively takes up no space and gives you four more outputs, this simple and cheap mod seemed to be a great value for me! If you try it as well, I hope you see similar results.
December 14, 2016
Refurbishing a Strobe Tuner
In developing my own precision tuner and being interested in strobe tuners, I found a working-but-needs-refurbishment Peterson Model 400 inexpensively on ebay, so I bought it with the intent to fix it up, calibrate it, and use it. I replaced a few parts, made a couple modifications, and added an internal mic to make it quicker to setup and use.
How a strobe tuner works:
A strobe tuner, at least traditional ones, is an electromechanical tuner that relies on the strobescopic effect (surprise surprise!) for its display. What that means is that a strobe tuner converts an audio input into a blinking light - neon lamps in this one - and shines it on a wheel with patterned markings that a motor is spinning at a constant speed. When the rotation speed of the disk, which has its speed precisely governed by a separate circuit, and the speed of the flashing of the light match up in the right way, it looks like the markings on the disk are moving very slowly, or not at all. This is the same sort of effect you can see watching a video of a driving car's wheels, where the wheel seems to rotate quite slowly, but in this case, the designers have done all the math needed for the speed of the motor and the patterns on the disk to look like they stop moving when the incoming audio frequency is in tune. It sounds complicated, and I suppose it is, but the circuitry involved is comparatively much simpler than other electronic tuners, so when electronics were comparatively primitive, it could be an extremely accurate instrument without too much electronic complexity.
You set the note you want to play, make sure the vernier knob is set to the right reference pitch, and then play your note - when close to the right pitch, you will see some of the markings on the disk get darker. If the markings are moving to the left, your note is flat, if they are moving right, your note is sharp, and if they appear but are not moving at all, you are perfectly in tune. The rings on the disk match up to different sounding octaves, so the higher the pitch being measured, the higher up on the disk the pattern will seem to slow or stop moving, and because the tuner measures all of the incoming audio, you will typically see multiple rings looking active - higher harmonics in the sound will show, usually more faintly, on the other rings of the tuner disk. Because the motor speed has to be precisely controlled to measure against a fixed reference, you have to change the note dial (centermost large dial) when tuning other notes, but because the harmonics show, you can still get good tuning information on the perfect fourth and fifth of whatever note the tuner is set to - the patterns will still be visible and will stop moving when the note is in tune. Interestingly, when playing the major third below the note the selector is set to, you will see one ring telling you that you're playing flat, even if you are playing the correct pitch. This is an artifact of equal temperament and the harmonic series, so if you play your note 12 cents sharp, that ring will stop moving, because you will be fitting in the just intonation of the major third. Conversely, if you set the vernier to 12 cents low, when you play your not a major third below and see the ring stop moving, you'll be playing the note in tune with equal temperament. The reference pitch vernier is marked in cents, but you can use it to play with a non A=440 reference pitch, for example, if you set it to be just over 7 cents high, you will be effectively playing with an A=442 reference pitch.
It helps in understanding the design and troubleshooting or refurbishing to have the schematic available, and it is available online, including here. The schematic even shows which board each part is on (dotted outlines), which is especially useful because there is no silkscreen or part markings on the boards, and it includes some of their design considerations - using low current noise resistors on the audio input line and using high stability, low leakage capacitors on a few key components used in keeping tuning frequency stable. To control motor speed, the tuner uses a high stability oscillator (at least, for the time) that drives a bipolar stepper motor, and each note on the selector has an individual resistor to trim the speed exactly. The audio processing goes through an optional low pass filter (the image clarifier switch) which I like to leave on, and then to the lamp driver board - to get that relatively small signal to drive neon lamps which have a 400V power supply. Later model 400s included an internal mic, but this one and this schematic do not include one, the input connector also does not supply any sort of bias voltage or phantom power.
Refurbishing the tuner:
If you're planning on trying this yourself, if you have some experience working with electronics and mains voltage electrical appliances, it's a fairly straightforward job - but even if you are, please be careful. Not only is there exposed mains wiring inside, there's also a high voltage 400V rail for the neon drivers and there's spinning parts thanks to the motor and disk, so there are a number of bits to be careful of. My unit's capacitors discharged fairly quickly when unplugged, but be sure to check them with a multimeter before working inside, even when powered down and unplugged.
I powered the unit up using the included mic and while it lit and whirred, it was entirely unresponsive. I used another external recorder's line out to run into it and suddenly the tuner sprung to life... but it was something like a fourth off of what the note was actually sounding. I knew it needed some help, so I went to work. Checking out the obviously dead mic I took it apart. I tried to get the element back on the little bar in the middle of the copper cup housing it, but since the mic wasn't dynamic, I'm not sure it ever could have been used with the tuner alone as no bias voltage was being supplied. I couldn't find any information on the mic model and wasn't expecting much, so I ended up tossing it.
Taking it apart, there are four screws in the wooden road case style housing and then the entire tuner chassis slides out. There are boards everywhere (the top is the power supply, the internal board drives the motor, the board on the side processes the audio, and the board that drives the lamps is tucked right next to the disk up front) and wires that fly all around, but because they are divide on the schematic and color coded, it's not too hard to find your way around. On the main board under some masking tape was a cluster of capacitors, and these turned out to be the tuning cap and one of the bunch had one leg not attached - probably broken because of vibration at some point. Reattaching it instantly fixed the problem of the tuner being very far off from the right note, now it was only a little bit off on some notes, which I think should be expected given the aging of components over more than 30 years - some part date codes suggest a manufacture date for this tuner around 1974. The first fix is an easy one!
I decided that the tuner would be much more useful with an internal mic, so I found a spot on the front place where you could add it, looked through the parts bin, and put together a little circuit. A switch connects the mic to the input line (if it were located differently, you could switch in the input or mic, but that would have required more cable and everything going right by the high voltage lamp driver board), then a small electret microphone is biased by a couple of thin film resistors and is powered off the 20V rail from the audio board. A couple holes in the front plate and a little bit of assembly later, it fully works and shows up well on the tuner's screen. Not as nice looking as some options, but plenty effective. I used a shielded cable for the signal and ground and the original design uses one to the input jack, but when I went to attach it to the jack, I discovered that their shielded cable used a foil shield which wasn't soldered to the jack, but just wrapped around. The jack was looking dirty and the cable going to the board needed to be replaced, so I just swapped all of it.
At this point, I thought I was done, but in giving the motor a second shot of contact cleaner, I noticed a slight tingle touching the front panel of the unit. I brought it upstairs (was in the basement) and tested again with no tingle, but hooked the multimeter between the chassis of the tuner and an earth terminal on a function gen, the chassis was at 60VAC. That potential was very, very low current, one microamp on the same meter (which is also one least significant digit), but it was enough to be felt, so I wanted to fix it. Reading around, I checked the capacitors on the primary and secondary sides of the transformer and while they measured well, one of the large filter caps on the secondary side had electrolyte bubble up from one terminal when testing it with the multimeter... so it needed to be replaced. I ordered up a proper three wire earthed plug and two replacement filter caps. Earthing the chassis was simple because there were already a few options as tie points, and replacing the caps meant trying to figure out how to hold them in place, but was quite easy to wire up. That eliminated the voltage on the chassis and prevented the incoming failure of those filter caps.
Calibrating the tuner:
I actually did the calibration before finding the 60VAC issue, but only because I had thought I was nearly done before I felt that tingle! Calibration of the unit is done with 12 potentiometers on the motor control board, one for each semitone of the scale, and most of them were slightly out because of the age of the thing. Procedure for calibration is fairly simple, but you have to have the wooden case off while it's powered up, so you do have to be a bit careful.
First, you feed a reference tone into the input. A simple sine wave will do, but any completely stable, completely accurate signal will work, and work out the math for the frequency of each with this formula: frequency = reference tone * 2 ^ (half steps from A / 12). The reference the machine states is A = 440 Hz, and the number of half steps can be positive or negative, the resulting number will be different, but the pitch will be the same, just in different octaves.
Then, locate the adjustment potentiometer for the corresponding tone and adjust it with a screwdriver (or better yet, a nonconductive trimmer screwdriver) until the darkest pattern on the display stops moving left or right. I like to let it run for a few seconds to see if there is very slight movement, but it will take some trial and error to get the adjustment right, the potentiometers are fairly coarse adjustments.
Repeat this for all 11 other semitones.
Since the board doesn't mark which adjustment corresponds to which note, I wrote in sharpie for each and included photos. It's not difficult to determine in testing, but it's handy to know in advance. It's also worth being absolutely sure that your pitch vernier is centered exactly at 440 Hz for calibration, as you can see in the earlier picture, my first full calibration was done 7 cents off until I realized it wasn't set right.
Now I've got myself a working, calibrated, vintage strobe tuner. The original spec list it as accurate to 1/3 of a cent, which is about as a fine as a person can hear and a bit better than my normal electronic tuner. There's a little bit of noise from the motor (which matches the pitch of the note you're set to!) and it's large for a tuner, but it's a well made bit of gear and a useful tool all the same. The visualization of a strobe tuner is definitely an improvement vs. your standard needle tuner to me.
December 6, 2016
Not Your Average Nixie Clock
Not Your Average Nixie Clock is just what it sounds like, a nixie clock with more functionality than just a standard clock. This 10-tube display reports time, date, temperature, humidity, and pressure and can be controlled directly over serial to display anything that the tubes used can display. The clock uses a single Arduino Nano to run the backplane with all of the sensors and controls 10 display driver boards which each run a discrete ATMega328 processor to drive a single tube.
Update! 4/4/2017
Another small update to fix a couple of quirks. I noticed that very occasionally, the clock would display 100.00kPa as the barometric pressure, but added an extra space before the number that misaligned the units and didn't display them. After some considering and digging around, as well as witnessing some properly formatted 100.00kPa displays, I found out the issue - an odd rounding error with the way arduino processes floating point numbers. The normal default is to display two digits of precision and round, so what was happening is that when the pressure was 99.995kPa or more, it would round up to display 100.00kPa, which is fine for accuracy's sake, but which meant the calculations to add leading spaces to get it positioned right added one too many until the value actually hit 100.00kPa. This is now fixed, and on other ranges where I never saw the problem, but where it should theoretically exist.
The only other significant change was in the calculating of the displayed relative humidity. Because there's no active ventilation for the clock, the interior (where the temperature sensors are) heats up somewhat above ambient. To fix this, I measured the outside temperature with a thermocouple and set a fixed offset assuming no forced air from an outside source. It works fine, but it means the relative humidity value read at the higher temperature is actually a ways off from the real one, and it measured about 6-7% low consistently. Rather than just add another offset and accept whatever error that made, I decided to convert relative humidity to absolute, then convert back to relative factoring in the displayed (adjusted) temperature. Unfortunately, there's quite a few variables in the calculation of relative and absolute humidity, so I found a formula with a set of constants that was accurate within about -35C to +35C and only requires the other humidity and the current temperature. So now the clock converts the sensor-read relative humidity to absolute humidity at the same temperature, and then back to relative humidity at the adjusted temperature. As a result, I can see an increased humidity display right in line with the offset I had measured, but which is calculated rather than just manually offset.
There were a couple of other minor changes and a couple modified EEPROM settings, but I also found that the RTC module kept extremely accurate time - the last time it was set to internet time from the computer was almost two and a half years before, before the backplane was even finished, and it was only 15 seconds off of internet time when I resynchronized it as part of this update. The updated code can be found on github!
Update! 3/17/2016
Daylight Savings Time in the US rolled around and I realized I never wrote anything into the code to compensate for it... so within a few days I had an update coded up to do just that. I also wrote in a handle to set the RTC module via serial (I originally used a separate sketch to set it, and I hadn't need to set it since I built the backplane), and modified the provided processing sketch to send the needed code. There was a bug that after a month or something of run time, the short press for the capacitive sensor stopped working (long press still worked), so I've swapped a variable type and added an additional check - I believe this broke when the uptime in milliseconds overflowed the signed long variable it resided in. All this should make the clock a more robust platform, but the testing for all the new code has consisted of about an hour of runtime, so if something shows up down the line, I'll tweak it and reupload. The revised code only effects the backplane and is uploaded to the GitHub page!
Original page:
Development time for this project is just about two months, and it totals almost 1400 lines of code and uses 473 electronic components by my count. It is intentionally overbuilt from what a clock would normally need to do and very similar functionality can be done with less, but I wanted to make some modular and swappable elements (every driver module is the same and be inserted in any order to drive any one of the four tubes). I also wanted to include lots of debug and status options that would be entirely unnecessary in a final product. I think the 10 vertical riser boards that drive the display look pretty nice too!
The backplane houses the main Arduino Nano controller which manages everything and acts as the interface to an external device. For sensors, it uses a DHT22 for temperature and humidity, a BMP180 for temperature (the two are averaged) and pressure, and a DS3232 RTC for timekeeping. It reads the value of a variable resistor to drive the NCH6100HV high voltage step up converter from with a PWM signal to control display brightness. Each of the 10 driver modules uses an ATMega328 with custom firmware to control 11 MPSA42 high voltage transistors and drive each pin of a 12 pin nixie tube - designed for Soviet IN-12 and IN-15 tubes in A and B variants. Each driver has a switch to choose IN-12 or IN-15 and detects the A or B portion automatically, and each driver communicates to the backplane processor through an I2C bus, deriving its I2C address from a resistor in the backplane to control ordering without having any difference in software. An aluminum bracket holds the tube sockets and tubes in place while an aluminum band around it which is electrically isolated from it acts as a capacitive touch sensor for a simple one-button input. Any tube can be connected to any socket or left unpopulated and driver modules can be inserted and configured in any way - the normal clock display won't work right with a totally different configuration, but the display can still be driven properly through the serial port in any combination.
I ran into countless problems developing it as I was working with several things I hadn't worked with before and because the scale was fairly large, but I'll run through a few things I worked through and how I fixed the problem, because it could be useful to someone using the same sorts of parts or general design.
The tube datasheets for the IN-12 and IN-15 tubes indicate a pinout and specify cathode and anode, but they are somewhat misleading. Pin one on the tube data sheet is actually pin 7 on the number written on the back of the sockets - which are intended for these tubes - and counts up going clockwise. What makes this more confusing is that you can actually power a cathode pin and ground the anode and still light the display... but for certain pins the entire tube will light somewhat instead of seeing a normal digit or symbol. It was a headache to deal with until I figured out just hooking up the socket leads in a different order made things act as I expected.
Making things work on the I2C bus seems straightforward, but it gets more complicated when you're sharing the bus with commercial sensors. Making sure the addresses don't overlap helps, but you also have to build in some replies to differentiate between types of things on the bus. It helped me to display the data that was coming back from the I2C scan, and then I configured the module code to reply in ways that didn't interfere with or get confused with other sensors on the bus. It's also worth checking the solder joints, with the pullups and the capacitors over the power, probing the connections could give incomplete information and early on I had a bit of trouble with some high-resistance shorts between the SDA and SCL lines that made the initial scan just lock up.
While I expected it going in, when I added the capacitive touch sensor, I was surprised at how much noise the tubes made. I originally used the socket mounting bracket as the sensor, but it auto-triggered itself when there were many tubes enabled (like in test mode where everything is running). While the sensor would increase in reading by a thousand or more when you touched it, if in some modes the noise was 300-400 and some it was 2000-2500, it would take some serious data analysis to determine whether it was actually touched, and you'd have to factor the number of on tubes and the lengths of the cathodes in use to eliminate the noise from the reading. Instead of that, I put a thin insulating layer on the edge of the bracket and surrounded it with another strip of aluminum, then grounded the bracket. This provided some noise isolation (not a huge amount since the tubes were still close and a straight shot through open air), but also increased the sensor value when pressed because of the close proximity ground.
Dimming the display was more complicated than I expected, after realizing the power supply module could be toggled with a logic level drive to the SHDN pin it seemed like a simple PWM would suffice. I got that PWM from an analogRead() of a pin connected to a voltage divider and a potentiometer, but I should have used a single turn potentiometer, the 10-15 turn one in place now simply takes forever to adjust the brightness of. You then scale down that value, factor in a minimum and maximum duty cycle to let the display be lit even at lower brightness settings, then invert it to drive an analogWrite signal. The defauly PWM frequency is 490Hz, though, which means an audible hum from your high voltage circuitry. Configuring timer prescaler bits you can go to 980Hz and a step much higher, but 980 is still quite easily audible and the only option was to go well above that and the 20kHz human hearing range, but the circuit in the power supply stopped responding at such a frequency. My solution was to go the other way, around 30Hz meant visible flashing, but 122.5Hz was much less audible and was still a fast enough signal to keep from seeing the flicker of the display. There is still some noise, but I believe at least a little is from the tubes themselves and would be impossible to eliminate.
Finally, right as I was writing the last few features into my program, I ran into memory overflow issues. The ATMega328 software doesn't really have overflow protection, so if you've got most of the SRAM used and you enter a function which allocates more than is available, it just reads or writes over existing data. I managed to get to more than 90% usage in the compiler before issues sprang up, but ultimately to get all of the serial communication stuff working properly, I had to optimize memory management quite a bit - unsigned ints instead of longs, bytes instead of ints (even in for loops), and surprisingly, reducing the length of Serial.print commands. As it turns out, returning a long string of text over the serial port actually allocates a good bit of RAM, so moving from returning "Invalid command" to "Bad command" saves a few bytes of RAM when you're running. I wanted the serial commands to be a direct user interface - no computer-side software and plaintext responses to queries, and I had to go over every line and swap for shorter synonyms or other tweaks to get more memory. When the memory was overflowing some of the symptoms included: entire lockups of the system, partial writes to drivers, garbled serial replies, missing received data, valid command strings being read correctly but then misinterpreted... memory problems are intermittent and hard to guess at a lot of times, so they can be particularly nasty to troubleshoot.
I made a short video showing the clock in operation and demonstrating some of the features:
The PondMaster is a solar powered pond pump controlled by an Arduino based robot. Beyond turning the pump on when the sun shines, the robot is programmed to check temperature, water level, and power level to let it remain installed and operational throughout the year without outside interference, and it can report its status over bluetooth, with a more limited readout of what it is doing through LEDs.
The Build
This project had been on my to-do list for quite some time, but with other projects and limited funds, it kept getting pushed back. When I finally bought the parts, it was more than two months before I could begin building, since the pump, shipped from China via inexpensive shipping, never arrived and had to be reordered. When the parts were finally assembled, it took another month to determine that the relay used was faulty and to rework different aspects to suit what I wanted out of the circuit and programming – there was minimal written planning done. From then, it took several weeks to build the protective/mounting assembly around the solar panel and a couple more months devising a solution for measuring water level – I had initially tried infrared reflectance off of a float in the water, but when installed, they proved to give little useful information and couldn't be used.
Months after the start, partly due to various setbacks and partly because it was one of a handful of projects I had going, I brought the prototype up to the pond to be tested out. For a couple of weeks, there were overhauls in the coding to fix glitches and rework the flow of the main loop. The whole project ended up being very seat-of-my-pants in nature, with the circuit being reworked to accommodate changes and new requirements while the code evolved to fit sensor readings, better compensate for brown outs to keep the bluetooth module on, and all sorts of other fixes. When it was operating well, I set the post, hid the cables somewhat, and attached it to the top. There were still some software tweaks after putting it up, but nothing significant.
The Circuit
Short of drawing up a circuit diagram, which would obviously be handy but which would take a fair amount of work and trying to reconstruct what I actually made after all the revisions, I'll just outline the basics of the circuit – what connects to what and in what order. It's generally not all that complicated and is a collection of smaller circuits developed for other projects or for individual sensor readings and whatnot all compiled together. It's also likely that this can be done in a more efficient way or that parts are extraneous.
The solar panel has a built in diode and then plugs into the box. On the smaller power board, the large capacitor smooths out the power somewhat and connects to both a 5v regulator circuit and and a low power relay, used to switch on the pump. On the 5v side of the regulator, there's a very large (1.5 Farad) capacitor to make sure that fluctuations in power draw and input don't start restarting the microcontroller or corrupt memory. It's not a guaranteed solution, but it's good enough for this application. On the other side of the relay, the power is dumped out towards the pump jack – it is routed through the red toggle switch, which lets me select between off, on (direct connection to solar power), and auto, which is routed through the relay controlled by the microcontroller.
On the other board, the Arduino is directly connected to the five indicator lights, is connected through the serial pins to the bluetooth module, and of course power from the other board. There's the in-box DS18S20 temperature sensor connected to the declared oneWire pin, all three connected pins also run out to the temp sensor jack, which has another of the same sensor on the end of a long wire. When the software enumerates the oneWire devices, they always come up in the same order, so you can tell which is which quite easily. The capacitive level sensor, which is detailed here, connects directly to the Arduino as specified by the capacitiveSensor library – the supporting resistor and small capacitor to make the sensor are on the sensor, so there's no need for those parts in the box.
Then there's two Arduino pins connected to transistors – one to switch the relay, which may not be required, but was going to be a larger current drain so I figured I'd be safe – and one to reset the bluetooth module, which when activated, grounds the power pin of the module to force a reset.
The second level sensor jack was originally to accommodate a pair of optical sensors, but since switching to the capacitive sensor, it goes entirely unused, an unconnected jack plugged in to keep it from being a hole to the outside.
The Structure
Aside from a few circuit boards bolted in a waterproof box, putting the build together wasn't too complicated, but took a while to design and fabricate. Starting with the electronics, I opted for quarter inch stereo jacks for interconnects, decent quality jacketed three conductor cable, and as much water and oxidation resistant bits as possible, since it was going to be outside. The cable from the solar cell was already installed – silicone covered high gauge wire – but there is never a ton of power going through any one cable, so I have not opted for metal jacketed cables or conduit – though in farther installations or higher power ones, it would certainly be recommended, if not required.
The plumbing is just 1/2" CPVC cut and glued to fit the pond, then painted black. A holder was made out of spare tee joints to keep the water level probe in place, and zip ties keep everything somewhat organized and in place. The intake for the pump isn't glued, but is two 12" sections of CPVC coming out of a tee, each riddled with holes and covered in 3/4" filter floss. The idea was to spread out the intake as much as possible, so as not to suck anything in.
The mount and shield for the solar cell is the most complicated part, structurally. Even though the panel is mounted to an aluminum frame and covered in glass, I needed a sturdy way to attach it to the post and wanted to protect it from branches and whatnot, given the trees in the area. I built the shield out of a quarter inch sheet of acrylic, bent to fit with a heat gun, but I can't recommend doing it with a heat gun if you want to make one. To bend a full two foot sheet, you have to have the whole joint hot at once to bend it, which is extremely difficult to do with a point heat source like a heat gun. I built an aluminum frame to attach the shield to the panel, from L strips, flat strips, and stainless hardware, then eventually built several thicker pieces to connect it to the post securely. The panel has only four mounting holes, so the back frame tries to tie everything together with some redundancy to keep it from coming off.
On the top of the post, there's a pair of brackets designed for support post mounting on concrete slabs in home construction and the like, attached together like a hinge with a single large bolt. While using two short bolts, one on each side, would make for a firmer grip, a single bolt is simpler, and a piece of PVC acting like a spacer keeps the pressure on each side high, without bending the sides in, and keeps up enough friction to keep it from flopping around. This assembly screws into the top of the post and directly into the aluminum structure on the back of the solar panel. Originally, I wanted two degrees of freedom – a rotation and an angle adjustment – and I built it with just that, but to fit the parts I was finding, the rotation was going to be at the point where the mount attaches to the panel structure. The problem is, that rotating there is useless – because of the shape of the solar panel and the facing requirements, you don't actually get any benefit from being able to move in that direction, so I just added some extra bolts and kept that joint fixed. If I had made the rotation point directly on the top of the post, it would have been much more useful, but the hardware involved would have been more expensive and elaborate.
The Software
This was built in the Arduino IDE, version 1.0.5 and uses three common libraries: CapacitiveSensor, OneWire, and DallasTemperature (which comes with OneWire). The source code with some commenting is available for download here.
Essentially, the program checks solar voltage every quarter second and temperature and water level every five seconds, it compares them to set minimums and if everything is within the limits, the pump is turned on, but can only be restarted every 20 seconds. This is done to limit the uptime when the sun is bright enough to power the robot, but not steadily power the pump – letting it run too long will brown out the system, which makes the bluetooth module not restart under some circumstances. Checking every quarter second and having high enough minimums for starting the pump catches this before the power level for the bluetooth module drops too far. The Ardiuino actually runs properly down to just above 3V, and thus is almost totally protected when trying to get the bluetooth module its full 4.7V or so.
The bluetooth module used needs basically no input from the microcontroller, so the Arduino simply waits to hear "read" from it (it acts just like a serial port open to the connected device and doesn't say much of anything else, by default) and then sends a full report of basic statistics to the connected device. The device also has a set of lights to show a heartbeat, whether the pump is on, and what's wrong if the pump isn't on. There is also the normal power light on the Arduino, the status light on the bluetooth module, and a power indicator inside of the 5v regulator to show the status of the system without anything connected.
The installation
The setup, at the time of writing, has been in place for a little more than a month, though it's only been on the post for a few weeks. The installation area is pretty heavily shaded, and the trees still have all their leaves, so the pump run time is only a couple hours a day, but I knew this when I made it, and it should improve when the fall rolls around. Aside from needing to replace some horrible quality stereo connectors early on, it has held up quite well: no visible humidity in the box, no problems from dirt or heavy rain, no damage to the top, no leaves or other debris getting stuck, easy to take apart and reprogram, etc. It will be months before I can really tell how well it's doing, but so far, so good. I will update this section a ways down the line to report how it has held up after a couple of season changes in place.
September 1, 2014
Capacitive liquid level sensor
Capacitive sensing using a microcontroller, in this case an Arduino, is reasonably well documented online. There are fairly complete tutorials for how to measure how much liquid is in a vessel and touch sensing applications like buttons and even proximity detection. The kind of sensor that I needed though, a liquid level sensor to be used partially submersed in the liquid it was measuring, was difficult to find. With some understanding of what makes a capacitive sensor works and a picture of a working probe of a similar kind, I put together a simple probe that can be made with only some basic materials and have documented it here.
I started by looking at existing probes, there are touch sensors, like this one , and there are vessel measuring devices like this one , but neither will work for this application. I want to be able to measure the liquid the sensor is in, which in either of these examples, just shorts out the electrodes making a resistor instead of a capacitor. I knew from research that the essence of sensing liquid level in this way is that the capacitor which is created with two electrodes and an insulator between them, but the liquid between the plates has a dielectric value different from the air, so by changing the amount of liquid between the plates, you change the capacitance of the sensor. The trouble was isolating those plates from the liquid that would short them out while still having it be able to pass freely between them.
After researching and some thinking, I found that the plates only had to be insulated from each other, they didn't necessarily have to be insulated from their surrounding liquid. That realization made me consider this sensor design, the coaxial electrode. Basically, you have a tube with an insulated wire running inside it, then you can immerse the tube partially in liquid but still keep any current from flowing through it, since one electrode is still fully insulated. With this design in mind, I headed to the hardware store to look for parts.
Building the sensor
Since this was for an outdoor project, I wanted to be sure that it wouldn't rust, so I looked exclusively at stainless and aluminum parts for the metal components. Based on availability, I ended up going with an aluminum tube and stainless hardware. I wanted the probe to be small so it could be at least partly hidden when installed, so I went with the smallest aluminum pipe they had, 1/2". I bought a set of 3/4" 6x32 stainless bolts as well as nuts and washers to assemble everything. Then I took a length of insulated wire from my stash, trying to look for something with insulation that would hold up to the rigors of outdoor use.
The assembly was quite simple. First you cut the tube to length, for me, this was 12". Then you drill a hole in the top and bottom for the screws, straight through the center of the tube. Insert the bottom screw and fasten it in place, then take the wire, a little more than twice the length of the tube, and insert it in a U shape into the end with the screw in it, half on each side of the screw so that the U will rest on the screw if the ends are pulled from the other side. Then I twisted the wire several times and put in the upper screw, again having wires pass on each side, and used a nut and washer to secure it in place.
I pulled the wire tails from the end and tied them together, trying to keep the wire in the center of the tube taught. Between the twisting and the tieing, it should be relatively centered in the tube. Then you strip one end of wire coming out, this will be one electrode. Your other electrode is the screw terminal you made by putting the top screw in.
A quick test in a glass of water shows the changing capacitance, though a very small one. A larger pipe or a larger internal electrode (like using a small pipe inside of a large one) will make a larger value capacitor, as it's directly related to the surface area of the electrode plates, but is not required.
Connecting and programming the microcontroller
The Arduino's way of measuring capacitance involves charging it and measuring the time it takes for the voltage to rise on the other electrode – at a certain threshold it compares the current time to when it began charging. Because of this method, by using a larger and larger resistor between the power source and the measurement pin, you can slow the charging speed and lengthen the time it takes to reach the threshold. This means that while a larger capacitor from a larger probe will give you more of a change in capacitance to read – theoretically more accurate given so-so sampling hardware – but by slowing the charging speed you can get the same finer granularity in the resulting reading. The disadvantage of the larger resistor is that it charges slower (that is intentional!), which means it takes longer for the microcontroller to read the sensor, and you can make fewer readings in a given time.
I followed the circuit and capacitor/resistor values recommended in the CapacitiveSensor library documentation(found here), including the extra fixed capacitor to even out readings. That setup, using a one megaohm resistor and a 100 picofarad capacitor gave me these readings with some basic code:
Hooked up to a spare Arduino nano programmed with just a bit of code, I got a functioning level probe. You can see in the later screenshot the process of filling the pitcher being measured and then removing the probe, but you can also see its inaccuracy. The first 3 lines are with no water, yet the values vary quite a bit, the 2000 value lines are all full, again varying a bit. When I remove the sensor it is a fairly continuous fall, but then I hold it and the values are all 0 from the influence of me touching it. This was made obvious when I set it down on the stone counter top (alternating holding it and setting it down in the last three lines) and it read as if there were some liquid present. While there is some level of inconsistency, you can also see that the data is overwhelmingly useful, as you can see the clear increase with increased water level, even with the significant level of noise. With a little bit of calibration, you can get a fairly accurate measurement in your height units of choice, given a specific liquid and rigid mounting. It's worth noting that the function I used in this code, the default one CapacitiveSensor(), auto-calibrates. For my purposes, this was great for testing but useless for operation, as my probe started submerged. With the auto-calibration, it would then calibrate to the lowest level on startup, and only register changes in level. Once I realized this was the case, I switched to use the CapacitiveSensorRaw() function, which instead gives you the raw sensor reading, which is important if you want an absolute level based on your probe instead of just the difference from the lowest recorded value.
This simple probe does a good job, once I had it working I built it into my PondMaster robot project, where I used it to measure the water level in our family's pond, so that a microcontroller could turn off the pump if the level was too low. To use it outdoors, I built the capacitor and resistor onto the top of the sensor, then covered the end with liquid electrical tape and covered that with a PVC cap, secured in place with screws. This lets it operate with just power, ground, and the sensing pin at the end of a cable and out in the elements.
August 15, 2014
The Eye - 64 pixel Photoresistor Imager
The Eye, a project to build an imaging sensor (a webcam of sorts) from discrete, low quality sensors. Something to let me have some fun with data manipulation and noise rejection, since the sensors used vary a lot and the idea of having a sensor size of roughly 4 inches square with no optics makes it pretty difficult to visualize much of anything.
Update! 4/4/2017
I came back to revisit this project to see what I could improve on, in the time since designing it my understanding of electronics has come a long ways, but I also found out how gamma adjustment worked, and wanted to incorporate it into the project. In this revision, I made a couple of hardware changes (though there are some design flaws that can't really be overcome with tweaks), I ported it to the Arduino IDE (using STM32_Arduino), I added a gamma adjust function for the microprocessor, slightly optimized the data transmission speed, and tweaked some values for better automatic adjustments. I added controls for the gamma function into the interface application, and I added individual control of the LEDs - something that was hardware supported in the earlier version, but which had not been implemented in software. I also put the code up on GitHub to share around - though it's a niche project, some of the techniques may be useful to see fully coded out.
The hardware modifications are two things: I replaced the wires running to the sensors with soldered jumpers because in the time in storage, the contacts had gotten questionable and pressing a little on the wires would change the readings of the sensor. I also swapped the old white LEDs with surface mount ones - they are still too dim for the purpose I was envisioning (Illuminating a near target), but they are at least short enough to not interfere with putting things close to the sensor. If I had to make a new revision, I'd drive the LEDs with more current to get that illumination target, but I wouldn't put them in between the sensor lines. This ends up distorting the image somewhat and even lighting can be achieved with a ring of lights around the sensor (individual control doesn't help much, it turns out). Having the sensor elements packed more evenly and tighter together would be better because without optics, your focal length is VERY short. A tighter cluster would get more detail up close and may get close to being able to use a large lens as basic camera optics - and since I'm now fairly comfortable with PCB design, wiring up the bottom manually wouldn't be a concern and it would be easier to pack them together without construction concerns. It also seems that too much darkness in a line of sensors being read depletes the supplied current and dims the whole row. Extra balancing resistors on each element could fix this but would be a lot of extra parts, a different multiplexing algorithm would help but could be complicated, and more drive current (or selecting sensors for slightly higher dark resistance) would all help.
And the new software, showing a spool of wire on the sensor (circularish thing) casting its shadow diagonally to the left. You can see a dark horizontal line under where the wire spool is, and this is the problem where too much dark in a horizontal line makes all of the sensors on the row read too low.
Full source code for the firmware and computer interface is available on github: The Eye on Github
Original page:
This project is built off of a Leaf Labs Maple Mini clone, built with the same PCB but by a different manufacturer, and programmed through their IDE, the imager is made of 64 CDS Photocells, rated for 10K ohms, 9 white LEDs for some additional light, and a couple of support chips to reduce the number of pins required to interface to the maple mini - while the framerate would be awful through the serial connection, one Mini has enough interface pins to run two imagers. The Maple Mini uses C and is programmed just like an Arduino, many libraries don't easily port over because the Mini is based off of an ARM Cortex M3, but some have been ported by Leaf Labs and some additional ones through the community.
As a proof of concept, before I ordered all the parts, I built a prototype on a breadboard: a 3x3 pixel imager using an arduino nano. Nothing fancy, but it proved that I could make the interface with my PC work and gave me probably the world's lowest resolution webcam, at .000009 megapixels.
Programming this thing has taken a while and is by no means is in a final state. I built the hardware in the summer of 2013, but didn't complete much software then. I got enough working to read the imager on my PC in September of 2013, but didn't return to the project to iron out some bugs, flesh out the interface, and get it to this point until February of 2014. The microcontroller interfaces through a USB serial connection to a program written in Processing that displays the data and requests new data or issues commands as needed. The bottleneck in the system is the USB serial baud rate, even at 1.1Mbit/s, I can only reliably get about 2-3fps from the imager on the PC... though when not attached, the system can easily operate at a smooth framerate, well over 60fps. Some basic processing is done and there is auto brightness and contrast settings, the whole system self-calibrates based on the maximum and minimum sensor readings for each pixel and a set of offsets recorded from the frame with the smoothest output. The auto calibration rates itself based on how wide the range between the maximum and minimums are and how smooth the smoothest frame is, then applies adjustments to the raw data, scaling the adjustment amount with the calibration rating. This means that when first switched on, the image is quite noisy, but with time and very dark and bright environments, the calibration makes an even frame look fairly even, and makes the auto contrast and brightness adjustments improve the usefulness of the image considerably.
This project is ongoing, with improvements to the calibration algorithm at the top of the list. I'm also considering breaking out one of the hardware serial ports and connecting it to an FDTI chip to get a second link to the computer and effectively doubling the image framerate. This has taught me a lot about what to pay attention to in calibrating sensors, and about making an asynchronous serial link with the computer work properly with compensating for errors, which took a lot more effort than I expected. I may try to improve the lights built in, which should be possible of decent illumination, but which do very little at the moment and which are not particularly even in spread. If I were to do another similar project, it would probably have a few more pixels, maybe 10x10 or so, and would be much more compact. The black silicone tube which is meant to isolate pixels from side lighting, would be removed and the CDS cells would be packed much tighter together to make a more usable image and a little more fidelity, though building it closer together would be considerably more difficult to assemble. Even in it's current state of calibration, you can only faintly see the B that the imager is reading off the monitor.