Introduction: Spotter Scope

So this Lazy Old Geek (LOG) decided to build a Spotter Scope. Since I’m a Geek I decided to add an Arduino.

Now this isn’t totally frivolous. I share WiFi with my cousin whose house is about 780 feet from mine. I’m using directional transceivers and need to point the antennas at each other.

The Spotter scope would be mounted to a tripod and swivel. And later be able to tilt. So I wanted to do a few things. First I wanted to level the scope, so that when it swiveled it would be looking at the same elevation. Then I would also be able to tilt the scope and display the angle. Third I would like to display the compass bearing.

And I had the perfect sensor for this, an LSM303dlhc (see picture) It is a magnetometer (compass) and an accelerometer (level) combined.

Step 1: Hardware

So I needed a Spotter Scope.

The cheapest ones I could find are for Air rifles (BB guns) so I ordered this 4 x 20 Air Rifle Telescope Sight:

PROBLEM: So the first problem was to find something to attach the scope to.

SOLUTION1: The scope description said it will fit a 9 – 11 mm rail. So I found and bought this rail (see picture):

Now this says it’s a 3/8” rail which is about 9.5mm.

When I finally got them both in, the two did not fit. Apparently, the Scope was using the outer dimensions and the rail was using the inner dimensions. I did a little research on this and there doesn’t seem to be any standard on measuring rails and nobody seems to give actual dimensions.

SOLUTION2: Well, this is not going well. I thought I could order another rail but still wouldn’t have any idea if it would work until I got it in. So I went over to my local hardware store and found these brass mending plates (see picture) that were close to the right width. I did grind off the long edges so it fit a little easier.

PROBLEM2: So my first attempt was using this brass plate with the LSM303 attached to it. Well, it mostly worked until I tried to get the magnetic heading. Doing some testing, I found out the brass plate was magnetic. Apparently, these are brass plated not brass.

SOLUTION3: I had to redesign the whole assembly using an aluminum L bracket. (see picture)

Since I wanted it to swivel, I bought this Lazy Susan 3” Bearing:

(see picture)

Step 2: Assembly

I used a 1/2” aluminum L bracket to mount the scope. (see pictures). I cut it to about 4.5”. This is not clamped into the scope clamps but is bolted to the side of the clamps. (see picture) This is not the most stable mounting but should keep everything aligned.

TIP: The LSM303dlhc module is sensitive to twisting pressures so be sure to drill the mounting holes so that they’re larger than the module so when attaching there is no additional stress on the module.

I needed to attach the bearing to the tripod. Tripods have a standard camera mounting screw which is ¼ x 20 thread. I cut a piece of Lexan to fit the bearing, drilled four holes to attach it and inserted a ¼ x 20 insert and used gorilla glue (the yellow stuff) to glue and center it. (see picture)

I cut a piece of 0.093” Lexan to 3.5” x 5” for the top plate. (see picture)

There’s four holes for the bearing, two holes for the L bracket and two holes for the LSM303 module.

NOTE: The LSM303 is affected by nearby magnetic metals. I mounted the LSM303 module away from the scope and metal bearing. I used nylon screws and standoffs so the hardware won’t affect the magnetometer.

The next picture shows the bracket attached to the top plate. Due to my poor mechanical design skills, I didn’t allow much clearance for the bolts so I had to use 4-40 hardware so that it would clear the bearing and the scope clamps. The L bracket is parallel to the LSM303 module.

The next picture shows the scope attached to the bracket.

The next pictures show the LSM303 module attached to the top plate.

The next picture shows the Arduino and battery attached to the top plate. I used Velcro to attach the battery to the top plate and Velcro to attach my Arduino PCB to the battery.

NOTE: I also put a tie wrap under one of the screws and anchored the wires going to LSM303 module. Any additional stress on the module can affect the accuracy of the readouts.

Step 3: PCB

This is actually similar to the PCB I used for my Monkey Tracker:

The PCB connects the LSM303 to the Arduino and the LCD to the Arduino. It also has a 3.3Vdc voltage regulator powered by the battery and supplying the LSM303, the LCD5110 and the Arduino.

I did make and attach the Eagle files for this PCB but for some reason, I actually made a PCB from the Monkey Tracker files. Differences, I did not put in the connectors for the GPS and the nrf24L01. Also for the LSM303dlhc, I put some wires on a female header and soldered them to the PCB. Later I replaced those green wires with some 30 gauge wire wrap wire so there would be less strain on the module.

This PCB is designed to run on a 3.7Vdc lithium battery. The battery I used was designed to be used in a smartphone. I soldered a JST2.0 connector to the connector.

I also soldered a female JST2.0 connector to a USB lithium battery charger so I can charge the battery. (see picture)

Schematic and Eagle Cadsoft files attached.

Step 4: Software Calibration

CAUTION: My PCB uses an Atmega328 programmed with PRO-MINI 8MHZ 3.3V bootloader. If you build this PCB, you must program it with the PRO-MINI 8MHZ 3.3V bootload and must select it when using the Arduino environment. The PCB is designed to use a USB-BUB adapter or, I use, a PL2303 equivalent.

For the LSM303dlhc, I used this Pololu library:

This includes a procedure to calibrate the magnetometer. I modified it to work with my Arduino and LCD5110. It is attached:

CALIBRATE: This program is similar to the Serial example, but instead of printing the most recent readings, it prints a running minimum and maximum of the readings from each magnetometer axis. These values can be used to calibrate the heading() functions and the Heading example after moving the LSM303 through every possible orientation.

I modified it so that the Mins and Maxs will display on the LCD5110. Run sketch, slowly, twist and turn the module in all orientations. Record the Mins and Maxs on the display, then plug them into SpotterLevel sketch, replacing the values in the following lines:

compass.m_min = (LSM303::vector){-433, -600, -546};

compass.m_max = (LSM303::vector){570, 488, 579};

This should improve the compass readings.

For this application, the accelerometer portion is used to determine when the assembly is level.

THEORY: Accelerometer measures acceleration. Gravity is a form of acceleration. The LSM303dlhc module measures acceleration in three directions x, y and z(see picture). Z is actually up and down. In this application, since the LSM303 is mostly stationary, the acceleration measured is gravity. So if the LSM303 is level, then the x and y accelerations would be 0 and z would be 1g (standard gravity). Now the LSM303 is set for +/- 2g so 1g is about 16384 counts. (The Geek in me says this should be 32768 !!!)

Now if the LSM303 was upside down, the z value would be -1g, about -16384.

Although probably not necessary, I also wrote a calibration program for the accelerometer,

NOTICE: The calibration pictures were taken with my first version of spotter scope. For the latest version, I assembled the complete spotter scope assembly but did not attach it to a tripod. Use the same method as in the pictures.

To calibrate, I assembled my spotter scope and loaded each of the programs.

For each program take the whole assembly outside, power up the Arduino. Slowly, move it around in all orientations, level, upside down, scope up, scope down, scope on right side, scope on left side and slowly spin it around.

Record the min and max values for Calibrate and AccelCal sketches. They will be used in the next step.

Step 5: Arduino Sketch

WhatItDoes: My SpotterLevel sketch displays the heading or bearing that the scope is pointed towards. The standard magnetic compass is divided into 360 degrees with North at 0, East at 90, South at 180 and West at 270. The heading is the direction the scope is pointed towards in degrees.

For the compass in this picture, the heading is about 123 degrees.

Also displayed are the x, y and z values of the accelerometer in degrees with level at 0 and straight up at 90. So perfectly level would be 0, 0, 90.0.

I use Adafruit libraries for the LCD5110 module.

WARNING: When I updated to Arduino to 1.6.1, I had to update Adafruit_GFX and Adafruit_PCD8544 libraries:

As stated before:

CAUTION: My PCB uses an Atmega328 programmed with PRO-MINI 8MHZ 3.3V bootloader. If you build this PCB, you must program it with the PRO-MINI 8MHZ 3.3V bootload and must select it when using the Arduino environment.

Arduino Environment Version 1.6.4:

Select , Select correct Port

Select , Under Boards, select (Arduino Pro or Pro Mini)

Select , Under Processor, select (Atmega328 (3.3V, 8Mhz))

NOTE: Older versions don’t have Processor selection but have a Pro Mini AtMega328 (3.3V, 8MHz) selection under Boards.

The PCB is designed to use a USB-BUB adapter or, I use, a PL2303 equivalent.

My SpotterLevel sketch needs to be modified for your calibration values found in the last step:

From the Calibrate program, plug the min/max values into SpotterLevel sketch, replacing the values in the following lines:

compass.m_min = (LSM303::vector){-433, -600, -546};

compass.m_max = (LSM303::vector){570, 488, 579};

This should improve the heading readings.

From the AccelCal program, plug the min/max values into SpotterLevel sketch, replacing the values in the following lines:

// Accelerometer Calibration{x,y,z}

const long acmin[3] = {-17008, -16432, -17120};

const long acmax[3] = {16064, 16480, 18176};

This should improve the level readings.

LSM303dlhc Orientation: There is another software setting that may need to be adjusted depending on how the LSM303dlhc module is oriented and which direction you are interested in. In the spotter scope, I want to know what direction the scope is pointing. When attaching the module, you want to make sure it is parallel or at right angles to the direction you are interested. In this case the X arrow is pointing in the direction I am interested in. The following line reflects this:

heading = compass.heading((LSM303::vector){1, 0, 0});

If you’re interested in the opposite direction as the X is pointing you would use:

heading = compass.heading((LSM303::vector){-1, 0, 0});

If you’re interested in the same direction as the Y is pointing you would use:

heading = compass.heading((LSM303::vector){0, 1, 0});

If you’re interested in the direction pointing down (Z) you would use:

heading = compass.heading((LSM303::vector){0, 0, -1});

To summarize, the three values are X, Y and Z. Only one of them can be non-zero. If it’s the same direction as the direction than it is 1. If it’s the opposite direction than it is -1.

TECHNOBABBLE: I believe this is using linear algebra and vector math.(Yuck!)

Unfortunately, there is some more calibrating to do. The LSM303dlhc IC is attached to the interface PCB. The board is bolted to the top plate. All of these stresses on the IC will affect the accelerometer reading so zero won’t be zero. So I added a little correction factor in my sketch.

Final calibration procedure:

Open the SpotterLevel sketch for editing. Make sure the values in this line are all 0.0:

double ac_off[3] = {0.0, 0.0, 0.0}; // Use these to calibrate.

Load the sketch to Arduino.

Attach the assembly to a tripod.

Level the top plate of assembly. I have a little T-bubble level on it. Most tripods have a couple of adjustments to adjust it for level.

This is hard to do. What I do is align the level parallel with one of the adjustments. Make the adjustment then spin it 180 degrees and check. Then rotate the assembly 90 degrees and repeat for the other adjustment.

CAUTION: the bearing has a lot of play in it so make sure the assembly is resting evenly on the bearing.

Once you have the top plate as level as you can get it, turn on the Arduino. Now slowly rotate the plate around and get the min and max values for x, y, z. Then take the average. Here’s what I got, one time:


Max -0.0 0.4 83.7

Min -1.6 -1.0 83.3

Ave -0.8 -0.3 83.5

For the Z you have to subtract 90 from it (-6.5)

Plug these into the sketch

double ac_off[3] = {-0.8, 0.3, -6.5};

You are finally done with calibrating!!

Step 6: Testing

HowToUse: The Arduino displays the Heading (the direction the scope is pointed at) and the X, Y, and Z values of the accelerometer in degrees.

Place the assembly on a tripod.

Turn on the Arduino.

The tripod has a couple of adjustments to level the base. What I do is swivel the assembly so that it is approximately parallel with one of the adjustments. You can see the X and Y directions from the LSM303 module. The goal is to adjust the tripod so that the X and Y are both zero. So carefully adjust the tripod until they’re both close to zero. Then you can rotate the assembly and they should remain close to zero.

NOTE: Spinning the assembly will affect the readout so you need to wait a couple of seconds for the readout to settle.

The Z readout should be close to 90 (which means the Z axis is pointing straight up).

So I took this outside and did some testing. Well, it actually worked pretty good. The leveling was probably good within a degree. And the heading was also pretty good. (see pictures) I have trouble reading a compass to much accuracy anyway and this is much easier and seemed to be pretty accurate.

The main problem was the scope. I could rotate it around but it would only show everything that was level with the scope. This is actually good for some purposes like two man surveying. (see picture)

But I wanted to be able to tilt the scope.

Step 7: Tilt Spotter Scope

So I needed a new Top plate so I could tilt the scope. As I have trouble visualizing mechanical designs and problems, I just tried some ideas and see if I could make them work.

First, I took a couple of pieces of Lexan and Gorrilla-glued them together at right angles. (see picture)

The bottom has four holes to mount it to the bearing. On the side I glued a ¼” nylon insert. One of the reasons I chose an insert is that I know it’s squared up so it should keep things pretty aligned.

Okay, later I Gorrila-glued another piece of Lexan to form a little shelf so the Arduino would be easier to see. (see picture)

I used the aluminum bracket from the level Spotter Scope but added a ¼” hole for a bolt. Note: the bolt and wing nut are brass so not magnetic. And I attached the LSM303 module. (see picture)

The next couple of pictures show how it goes together. Note, that I changed the battery to an 18650 as it fit a little better.


The last two pictures show the complete assembly. This is what I used to re-calibrate using the Calibrate and AccelCal sketches.

Before doing the calibration, using the brass wingnut, make sure the scope is parallel to the base.

Since I made the tilt plate rectangular, I measured the distance from the scope angle bracket to the top of the tilt plate and using the ¼ x 20 brass wing nut and adjusted the scope so the front and rear distance is the same.

Step 8: Tilt Sketch

The SpotterTilt sketch is almost the same as the SpotterLevel sketch. The calibration values are different.

Actually, the only difference is that when doing the accelerometer offset, instead of subtracting the Z value from 90, I used the actually value.

double ac_off[3] = {-1.85, 2.05, 89.35}; //Calibrated values

What this does is sets the X, Y, and Z values to zero when level. So if the Scope is tilted, the Z axis should display the angle of the tilt. (Actually, the X reading should also show the tilt angle.)

Step 9: Conclusions

So once the assembly is leveled, the brass wing nut can be loosened and the scope tilted up or down. The tilt angle is the Z value in degrees.

Well, it works pretty good. The tilt feature makes it more useful and is probably accurate to about a degree.

Two pictures kind of shows the headings. (Yes, it's hard to tell) I don’t think it’s quite as accurate as the level scope. I’m guessing that is because the LSM303 module is right above the metal bearing.

CONCLUSIONS: Two of the nice things about the LSM303 is that it has a three-axis accelerometer which is good for making it level and the three-axis magnetometer means that the compass is tilt compensated which means it doesn’t have to be level to give you an accurate heading.

Now I wish I had better mechanical skills so that I could get everything squared and aligned better and I wish I understood the LSM303 software so that I could improve on the accuracy. But for the cost and my abilities I think this works pretty good.

Professional equipment can costs hundreds or thousands of dollars.

FYI: There are some smartphone apps that do basically what this Instructable does. Some are under surveyor tools or theodolite.


raptor_demon (author)2015-07-13

neat! took me a second to work out what it did but very cool!.

msuzuki777 (author)raptor_demon2015-07-13



About This Instructable




Bio: Lazy Old Geek
More by msuzuki777:Senior MomentsWeather Station 5IP Time Clock Part 2
Add instructable to: