I always was thinking of a measuring tape that never ends and be able to measure very long things. So I decided to make a small odometer and use it as a digital measuring tape.
I used a PIC16F819 microcontroller and a sensor from an old computer mouse (the remaining parts of one of my other projects Crazy Mouse) to make this simple measuring tape.
Do you want to make yourself? If yes read the rest of this instructable.

Step 1: What You Need

To make this measuring tape you need the following components and tools:
  • Printed circuits (find files in the next step)
  • Copper board
  • Sandpaper
  • Iron
  • Circuit board acid
  • 1mm drill
  • Soldering tools
  • 1x PIC16F819 microcontroller + socket
  • An old mouse (or one of its IR shaft encoders)
  • 3x BC547 transistors
  • 3x common anode 7 segments
  • 1x 100uF electrolyte capacitor
  • 1x 470ohm resistor (1/8 watt)
  • 7x 10k resistors (1/8 watt)
  • 2x Simple push buttons
  • 1x Simple switch
  • 2x AA batteries with a battery holder
  • 1x Wheel (+ maybe some gears)
  • A box for this measuring tape

Step 2: Making the PCB

First you need to make a PCB. Here is a good instructable for making PCBs.
  1. Print the circuit on a glossy paper with a laser printer without scaling.
  2. Cut some copper board and clear it with sandpaper.
  3. Put the printed circuit on it.
  4. Press the hot iron on the board.
  5. Remove the papers.
  6. Soak boards in acid and wait till visible copper disappears.
  7. Wash the boards.
  8. Drill the holes.
  9. Clear the board with sandpaper.

Step 3: Soldering Components

Now it's time to solder components on the board. Here is a good instructable for Soldering.
  1. Solder the mouse IR transmitter and receiver on the board.
  2. Solder 470ohm resistor behind the IR transmitter.
  3. Solder 10k resistors on the board.
  4. Solder some wires on the lines that connect two holes together. (jumpers)
  5. Solder microcontroller socket on the board in a correct direction.
  6. Solder seven segments.
  7. Solder transistors.
  8. Solder buttons with some wire.
  9. Solder the capacitor on the board in a correct direction.
  10. At last solder the switch to the battery holder and solder its wires to the BAT terminal.

Step 4: Programming

Download the following file and program your PIC16F819 microcontroller. You can use any programmer to do this, I am using WinPic with a JDM programmer. After programming your microcontroller place it on its socket on the board.
Don't forget to:
  • Set oscillator to internal RC
  • Set RA6 port to I/O port
  • Turn off all timers
  • Set MCLR to input pin
  • Turn off the brown out detect
In other words: config word ($2007) = 0x3F18

Step 5: Attach the Wheel

Solder two legs on the board to hold the shaft encoder wheel, turn on the measuring tape and adjust the position of the toothed wheel. Rotating the wheel must cause increase in displaying number and rotating it back must cause decrease in displaying number.
Finally attach a wheel to the toothed wheel shaft directly or using some gears, and put all in a box.

Step 6: How It Works?

The IR receiver component contains two IR receivers that the sequence of their state change indicates the direction of rotation (00 10 11 01 00 ... and 00 01 11 10 00 ...).
One of the IR receivers is connected to A4 pin and the other is connected to B0 pin. Every time the state of B0 pin changes from 0 to 1 the microcontroller increases or decreases the "Ticks" variable depend on the state of A4 pin, high A4 indicates forward rotation and low A4 indicates backward rotation:

void interrupt(void)
    if (Sensor1)
      if (RButton)
        if (OneMeterTicks == MaxOneMeterTicks) OneMeterTicks = 0;
      if (RButton)
        if (OneMeterTicks == 0) OneMeterTicks = MaxOneMeterTicks;
    if (abs(Ticks) >= OneMeterTicks * 10) Ticks = 0;
    INTCON.INTF = 0;

The number of ticks made by the change of B0 pin state determines the distance traveled after scaling by factor "OneMeterTicks". The value of "OneMeterTicks" can be changed by rotating the wheel while holding down the "RESET" button.

if (Ticks < 0)
  n = -Ticks;
  n = Ticks;
n *= 100;
if (UButton == 1)
  n /= (unsigned long int)(OneMeterTicks * 2.54);  // inch
  n /= (unsigned long int)OneMeterTicks;  // cm
Digit[2] = n / 100;
n = n % 100;
Digit[1] = n / 10;
Digit[0] = n % 10;

I used "mikroC PRO for PIC" to write the program.

Step 7: Calibration

  1. Turn on the device.
  2. Move it gently through a line that you know its length.
  3. Hold the "RESET" button down and rotate the wheel to see correct number on the display.
  4. Release the "RESET" button.
  5. The device is now calibrated.

Step 8: How to Use

  1. Turn on the device.
  2. Move it on a line gently to measure the distance traveled.
  3. Press the "RESET" button to set display number to zero.
  4. Hold down "INCH" button to see the display number in inches.
<p>good idea thankes</p>
<p>can i replace pic16F819 with pic16F627? and can you sent me your schematic project to febriansahsetiawan@gmail.com thanks</p>
Yes, but you must make little changes to circuit diagram and program. Try to DIY!
<p>Hello dear Vahid. Thank you for sharing this. I really liked your project and i'm going to make it. But I need to measure small distances with millimetric precision. I wonder if it's possible to change the code so that it can measure from 1 to 999 millimeters? </p><p>Regards</p>
Yes, You must change the software and gears ratio.
<p>what software you used to sketch the circuit?</p>
<p>what software you used to sketch the circuit?</p>
<p>what software you used to sketch the circuit?</p>
<p>what software you used to sketch the circuit?</p>
<p>what software you used to sketch the circuit?</p>
<p>what software you used to sketch the circuit?</p>
<p>what software you used to sketch the circuit?</p>
<p>what software you used to sketch the circuit?</p>
<p>Yes, but you must design new circuit and write new program.</p>
I'm trying to make this project but am running into a problem. How can i check if the IR receiver and transmitter are working or not? What are the voltages on their pins supposed to be if i apply a voltage of 3 volts after putting them on a breadboard?
If you found this components in a mouse you can take a look at mouse board to find resistors you need to use (most of mouses are 5V). In my circuit I used a 470 ohm resistor for transmitter, no resistors for receivers and 4.5V battery pack. You can see IR transmitter light using a digital camera or mobile phone camera. You can test receivers by connecting it to an ohmmeter and any IR remote control like TV remote control. If you have the components ID search for their datasheet on the Internet.
can u explain it to me, thanks a lot mr. <br> <br> LRButton = 0; <br> if (EEPROM_Read(0) == CorrectROMValue) <br> { <br> unsigned short int k; <br> OneMeterTicks = EEPROM_Read(1); <br> k = EEPROM_Read(2); <br> OneMeterTicks = (OneMeterTicks &lt;&lt; 8) + k; <br> } <br> LOneMeterTicks = OneMeterTicks; <br> while (1) <br> { <br> if ((!RButton) &amp;&amp; LRButton) <br> { <br> Ticks = 0; <br> if (OneMeterTicks != LOneMeterTicks) <br> { <br> EEPROM_Write(0, CorrectROMValue); <br> EEPROM_Write(1, (unsigned short)(OneMeterTicks &gt;&gt; 8)); <br> EEPROM_Write(2, (unsigned short)OneMeterTicks); <br> LOneMeterTicks = OneMeterTicks; <br> } <br> } <br> LRButton = RButton; <br>
LRButton = 0; (*Initial assigment of LRButton variable*) <br> if (EEPROM_Read(0) == CorrectROMValue) (*if the user did not calibrated yet the value stored in posiition 0 of EEPROM is zero so if only already calibared read calibration value from EEPROM, CorrectROMValue is an arbitrary constant value*) <br> { <br> unsigned short int k; <br> OneMeterTicks = EEPROM_Read(1); (*read first byte of calibrated value fromm EEPROM*) <br> k = EEPROM_Read(2); (*read 2nd byte of calibrated value fromm EEPROM*) <br> OneMeterTicks = (OneMeterTicks &lt;&lt; 8) + k; (*join 2 bytes together*) <br> } <br> LOneMeterTicks = OneMeterTicks; (*store OneMeterTicks value to LOneMeterTicks*) <br> while (1) (* the endless loop to run the reset of the program*) <br> { <br> if ((!RButton) &amp;&amp; LRButton) (*if RButton is Up (=0) but in last state was down (LRButton=1)*) <br> { <br> Ticks = 0; (*zero the display value*) <br> if (OneMeterTicks != LOneMeterTicks) (*if OneMeterTicks not equals last saved OneMeterTicks means that the user changed calibration value so it must be saved to EEPROM*) <br> { <br> EEPROM_Write(0, CorrectROMValue); (*write the value that indicates already calibrated to EEPROM*) <br> EEPROM_Write(1, (unsigned short)(OneMeterTicks &gt;&gt; 8)); (*write 1st byte of calibration value to EEPROM*) <br> EEPROM_Write(2, (unsigned short)OneMeterTicks); (*write 2nd byte of calibration value to EEPROM*) <br> LOneMeterTicks = OneMeterTicks; (*store new value of OneMeterTicks value to LOneMeterTicks*) <br> } <br> } <br> LRButton = RButton; (*store the sate of RButton in LRButton*)
if (abs(Ticks) &gt;= OneMeterTicks * 10) Ticks = 0; <br> INTCON.INTF = 0; <br> <br>what is means with this coding
This is the maximum distance limit, if the distance is 10 meters it could not be displayed on 3 digit seven segment display so reset the number to zero again. And also if you do not do this the &quot;Ticks&quot; variable may be overflow, or you must use variable type with more capacity.
can i use 1 transmitter n 1 receiver only?
No, you must use 2 receivers in order to detect direction of movement. All IR encoders like that I used have a component that contains at least 2 receivers in a block.
if i need use LCD which part of programming i need to change
Change: <br> <br>Cycle++; <br>if (Cycle == DigitChangeCycle) <br> { <br> SS1 = 0; <br> SS2 = 0; <br> SS3 = 0; <br> if (Ticks &lt; 0) <br> n = -Ticks; <br> else <br> n = Ticks; <br> n *= 100; <br> if (UButton == 1) <br> n /= (unsigned long int)(OneMeterTicks * 2.54); <br> else <br> n /= (unsigned long int)OneMeterTicks; <br> Digit[2] = n / 100; <br> n = n % 100; <br> Digit[1] = n / 10; <br> Digit[0] = n % 10; <br> dig = Digit[DigitIndex]; <br> SSA = ((dig == 1) || (dig == 4)); <br> SSB = ((dig == 5) || (dig == 6)); <br> SSC = (dig == 2); <br> SSD = ((dig == 1) || (dig == 4) || (dig == 7)); <br> SSE = ((dig != 0) &amp;&amp; (dig != 2) &amp;&amp; (dig != 6) &amp;&amp; (dig != 8)); <br> SSF = ((dig == 1) || (dig == 2) || (dig == 3)); <br> SSG = ((dig == 0) || (dig == 1) || (dig == 7)); <br> if (DigitIndex == 0) SS1 = 1; <br> if (DigitIndex == 1) SS2 = 1; <br> if (DigitIndex == 2) SS3 = 1; <br> Cycle = 0; <br> DigitIndex++; <br> if (DigitIndex == 3) DigitIndex = 0; <br> if ((DigitIndex == 2) &amp;&amp; (Digit[2] == 0)) DigitIndex = 0; <br> if ((DigitIndex == 1) &amp;&amp; (Digit[2] == 0) &amp;&amp; (Digit[1] == 0)) DigitIndex = 0; <br> } <br> <br>To: <br> <br>if (Ticks &lt; 0) <br> n = -Ticks; <br>else <br> n = Ticks; <br>n *= 100; <br>if (UButton == 1) <br> n /= (unsigned long int)(OneMeterTicks * 2.54); <br>else <br> n /= (unsigned long int)OneMeterTicks; <br>Your code to display n on the LCD
i dont understand with Void intterupt part..
At the beginning of the program I configured PIC to go to interrupt routine every time the state of B0 pin (that is connected to oner of receivers) changes from 0 to 1. <br>&quot;if (INTCON.INTF)&quot; ensures that B0 pin changed. <br>&quot;if (Sensor1)&quot; means that if the other receiver that is connected to A4 pin is 1. <br>&quot;if (RButton)&quot; means that is user held down the Reset button in order to calibrate. <br>When the B0 pin changes from 0 to 1, if the A0 pin is 1 it means that wheel if rotating forward, and if the A0 pin is 0 it means that wheel if rotating backward. So if the user wants to calibrate the program changes the Ticks/Meter constant that is stored in the ROM of PIC, and if the user want to measure (not holding down Reset button) program counts the number of ticks made by rotating toothed wheel and convert it to meter using the conversion ratio. <br>
is it true, i just need 1 set of optical sensor (1 transmitter and 1 receiver)...or i need 2 set..
you need 1 transmitter and 2 receivers, the receiver part in old mouses is a single component that contains 2 receivers inside.
hello, i dont understand for &quot;if(Rbutton)?...can u explain it to me..
If you download and see the rest of code, you'll see that RButton is defined as A2 pin that is connected to Reset (Calibrate) button, so this line means that &quot;if that button is closed&quot;.
hi, I want just to ask if the program is running? or there's some changes ?
Hello. are the IR receiver and the IR transmitter both found in the IR shaft encoder from mouse? <br>if not, what is that IR shaft encoder a trasmitter or a receiver? Thanks in advance for the answer.
Hi, Yes, You can find all these 3 components in a old mouse, shaft encoder is the toothed wheel, and transmitter and receiver are the components that toothed wheel is among them.
nice project! <br>i just want to ask if we can use meter, ft, inches, cm, etc. units at the same time?
Thanks, Yes, All you have to do is to add conversion factors between units to the program and use a display with more capacity like LCD.
can i replace PIC16F819 with PIC16F84A ?
Yes, But a few changes must be made in the source code.
how long does it took to finish<br>can ii do it in less than a 3 weeks
If you have all things needed, you can do it in a day.
Cool project.<br>How accurate is it?
I made this for long distances, It's accuracy is 1 cm or 1 inch.
Cool project. I love how you used the ink carts as the shell. Bonus for the recycle! <br>OK, dumb question incoming (sorry, I have to ask it) but, 1 cm or 1 inch...? That's a big discrepancy. If you were talking about 1cm per 1/2 kilometer or 1 inch per 300 yards or something along that line, then it's not that big a deal. But, if it's less than that then I question the accuracy.<br>Can you be a little more specific about it's accuracy, please?<br><br>Thanks!
You select the units (cm or inch). Resolution is +- 1 count on the optical wheel. You could use different gearing to get better resolution but the accuracy depends on how well the wheel is in contact with the map (wall, ground ...). Great use of a PIC, I like the way vahid(author) drew the little hands next to the buttons.
Actually you could increase your resolution up to 4 times by using Quadrature encoding.<br>http://zone.ni.com/devzone/cda/tut/p/id/4763<br>By putting the encoders out of phase by 90 degrees you essentially quadruple the counts per turn. The old mouse should have 2 break beam sensors in it already.
Very good idea, thanks.
The little hand mean that you must hold the button, I saw this sign on my refrigrator panel!
Its accuracy depends on the calibration, according to the 7th step you can calibrate it with 50cm line or with a 9m line, of cource calibrating with a 9m line makes the device more accurate. Actually the shortest distance that you can measure with this device is 1cm, when the software converts the result to inches it rounds the number so if you use inch unit the shortest distance is 1&quot;.
You could also get the IR bits form an old ball mouse! They work exactly the same way actually. You might even be able to use the inside of a scroll wheel for the wheel here. It has the notches in it and everything.

About This Instructable



Bio: I'm a mechanical engineer, and I like computer programming, mechanics, electronics and specially the robotics.
More by vahidyou:Serial Port over WiFi Cheap Logic Analyzer Cheap STK500 AVR programmer for Atmel Studio 
Add instructable to: