Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Scott Mendenhall
Published

Tracking TV Stand

The Tracking TV Stand uses a Walabot to angle a monitor in the optimal angle for viewing depending on the audience in the field of view.

AdvancedFull instructions provided4 hours3,121

Things used in this project

Hardware components

Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
Walabot Developer Pack
Walabot Developer Pack
×1
Unitek USB3.0 4-Port Hub
×1
Power Sonic Model PS-640 F1 6 Volt 4.5 AmpHr Battery Supply
×1
Servos (Tower Pro MG996R)
Personally modified Futaba S3003 for continuous rotation. If using a different brand of servo research the number of spline teeth for your attachment of the Servo Spline Gear.
×1
Servo Spline Gear
32 Pitch 25T 12 Teeth (Acetyl). After testing, it appears that metal would be the best material for the gears.
×1
Plain Bore Gear with Hub
32 Pitch 48 Teeth (Acetyl). After testing, it appears that metal would be the best material for the gears.
×1
Computer Monitor
This additional monitor will be placed on the turntable and rotate on the TV stand. Its size is for the Technical Demonstration.
×1
M5X30 Bolt and Nut
×4
Nylon Spacer
OpenBuilds Nylon Spacer
M5X6mm
×8
Delrin V Wheel Kit
OpenBuilds Delrin V Wheel Kit
The exact parts are not these, but they are very similar.
×4

Software apps and online services

Sublime Text
Or any other generic text editor.

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

basePlate

This is the plate that the 4 stands and clamps slot into. There is also a spot for the potentiometer and servo to be held.

baseClamp

This holds the wheel bearing assembly and connects it to the basePlate.

baseStand

This is a generic stand that slots into the basePlate.

baseStandMagnet

This is the stand with a slot for a metal disk to hold the Walabot magnetically.

potentiometerAdapter

This part connects the gear of the turnTable to the potentiometer.

turnTable

This is the top rotating surface.

Schematics

Diagram

Use this for wiring the electronics.
File missing, please reupload.

Code

trackingTV.py

Python
This is the code that runs on the Raspberry Pi
from imp import load_source
import wiringpi
import math
import time

servo = 1                   # The pin the servo signal wire is connected to
totalDegrees = 130          # Range of the servo +-(130/2)

lastAveragePosition = 0     # Previous average position of targets from Walabot
lastMoveTime = time.time()  # When the servo was moved last
minimumAverageDelta = 10    # Amount of degrees required for servo to move
maximumStillTime = 10       # Maximum amount of time servo will be still for
servoSpeed = 20             # Speed of servo in degrees/second (only tells servo when to turn off after setting position)

turntableAxisOffset = 10    # cm's of space between axis of turntable and Walabot origin point
                            # Allows angles to be calculated for direct aiming of turntable

# Sets up the servo pin with wiringpi library

def startServo():
    wiringpi.pinMode(servo, wiringpi.PWM_OUTPUT)
    wiringpi.pwmSetMode(wiringpi.PWM_MODE_MS)
    wiringpi.pwmSetClock(384)
    wiringpi.pwmSetRange(1000)

# Sets the position of the servo (degrees)

def setServo(deg):
    value = deg / totalDegrees / 2 + 0.5
    wiringpi.pwmWrite(servo, int(123.6 * (value) + 14 * (1 - value)))

# Stops the servo from moving

def stopServo():
    wiringpi.pwmWrite(servo, 0)
    wiringpi.pinMode(servo, 0)

# Connect to the Walabot, if failed wait and try again

def connect():
    while True:
        try:
            bot.ConnectAny()
        except bot.WalabotError as err:
            time.sleep(1)
        else:
            print("Connected")
            return

# Setup Walabot profile and scanning area

def setup():
    bot.SetProfile(bot.PROF_SENSOR)
    bot.SetArenaR(10, 300, 2)
    bot.SetArenaTheta(-1, 1, 1)
    bot.SetArenaPhi(-40, 40, 2)
    bot.SetThreshold(60)
    bot.SetDynamicImageFilter(bot.FILTER_TYPE_NONE)
    print("Configured")

# Begin Walabot calibration

def calibrate():
    bot.Start()
    bot.StartCalibration()
    print("Calibrating")
    while bot.GetStatus()[0] == bot.STATUS_CALIBRATING:
        bot.Trigger()
    print("Ready")

# Disconnect Walabot

def disconnect():
    bot.Stop()
    bot.Disconnect()
    print("Disconnected")

# Main function
# Scans for targets
# Averages position
# Moves servo to position

def function():
    global lastAveragePosition, lastMoveTime

    # Get targets from Walabot
    
    bot.Trigger()
    targets = bot.GetSensorTargets()
    average = 0
    count = len(targets)

    # Find average position of all targets
    
    for target in targets:
        angle = math.degrees(math.atan(target.yPosCm / (target.zPosCm + turntableAxisOffset)))
        average += angle

    # If any targets found, determine if should move the servo
    
    if count != 0:
        average /= count
        delta = abs(average - lastAveragePosition)

        # Only move servo if targets moved at least minimumAverageDelta degrees
        # Or it has been >= maximumStillTime since the last servo move

        if delta >= minimumAverageDelta or time.time() - lastMoveTime >= maximumStillTime:
            print("Move: " + str(average) + "\n")
            lastMoveTime = time.time()
            startServo()
            setServo(average)
            time.sleep(delta / servoSpeed)
            stopServo()
        lastAveragePosition = average

# Main code start
# Setup Walabot library

bot = load_source("WalabotAPI", "/usr/share/walabot/python/WalabotAPI.py")
bot.Init()
bot.SetSettingsFolder()

# The Walabot setup process

connect()
setup()
calibrate()

# Setup WiringPi library and servo

wiringpi.wiringPiSetup()
startServo()

# Make sure turntable starts at 0 degree position

setServo(0)
time.sleep(2)
stopServo()

# Main loop execute main function repeatedly

try:
    while True:
        function()
except KeyboardInterrupt:
    stopServo()
    disconnect()
    

Credits

Scott Mendenhall

Scott Mendenhall

3 projects • 8 followers
Mechanical Engineering Student at UNC Charlotte

Comments