Anth's Computer Cave

Rotating Sensor Mast

The latest project in the cave is this 360 degree rotating sensor mast for our robot, AAIMIv2. Today I'll share the details of the build, as well as the code to run the mast.

The new sensor mast for my robot. Picture: Anthony Hartup
The new sensor mast for AAIMIv2. Picture: Anthony Hartup

Many of my robot's functions involve taking measurements at numerous accurate angles to learn about its environment. AAIMIv2 can turn on her wheels accurately enough for this task, but there are several good reasons to have a dedicated sensor mast.

Firstly there should be significant increase in battery-life using one small 5V motor to turn the mast rather than the two 24V motors that drive the wheels.

More importantly, I need AAIMI to know exactly where it is within its environment. Each turn the robot makes adds a minute element of error to these calculations, so the less physical 360 degree turns it needs to perform, the more accurate the calculations will be.

The Build

I have used mostly recycled parts, as usuall. I salvage the stainless steel shaft from an inkjet printer, along with matching bearings.

The base of the sensor. Picture: Anthony Hartup
The base of the sensor. Picture: Anthony Hartup

I made the base of the unit from a piece cut from a CD ROM drive. Underneath the steel plate, the main bearing is drilled into a small square of 3mm MDF timber, which can adjust several mm within the plate.

The entire unit is only fixed on one side and can swivell sligthly to adjust the verticle angle of the shaft.

The timber bearing plate. Picture: Anthony Hartup
The timber bearing plate, right-click and select "view image" or "open in new tab" to see larger image. Picture: Anthony Hartup

The gears came from one of my printer teardowns. One fitted the motor well enough to require just a drop of glue to hold it in place. The other was too large for the shaft, but the sleeve of a masonry dyna-bolt bridged that perfectly.

The new sensor mast for my robot. Picture: Anthony Hartup

The lower bearing is underneath the robot held in place by a large, slightly cupped washer. This allows a few milimetres of adjustment. In the image above I have adjusted it fully to the left to demonstrate.

The new sensor mast for my robot. Picture: Anthony Hartup

The motor is a 5V stepper motor of the same type I used for driving the wheels of my previous robot, AAIMIv1. These motors cost about three bucks on Ebay including the controller. It is geared with a 40 to 28 ratio and turns the mast a full rotation in a few seconds.

The new sensor mast for my robot. Picture: Anthony Hartup

The head of the unit is simple. I found a plastic bracket in my kit and screwed it to a piece of MDF in a way that allows sideways adjustment if required. Rubber bands hold the sensor in place and the whole assembly is tacked onto the steel shaft with a dob of glue.

The new sensor mast with wiring connected. Picture: Anthony Hartup

The mast needs the freedom to turn 180 degrees in either direction so I have used cables of adequate length to allow that.

Overall I am happy with this project. It is really not heavy-duty, but neither is it fragile. There are four separate adjustment points to remedy any future damage. Best of all, because I already had the motor and sensor, I didn't have to spend a penny.

The code

I have written the code below specifically for a Raspberry Pi running Raspian Linux.

One of the main requirements for the movement functions was the intelligence to stay within a 360 degree arc to avoid tearing the sensor wires apart. It also needed the ability to move the sensor directly to a given position regardless of the starting point. It achieves this with two variables, current_pos, and target_pos. The default starting value for current_pos is 0, which means the sensor is pointing directly ahead.

By default the code below provides accurate turning with the motor I have used and and the 40-to-28 gear ratio. By sheer luck this configuration requries 359 step sequences to move 360 degrees, making calculations easy. For different ratios you will need to change the adjuster variable at the top of the code. For example, if the mast is only turning to 120 degrees when you command it to 180 dgrees, you could change the adjustment variable from 1, to 1.3 and try again.

Copy and paste this code into a file and save it as In the Raspberry Pi terminal type sudo python and type your password if prompted.

Type import mast then press Enter. Next, type mast.calc_move(position), placing the target position in degrees within the brackets. For example, to turn the sensor directly left, type mast.calc_move(270). To turn the sensor directly right, type mast.calc_move(90). Press Enter and watch the mast turn to your chosen position.

# Run a 360-degree rotating stepper-motor-powered sensor mast

import time
import RPi.GPIO as GPIO

# Convert full steps to degrees
adjuster = 1
# Current position in degrees
current_pos = 0
# Define pins for motor
motor_gpio_pins = [22, 23, 24, 25]
# Set all pins as output and set LOW
for pin in motor_gpio_pins:
    print("Setup pins")
    GPIO.output(pin, False)
#Define waitTime between steps
pause = 0.006

# Create stepping sequences
orders = [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]

# Move the mast one full step sequence
def mast_motor(mdirection):
    global orders
    current_order = 0
    # Define order of GPIO signals to use
    if mdirection == "anti_clockwise":
        motor_gpio_pins = [22, 23, 24, 25]
    elif mdirection == "clockwise":
        motor_gpio_pins = [25, 24, 23, 22]
    # Work through all combinations in orders array
    while current_order < len(orders):
        # Switch each pin to suit the current combination
        for pin in range(0, 4):
            targetpin = motor_gpio_pins[pin]
            if orders[current_order][pin]!=0:
                GPIO.output(targetpin, True)
                GPIO.output(targetpin, False)                
        current_order += 1        
# Calculate the distance and direction and move the motor to a location in degrees
def calc_move(target_pos):
    global current_pos
    if target_pos < 360:      
        if target_pos < 181:
            if current_pos < 181:
                if current_pos < target_pos:
                    distance = target_pos - current_pos
                    direction = "clockwise"
                elif current_pos > target_pos:
                    distance = current_pos - target_pos
                    direction = "anti_clockwise"
            elif current_pos > 180:
                distance = (360 - current_pos) + target_pos
                direction = "clockwise"
        elif target_pos > 180:
            if current_pos < 181:
                distance = (360 - target_pos) + current_pos
                direction = "anti_clockwise"
            elif current_pos > 180:
                if current_pos < target_pos:
                    distance = target_pos - current_pos
                    direction = "clockwise"
                elif current_pos > target_pos:
                    distance = current_pos - target_pos
                    direction = "anti_clockwise"
        moves = 0
        while moves < int(distance * adjuster):
            moves += 1                    
        current_pos = target_pos
        print("You must choose a target position between 0 and 359.")        

def clean_up():
  print("Pins reset")

I will have the full version of this code, including the module to work the measurement functions, available for download from the AAIMI source code page shortly.




Next: AAIMI home-automation hardware.



Comments are now live on this page.

Leave a comment on this article