Flip-Top Coffee Table

 


Design

Almost a year ago I picked up a slab of White Oak from my friend Suman. I was saving it for a special project, but there was a problem with the slab: it was extremely rough looking, like someone had cut it with a chainsaw–not with an Alaskan chainsaw mill, just freehand. 

So it was going to take a lot of work to turn the rough slab into a coffee table. But not just any coffee table, but the table of my dreams: one with a top that can flip over to the underside, where there’ll be an upholstered cushion, AND it’ll be automatic with the push of a button.

I drew up many iterations. I didn’t know if I could even make the flip top mechanism work! When it comes to furniture design, I always think aesthetics should come first, and I figure out the build process after. The designs were complicated, some were just plain groady, but I knew I needed to create a piece of fine furniture. 

Trimming the Slab

For the top of the coffee table, I had the one large slab. It's very common to use the entire slab including the live edge, but that wasn’t going to look very good with the more modern and refined aesthetic I was going for. So, I wanted the live edge gone.

I know you’re probably thinking: “You’re removing the character!” But of all the adjectives in woodworking, I find “character” is one of the most misused. I don’t like knots. They’re not to be confused with curl, burl, crotch, quilting, feathering or any other type of figuring in wood. Character and good design are not the same thing. Character is built over a lifetime of use, not something you can force into a design.

Before milling the slab down to thickness, it's best to trim it down first to get it as close to final dimension as possible. I used a track saw to trim it down to rough dimension, which included cutting off the live edge. Not flat slab tabletopIt's quite popular to use a router sled to flatten a slab, but my slab was so far off of being flat that I thought it would take forever with a router sled. Instead I grabbed the power plane, which may seem like a crude choice to some people, but I found that although arduous, it was actually faster in the end.

I managed to get the slab even flatter than I honestly expected it would be. But the slab twisted just a little bit overnight. It wasn’t too surprising, since I removed probably ¾” or more of thickness. 

It's always good to let any wood that you milled down to acclimatize to its new thickness. This is because you can remove stresses, and in doing so, add new stresses that can take time to work out. You can also release trapped moisture, and the wood needs to re-acclimatize to an equilibrium moisture content. 

It was at this point that I decided to crosscut the slab in half because what’s better than a coffee table with a flip top? A coffee table with TWO flip tops! That way I can have my feet up on a cushion on one side, while the other side can be normal.

Table Legs

It was time to start making the base of the coffee table, so I began with the legs. Although the final design looks quite slender because of the heavy curvature, I needed to start with a 4” by 4” square leg blank. 3D printed template to assist cutting out leg curvatureI don't have a CNC, but I do have a 3D printer, so I designed a template to print and assemble for making the curvature on the legs. First I traced the template with a sharpie onto my leg blanks onto adjacent sides, and I cut out the first side roughly on the bandsaw. I then double-sided taped the offcut back into place to cut out the adjacent side. By taping the first side back on, this created a stable surface so I didn’t have to balance a curve on the bandsaw table.

Going against the grain when pattern routing can land you in the emergency room, but there was no way around it, I had to go severely against the grain while trimming half of the legs. I’d wanted the large template routing bit for probably years, and I was so glad to have it because it had no problems going against the grain, and I was pattern routed the desired curve with the template double-sided taped to the leg.

The inside of the leg features a curve at a 45° angle to the two faces I routed. Using a jig to hold the leg at a 45° angle on the bandsaw, I was able to cut this inside curve following the lines created by the template bit from the router table. 

To clean up these curves, I used my spokeshave. My first instinct was to use the spindle sander, but it was difficult for me to see my line because the workpiece faced away from me as I used the sander. With the spokeshave, I could easily see where I needed to shape to get the desired result. Furthermore, a spindle sander is usually only 80 grit, so that still means I’d still need to smooth more after using the spindle sander. With the spokeshave I got a surface that was nearly finish-ready.

The challenging part of my design for the base is that the legs meet the aprons with a curve. It's fairly straightforward to get a tight-looking joint when the joint face is flat, but a curved face is not so easy. So I needed to 3D print another template for the ends of the apron to join the inside curve of the legs. By using my 3D model, I was able to print an exact negative curve for me to use as a template to trim the end of the apron at the router table. After which, the curve matched the leg exactly.Table legs meet the base's aprons with a curve

Joinery

Because the joint faces were curved, I couldn't simply stick the domino up to the legs and aprons, or use a dowel jig for that matter. Luckily the pantorouter, a Matthias Wandel design, or any mortising machine typically doesn't need to reference off of the joint face itself. I used the pantorouter to make some 2” floating tenons to join the aprons to the legs. The floating tenons themselves were made from scrap white oak that I planed down to thickness and finessed with the smoothing plane to get a tight fit.

I did use the Domino to join a simple divider piece between the long aprons that divides the coffee table into its two halves. 

Aprons 

It was at this point that I decided to shape the legs and aprons a little bit further. I had created an offset between the apron and the outside of the leg, and I wanted to chamfer the inside of the leg so the offset would blend into the apron with a curved facet. I created this with a spokeshave, since the chamfer starts heavy at the top and gets lighter as it goes down to the bottom of the leg. I wouldn't have been able to do this with a router.

The bottom of the apron got a curve that I used a paper template to trace out. This was not a simple radius, but rather a skewed curve, and this made it easier for me to model it in SketchUp and print off a paper template to trace it onto the apron. I rough cut this curve on the bandsaw, and shaped it with the spokeshave again to the line.

The apron then got a second curve, this one more like a facet on the outside face. Again I modeled it in SketchUp. I printed off another paper template with this curve to line it up perfectly with the rest of the apron, traced it with a pencil, rough cut it with the bandsaw, and finally smoothed it with the spokeshave.

I didn't feel like the design was quite right, now that I was looking at the table in real life. For some reason, it looked like there should have been a tabletop on top of the legs and apron, rather than inset within it. To make it look more intentful, I trimmed down the top of the aprons and middle divider so the top of the legs would be slightly raised. I then put chamfers around the top edges of the legs, and felt like I achieved what I was going for.  

Tabletop

Filling tabletop knot with epoxyTurning my attention back to the top, or rather tops in my case, there was one big knothole that I didn't like, but had to include because I couldn’t cut the top around it. So I mixed up some black epoxy, filled the knothole, and waited for it to cure. A few days later I was able to mount the tops in a router sled and take them down to final thickness. Luckily, the tops didn't move that much after rough planing them with the power plane, so I only needed to take off about a 16th of an inch to get the tops perfectly flat.

Now I was able to trim the tops to final size, which also included trimming off the outside corners so that they wouldn't intersect with the inside of the legs. 

Texture

The table looked a little too formal for my taste, and there was a technique I'd always wanted to try. I thought it would look really good in this instance, because it might make it look more inviting. Nick Pedulla designed a desk that inspired me to look at different ways to texturize wood. What I especially liked was the texture he added to the aprons. This sent me down a rabbit hole of different techniques and I found a channel called “On Wood,” which is filled with different types of Japanese carving techniques, and gave me the idea to sweep the texture in the direction of the apron curve. I settled on a technique called Naguri, picked up a set of Narex Firmer Gouges, practiced for 15 minutes, then dove right in to creating this texture on the curved facet on the aprons that I had shaped prior.Naguri Japanese wood carving technique

Glue Up

I had to make a bunch of recesses in the middle divider, as well as one of the long aprons, so that several wires could be fed through channels and be hidden by 3D printed plates in the end. It was easier to do this now before it was glued up, because it would be difficult to hold the router once the base is one solid piece. 

I glued up a pair of legs to a long apron first, and then once that was dry, glued up the other pair of legs to the other long apron. This will allow me to just focus on gluing together these two halves with the short aprons and the middle divider. Dividing the glue up into smaller portions allows you more time to get clamps on before the glue sets up.

The glue up was mostly uneventful, but it was a little tricky since those curved joints caused the aprons to want to shift as the clamp pressure was put on it. I resolved this by clamping the aprons to my workbench as I put pressure across the legs.

There was one more curve that I wanted to shape on the legs, but I had to wait until the base was glued up, since shaping this curve would have eliminated the area that I’d need to put the clamps on. I discovered this issue in the design phase, when I envisioned myself clamping together the base when gluing up.

To make this shape, I printed out a paper template of the curve to trace onto the legs. Because the base was already glued up, I couldn't bring the legs to a machine to cut off the shape, so I had to use the power plane to cut away most of the material until I was close to the line. Then I grab the spokeshave, to refine the curve down to my line.

Finish

First time finishing White Oak with Osmo PolyxI broke one of my main rules in woodworking for the finishing stage: always test a new combination of wood and finish. I’m very familiar with regular Osmo Polyx and I like how easily it applies. This was also not the first time I’d used white oak. But it is the first time I used them together. In my experience, Osmo tends to not darken or yellow as much as other hard wax oils, so I was pretty surprised how dark the oak turned, and I regretted not testing the finish first. If I had, I probably would have opted for a different finish to make it look even more natural. I’d gotten very used to the look of natural white oak at this point and wanted it to remain the same. But I had to push on.

Flip Top

For the coffee table top to actually flip, I needed some mechanical components. Because I wanted the top to rotate very smoothly, I installed some pillow block bearings on each top. A hardened steel shaft goes through these pillow block bearings and gets mounted to the aprons in the base with a flange to secure it. These bearings are super smooth and the top flips very easily. For the flipping action I needed a motor. I didn't need the top to spin very fast, but it is kind of heavy, so I wanted something with a lot of torque. I got a Worm Gear drive motor rated at 10 RPM at 12 volts. I was able to mount the motor to the bottom of the coffee table top and connect it directly to the shaft that's supported by the pillow block bearings.

To make the top flip automatically, I need some electronic components. I wanted the top to flip with the push of a button–even more, I wanted the button to be completely invisible. I bought a capacitive touch sensor for each side so that when the touch sensor detects a change in capacitance from your finger, it sends a signal. To receive this signal I needed a microcontroller. The most common and easy to use microcontroller for this is the ubiquitous Arduino, which allows you to program a code to control a series of inputs and outputs. Simple.Coffee table touch sensorTo make the Arduino talk to the motor, I needed a controller in between. This is called an H Bridge motor controller, and it’s used to convert a signal from the Arduino into a simple voltage that the motor can understand.  That way I could then program the Arduino to start spinning the motor when it detects that the capacitive touch sensor has been triggered.

To make the motor stop spinning, the Arduino needs to know when the top reaches its angular destination. For this I used a hall effect sensor, which can detect a magnetic field. This gets mounted to the underside of the top, and I recessed a small magnet into the divider so that once the top is level, the hall effect sensor will detect the magnet. This sends a signal back to the Arduino so it knows when to stop spinning the motor.

Because there would be wires going from one top to the other, the top could only spin in one direction. It had to flip one way and flip back in the opposite direction because it can't continually spin in one direction, otherwise the wires would bind up. Because of this, I needed the Arduino to know which side of the top was facing up at all times. So I mounted an accelerometer to the underside of the top telling it which side was up. This prevents it from getting confused and sending the top the wrong way, which could result in broken wires.

The motor itself wasn't enough to keep the top in place when it's not spinning. In fact, it could really damage the motor if the top starts to spin when the motor isn't. I needed a way to lock the top in place when it's not spinning.Linear ActuatorI mounted a linear actuator underneath the top, which drives an 8 mm pin from the top into the apron. I fabricated two escutcheon plates: one for the top side, and one for the divider side, so that the linear actuator doesn't receive any stress keeping the top locked. The load is spread between the pin and the escutcheon plates.

A linear actuator is really no different than a regular DC motor. In fact, it is a DC motor with a rack and pinion to convert a rotational action into a linear action. Therefore, the linear actuator also needs an H Bridge controller. Luckily the one I bought had two channels so that I was able to use one half for the drive motor and the other half for the linear actuator.

To summarize the whole system: when someone triggers the capacitive touch sensor, the first thing the Arduino does is retract the linear actuator to unlock the top. The second thing it does is determine which side is up with the accelerometer. The third thing is that it starts spinning, and now it can do so in the correct direction. The fourth thing that happens is the hall effect sensor detecting the magnet as it completes the rotation, so that when it's level it can stop moving the drive motor. The final thing it does is lock the top back in place with the linear actuator. 

If you're curious, here is the code that I wrote to program the Arduino:



#include
const int MPU=0x68; 
int16_t accel;
int16_t accelArray[10];
static uint32_t lastAccelTime = 0;
#define accelAvgTime 100
int16_t avgAccel;
int32_t sum = 0;

int IN1 = 5;
int IN2 = 6;
int actIN1 = 9;
int actIN2 = 10;
int but = 2;
int hallPin = 8;
int i;
boolean stateCap, stateHall, spinCW, spinCCW;
int hallCount;
//previous spin state - HIGH for CW, LOW for CCW
boolean prevSpin = LOW;
boolean prevStateHall = LOW;
#define BOUNCE_TIME 50
#define RAMP_TIME 5
#define DEC_CW_RAMP_TIME 7
#define DEC_CCW_RAMP_TIME 2
#define ACT_TIME 500
static uint32_t lastPressTime = 0;
static uint32_t lastRampTime = 0;
static uint32_t lastHallTime = 0;

void setup() {
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(actIN1, OUTPUT);
  pinMode(actIN2, OUTPUT);
  spinCW = LOW;
  spinCCW = LOW;
  hallCount = 0;

  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  
  Wire.write(0);    
  Wire.endTransmission(true);
}

void loop() {
   // read cap sensor
   stateCap = digitalRead(but);

   // read hall sensor, debounce, and count
   stateHall = digitalRead(hallPin);
   if (!stateHall && !prevStateHall && millis() - lastHallTime > BOUNCE_TIME) {
     hallCount = hallCount + 1;
     lastHallTime = millis();
     prevStateHall = HIGH;
   }
   else if (stateHall && prevStateHall && millis() - lastHallTime > BOUNCE_TIME) {
     prevStateHall = LOW;
     lastHallTime = millis();
   }

   

  //run every 100ms
  if(millis() - lastAccelTime > accelAvgTime) {

    // read accelerometer ever 100 ms and take rolling average
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);  
    Wire.endTransmission(false);
    Wire.requestFrom(MPU,12,true); 
    
    lastAccelTime = millis();
    //shift existing array entries to create space for new entry
    for (int i = 9; i > 0; i--) {
      accelArray[i] = accelArray[i - 1];
    }
    //read current accelerometer value
    accel = Wire.read()<<8|Wire.read();
    accelArray[0] = accel;
    //take average of array
    sum = 0;
    for (int i = 0; i < 10; i++) {
        sum += accelArray[i];
    }
    /*
     avgAccel is the useable number for determining whether the top is up or down
     In reference to the text on the GY-521, if the value is positive, then the board
     is upside down. If the value is negative, then the board is right-side up.

     Positive values are when top is up
     Negative values are when cushion is up
     */
    avgAccel = sum / 10;
  }
   
   
   //Flip CW
    if(stateCap && !spinCW && !spinCCW && avgAccel < -100 && millis() - lastPressTime > BOUNCE_TIME){
      lastPressTime = millis();
      spinCW = HIGH;

      //unlock actuator
      i = 0;
      while (i <= ACT_TIME) {
        if(millis() - lastRampTime > 1) {
          lastRampTime = millis();
          analogWrite(actIN2, 255);
          i++;
        }
      }
      analogWrite(actIN2, 0);

      //start spinning CW
      i = 0;
      while (i <= 175) {
        if(millis() - lastRampTime > RAMP_TIME) {
          lastRampTime = millis();
          analogWrite(IN1, i);
          i++;
        }
      }
    }

    //stop spinning CW
    else if((hallCount > 0) && spinCW && !spinCCW && millis() - lastPressTime > BOUNCE_TIME){
      lastPressTime = millis();
      spinCW = LOW;
      //prevSpin = HIGH;
      hallCount = 0;

      //stop spinning CW
      i = 175;
      while (i >= 0){
        if(millis() - lastRampTime > DEC_CW_RAMP_TIME) {
          lastRampTime = millis();
          analogWrite(IN1, i);
          i--;
        }
      }
      //lock actuator
      i = 0;
      while (i <= ACT_TIME) {
        if(millis() - lastRampTime > 1) {
          lastRampTime = millis();
          analogWrite(actIN1, 255);
          i++;
        }
      }
      analogWrite(actIN1, 0);      
    }  

   //start flip CCW
    if(stateCap && !spinCW && !spinCCW && avgAccel > 100 && millis() - lastPressTime > BOUNCE_TIME){
      lastPressTime = millis();
      spinCCW = HIGH;

      //unlock actuator
      i = 0;
      while (i <= ACT_TIME) {
        if(millis() - lastRampTime > 1) {
          lastRampTime = millis();
          analogWrite(actIN2, 255);
          i++;
        }
      }
      analogWrite(actIN2, 0); 

      //start spinning CCW
      i = 0;
      while (i <= 124) {
        if(millis() - lastRampTime > RAMP_TIME) {
          lastRampTime = millis();
          analogWrite(IN2, i);
          i++;
        }
      }
    }

    //stop flip CCW
    else if((hallCount > 1) && !spinCW && spinCCW && millis() - lastPressTime > BOUNCE_TIME){
      lastPressTime = millis();
      spinCCW = LOW;
      //prevSpin = LOW;
      hallCount = 0;

      //stop spinning CCW
      i = 124;
      while (i >= 0){
        if(millis() - lastRampTime > DEC_CCW_RAMP_TIME) {
          lastRampTime = millis();
          analogWrite(IN2, i);
          i--;
        }
      }

      //lock actuator
      i = 0;
      while (i <= ACT_TIME) {
        if(millis() - lastRampTime > 1) {
          lastRampTime = millis();
          analogWrite(actIN1, 255);
          i++;
        }
      }
      analogWrite(actIN1, 0);
    }
}

 

Ottoman

Connecting all of the motors, wires, electronics etc. where I wanted them to be discreet forced me to route a bunch of strange and complicated channels, which I had to stuff the wires into, under the divider and behind an apron. Not the most elegant thing I’d ever done.Electronic components of coffee tableThe C-channel got screwed into the bottom of the top next to all the electronics I already mounted. But everything getting mounted would be covered with an upholstered cushion. 

I know it sounds like a bad idea to put electronics in an inch of foam, but the components produce no perceivable heat when idle. Plus, there’s an off switch for the whole thing, and the plan is to keep the coffee table turned off when I’m not flipping it. 

To fulfill my ottoman dreams, I had to make it all soft and squishy, so I went down the road of a whole new craft: sewing and upholstery. I’m pretty proud of how my cushions turned out. 

Finished Flip-Top Coffee Table

I moved my coffee table to its new home in the living room and tested it out…and the cushions seemed to be ever so slightly rubbing on the aprons. That was enough to mess up the flipping. I thought it was the motor slipping on the coupler, so I replaced it with one with a set screw, but then that didn’t work, so I tried reprogramming the coffee table (totally a normal thing to say). In the end I got it near perfect, and I was so sick of the electronics that I decided it was high time to move on with my life, and near perfect was good enough for me. Upholstered cushions on flip-top table 

Project Parts

 

DeWalt Cordless Powerplane: https://geni.us/mahJTJ9

Pattern Routing Bit: https://geni.us/R7umB

Pantorouter: https://woodgears.ca/pantorouter/ (not affiliate)

Narex Firmer Gouges: https://lddy.no/1gj1j

Pillow Block Bearings: https://geni.us/BJNx

8mm Shaft: https://geni.us/BMFURuO

Flange Coupler: https://geni.us/WZEM13

Motor w/ Worm Drive Gear Box 10RPM: https://geni.us/q7Fdjg

Capacitive Touch Sensor: https://geni.us/LVLyU

Arduino Nano: https://geni.us/XmbZB

Motor Controller: https://geni.us/AYDHO

Hall Effect Sensor: https://geni.us/AFA2nNW

Accelerometer: https://geni.us/80BXW

Linear Actuator: https://geni.us/B64qc

Links Below ↓

Back to Furniture Projects