Reading digital calipers with an Arduino

What do you use to measure sizes accurately? A pair of calipers of course! And what would you use if you need accurate measurements as input for a computer program? Again, a pair of calipers. Most digital calipers have a hidden port that outputs measurement data. In this post I will show how to interface digital calipers to an Arduino.

Digital calipers
A pair of digital calipers. There is a small data connector behind the lid.

This is the pair of calipers I will be using. Behind the black lid at the top are solder pads carrying – from left to right – ground, data, clock and +1.5V. This should be the same for most calipers, although it’s best to measure using an oscilloscope or multimeter to be sure.

So let’s hook up the data and clock lines to the oscilloscope to see which data is transferred with the caliper jaws closed (0.00mm):

Caliper sends data every 100ms
The caliper sends its data every 100ms. The oscilloscope is set at 50ms per division.

As you can see, the calipers send their data in bursts every 100ms. This means 10 measurements per second. Let’s zoom in a bit further to see how the data looks:

Caliper clock (yellow) and data (red)
Caliper clock (yellow) and data (red) at 0.00mm. Every vertical division is 1.0ms

The signal is inverted: a low voltage is a 1 and a high voltage a 0. The yellow clock line goes low 24 times, meaning 24 bits of data are sent. The protocol looks a lot like what Robocombo found, so I’ll be using his code for the TI Launchpad as the basis for my Arduino code.

Hooking it up to the Arduino

The calipers are powered by a 1.5V battery. This means the high level signals will be no higher than 1.5V, which is too low for an Arduino to register as a logical ’1′. The obvious way to solve this is with level conversion: use transistors or an ic to translate the 1.5V to a higher voltage.

However, I don’t feel like adding an extra chip or a few transistors and resistors. For an Arduino to register a signal as a logical one, it needs to be at least half of the supply voltage. So if your Arduino runs at 5V, a logic ’1′ is any signal from 2.5V up. If the Arduino runs at 3.3V, 1.65V should be enough to trigger a logic ’1′. That means if I run my Arduino at 3.3V and power the calipers with a voltage just above 1.65V things should be fine. A matter of taking out the calipers’ battery and building a small voltage regulator circuit to provide 1.8V to the calipers:

Digital Calipers and voltage regulator
The circuit provides the calipers with 1.8V so that the battery is no longer needed.

The Arduino code

The Arduino code is loosely based on work by Robocombo as mentioned earlier. Let’s first set up our serial connection and define the clock and data pins:

void setup() {
  Serial.begin(19200);

  pinMode(CAL_CLK, INPUT);  // Clock pin = 2
  pinMode(CAL_DATA, INPUT); // Data pin = 3

  attachInterrupt(0, dataReceived, FALLING);
}

Instead of constantly polling the clock and data lines in a loop, we’ll be using attachInterrupt() to handle the data every time the signal at the clock pin goes from high to low (FALLING).

dataReceived() is the function that is called when an interrupt occurs:

void dataReceived() {
  unsigned char data;
  data = digitalRead(CAL_DATA); // read DATA value as soon as possible

  now = millis(); // What time is it now?
  if((now - lastInterrupt) > 50) {
    // More than 50 ms have passed since the last clock pulse.
    // Let's start with a new value
    finalValue = value; // This is what gets sent to the computer
    bits_so_far = 0;
    value = 0;
    flag = 1; // Let the main loop know the value is ready
  } else {
      if (bits_so_far < 15){          // But we need only 16bits
         if (data)                    // if 0 received, invert = >1
            value |= 0x8000;          // then set most significant bit
         value = value >> 1;          // and move it one right
      } else if (false && bits_so_far == 21) { // Bit 21 indicates (+/-)
         if (data)
            value = (~value)+1;                // make it negative
      }
      bits_so_far++;
   }
   lastInterrupt = now;
}

The function checks whether the last time a clock pulse was detected was more than 50ms ago. If so, that means we will be reading a new set of data. If not, the bit gets added to the final value.

The loop() function is very simple:

void loop() {
 if(flag) {
   if(finalValue != previousValue) {
     Serial.println(finalValue,DEC);
     previousValue = finalValue;
   }
   flag = 0;
 }
}

It just checks whether a new value is available, and if so, sends it to the computer (but only when the new value is different from the previous one). It then clears the flag.

Fire up the Arduino serial monitor at 19200baud and there you have it: measurements streaming in at up to 10 measurements per second. I used an Arduino Mini at 3.3V and the calipers at 1.8V. The electronics inside the digital calipers are so simple that it’s probably no problem to run them at 3V and hook it directly to an Arduino running at 5V.

8 Responses to “Reading digital calipers with an Arduino”

  1. Oli Kingwell

    Hi there, I stumbled across this page whilst researching interfacing these calipers with arduinos, and noticed that you have not declared any of the variables in this code sample, i have interpreted it as best i can, however the serial data i get doesn’t read the caliper properly, what are finalValue, previousValue, and value supposed to be declared as?

    cheers.

  2. Bill

    Very nice, clean sketch. I think I will try it with my own calipers. Did you see any bad messages? Thanks.

  3. David

    @Oli: the values should be declared volatile because you are using them inside an interrupt. A volatile int should work.

  4. Sverre

    Hello; Interesting page!
    Is it possible to use this approach for reading 2 or more calipers – like reading X, Y and Z from a milling machine? Would tha Arduino handle that many interrupts?

  5. David

    @Sverre: yes, that should be possible. The Arduino has two hardware interrupts. Once you want more than two calipers the code will become a lot more complex (but still doable)

  6. Sverre

    Thanks! I thought a little more about it. May be it is a better approach to make a modular DRO, with a small box containing an Arduino Micro and a large LED display, and then stack as many modules on top of each other as I need. The Arduino cost is so low….

  7. Leon

    So in this example the data rate is equal to clock rate ?
    I have clock rate of 76.92KHz and data rate of 3.125 hz, What changes should I make ?

  8. Paolo

    Hello David! Very interesting job! Any suggestions about the little electronic schema that I see in the picture (voltage regulator)? Thanks so much!

Leave a Reply