Repair/hack of Vivo motorized TV mount FD-55

Note: Click on the pictures to embiggen.

The Vivo FD-55 TV mount holds a flat panel TV (LCD, plasma, etc) and will fold it "flat" against the ceiling, and then lower it to a customizeable viewing angle when commanded by the infrared remote.

The unit is sold by Amazon (and probably others) and sells for about $150 US.

The Vivo was flaky right out of the box, and then a power failure seems to have killed it, as after, it no longer responded to the remote at all. The directions say you can manually get it to move by lifting the swing-arm a tiny bit, but not only did this not work, I could see no mechanism where it ever worked.

The unit as represented in the company's advertising.

I can't supply a photo of the unit in it's expanded state because mine won't move anymore. Yet.

Photo of the unit with cover removed. This side normally faces the ceiling.

Close-up of the gubbins. Power input and IR remote receiver on left, potentiometer for location feedback is the small board next to the big gear, main board with computer and motor drivers, and lastly, DC motor on the right.

Close-up of the "main board". I don't feel like debugging this to figure out why it no longer responds to the remote control.

Test lash-up (in its final form). The big orange/black clamp is holding the actual TV mount to the bottom of my dining room table.

Close-up of the final test lash-up. The visible boards are: 12v regulator on perf board, radio receiver (has two blue relays), current sensor (small blue board on the left), L298N H-bridge board (red pcb), Arduino Nano (small blue pcb on the right). (not shown) 45 ohm speaker.

View showing the test lash-up with the TV mount clamped to the table. The mount has been lowered. Attached to the mount is a 7lb barbell, to simulate the weight of my TV.

Controlling the mount is straight forward. To lower the TV, apply power to the DC motor so it unwinds the nylon strap, and read the value of the feedback pot. Turn off the power when the feedback pot value reaches the chosen limit.

To raise the TV, reverse the power to the DC motor, and read the feedback pot. Shut off the power when the pot says we've reached the top.

Additional complications: it would be nice if the user could specify the angle to which to drop the TV. It would be nice if the unit didn't catch fire if something jammed the works and the motor drew too much current.

To accomplish all this, I sourced the following items:

  • Arduino Nano -- plenty big enough for a simple project like this. Literally any microcontroller board would work for this, as long as it has two A-D inputs, two digital inputs, and 3 digital outputs. An ESP32 would be massive overkill. I had a Nano in my junkbox.
  • L298N H-bridge -- because relays are so last century. About $3 from some random eBay vendor.
  • eMylo 2 channel radio transmitter and receiver -- two buttons and two relays, for "up" and "down". About $18 from some another random eBay vendor.
  • Seeed Studio "ACS70331 2P5U3" 2.5A DC current to voltage converter -- to sense motor current. I bought one for about $15 from Amazon.
  • 7812 12v regulator -- the power supply for the TV mount is 24VDC, so we need to step that down for the 12v radio module and the 5v Arduino. I had one in my junkbox.
  • small speaker for beep feedback. I have some 45ohm speakers in my junkbox. Later, I discovered I had no room for this speaker, so I cannibalized the piezo beeper from the original circuit board and used that for user feedback.

Software Description

The code is simple. Listen for the button presses (via the radio link, but we can ignore that complication), and move as the user commands. If the user asks the impossible (move up above the top, or down below the bottom), ignore the command. Once we start moving, monitor the following and stop if any are true:

  • The user presses either button.
  • up limit is reached if moving up.
  • down limit is reached if moving down. (There are two down limits, so stop at whichever is the higher one.)
  • too much time with motor on. Full swing from top to bottom is less than 90 seconds, so if we hit 90 seconds, something is broken, so stop.
  • too much motor current. Lifting my simulated TV, the motor draws just over 100mA, so a 200mA current limit should be sufficient.

We do need to allow the user to set the angle at which they want the TV to stop. We also need a way to erase that limit, so that we can move the TV lower than that limit (within the ultimate limit of the max travel of the machine). The radio link won't allow a button press less than about 80msec, so things like doubleclick are impossible. I chose extra long button presses as the way to signal changing the limits. An extra long press of the "up" button clears the limit, and an extra long press of the "down" button sets the limit to the current position of the TV.

Filtering noisy signals

The output of the ACS712/ACS725/ACS70331 current to voltage converter is quite noisy (relative to the small currents I'm measuring), so I filter the readings using a infinite-impulse-response (IIR) filter, because this is easy to implement and takes little storage.

Referring to the code excerpt below, the first line defines a constant that gives us the "depth" of the filter. A bigger number is more filtering, but 5 is the maximum. The number must be an integer between 1 and 5. An value of IIR_EXPONENT greater than 5 could result in the unsigned integers overflowing. You could have greater filtering if you used longs or unsigned longs, but eventually the time delay of the filter will bite you.

The second line declares the variables.

The lines inside the loop function do the following:

  • read the analog voltage representing the motor current.
  • subtract from the running total 1/N of the total, where N is 2 ** IIR_EXPONENT, in this case 2 ** 5, or 32. Result: sum = sum * 31/32
  • add the latest reading to the sum.
  • set the average to the sum divided by number of samples, which is 2 ** IIR_EXPONENT, or 2 ** 5, or 32, so average = sum / 32;

#define IIR_EXPONENT 5
unsigned int MCurrentRaw, MCurrentSum, MCurrentAve;
void loop() {
  MCurrentRaw = analogRead(M_CURRENT);
  MCurrentSum -= MCurrentSum >> IIR_EXPONENT;
  MCurrentSum += MCurrentRaw;
  MCurrentAve = MCurrentSum >> IIR_EXPONENT;
  . . .

Because the filter code uses integer arithmetic and bit shift operations for multiply and divide, it runs quickly, even on a low powered CPU like the Atmega 328. There is no need for floating point arithmetic since this calculation does not need super duper accuracy.

Reading button presses

One wierdness involved reading the "buttons" (really, relay closures on the wireless receiver, but they look like buttons to the Nano.) I was using the Button2 library, which I have had good luck with before (with an ESP32), but for some reason, with the Arduino Nano, Button2 was extremely flaky. I ended up writing my own very stripped down version of Button2, which doesn't try to recognize "double-click" and "triple-click"; it just recognizes a keypress and reports the duration of the press.

Giving feedback to the user

It's nice to give the user feedback that his commands have been recognized. I was originally using the Arduino "tone()" function to make different pitched beeps for different conditions (move, stop, store and clear user preference), but the speaker I had in mind wouldn't fit inside the enclosure. In fact, pretty much no speaker made would fit in that enclosure.

I decided to go with beeps from a "Sonalert"-style beeper. Conveniently, there was one I could cannibalize off of the original circuit board. I re-coded the sound feedback to beep different durations and numbers of beeps to let the user know that different things are happening. It's not intuitively obvious what the different sounds mean, but I think that just the fact that they are different is valuable.

The code

The entire code for the project is here.

Circuit Description

Power is the most difficult problem to solve in this project, since there are three voltages in play: 24v for the DC motor, 12v for the radio receiver, and 5v for the Arduino, the current sensor, and the H-bridge logic. I decided to use a 7812 regulator to make the 12v as we're not talking about a lot of current. A small clip-on heat sink is sufficient to keep the 7812 temperature within reason.

The L298N H-bridge board has a built-in 5V regulator for it's logic, and I decided to use this to also supply the 5V for the Arduino Nano and the current sensor (and the position sensor pot). The instructions for the L298N board warn against installing the jumper that connects the 5V regulator input to the "high" voltage input of the L298N board if said voltage is above 12v, though I think this warning is excessive. But since I had a source of 12v, I ran a wire from my 12v source over to the jumper pin on the L298N board that feeds the input of the 5v regulator, so now it's "happy".

The position pot inside the TV mount needs to be hooked across 5v and ground, with the wiper feeding one of the A-D inputs of the Arduino Nano, so it can determine the position of the TV mount. Another analog input on the Nano reads the output of the ACS725 current sensor, which is a 0 to 5v signal representing 0 to 10 Amps. I'd prefer a more sensitive scale, but I go with what I can buy quickly and cheaply on Ebay and Amazon, so a 10A scale is what I ended up with. (Update I found an ACS70331 2.5A current sensor on Amazon, which is four times the sensitivity of the ACS725. This gives much better readings.)

The rest of the circuit is just plugging the stuff together. The only reason I chose A7 and A6 for my analog inputs is because they're next to 5V on a Nano, so I could make a 3 pin connector to make the wiring easier to deal with. Similarly, Ground and D2 through D6 are all in a row, so a 6 pin connector body makes the wiring neat(er).

The finished unit

I know it looks like a dog's breakfast in there, but it's actually fairly organized. I screwed down the L298N board, the current sensor board, and I velcro'd down the eMylo radio receiver. I used the original input jack pcb, and I sliced the motor snubber off of the original PCB and used that bit as well (upper right above the motor in the above photo.)

The Nano is hard to mount on a good day, seeing as how it has teeny tiny "mounting holes" that are too small for any screw I'm likely to own, so I drilled 6 holes in a scrap of vinyl and "mount" the nano by plugging the programming port into the block of vinyl.

With the USB cable attached to the Nano, and that held by a tie-wrap, the Nano is held pretty well.

I'm especially proud of the wiring harness. Being able to crimp the .025 square pins and sockets on to wires enabled me to build a custom harness, instead of just using ready-made jumper wires to lash the thing together.


Q. Will you make one for me?

A. No, I'm retired and so not interested in a job.

Q. Why not use the original IR remote control?

A. I figured that reverse engineering an IR protocol was a lot more work than just buying a two channel radio setup on Ebay for $7. Call me lazy if you like.


This is just my "build log". I don't claim that building this is safe or recommended.

Soldering irons are dangerous, be careful. Oh, and don't eat the solder.

William Dudley
June 20, 2020