Oxygen Rebreather Dive Notes

Diving in Rockport MA

At this point this rebreather has been dived “wet” four times and it seems like a good time to make some notes on how it preforms. It certainly seems adequate-to-usable as an underwater breathing device, and as of the latest dive, I have even achieved a semblance of neutral buoyancy.

Dive Procedure

Building the unit up in Acadia ME

This is not a definitive “How to dive an O2 rebreather” manual. This is how I dive my scary prototype rebreather, usually alone, and unsupervised. I have no formal training and you shouldn’t use this as a basis for any kind of diving. That said, here is what I do to dive this thing:

The first step is to assemble the unit, including packing the scrubber. The scrubber should be filled with an appropriate amount of sorb appropriate for the dive (or more). As previously discussed, its about 4″ per cylinder of oxygen, for this given scrubber. The sorb should be shaken to allow to settle, and then the screen and spinner (see drawings) should be screwed on tight. At the end of this step, the oxygen should very slowly and very carefully be turned on, but not injected into the system yet.

The second step is a 3 minute pre-breathe. The goal of the pre breathe is to ensure that all systems, such as the MAV and regulator, are operational, and to warm up the scrubber. After putting on a dive mask, suck all the air out of the couterlungs and exhale it through the nose into the atmosphere. I exhale completely through the nose to empty the lungs, then start to fill the counterlungs and inhale. This ensures that there is minimal nitrogen in the system. Having too much nitrogen could cause a loss of consciousness if the mix goes hypoxic (hilariously unlikely with an O2 rebreather). Excess nitrogen could also allow nitrogen loading (leading to the bends). At the end of the pre-breathe, have a buddy or use a mirror to check the canister for condensation and for warmth. Condensation and warmth indicate that the CO2 scrubbing reaction is proceeding in the absorbent.

The third step is a bubble check. Divers should descend to 2-3 feet under the water and check each other (or use a mirror) to check for bubbles coming out of the unit- there should not be any. Bubbles coming from the unit call for an immediate abort- its not a rebreather anymore, its open circuit!

If the bubble check is negative for bubbles, the dive can proceed for up to 10 minutes (or other gas/scrubber limits). It is recommended to terminate the dive after 10 minutes since there is no convenient way to see how much gas is left (no SPG). This does not take into account chronic oxygen exposure toxicity of O2 at depth, but it is difficult to run up the O2 clock in only 10 minutes.

Once back on the surface, the DSV should be switched to the surface position and the diver can come off the loop.

Buoyancy

Buoyancy has been a challenge with this unit, but only because I am improperly weighted, since I only have one 10lb weight. The unit itself is about neutral to negatively buoyant in fresh water, and I am about neutral to negative in seawater (even with a partially inflated lungs). This leaves the wetsuit and a few liters of air to be balanced out by the weights- way less than 10lbs.

On open circuit, this additional weight can be balanced with a sac of air that the diver can fill and empty (a buoyancy control device). The remaining net small amount of positive or negative buoyancy is trimmed out by modulating breathing. Deep breaths and spending more time with more lung volume increases buoyancy, and the opposite decreases it.

With a rebreather, this is completely useless, since breathing out simply moves the gas to the counterlungs, which are still attached to the body. So the whole loop volume is what needs to be trimmed against the rest of net buoyancy of the diver, which, in this case, is very negative with 10lbs of weight.

However, it is still less than the volume of the counterlungs, so it is possible (as seen above) to achieve neutral buoyancy!

Trim

Trim has not been a big issue so far. Folding up my legs moves my center of mass close to the center of buoyancy, so I don’t have much trouble staying horizontal in a nice streamlined position. This might need more investigation, since I have not dived it in particularly calm water yet, and most of my time has been spent swimming, which helps keep a good trim.

Attitude and Work of Breathing

Work of breathing (WOB) is a big figure of merit for rebreather design. Work of breathing depends on counterlung (CL) position, and for any given rebreather the CL position changes as the diver moves around. In particular, pitching and rolling change the pressure of the lungs vs the counterlungs. I don’t have a way of measuring WOB, but it has been breathable through 90 degree rolls to either side, and about 30 degrees of pitching up. Pitching down tends to result in incurable mask squeeze, since the nose essentially makes the mask the lowest connected air volume. It is much more comfortable to avoid that, unless you really want to look at something in a deep hole. On another note (often echoed by rebreather divers), I have not had any issues with dry mouth or feeling “thirsty” during my dives, since the air is quite warm and humid when breathed- even in the chilly waters of the northeast.

Ergonomics

A couple easy, but substantial improvements could be made to the harness. It is very inconvenient to put on, involving an intricate dance of bending over and weaving the harness behind your back, while balancing the unit on your shoulders. Bolting it to a backplate or having seprate waist and hip connections (maybe even a chest strap) would make it much easier to don, and easier to tighten to prevent it from floating around underwater.

Additionally, it would be helpful to be able to clip off the MAV so that it lives somewhere on the users chest, enabling either hand to find and use it.

On the bright side, the hoses are fairly non-intrusive when diving, even though they are somewhat long, and even thought the unit is wide, it does not impede any movements to the front of the body, which is where the arms usually are while diving.

Cleaning and Storage

The unit is pretty small, and since most parts are plastic andhave no moving parts, it doesn’t require a huge production for cleaning. Everything just goes into the storage bin, gets rinsed, and then is set in the storage bin to dry. The two exceptions are the MAV and the Oxygen valve- the MAV gets soaked, and the oxygen valve gets soaked, while worked open and closed. These soaks happen with hoses installed, since I want to prevent the inside surfaces from getting salt/salt crystals inside of them.

Final Thoughts

This thing is pretty darn fun, and not as sketchy as I imagined it would be. It really does let you get a lot closer to fish and animals. I’d love to take it somewhere shallow and calm and clear, like blue heron bridge or crash boat beach, or a nice warm lake somewhere.

Oxygen Rebreather Design and Fabrication

Going on the loop, Acadia NP

To Swim is Human,

…To Dive is Sublime,

……To Suck Thine Own Bubbles is Extreme

Dr. Robert R. lannello, Director, CEDU

There is something romantic about making a machine that to allow you to travel past the limits of terrestrial physiology. From the early sci-fi of Jules Verne to the Apollo missions, life support systems have been an icon of adventure for hundreds of years. Here I will document my own prototype oxygen rebreather, as well as some figures for those seeking to make their own dive equipment, including detailed drawings of the prototype rebreather I made.

Theory Of Operation

Click through slideshow for annotations

The type of rebreather I built is the oldest and simplest type- an oxygen rebreather. As its name implies, the gas that is breathed and added is 100% oxygen. If a human breathes in a breath of 100% oxygen, they will breathe out a mixture of CO2 and oxygen. If the toxic CO2 is removed, you can re-breathe the remaining gas- hence the name.

In a rebreather, CO2 is removed by a chemical scrubber, which is the white stuff in the horizontal tube in the above photo. In order for the CO2 to be removed, it needs to be pushed through this tube of scrubber. In a rebreather, the lungs of the diver are used to move gas by breathing. Obviously, a diver would not be able of compressing all the gas in their lungs into a rigid container, so there are soft counterlungs in the gas path. The gas moves back and forth from the lungs of the user and the counterlungs, through the scrubber. The simplest oxygen rebreathers do not even move gas in a loop- they are of a type called a “pendulum rebreather”, where the bulk of the gas is in the counterlung or in the lungs of the user. This rebreather is slightly more sophisticated- the gas moves in a loop instead.

This is achieved by a one-way valve in the mouthpeice. It only allows exhalation to one side of the scrubber, and inhalation from the opposite side of the scrubber. In a pendulum rebreather, it is easy to have dead volume on the ends of the pendulum- short breaths can create a buildup of CO2 which is bad. This is less likely to happen with a loop.

Of course, with oxygen is consumed by the body, and CO2 is absorbed by the scrubber chemicals, so over time the volume of gas in the loop decreases until the diver can no longer breathe. The silver item with two hoses coming out of it is the manual add valve (MAV). This allows injection of oxygen into the system.

Experienced divers (or even beginner divers, or anyone familiar with boyles law) will realize that on ascent, gas expands and that there needs to be some kind of gas dump. In order to minimize leakage potential, the gas dump for this unit is the users nose, which vents from the lungs to the water.

Design Philosophy

Finished CAD model

The driving philosophy behind this rebreather was to make something that was simple, but not too simple. For example, instead of using zip ties, clear PVC tubing and hose barbs, I went to the trouble of machining fittings for proper scuba hoses- in my opinion these are a lot safer, even though they are more expensive and require more complicated machining. On the other hand, there is no overpressure dump valve, because I did not want to botch something that could accidentally allow water into the system, which would be unpleasant.

Engineering and Physiological Constraints

rough size comparison of the ubiquitous AL80 to a bernz-o-matic disposable cylinder

The kernel of this rebreather design and sizing is the duration that it can be used to support life. In this case, the limiting reagent is oxygen. If you use more oxygen, you will be up and out of the water faster. The amount of oxygen also determines the amount of scrubber which is appropriate. For this prototype, I am using disposable welding gas cylinders. They are quite low pressure, roughly 450PSI*. This is calculated from knowing that there are roughly 30L in the cylinder, and the volume of the cylinder is about 1L. Therefore it should be 30*15 PSI. This corroborates the information found here.

*N.B. feeding this directly into scuba inflator hoses violates the hoses 300 PSI rating- a regulator would help with that. However, the volume of gas is so small that after only a small amount of O2 is dispensed, we are back under the pressure rating. I can’t say anything here aside from that I turn the O2 on very slowly, and that these hoses will probably have a very low cycles.

An M4 medical cylinder of about the same size filled to 2200 PSI might carry 113L of gas, and a scuba AL6 cylinder would carry ~160L gas. These are all very similarly sized cylinders, but the higher pressure allows for a HUGE improvement in capacity.

One question to ask is “how long will 30L of O2 allow someone to live?”. The answer (as always) is that it depends. The rule of thumb for O2 consumption that I used (pulled from here) is 3.5mL/(kg*min) at one MET where the weight is you body mass. That means as a 90 kilo person I consume about 19 L of oxygen per hour at one MET. One MET (metabolic equivalent) is if I am sitting in a chair- a walk might be 3 MET and something like running could be higher- therefore, the duration that the oxygen will last is heavily dependent on body size and personal physiology. However for a very relaxed dive, it seems like 30L could last 15 minutes or so (testing on the couch seems to confirm this rough estimate). Unlike OC scuba, there is no volumetric penalty for breathing at depth, since the gas is recycled- although more gas is required to fill the lungs to the minimum volume at depth.

The next question to ask is “How big should the scrubber be?”. One of these disposable oxygen cylinders contains about 32.5 L of oxygen, which is 44 grams. Using some math (and chemistry) we can see that 44 grams of O2 means that there are 60.5g of CO2 produced. I used this paper to derive what the ratio mass:mass of sofnolime to CO2 should be. The paper gives the time until complete scrubber breakthrough, where ppCO2 is about .1 Atm, which suggests a 3.3:1 ratio of sofnolime to CO2. I backed off of that to where the curve started to really take off around .05 Atm, and calculated using a 3.7:1 mass:mass ratio. In my calculations I also added a factor of safety of 2 to account for any variations in scrubber quality or condition. This gives me a scrubber length (for the designed diameter) of about 4″, but embarrassingly I decided to make the canister much longer to match it with the width of the O2 bottle+regulator I had, assuming they would also be mounted horizontally. On the bright side, I could pack the scrubber once, do a dive, swap tanks, and then get in another dive. You can see my math here.

Old chest mounted design- the valve was to be manually operated (no MAV) to add gas to the loop

On this iteration, I decided that the end caps of the design would route the hoses out horizontally. Ultimately, this made the unit very wide, and I think it would have been wiser to have the hoses routed straight up. However, this did allow for more configurations- front mount or back mount with a larger bend radius, and therefore less force on the divers jaw.

Components

The next few sections describe details of various components of the rebreather.

DSV

A dive surface valve (DSV), allows the loop to be closed off by closing the opening to the mouthpeice when at the surface. This is useful for when you are between dives and do not want to let ambient air into the system. The DSV I chose is labeled NOT FOR REBREATHER USE- it is the Argonaut kraken DSV. It’s definitely another part that one could make, but the complicated shape makes it more appropriate to buy since it will be easier to maintain/replace.

Counterlungs

Testing the old unit. CL attachment is on viewers left, and it goes into the bag at the bottom. This causes all the air to go to the top of the lung due to water pressure, and requires the lung to be very full to work.

The previous design I worked on had a huge counterlung problem: the lung tended to form a bubble at the top, far away from the hole which led back into the loop. This caused the fabric of the lung to close up against the inlet, like a flapper valve. Gas would get trapped in an un-breathable portion of the lung, which led to excess buoyancy and to gas getting trapped outside of the loop- this is bad for breathing, and scary for the diver.

For this next design, I opted for two counterlungs- one on either side, which should make it easier to breathe at any diver attitude. I used hydrapak 4L “seeker” bags. As best as I can tell, these are RF welded urethane, and they are tough and O2 compatible (or at least they are not contraindicated).

The new design better accommodates changes in diver attitude. Rolling to one side should cause at least some gas to be forced into the other lung. Pitching up and down should be accommodated by the piccolo tubes fitted to the lungs. The volume of the lungs was determined by breathing into empty 4L hydrapak seeker bags. The metric here is vital capacity- the most you can breathe out after the deepest breath (about 6L for me). My tidal volume is much much lower than that, and that is the minimum the bags need to be inflated to. However, excess capacity is not bad, in that it can help prevent immediate lung overinflation on ascent.

These 4L bags were fitted to pipe unions, allowing them to be removed and rinsed. The sheet metal casing of the unit forms a boundary for the lungs as well, preventing them from floating up and torquing the scrubber, or pinching themselves off. Two colors were used to indicate inhale and exhale, as one piccolo tube is longer than the other for hose routing reasons.

MAV

The last system was the MAV. Originally it was to have a CMF orifice as well, but that was not installed due to concerns about pre-dive leaks/overfilling of the lungs prior to the dive. The MAV is one of the more fraught parts of the system in terms of cost and rework, and thought. Originally I was planning on machining the whole valve myself, but that is annoying- parts corrode quickly in seawater, and I don’t want to have to re-do hours of lathe work every time it leaks. I want to build a rebreather, not a valve.

After some research, I found Duncan Price’s website which turned me on to clippard cartridge valves. These things are awesome! Drill a hole, drop it in, and you are good to go, aside from the rest of the plumbing.

Ultimately, that plumbing consists of two BC hoses with the 3/8″ end screwed into the MAV, and a single -4 SAE port plug to plug up the end where the valve goes in. Because the hoses are very different lengths, I opted to make both connections on the MAV side the same, because there’s little danger of assembling the unit with the wrong length of hoses.

The hoses place the MAV mid chest for ambidextrous use, which is very important, since the MAV provides life-giving oxygen.

Mistakes Were Made

I think it is important to address a few safety errors in the design of the unit. The two major lapses in the design are the use of aluminum in the MAV and scuba hoses which are not rated for an appropriately high pressure.

The hose issue is obvious in retrospect, and could easily be resolved with a regulator by finding a higher pressure rated hose and actually, I have no idea what the output pressure of the regulator I have is- I dont have an gauge that can read it- I have assumed it was tank pressure, but it may be reduced. The real trouble is with material compatibility and high pressure oxygen.

I recently got a copy of Vance Harlows Oxygen Hackers Companion (highly recommended- worth the money and you won’t find a pdf). It explains in great detail that material compatibility with high pressure oxygen is critical for preventing rapid unplanned and uncontrolled oxidization (oxygen fires). While unlikely, a sparking metal shaving, accelerated by the high pressure oxygen from the cylinder, could spark and cause the MAV to catch fire. Brass would be a much better material than 6061 (NB- 6061 does contain a small amount of iron and could possibly create sparks) brass is considered to be “non-sparking”.

On the bright side, the lack of ferrous metal shavings and oils by careful cleaning seems to have prevented any kind of unpleasant exothermic reaction. The only removable threaded connection is that of the oxygen cylinder to the brass regulator. The regulator is very soft and is unlikely to create steel slivers from the steel oxygen bottle. The other two connections are scuba BC inflator hose QDs which do not have tight metal-to-metal fits.

Drawings

Ah yes…engineering drawings

Here are the drawings of the entire unit, including part numbers for off the shelf parts. N.B. that all the mistakes under the “Mistakes were made” heading are documented here- not corrected. Keep that in mind when you look at them.

Resources/Inspiration

A little joke, courtesy of Merriam-Webster online dictionary

CEDU diver website, by Robert R. lannello. Down to earth and tongue-in-cheek (or perhaps very serious?), this website has a huge amount of information for and shows what you can do with a garage and a little knowledge.

Right up there with Dr. Bob is Alex Pierce. His youtube series covers many many dive subjects, including a DIY O2 rebreather that he and his friends built!

Jef Mangelshots excellent collection of links on the starck electrolung, one of the first closed circuit mixed-gas rebreathers was very inspirational and incredibly informative.

The rebreathersite is of course, about rebreathers. It is probably the greatest resource for research, complete with detailed photos of commercial and DIY units, including non-diving rebreathers. It also has information on the theory and operation of rebreathers.

DIY rebreathers has a lot of information, but is mostly a good collection of links to random information.

Rubicon foundation (possibly down) hosts some amazing images/text from the development of early rebreathers, including early lambertsen reabreathers (LARU).

The airspeed press has great books on technical subjects for divers, especially divers playing around with voodoo gasses. I have read the oxygen hackers companion and I am excited to dig into the rest of the books published there soon!

Richard Kinch’s website, which is mostly not about scuba, but provides some good tips on how to make a dash 3 SAE ORB fitting without a reamer.

Written by Hans Haas, an influential oxygen rebreather diver, is an honest-to-goodness book. “MANTA: Under the Red Sea with Spear and Camera” is an interesting look back at history, and a lens into early diving. Some parts of the book have not aged well, but the photos and the sense of adventure it conveys are worth a read.

Suppliers

These websites also are chock-full of useful info and are staffed by smart people. The difference compared to the above is that they will also sell you stuff! Good stuff!

Mcmaster-carr.com (need I say more?) Screws, aluminum extrusion, aluminum sheet…almost anything you could need.

vintage scuba supply and vintage double hose are good places to look for hose sets. Much nicer than anything I found at home depot.

dive gear express– sofnolime, hoses, fittings galore. Be sure to check out their BCD parts section too!

Withings Pop Activite: Electronic Analysis

IMG_20170306_195524907.jpg

There are two big electronic questions to answer about the activite:

  • Why does the double tap not work well?
  • What are all the parts on the board?

I have decided to document my answers to these questions in a narrative form because I think it is interesting to hear how people solve problems.

Double Tap:

It is pretty obvious that the double tapping is going to be sensed by the accelerometer, the ADXL362.  Unlike the popular STM accelerometers, the ADXL362 does not have built in double tap detection, although it does have a acceleration-based interrupt that can wake it from sleep.  In order to see how the accelerometer was configured, I stuck a logic analyzer on the SPI lines of the device and took several logs of the device in various states, especially power-on and while being tapped.

I used a saleae logic 8 and the logic software to capture the logs and exported them to text files to be parsed by python, which was necessary since each log was several hundred entries long.  This made it easy to distinguish between things that are important that change across logs from things that are not important, like slightly different acceleration readings.

The gist of what the device does on startup is:

  1. turn on the device and read some ID registers
  2. reset
  3. Read the registers again, set some thresholds*
  4. Set up FIFO and FIFO watermark
  5. Read status until FIFO watermark overflow
  6. Read FIFO
  7. Reconfigure FIFO**

The asterisk-ed items are the most interesting, since these are he registers that carry over to the actual operation of the device, and to detecting taps.  Since they get reconfigured several times, we need to look at the register states at the very end of all the configuration.  It is odd to me to see that the ID registers are poked so much and that the device is reset and read again-it makes it seems like they are using some boilerplate library to set this up.

The relevant registers that have been touched are:

THRESH_ACT_L 0XC7: sets the activity threshold to 199, which is about 1/4 g when FILTERCTL is set to 0x41

FIFO_CONTROL 0X0A: puts the device in stream mode, set MSB in FIFO buffer watermark, and turns off temperature measurement

INTMAP1 0X24: interrupt on pin 1 on either hitting the inactivity threshold or the fifo watermark

INTMAP2 0X10: interrupt pin 2 on hitting the activity threshold

FILTERCTL TO 0X41: +/-4 g range, at 25 hz, half bandwidth off

POWER_CTL 0X02: put into measurement mode

So there you have it- the device is just waiting for a signal of more than a quarter g, and then it will signal the host processor that an activity occurred.  But lets dive in a little deeper on the double tapping to see how it is detected.

Capture.PNG

 

In practice, we can investigate this behavior with the logic analyzer by sniffing the SPI lines as well as the output pin to the minute hand that moves when you double tap.  Circled in blue is the minute hand moving, and in red is the SPI transaction that detected the double tap.  The block of transactions in the middle is very similar to the power on interactions mentioned above.  I saw this pattern in several instances about 5 seconds before the minute hand ticks.

Capture2.PNG

 

zooming in on the red part shows us that there is a long time where the chip is selected, but not being read.  Lets take a look at the accelerometer data from that read.

tap 2 total.png

 

The pink line is the total acceleration, and the horizontal line is the activity threshold, which the tap threshold is probably greater than.  The blue line is the “break” in reads.  Since the total number of reads is the whole FIFO, it seems like the window for tapping is at most about 6.8 seconds (512 records % 3 * (1/25Hz)).  Likely the window is smaller than that- assuming the break happens right when the second tap is detected, we can see that the window from the last tap to the previous one is about 25 records, or about 1 second.

tap 1 total.png

 

This is backed up by a second reading, in which the second tap was detected after about 25 readings.  This very strict timing and a relatively high acceleration threshold is probably why it is so hard to get the double tapping to work.  One thing that could make it easier on users is having a larger or more permissive window, but to only sense tapping one direction- it would reduce the cost of having to sift through 1/3 of the data, and it would probably be less prone to noise.  Or you could just do what I did and bang on the face of the watch all day.

What is on the board?

img_0137

The board is shockingly bare.  In the upper left hand corner, there is the NRF51288, and its accompanying crystals (silver).  Right below it is an almost invisible ST micro Balun.  Just south of the crystals at 9 o’clock is some kind of mystery part with an inductor, or possibly an antenna.  South of that looks to be a reverse polarity protection diode.  At 6 o’clock is the motor, and at 5 o’clock is the motor driver, marked “1X W48”  At 1 o’clock is the ADXL 362 accelerometer, mounted right next to where the chassis PCB is screwed to the case.  Just CCW of that looks like some antenna balancing circuitry, but it is hard to be sure.

The really interesting thing is what is not on the board.  Very frequently with this kind of product, you will have some kind of voltage converter and a memory chip.  And for the relatively higher-current steppers, I would expect to see some kind of h bridge or FETs.

For the pop, it seems like a voltage regulator (or converter) is not needed since there are so few components, and the two heavy hitters on battery usage- the NRF and the ADXL, need to be on in low power sleep or collecting data all the time.  Since they sleep so much it is possible that the quiescent current to keep the converter running would overcome the savings in power from running at a lower voltage.

As for memory, this is the AA variant of the chip which has the expansive 256 kB flash (twice the AB variant), but only 16 kB RAM (Half the AC variant).  I imagine most of the records are then processed in some way and stored on the chip.  This saves on parts, and power on a second chip, but apparently limits the tracking 38 hours between syncs.

connex1 wheel.png

The motors that drive the hands (the movements) are probably driven from the 5mA high-current outputs on the NRF.  There can be up to 3 at any given time, meaning that a the NRF can dump a shocking 15mA out at a time, at the battery voltage.  This is consistent with reports form users that at the end of the battery life, the hands stop working, even though the watch knows what time it is.  At the end of the battery’s life, the voltage will drop, and less power will be delivered to the motor- some of these motor movements will fail, and the clock face will be wrong.  Above you can see the current output (green line) from driving the motor- the peaks are around 15 mA above the “floor”.

5x press3.png

On the other hand, the motor is too large for the NRF to handle, so some kind of FET arrangement is used to drive it.  It takes 60 mA (peak) from the battery!  That is why setting a lot of alarms is taxing on the device.

Final Thoughts:

This is a pretty simple electronics-wise for such a sophisticated device, which speaks volumes about the team that designed and built it- it is pared down to the absolute minimum complexity, with only the barest of sensor packages.  Yet I feel the device does deliver on what it promises to do.

 

Withings Activite Pop Teardown

IMG_0022.JPG

The best looking wearable I have seen, and this is the cheap version

Shockingly, nobody has taken the time to do a detailed teardown of the engineering marvel that is the Withings Activite.  I snagged the “pop” version for $40 bucks on ebay and wore it for a few days before tearing it down.  I noticed a couple of things in that time:

  • it’s not good at measuring bouldering as activity
  • the double tap function almost does not work
  • the alarm seems like it works pretty well
  • you cant read it in the dark, which makes it pretty useless as a watch

Now for the teardown- this will be the first of several posts.  This just details actually taking the thing apart.  The next two will look at the interesting electrical and mechanical aspects.

Mechanical Teardown:

IMG_0071.JPG

Step one is to pry off the back with a screwdriver using the small divot under the button.  This is the official way to replace the battery, although withings recommends taking it to a professional screwdriver user to do this.  NB if you are not going to destroy your watch, it is probably a good idea to do this with a soft, wide, rounded tool, not a random screwdriver.  This will avoid marring the case.  In the rear case there is a tiny spring plunger, a piece of foam to back up the battery, and an o ring.

Here you can see the back, the battery, and the watch.  Note the holes on the left bottom of the watch.  These cover a programming/debug header.

IMG_0104.JPG

Once the screws are removed, the vibration motor needs to be carefully pried off of the plastic, since it is still attached to the PCB with wires.

IMG_0116.JPG

At last, the PCB is unmasked.  Here you can see the vibration motor (6 o’clock), dome switch (12 o’clock, yellow), debug/programming header (6 o’clock to 9 o’clock), and battery clips.  Also sprinkled throughout (and important) are a number of screw heads (silver) and test points (yellow).

IMG_0125.JPG

With the smallest screws in the world removed, we can now separate the PCB from the movement of the watch.  The V-twin in the middle is from the minute and hour hand, while the single-cylinder looking thing drives the activity meter.  We can also see the front of the PCB for the first time.  Interestingly, the movements are attached electrically to the thin PCB with ENIG plated pads being screwed directly to metal standoffs in the movements.  Behind the movements is a piece of plastic, which serves to help orient the components and seat the vibe motor.

IMG_0137.JPG

Here is the PCB.  Major components include:

-NRF51288 Bluetooth SOC, of course.  This is the WLCSP BGA version, which makes sense because much of the board is covered by the movements. (11 o’clock, rectangle)

ADXL362 accelerometer by analog devices.  A super low power accelerometer.  It will be interesting to think about why they went with that over something cheaper from ST micro. (1:30, square)

-Probably an h-bridge or motor driver (4 o’clock, square)

The rest of the paraphernalia is the usual flotilla of antennas and crystals.  Interestingly, there is a non-pop 8 pin device, 3 pin device, and 2 pin device.  I will have to think about what those might be.

img_0147.jpgThe next step of course is to remove the crystal/glass (in this case, lime glass).  This is so I can take off the hands, which will let me take a closer look at the movements by detaching them from the face of the clock.  I was not sure how everything was held in, but I suspected glue, since a press fit would be a bit risky (and possibly not very water tight).  After evenly heating to about 275 C to soften any glue, I was able to press everything out of the front of the watch with my fingers.

IMG_20170302_171634254

At this point, the hands were still pressed onto the shafts of the movments.  Like most dials, these can be removed with a careful application of tweezers as pullers near the shaft that they are pressed onto.

IMG_20170302_171908229

Here the hands are removed, the double shaft/collar of the hour/minute hand is exposed.  The hour hand rides on the outer hollow shaft, and the minute hand goes on the inside.  The activity hand is much smaller and brass, while the two other hands appear to be aluminum.

IMG_20170302_172454752.jpg

With the hands removed, the movements are no longer constrained to the face of the watch.  Here is the top of the activity movement, showing the output shaft.  Those four silver things are actually tiny machine screws.

IMG_20170302_172617288.jpg

Here is the bottom of the movement.  The four gold colored metal bits are threaded metal standoffs.  Tiny truss head screws pull the traces on the movement into intimate contact with exposed traces on the PCB.  On the reverse side of the copper-coated laminate, the two electromagnets are soldered to copper on the other side, connecting them to the PCB.

IMG_20170302_172704294

A shot from the side showing the internal gearing of the drive.  The complicated stackup of fiberglass, metal, plastic and tiny gears can clearly be seen.

IMG_20170302_180533889.jpg

With the screws removed, I managed a closeup shot of the magnet that drives the mechanism.

IMG_20170302_195146140.jpg

To determine how it worked, I screwed the movement back onto the PCB and connected to the app to “set the time” which works by positioning all the hands to reference positions.  This let me rotate the hand arbitrarily.  By putting a very tiny dot of prussian blue on the magnet, I was able to see that it was in the same spot every other tick- in other words, the magnet rotates 180 degrees per tick.

Final Thoughts:

IMG_0062.JPG

Most fitness trackers are a variant of a PCB in a box with some kind of typical (LCD, OLED, LED) interface.  Even the iconic nike fuelband is just a cool rendition of LEDS inside of a piece of plastic.  The activite is a well-crafted and very complicated departure from what I normally expect from an activity tracker.  It feels a lot more sophisticated and it blends into everyday clothing compared to a colored piece of plastic with a glowing display.  Since it has a primary battery, it does not even intrude in my daily thing-charging rituals.  I think I understand why people would choose this over a fitbit or garmin vivo-thing.

 

 

Thermal Camera Redux

IMG_20160713_231049674

After chilling out in my parts box for a few years, I decided to drag out my old panasonic GRID EYE thermopile array, because lets face it, we all want thermal vision.  I felt like last time I worked with it, I did not do the sensor justice.

So I whipped up a quick model for an enclosure.  I was not sure how I wanted it to look, but I settled with something like a pana-view stero viewer.  The device really does not need to be any bigger.

After printing out the enclosure and writing some code, it is working!  But I ended up using the lens and the enclosure shape for the gopro viewfinder instead.  I guess I will have to do something else with this sensor.

GoPro Viewfinder

IMG_20160720_165046844

The GoPro is quickly becoming my favorite camera to take hiking.  It is lightweight and unobtrusive, compared to even a small DSLR or compact.  The battery lasts long enough, and with a case on it it can be waterproof.  I actually carry a pair of them, one with a screen and a polarizing filter and an LCD for landscape photography, and one just for pointing and shooting with no filter or LCD.

eyefinder

One issue I have with the LCD is I can’t see it at all in the sun.  Its not particularly high brightness, resolution, or contrast, and if I can’t see it, it is just burning battery.  Not being able to see it also makes it impossible to properly adjust the polarizing filter, which means I end up with blurry, flat photos sometimes.

To resolve this problem, I printed a shroud to go around the back of the camera.  Friction and potentially rubber bands can be used to hold the camera in place.  A lens and an eyeshield make it comfortable to hold up to the eye and see what you are shooting.

IMG_20160720_165129199

It looks like it works so far.  I am excited to give it a test run in the real outdoors, although it may need a few more features before then- like something to hold in the camera, and eyelets for a strap.

Custom Service with SD110 the NRF51288

As a person who makes their living in the IOT world, I decided it would be handy to learn how to get data to and from the venerable NRF51288, which is certainly a contender for the best bluetooth SoC out there.  One annoying thing is that the wonderful Softdevice that Nordic provides does not have a particularly clear English translation, or good pictures in their documentation.  Here I will try to describe with pictures and arrows that my mechE brain is accustomed to, instead of with comments like “Attribute metadata for the User Description descriptor, or NULL for default”.  Hopefully after reading this, you will have a better feel for how to make a custom service, as well as what the more formal terms are for the different parts of the service in the softdevice API.

How to read this:

The 10,000 meter view will start with the softdevce and the GATT server, then at 1,000 meters, we will inspect bas.h to see what the minimum viable functions for a bluetooth service are.  At 100 meters we will look at the softdevice calls that add the information to the GATT server.  at 10 meters we will look at what gets passed to those calls- the real key to understanding how to add things.  At the very end, I will show you how I changed the bas example to report acceleration values.  This is by no means a definitive guide, but hopefully it will give you a jumping off point for adding services to your code.

10,000 Meters: GATT and the Softdevice

path3459-1.png

The thing we want to do is add a new service to our Generic Attribute Profile (GATT) server.  Adafruit does a wonderful job of explaining it here, with pictures.  Once you connect to a BTLE device over a Generic Access Profile (GAP), your bluetooth client, usually something like a phone or computer, can access the GATT server, usually something like a the NRF5.

A GATT server can have characteristics, as well as services.  Services are groupings of characteristics.  Services are distinguished by a 128-bit UUID.  Some of them are reserved for particular types of services, like a heart rate monitor, but we will deal with making sure we don’t use those later.  Two that are always included are the Generic Access Service and The Generic Attribute Service.

Characteristics live inside of services, and have characteristic values.  These characteristics can also have descriptors, which can tell you useful stuff like what the name of the characteristic is.  Characteristics are things that can be read and written to the server.  A client might read log data or a sensor value, and it might write a new state for the device or a device name.

The way that you access the GATT server on the NRF51288 (as well as the NRF52) is through the nordic softdevice (SD), which is a pre-compiled binary that you append to the beginning of your user application code.  It handles all the GATT and GAP stuff, and you need to tell it to do things like add services and characteristics using calls to the softdevice that are provided by nordic.

1000 Meters: What is in bas.h

typedef struct
{
...
} ble_bas_init_t;

typedef struct ble_bas_s
{
...
} ble_bas_t;

uint32_t ble_bas_init(ble_bas_t * p_bas, const ble_bas_init_t * p_bas_init);

void ble_bas_on_ble_evt(ble_bas_t * p_bas, ble_evt_t * p_ble_evt);

uint32_t ble_bas_battery_level_update(ble_bas_t * p_bas, uint8_t battery_level);

Taking a look at an abbreviated version of what is in bas.h will let us know what kinds of things a a bluetooth service might need to do, and what kind of stuff we should have to use the SDK as a template.  Here is a listing of the most important stuff in bas.h

Structs:

ble_bas_init_t- this holds all the data for initializing the service

ble_bas_t – this holds all the data for actually running the service

Functions:

ble_bas_init – this initializes the service, and inserts your vendor specific UUID, your service, and characteristics into the softdevice

ble_bas_on_ble_evt – this is called when the softdevice thinks something interesting has happened over BT that concerns the bas service.  For example, a client might write a new value to the server, or want to read a new value from the server.

ble_bas_battery_level_update – this actually updates the value of the characteristic with the new battery level.

So, all the stuff you need is in ble_bas_init_t and ble_bas_t, for the actual data about the services, and then you call ble_bas_init and it gets added to the softdevice.  After that ble_bas_battery_level update gets called every now and then, and if anything interesting happens bluetooth-wise to the service, ble_bas_on_ble_evt handles it.

100 Meters: Adding a Service and Characteristics

Of these, ble_bas_init and ble_bas_battery_level_update are the most interesting functions, so we should look inside of them to see what is going on.  Here we will be focusing on sd_ble_XXXXXX calls, which actually add things to the Bluetooth Low Energy SoftDevice- hence sd_ble.  later we will go back and look at what we are actually feeding these functions.

ble_bas_init is a small function , but it also calls batter_level_char_add which we will need to take a look at- it is something we did not see in bas.h, but it adds the actual battery level characteristic to the service.  The big ble_sd calls here are:

BLE_UUID_BLE_ASSIGN

this is just a macro to put the BLE_UUID_BATTERY_SERVICE information into a struct for later- if we want to make a custom service we will have to do it a different way, since our custon ble UUID needs to be added to the softdevice.

sd_ble_gatts_service_add

This adds our service.  There are some options here, but as long as you have this you will be able to see a service with the BLE_UUID_BATTERY_SERVICE if you look at your device with something like the nrf master control panel app.

inside of battery_level_char_add, a lot of other ble_sd calls happen- lets take a look!

sd_ble_gatts_characteristic_add

this actually adds our characteristic.  This is pretty useful, since we want it added.

sd_ble_gatts_descriptor_add

this actually adds the descriptor of the characteristic to the characteristic.

10 Meters: What goes into Softdevice BLE Calls

This is the real dive into the nonsense that is the NRF5 SDK.  I think that a flow chart/visual way of organizing this information is nice, although you have to zoom way in to read the text.  This is just another way of organizing the data, but instead of having to jump around a bunch of windows and files, I put it all in one place- like a cheat sheet.

These are meant to be read from the bottom up- look at the “what can you control” bar to see what you can change, the “where it comes from” bar to see how to actually make the change, and then the “where you can put it” bar shows where you need to put the variables in the sd_ble call.

sd_ble_gatts_service_add

text4926-7

This char has three layers explaining the arguments of the sd call.  The bottom layer is what you can change, the middle layer is how to generate the change, and the top layer is the actual argument and type that gets passed to sd_ble_gatts_service_add.

Here you can change the type of service between primary and secondary.  A secondary service is a service within a service, which seems fairly unusual.  You can also set the UUID of the service.  If you want to use a bluetooth SIG approved service, then you want to something like:

BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_BATTERY_SERVICE);

 

which is a macro that will fill the appropriate fields of ble_uuid with the info for a battery service UUID. NB, if you put weird characteristics inside of this service, the client may not be able to find the correct data, and you will not be compliant with the BTLE spec.

If you want to make your own custom service, you should do something like

sd_ble_uuid_vs_add(&acc_acce_uuid, &p_acc->uuid_type);
ble_uuid.type = p_acc->uuid_type;
ble_uuid.uuid = BLE_UUID_TYPE_VENDOR_BEGIN;

 

This will make a new vendor specific (vs) UUID and then you manually stuff the values into ble_uuid before passing it to sd_ble_gatts_service_add.  When the function is called, the softdevice will write to the pointer for the service handle.  This is important for later on, when you may want to modify the service- for example, adding a characteristic.

sd_ble_gatts_characteristic_add

Here you can change the service the characteristic is attached to, the characteristic metadata, and the structure that holds the characteristic value.  Just like sd_ble_gatts_service_add we also pass it a pointer to a handle that gets filled in by this function.  Unlike sd_ble_gatts_service_add there are about a million things that go in here, so each one will need its own diagram.

In the bas service example, we are adding a battery level characteristic to the service, so we should pass in the handle that was written by sd_ble_gatts_service_add.  We could pass in any service handle that was written by the softdevice, and it would add the service to that softdevice.

g6568.png

The characteristic metadata is how you control the properties of the characteristic, such as the read/write permissions and user description (a text description of the characteristic), but nothing to do with the value itself.  It has many many fields and some of those are actually other kinds of metadata structs.  The main groupings of structures are:

First, things that have to do with the properties of the characteristic, such as broadcast, indication, notification and read write permissions, writing with queued request and writing the characteristic user description, as well as the use of bluetooth assigned numbers to indicate the unit, exponent, and format, of the characteristic.  These are all about the actual characteristic and the value that it represents.  This is useful if you wanted to say that the value you are sending to the client is a uint16_t that represents micro-coulumbs for your battery measurement.

Second, the user description- this is really handy if you want to have a string associated with the value that you send that says “battery level”.  Here the important things are a pointer to a string buffer that holds the value, as well as the current length of the value, and the maximum length. Maximum length is important if the descriptor is re-written.  The last part of this grouping is the ble_gatts_attr_md_t, which controls how the description can be read and written.

The final grouping has to do with permissions around turning on and off notifications and indications, which live in the Server Characteristic Configuration Descriptor (SCCD) and Client Characteristic Configuration Descriptor (CCCD).  This post does a decent job of explaining it.

g6742

The last thing that goes into sd_ble_gatts_characterisitc_add is a structure that holds the characteristic value contains two main groupings.  The first is a pointer to a buffer that holds values of the characteristic, as well as information about the max length of the buffer, the size of each record in the buffer and the current offset.  The other grouping contains the metadata about r/w permissions.

sd_ble_gatts_descriptor_add

This is the last softdevicecall, and mercifully it is pretty short.  Just like the other calls, you give it the handle of the characteristic it belongs to, as well as a pointer to store the handle for the descriptor.  The only real data you need to set up for it is a ble_gatts_attr_t which is the same as the one used in the sd_ble_gatts_characteristic_add call.

1 meter view- Custom Service

Lets make a new service- this will document the major changes from bas to a custom accelerometer service with three characteristics that represent x, y, and z accelerations.  For the sake of clarity, we will assume there are functions that do things like get the accelerometer data.  I will show code snippets in the post, but you can also see the whole project here, commit 705deb.

First off, we need to add a custom UUID to our service in ble_bas_init.

ble_uuid_t ble_uuid;
ble_uuid128_t acc_acce_uuid = {{0xAA, 0xCA, 0x55, 0xAC, ..., 0xEF}};

err_code = sd_ble_uuid_vs_add(&acc_acce_uuid, &p_acc->uuid_type);

ble_uuid.type = p_acc->uuid_type;
ble_uuid.uuid = BLE_UUID_TYPE_VENDOR_BEGIN;

 

This adds our new made-up UUID to the softdevice, and then we pack the data into ble_uuid for later use in sd_ble_gatts_service_add.

Next up, we need to make some characteristics to belong to this service!  I will focus on only one characteristic here, because they are all acceleration data (just in different axes).

Compared to the battery level, we will want to make it a uint16_t instead of a uint8_t, give it a text description and add some nice units to our characteristic.

Lets start with making the value a uint16_t.  To change this in the GATT server, we will need to edit the ble_gatts_attr_t that represents the characteristic value that gets passed into sd_ble_gatts_characteristic_add.  In the code, that is called att_char_value.  To make the characteristic value a uint16_t instead of uint8_t, we need to do this:

attr_char_value.init_len  = sizeof(uint16_t);

attr_char_value.max_len = sizeof(uint16_t);

 

This will change the expected size of the record in the characteristic.  Now it is expected to be a uint16_t.  NB this only changes what the softdevice expects, so there are several other places in the code that will need to be changed to use the proper variable size.

Now for the text description.  This is handy, because your app might want to know what each characteristic represents, other than some crazy uuid.  This is pretty easy, since this information lives in the ble_gatts_char_md_t struct that we already passed to sd_ble_gatts_characteristic add.  We just have to change it by actually making a char buffer and passing the information about the user description size and max size into the struct, like this:

uint8_t user_desc[] = "ACCEL";

char_md.p_char_user_desc = user_desc;

char_md.char_user_desc_max_size = 5;

char_md.char_user_desk_size = 5;

 

We also have to give ble_gatts_add_descriptor an idea of the read/write permissions for the description.  We do this with a ble_gatts_attr_md_t

ble_gatts_attr_md_t user_desc_md;

memset(&user_desc_md, 0, sizeof(user_desc_md));

BLE_GAP_CONN_MODE_SET_OPEN(&user_desc_md.read_perm);

 

Although I could have set whatever permissions I wanted.

Finally, this all gets put into sd_ble_gatts_descriptor_add via the attr_char_value that holds all of the data.

Finally, lets add presentation format data.  We make a presentation format characteristic variable and put some values in it:

ble_gatts_char_pf_t accel_pf;

memset(&accel_pf, 0, sizeof(accel_pf));
accel_pf.format    = BLE_GATT_CPF_FORMAT_UINT16;
accel_pf.exponent  = 0;
accel_pf.unit      = 0x2713; //code for acceleration

 

then add it to the characteristic metadata:

char_md.p_char_pf = &accel_pf;

 

With this field filled in, it will automatically be added when the characteristic is added with sd_ble_gatts_add_characteristic.

0 Meters: Inspecting The GATT Server

Screenshot_2016-07-03-15-10-42

To check to make sure the device is working properly, I used the nrf master control panel app to connect to and interrogate the GATT server.  As you can see, everything is working!